CX-3_CODEX.txt
You are working in the MIZOKI-3-5/MIZOKICloudRun repository (MIZ OKI 3.5, a governed
decision-intelligence platform: 39 Cloud Run cells, BigQuery, Firestore, Next.js command-center UI).
Read in this order before touching code: CLAUDE.md, CONSTITUTION.md (Article VI governs governance
surfaces), docs/audits/AUDIT_WORK_ORDERS_2026-09-08.md, docs/audits/wo/<your WO files>, and
docs/audits/AUDIT_2026-09-06_RECONCILIATION.md if it exists (CX-1 writes it).
Ground rules
- Audit findings are HYPOTHESES pinned at commit fc8b03f9. main has moved. Step 0 of every WO is:
reproduce the counterexample on current main with a failing test. If it does not reproduce,
record "not reproduced on <sha>" in your report and move on — do not fix what is not broken.
- Fail closed. Every fix must make a refusal path explicit and tested. Never widen access to make a test pass.
- No new architecture. Reuse the existing modules named in the WO. If a WO says "reuse X", reuse X.
- Tests are the deliverable. Each WO lists acceptance tests; write them first, watch them fail, then fix.
Name them test_wo<nn>_<what>. Keep the audit's synthetic counterexample numbers ($40 refund → $80,
$70+$70 vs $100 cap, DEL 91.7, etc.) as fixtures so the regression is recognizable.
- Branch: audit/<PROMPT-ID>-<slug>. NEVER use a claude/* branch (they auto-merge to main in seconds).
Commit per WO with message "WO-nn: <title>". Open ONE PR for the prompt when done. Do not merge.
- Protected paths (.github/**, deployment/terraform/**, deployment/cloudbuild*, CODEOWNERS): review PR only.
- Never write a typed gate token in full anywhere (docs, commits, PR bodies, reports): the gate-leak
ratchet (tests/test_gate_leak_scan.py) turns main red. Refer to it only as APPROVED: [MERGE].
- Do not deploy, do not change Cloud Run config, do not touch secrets, do not run anything against
production BigQuery/Firestore, do not spend money on any provider. Local + test fixtures only.
- Coordination: before starting, run
python scripts/claude_memory.py record --title "<PROMPT-ID> claim" --summary "<WOs> on branch <name>" --tags coordination
if the script exists; if not, add a line to docs/audits/COORDINATION.md.
- Stop and report (do not guess) if: a fix needs a new secret, a provider account, an IAM change,
a schema migration on a live dataset, or a change to a file owned by another prompt (see the
ownership table in docs/audits/AUDIT_EXECUTION_PROMPTS_2026-09-08.md).
Final report — write docs/audits/reports/<PROMPT-ID>_REPORT_<date>.md with, per WO:
status (fixed | not reproduced | blocked), repro test name + first failing run, fix summary,
files changed, acceptance tests + pass evidence, anything deferred and why. End with the PR URL,
the exact test command(s) that prove the pack, and the commit SHA the PR is based on.
PROMPT-ID: CX-3. Branch: audit/cx-3-perimeter-providers.
Work orders: WO-21 (P0), WO-24 (P2), WO-25 (P2). Lane: SEC + ENG + OPS.
You own: miz-oki-adk-agents/boss/**, miz-oki-adk-agents/app/main.py,
services/service-action-runner/execution_adapters/google_ads.py and credentials.py ONLY (CC-2 owns
the rest of execution_adapters/), services/service-data-manager-connector/**,
miz-oki-adk-agents/kg-canonical-ingest/mappers/google_ads.py. Deploy workflows are protected paths:
you may propose changes as a separate review PR but not in this branch.
WO-21 Authenticate the Boss service perimeter
Context from CC-1 (PR #1016): approval routing now derives approver identity from the verified principal; the BFF must send
the principal header and the roles seed/broker registration are deployment config (see CC-1 report §Deferred 5). Reuse that
principal-auth module here; do not add a second auth scheme.
Files: miz-oki-adk-agents/boss/app.py, miz-oki-adk-agents/app/main.py (the production entry that
re-exports the Boss app).
Step 0: FastAPI TestClient: POST the chat route and the direct-action route with no credentials;
assert 200 today.
Fix: (1) write docs/audits/BOSS_ROUTE_INVENTORY.md — every route, method, public|private,
required principal, and why; health/readiness are the only public routes unless the inventory
argues otherwise. (2) add an auth dependency (reuse the platform's existing principal-auth
module — find it via the DCP/approval services; do not write a new auth scheme) to chat and
direct-action and every route marked private. (3) In a SEPARATE review PR touching
.github/workflows/** and any deploy config, remove --allow-unauthenticated / allUsers for the
Boss service and document the invoker principal the UI uses. Do not merge; do not deploy.
Accept: anonymous chat → 401; anonymous direct-action → 401; authenticated principal → 200;
inventory committed; deploy-config PR opened with a one-paragraph rollback note.
Report: which routes changed from public to private, and the OPS verification step still needed
(read-only IAM invoker check on the live service — do not perform it).
WO-24 Google Ads adapter: leave sunset v21
Files: execution_adapters/google_ads.py (line ~55: API_VERSION default "v21"), credentials.py if
version-specific.
Step 0: assert the default is v21 (it is, as of main 15a6ba29b); check Google's sunset list.
Fix: default to the newest version that is BOTH listed in Google's current Ads API release notes
and supported by the installed google-ads client library (pin the library accordingly in the
runner's requirements — coordinate with CX-4's lockfile work by putting the pin in a clearly
marked single line). Audit every mutation and read-back call in the adapter against the new
version's changelog; fix renamed fields/enums. Keep GOOGLE_ADS_API_VERSION override.
Accept: unit tests for every mutation + read-back with recorded responses (VCR-style fixtures, no
live calls); a test asserting the default version is not in a committed SUNSET_VERSIONS
list; validate-only mutation path exists and is tested. Do NOT run against a real account;
write the validate-only run as an OPS checklist item in the report.
WO-25 Data Manager connector request contract
Files: services/service-data-manager-connector/main.py; kg-canonical-ingest/mappers/google_ads.py.
Step 0: unit test the built request against the Data Manager Event / IngestEvents / Destination REST
schema (write the schema as JSON-schema fixtures from the official docs): assert today it
omits productDestinationId, drops conversion_action, sends conversionValue as an object,
and does not encode hashed userData. Four failing tests.
Fix: conform exactly: productDestinationId per destination; conversion_action routed per event to
its destination (multi-action routing); conversionValue numeric with sibling currencyCode;
hashed userData normalized + SHA-256 + encoded as the schema requires; validate-only flag
plumbed and its diagnostics surfaced in the response.
Accept: four schema tests pass; a golden request fixture is committed; validate-only path tested
with a recorded diagnostics response. Do not build a second connector.
Gates: pytest for miz-oki-adk-agents/boss, the two adapter files, and the connector service.
PR title: "Audit pack C/F (perimeter + providers) — Boss auth, Ads API version, Data Manager contract
(WO-21, 24, 25)". Plus the separate protected-path PR for deploy config.