feat(ai-review): config-as-code provider/model + maintainer self-serve BYOK (backend, closes #662) - #664
Conversation
…e BYOK routes Makes BYOK AI review usable end-to-end by maintainers (backend for #662). Config-as-code provider/model: - RepositorySettings gains aiReviewProvider (anthropic|openai|null) + aiReviewModel (migration 0029), settable via .gittensory.yml gate.aiReview { provider, model } and the dashboard. The secret key is never in the yml. - The engine uses the effective provider/model: the stored key's provider is authoritative; a declared provider must match it (else BYOK is skipped → Workers-AI fallback); a declared model overrides the stored/default model. Maintainer self-serve (the missing enabler — keys can't live in repo secrets, since a GitHub App can't read them): - PUT /v1/repos/:owner/:repo/ai-review — set mode/byok/provider/model (merges onto current settings; preserves unrelated settings). - POST/GET/DELETE /v1/repos/:owner/:repo/ai-key — write-only encrypted key; GET returns only {configured, provider, last4, model}. - All session-authenticated + scoped to repos the maintainer owns/maintains (requireRepoMaintainer helper) and allowlisted in canSessionAccessPath. Fixes a real gap: the new repo subpaths must be added to the session path allowlist or every maintainer is wrongly 403'd. The internal-token routes from #652 remain for operator/backend use. Coverage holds above the 97% gate; alignment + OpenAPI + Workers checks pass. Closes #662
|
Note Gittensory Gate skippedPR closed before full evaluation. No late first comment was created.
💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers. |
|
gittensory · advisory review Reviewed 12 changed file(s) — two independent AI reviewers. Suggested action: ✅ Safe to merge — both reviewers found no blocking issues. Reviewer A · Suggestions
Worth double-checking
Reviewer B · Suggestions
Worth double-checking
|
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
…-only panel guard, key validation) (#670) Follow-up hardening from a security/completeness audit of the BYOK feature (PRs #664/#665). The panel was already maintainer-only via the backend gate; these changes close the confirmed gaps. Backend: - Bound the BYOK provider fetch with AbortSignal.timeout (20s), mirroring the github/gittensor timeoutFetch convention, so a hung Anthropic/OpenAI connection can't stall the queue worker. Surface the failure reason (timeout/http_error/exception) in the ai_usage_events audit metadata for observability — never any key material. - Classify POST/DELETE /ai-key and PUT /ai-review as "expensive" in routeClassForPath (POST /ai-key runs PBKDF2 100k iters + an encrypted upsert). - Enforce the provider/key prefix check the schema comment already described: Anthropic keys must start with sk-ant-, OpenAI with sk- (and not sk-ant-), so a mismatched key is rejected with a 400 instead of failing silently later. Frontend: - Add an explicit maintainer/owner/operator role gate to MaintainerPanel via useSession, so the dashboard query and the BYOK form never mount for a non-maintainer (the backend 403 remains the source of truth) and a clean "Maintainer access required" message replaces the raw 403. - Mirror the provider/key prefix validation client-side for instant feedback. Tests: provider-fetch timeout signal + recorded failure reason, rate-limit classification, and provider/key mismatch rejection (400). Branch coverage 97%.
Backend for #662 — makes BYOK AI review usable end-to-end by maintainers. (UI is #663.)
Config-as-code provider/model
RepositorySettingsgainsaiReviewProvider(anthropic|openai|null) +aiReviewModel(migration0029), settable from.gittensory.yml:providermust match it or BYOK is skipped (→ free Workers-AI fallback); a declaredmodeloverrides the stored/default model.Maintainer self-serve (the missing enabler)
Keys can't live in repo secrets — a GitHub App can't read them — so maintainers configure them through gittensory:
PUT /v1/repos/:owner/:repo/ai-review— setmode/byok/provider/model(merges onto current settings; preserves unrelated settings).POST/GET/DELETE /v1/repos/:owner/:repo/ai-key— write-only encrypted key;GETreturns only{configured, provider, last4, model}(never the key).requireRepoMaintainerhelper, mirroring the focus-manifest routes).Real bug fixed
The new repo subpaths had to be added to
canSessionAccessPath's allowlist — without that, the global protected middleware403 insufficient_roles every maintainer before the handler runs (caught by a session-auth test). The internal-token routes from #652 remain for operator/backend use.Tests
Config-as-code parse + round-trip + resolve; engine provider-match / mismatch-skip / model-override; the maintainer routes (operator-token + session owner success + non-owner 403 on every route + cross-repo 403 + 401 unauth + invalid-body 400 + 503 when key storage is unconfigured). Coverage holds at the 97% gate; alignment + OpenAPI + Workers checks pass.
Part of #525.