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:
cesnimda
2026-08-09 12:30:11 +02:00
parent c3f4a57195
commit 5eb9b3cb96
29 changed files with 967 additions and 145 deletions
+11
View File
@@ -463,3 +463,14 @@ Status: Implemented; real-handler/browser/production verification incomplete (20
- **Findings:** no new schema/raw private queue payload; multi-replica capacity needs a future database reservation; actual 202 producers and provider controls remain AI-003/004 and AI-002.
- **Blockers:** browser, MariaDB and production unavailable; worker intentionally off.
- **Next phase:** AI-002 Ollama adapter and central local-first routing.
## Post-audit programme execution — AI-002
Status: Implemented; browser/model/provider/production verification incomplete (2026-08-09).
- **Work completed:** revalidated every AI endpoint/caller; replaced direct configured-provider dispatch with one sequential local-first router; added task/consent/config/prompt-cost gates, bounded circuit/health state, typed sanitized failures and actual provider/model/route persistence for AI history and durable operations.
- **Commands/evidence:** verification-log V-098V-100; `docs/verification/ai-002-provider-routing.md`; `docs/audits/evidence/ai-002/README.md`.
- **Findings:** no schema/dependency change and no provider race. New durable tasks fail safe to local until allowlisted. Per-request prompt ceiling exists, but complete monthly cross-feature accounting remains incomplete. Circuit state is process-local for the current single-sidecar design.
- **Checks that remain:** real AI-003/004 handlers/producers; selected-model benchmark; browser disclosure; MariaDB; controlled synthetic external fallback; production health/restart/canary/rollback.
- **Blockers and limitations:** no browser, production access, model benchmark or provider authority/configuration; no real/private input used.
- **Next phase:** AI-003 Strategy Snapshot durable-operation migration.
+8
View File
@@ -0,0 +1,8 @@
# AI-002 evidence
- `../../../verification/ai-002-provider-routing.md` — route matrix, implementation and remaining gates.
- `../../verification-log.md` entries V-098 through V-100 — exact commands and results.
- `../../../../tools/summarizer/tests/test_app.py` — fake-transport local-first, consent, circuit, schema, cost-cap and failure tests.
- `../../../../JobTrackerApi.Tests/AiOperationQueueTests.cs`, `AiPrivacyPolicyTests.cs`, `SummarizerServiceTests.cs` and `AiWorkspaceTests.cs` — policy propagation and provenance tests.
No screenshot was captured because localhost browser access remains denied by administrator policy. No model/provider call, paid service, real private data or production system was used.
+3
View File
@@ -103,6 +103,9 @@ Only non-destructive commands are run. Commands that restore dependencies may po
| V-095 | Full backend `dotnet test`; full frontend `npm test -- --runInBand`; `npm run build`; `docker compose config --quiet`; `git diff --check` | Repository root / `job-tracker-ui` | POL-002 regression, production build, deployment syntax and patch hygiene | PASS — backend 576/576; frontend 47 suites/158 tests; build/config/diff pass | Expected unset optional Compose variables and line-ending notices only. Temporary API launch command was rejected before execution by policy; no service started | Runtime/browser/production verification blocked |
| V-096 | Source re-read plus `dotnet test ... --filter "...AiOperationQueueTests|...UserOperationStoreTests|...OperationsControllerTests"` | Repository root | AI-001 admission, capacity, priority, claim, owner execution, policy recheck and existing state/API regression | PASS — 17/17 final | Initial 15/15 and 16/16 passes preceded priority and retry/downgrade additions | N/A |
| V-097 | Full `dotnet test`; `docker compose config --quiet`; `git diff --check` | Repository root | AI-001 full backend regression and deployment/patch syntax | PASS — backend 581/581; config/diff pass | Expected unset optional Compose variables and line-ending notices only; worker remains default-off with no real task handler | Browser/provider/production verification pending later feature packages |
| V-098 | Bounded `rg`/`Get-Content` of every `/summarize`, `/extract-text`, `/cv/*`, `ISummarizerService`, privacy-header, operation-worker, provider-config, Compose and test path | Repository root | Revalidate AI-002 route convergence and existing mitigations before design | PASS — deterministic and summarize/extract paths remain local; all generative CV paths converge in the sidecar; configured external provider was direct rather than fallback; actual provider/failure provenance was lost | Browser/provider behavior was not inferred from source; route matrix records code-inspected status | Confirmed implementation gap |
| V-099 | `dotnet test JobTrackerApi.Tests\JobTrackerApi.Tests.csproj --no-restore --filter "FullyQualifiedName~AiOperationQueueTests\|FullyQualifiedName~AiPrivacyPolicyTests\|FullyQualifiedName~SummarizerServiceTests\|FullyQualifiedName~AiWorkspaceTests"`; `python -m pytest -q` | Repository root / `tools/summarizer` | Verify local-first order, policy/task propagation, schema/circuit/cost/failure routing and actual provenance | PASS — backend 26/26; sidecar 22/22 | First sidecar run passed 15/18 and correctly failed three obsolete external-first expectations; tests were updated to the new approved policy, then extended. No network/provider call occurred | Expected test-contract transition resolved |
| V-100 | Full `dotnet test JobTrackerApi.Tests\JobTrackerApi.Tests.csproj --no-restore`; `python -m pytest -q`; synthetic-token `docker compose config --quiet`; `git diff --check` | Repository root / `tools/summarizer` | AI-002 wider regression, deployment syntax and patch hygiene | PASS — backend 588/588; sidecar 22/22; Compose/diff pass | Five existing SWIG deprecation warnings; Docker config-file access and unset optional-variable warnings; line-ending notices only. Worker/external gate remain off | Browser, MariaDB, selected-model, real-provider and production checks remain blocked |
## Secret-scan commands