55a8be051a
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>
41 lines
1.6 KiB
SQL
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);
|