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>
This commit is contained in:
@@ -193,3 +193,56 @@ def load_from_config(config) -> dict[str, BaseProvider]:
|
||||
"OPENAI_API_KEY": config.openai_api_key,
|
||||
}
|
||||
return load_providers(env)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# §6.7 helpers — per-RFC funder credential plumbing.
|
||||
#
|
||||
# A picker key (the operator-enabled identifier like "claude" or
|
||||
# "gemini-flash") names exactly one provider family (Anthropic, Google,
|
||||
# OpenAI). The funder registers a key per family; the resolver in
|
||||
# funder.py picks the right family for a requested picker key, then
|
||||
# constructs a fresh provider instance keyed on the funder's API key.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
FUNDER_PROVIDER_FAMILIES = ("anthropic", "google", "openai")
|
||||
|
||||
|
||||
def provider_family_for_picker_key(picker_key: str) -> str | None:
|
||||
"""Map a picker key to its provider-family name per §6.7.
|
||||
|
||||
Returns 'anthropic' / 'google' / 'openai' or None for keys outside
|
||||
the known variant tables.
|
||||
"""
|
||||
if picker_key in _CLAUDE_VARIANTS:
|
||||
return "anthropic"
|
||||
if picker_key in _GEMINI_VARIANTS:
|
||||
return "google"
|
||||
if picker_key == "openai":
|
||||
return "openai"
|
||||
return None
|
||||
|
||||
|
||||
def picker_keys_for_family(family: str, enabled_picker_keys: list[str]) -> list[str]:
|
||||
"""Subset of `enabled_picker_keys` served by `family`. Preserves the
|
||||
operator's enabled order so the picker reads stably."""
|
||||
return [k for k in enabled_picker_keys if provider_family_for_picker_key(k) == family]
|
||||
|
||||
|
||||
def construct_for_funder(picker_key: str, api_key: str) -> BaseProvider | None:
|
||||
"""Instantiate a provider for a funder-supplied API key per §6.7.
|
||||
|
||||
Mirrors the variant table `load_providers` uses, without the env
|
||||
contract. Returns None for picker keys outside the known families —
|
||||
the funder cannot serve them and the caller treats the (slug,
|
||||
picker_key) request as unavailable.
|
||||
"""
|
||||
if picker_key in _CLAUDE_VARIANTS:
|
||||
default_model, default_name = _CLAUDE_VARIANTS[picker_key]
|
||||
return AnthropicProvider(api_key=api_key, model=default_model, display_name=default_name)
|
||||
if picker_key in _GEMINI_VARIANTS:
|
||||
default_model, default_name = _GEMINI_VARIANTS[picker_key]
|
||||
return GeminiProvider(api_key=api_key, model=default_model, display_name=default_name)
|
||||
if picker_key == "openai":
|
||||
return OpenAIProvider(api_key=api_key)
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user