Repository navigation
feat: enforce key data controls after protocol expansion - #89
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
multillm-proxy | 20433f5 | Oct 20 2026, 04:57 PM |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Stacked on the corrected #88 expansion revision. Enable data controls only after protocol expansion is deployed to the main Worker, Container and private Knowledge Worker.
Controlled content crosses a runtime boundary only after a fresh capability check of the actual peer. The Container also verifies the main account-RPC capability at controlled provider dispatch, and the private Worker verifies the current durable policy and sender protocol. Missing, malformed, unreadable or expansion-only capability refuses with 503 before content is sent. NULL-policy accounts remain compatible with expansion peers. Legacy upserts preserve policy columns atomically, so rollback cannot erase restrictions.
Restore provider classes, official-only keys, administrator-owned routing preferences and cached/reasoning token accounting. Retain current-policy checks at the final HTTP and SDK boundaries, credential attestation and API-origin restrictions, credential-free asset downloads, admitted redirects, current service-account credentials, Realtime and evaluation protections, and runtime network/binding guards with mutation regressions. Client-header and free-route fixtures use readable controls; the header suite also proves missing storage refuses with 503. Every CI-only Node contract is included in the Worker suite.
Actual pinned expansion and enforcement modules exercise all eight main/Container/private combinations for NULL, zero, empty-object, official-only and forced-deny accounts. The account path uses a realistic raw row in D1 migrated through 0043 and real HTTP RPC plus registered Container routes. Rollback cases assert zero provider sends, and controlled delegation to an expansion peer asserts zero content requests. Every combination exercises controlled-account sign-in and unrestricted administrator sign-in, reloads the entire management account list, and keeps unrestricted chat and model listing working beside a restricted row. Unversioned identity reads refuse controlled accounts; management lists retain the exact legacy shape. Account reads never require enforcement capability; dispatch still does. Pinned runtime probes load their matching templates. Pinned current-main/expansion cases and the concurrent legacy-write regression remain covered.
Every controlled-account decision uses the shared non-NULL predicate. Converted paths: worker/account-contract.mjs legacy authentication replies (management lists retain the legacy projection), worker/intelligence-auth-d1.mjs legacy integration lookup, worker/provider-dispatch.mjs credential admission, routes/intelligence.py candidate filtering, routes/cascades.py denied-route accounting, services/gemini_credentials.py restricted credential selection, services/key_data_guards.py canonical sampling admission, and services/shadow_eval_contract.py eligibility/sample construction. Worker native preferences and Python request preferences now distinguish an absent policy from an empty object. Official-provider flag checks use explicit enabled values; dashboard boolean serialization remains a value conversion, not a controlled-account predicate.
Zero-policy and empty-object regressions use the actual migrated D1 account/integration RPCs and both current and pre-negotiation expansion Container provider boundaries, independently of front-door admission. The matrix includes all five policy states across all eight runtime combinations. Credential tests reject caller overrides and unapproved origins, replace cached credentials with the current operator binding and refuse a missing binding. Loaded-account sampling tests preserve and re-read the canonical policy through capture and persistence. Legacy account lists remain readable for dashboard management beside controlled rows, while legacy identity reads cannot discard controls.
Rollout: deploy expansion to all three components and verify protocol 1 everywhere. Then deploy enforcement, verify protocol 2 with enforcement enabled everywhere, and enable restrictions last. Workers Builds independently deploys the main Worker and Container; it does not deploy the private Knowledge Worker. Disconnect Workers Builds or switch it to versions upload without automatic promotion, and use scripts/deploy.sh. Its D1, secret-list and deployments-read permissions inside Builds remain untested. Keep deployment preflight enabled: it checks configuration, migration ledger/schema, required secret names and the active private deployment before main upload. Missing prerequisite checks fail deployment. CI and release checkouts retain history for pinned compatibility tests and tagged capability verification. See docs/key-controls-rollout.md and docs/key-data-guards.md. Real staging reproduced both mixed-version incident errors and roughly 50–55 seconds of reverse-rollback chat failures; matched original runtimes were healthy on 45/46 probes. Keep the staging-verified Container-first rollback until A/B rollback passes real staging. Pre-existing mixed-load Container disconnects remain outside scope. No production read, deployment or remote migration was performed.
Retain the expansion redirect contracts and non-NULL policy fence, including zero and empty values. The compatibility tests pin the corrected expansion revision. Release admission verifies both account tables and the full migration ledger; standalone remote migration reads require an explicit target.
Deployment requires an explicit D1 target matching both chosen configurations. Status labels use the chosen Worker names. Each release gets a fresh build-only image identifier; deployment captures application detail before upload and refuses success until its version/image advance and the responding Worker/Container artifact fingerprints match. Regressions cover stale list versions, no-op rollouts and mismatched stamps.
Every CI command below ran locally through blade-testlock. Node jobs used Node 22, cloud builds Node 24, and integration explicitly selected the existing virtual-environment Python. Package-manager installation used an isolated prefix; bundles used isolated dry-run configurations.
python -m pip install --disable-pip-version-check --require-hashes -r requirements-ci.lock— passed.python scripts/check_static_secrets.py— passed.ruff check . --select E9,F63,F7,F82— passed.mypy --ignore-missing-imports --follow-imports=skip --disable-error-code import-untyped --disable-error-code var-annotated --disable-error-code arg-type --disable-error-code assignment --disable-error-code operator app.py routes services providers streaming— passed.bandit -q -c .bandit -r app.py config.py error_handlers.py route_helpers.py routes services providers streaming— passed.pip-audit -r requirements.lock— passed.python -m pytest -q— 5,329 passed, 975 subtests passed, two existing skips.npm ci— passed.npm audit --audit-level=high— passed.node --test tests/test_frontend_build.mjs— 2 passed on each Node version.npm run test:worker— 2,064 passed.npm run cf:migrations:check— 43 migrations checked.npm run test:deploy— 19 passed.node --test tests/test_free_routes_worker.mjs— 8 passed.node --test tests/test_client_headers_worker.mjs— 13 passed.npm run test:integration— 68 passed.npm install --global pnpm@10.11.1— passed.pnpm install --frozen-lockfile— passed.pnpm run build— passed.git diff --exit-code -- static/css/style.css— passed.node scripts/key_data_preflight.mjs --check— passed.node scripts/check_worker_bundle.mjs --config wrangler.knowledge.jsonc --outdir <isolated-directory>— passed.node scripts/check_worker_bundle.mjs --config wrangler.jsonc --outdir <isolated-directory>— passed.Provider classifications describe routing policy, not a verified external retention contract. Historical endpoint availability, subscription/reseller terms and distributed-network classifications remain operator-review items; the paid generative tier requires credential-specific operator attestation. The optional budget webhook is not included.
Existing oversized routing and authentication modules use minimal boundary wiring. Safe follow-up boundaries are Container forwarding, account persistence and provider preparation; the main router remains 2,187 lines, authentication 1,261, proxy orchestration 3,437, and the main Worker fixture 4,167.