feat(ai): enforce local-first routing
Keep external providers behind server consent, task, and prompt-cost gates while persisting actual provider provenance.
This commit is contained in:
@@ -279,3 +279,13 @@
|
||||
- **Consequences:** AI-003/004 only add typed handlers/producers. Current capacity serialization is process-local for the documented single-backend deployment; database reservation is required before multiple backend replicas. Provider/model semaphores and circuit/provenance remain AI-002 responsibilities.
|
||||
- **User approval required:** No; this follows both programmes' explicit instruction to reuse the smallest reliable existing infrastructure.
|
||||
- **Reversible:** Yes. Keep the worker switch false, remove admission/worker registrations, and retain operation rows/API history. No new schema was added in this slice.
|
||||
|
||||
## DEC-029 — One sequential sidecar router owns local-first fallback
|
||||
|
||||
- **Date:** 2026-08-09
|
||||
- **Decision:** Keep provider execution behind the existing sidecar boundary, make Ollama the default primary, permit at most one sequential external fallback, and carry the backend's rechecked privacy/task decision through the AI-001 execution scope. Reuse existing operation provider/model/progress fields for provenance; add no queue/provider schema or dependency.
|
||||
- **Reason/evidence:** every generative `/cv/*` path already converges on one `_provider_generate` family, while deterministic tasks and `/summarize` must remain local. Sidecar fake-transport tests prove local success, consent/config/task/cost denials, schema fallback, circuit behavior, external failure and no parallel duplicate call. Backend tests prove policy propagation and success/failure provenance.
|
||||
- **Alternatives considered:** provider selection in each controller; browser-selected providers; a second provider abstraction in .NET; simultaneous local/cloud racing; a new circuit/attempt table; increasing synchronous timeouts. These scatter policy, expose authority, duplicate the established boundary, risk double charge/output, add unneeded schema, or mask the queued-operation root cause.
|
||||
- **Consequences:** `AI_ROUTING_MODE` supports `local_only`, `local_first` and explicitly gated `external_only`; invalid values fail closed. New durable task IDs stay local until allowlisted. The current circuit is process-local and one AI worker is the effective single-model concurrency limit. Per-request prompt size limits external spend/exposure, but complete monthly cross-feature accounting and model selection remain rollout gates.
|
||||
- **User approval required:** No; this directly implements the approved local-first programme without invoking a provider or production service.
|
||||
- **Reversible:** Yes. Set `EXTERNAL_AI_ENABLED=false` or `AI_ROUTING_MODE=local_only`; the older `AI_PROVIDER`/model configuration is retained. Existing nullable operation fields and AI history remain readable.
|
||||
|
||||
Reference in New Issue
Block a user