Files
Ben Stull 55a8be051a Post-v1: per-RFC credential delegation (funder role) folded into §6.7
Second §19.2 settlement after v1. New §6.7 alongside §6.6: optional
`funder:` frontmatter field names a single gitea_login; a
`funder_consents` app-db row records funder-side opt-in; both halves
required for the binding to activate (two-key rule). Funder universe
replaces — does not augment — the operator universe per-RFC for
attribution-clean resolution. Funder role grants zero §6.1/§6.3
authority. Three revocation paths each restore the operator-credentials
status quo.

§19.2's credential-delegation entry is split: lighter half marked
settled with a pointer to §6.7; operational-realities half (mid-call
failure, rotation, billing, rate-limit attribution) lives on as its
own entry. Test suite is 125/125 green (106 prior + 19 new).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 06:08:43 -07:00

41 lines
1.6 KiB
SQL

-- §6.7: per-RFC credential delegation — the funder role.
--
-- Three pieces hang together:
--
-- 1. cached_rfcs.funder_login mirrors the optional `funder:` frontmatter
-- field. NULL means absent — operator credentials per §18 are used.
-- A populated value names the user whose registered credentials pay,
-- contingent on a matching consent row below.
--
-- 2. user_funder_credentials stores per-user, per-provider API keys.
-- A user can register at most one key per provider family; the keys
-- are stored as-supplied (encryption-at-rest is an operational
-- decision, deferred to §19.2's operational-realities half).
--
-- 3. funder_consents records the funder-side opt-in per-slug. A
-- frontmatter `funder:` field naming a user without a matching
-- consent row is operationally inert per §6.7's two-key rule.
ALTER TABLE cached_rfcs ADD COLUMN funder_login TEXT;
CREATE TABLE IF NOT EXISTS user_funder_credentials (
user_id INTEGER NOT NULL,
provider TEXT NOT NULL,
api_key TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
PRIMARY KEY (user_id, provider),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS funder_consents (
user_id INTEGER NOT NULL,
rfc_slug TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
PRIMARY KEY (user_id, rfc_slug),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_funder_consents_slug
ON funder_consents (rfc_slug);