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:
@@ -29,7 +29,7 @@ from fastapi import APIRouter, HTTPException, Request
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from . import auth, cache, chat as chat_layer, db, entry as entry_mod, models_resolver
|
||||
from . import auth, cache, chat as chat_layer, db, entry as entry_mod, funder, models_resolver
|
||||
from .bot import Bot
|
||||
from .config import Config
|
||||
from .gitea import Gitea, GiteaError
|
||||
@@ -576,7 +576,11 @@ def make_router(
|
||||
fetched = await gitea.read_file(owner, repo, path, ref=branch)
|
||||
body_text = _extract_body(rfc, fetched[0], branch) if fetched else ""
|
||||
|
||||
provider = providers[reask_model]
|
||||
# §6.7: pick the funder-credentialed instance when a consenting
|
||||
# funder is in effect on this RFC; otherwise the operator's.
|
||||
provider = funder.provider_for_rfc(slug, reask_model, providers)
|
||||
if provider is None:
|
||||
raise HTTPException(503, "No AI providers configured")
|
||||
system = chat_layer.build_system_prompt(title=rfc["title"], body=body_text)
|
||||
history = chat_layer.build_history(thread_id)
|
||||
reask_prompt = (
|
||||
@@ -907,7 +911,11 @@ def make_router(
|
||||
if not resolved:
|
||||
raise HTTPException(503, "No AI providers configured")
|
||||
model_key = body.model if body.model in resolved else resolved[0]
|
||||
provider = providers[model_key]
|
||||
# §6.7: pick the funder-credentialed instance when a consenting
|
||||
# funder is in effect on this RFC; otherwise the operator's.
|
||||
provider = funder.provider_for_rfc(slug, model_key, providers)
|
||||
if provider is None:
|
||||
raise HTTPException(503, "No AI providers configured")
|
||||
|
||||
# Fetch the live branch body so the prompt is anchored to
|
||||
# what's in Gitea right now, not the cache. For super-draft,
|
||||
|
||||
Reference in New Issue
Block a user