Scaffold secure external OAuth control plane
Merged
GI
1mo ago+2470+2470+0123456789012345678901234567890123456789-16-16-01234567890123456789
Summary
- contain legacy credential exposure by rejecting generic writes for registered OAuth providers and projecting task-integration status through a typed non-secret DTO
- add a provider-neutral external OAuth control-plane contract, executable lifecycle, deterministic fake provider, replay-safe callback orchestration, exact Google scope/grant families, and semantic Gmail/Calendar read adapters
- add application-level AES-256-GCM envelope-encryption custody seams with immutable AAD bindings, purpose/generation-bound leases, and no plaintext/local-key fallback
- add a checked-in production admission manifest that is disabled and empty until exact GCP client, Verification Center, and Gmail CASA evidence is supplied
- document the live-product architecture, migration boundary, tests, rollout gates, and rollback; the legacy migration helper is classification-only and performs no database or cloud writes
Security and compatibility boundary
- Calendar and Gmail use separate grant families and client aliases; scopes must match the versioned registry exactly after canonicalizing only known Google aliases.
- The old app-client request fields remain deprecated in OpenAPI solely to preserve released-client schema compatibility. Registered OAuth providers are rejected before persistence, so the route cannot inject or replace OAuth credentials.
- The credential executor exposes plaintext only inside a purpose-bound callback, verifies connection and generation independently of the injected authorizer, and zeroes mutable plaintext/DEK buffers on exit.
- Terminal revocation and reconnect transitions require explicit dispositions; admin-blocked reconnect also requires independent clearance.
- No connector is registered with the live app and the production admission kill switches remain closed.
Validation
35 passed: new external OAuth/admission/vault/lifecycle/read-adapter/public-contract suite52 passed: pre-hardening relevant existing integration/OAuth regressions- isolated existing task-integration and Gmail scope-gating regressions passed (
3 passed,9 passed); a combined in-process run demonstrated existing test-module monkeypatch leakage, while the repository runner isolates files - targeted pyright:
0 errors(strict warnings remain for dynamically validated provider/manifest JSON) - app-client OpenAPI export is current and directional compatibility passes against merge-base
0e2bd09785b512842725a6f2a9cdef9c0b239778 - broad
backend/test.shran the 1,013-file isolated suite for about 16 minutes with no observed failure; it was manually stopped in a pre-existing very-slowtest_mentor_notifications.pypath after reaching 56% of that file, following successful completion of the other emitted shards git diff --check
Deliberately not live / required finishing work
- no verified GCP project numbers, OAuth client IDs/redirects, Google verification evidence, or Gmail CASA evidence has been added
- no production Firestore repository, indexes, transactions, immutable audit sink, KMS key/IAM adapter, Secret Manager client-secret adapter, or Data Access logging configuration
- no live Google exchange/OIDC validation adapter or authorization/callback/status route registration
- no durable refresh/revoke workers, account-deletion integration, backup/restore anti-resurrection implementation, or cloud deployment
- no production/legacy database inventory or token migration; existing credentials remain untouched and the documented safe default is revoke plus explicit re-consent
- semantic adapters still require production transport hardening (shared bounded clients, DNS/private-address defenses, typed retry budgets, generation/deletion-epoch result rechecks) before registration
Rollback
The new subsystem is unreachable and both admission switches are closed, so rollback is to leave it unregistered or revert this commit. If reverting containment, preserve a typed non-secret status response and never reopen generic OAuth token persistence. Close future connector/cohort switches before reverting any registered runtime adapter.
Failure-Class: new