C2B1-S3-R1-SIMPLE — Repoint All Machine Consumers · Zero Admin Dependency (2026-07-22)
C2B1-S3-R1-SIMPLE — Repoint All Machine Consumers · Zero Admin Dependency
Date: 2026-07-22 · Scope: repoint every machine consumer off the bootstrap admin identity onto the shared non-admin machine-transition identity, and prove no runtime dependency on admin password or admin static token. No credential rotation, no new backup, no cleanup.
1. Verdict
PASS_C2B1_S3_R1_ALL_MACHINE_CONSUMERS_REPOINTED
All six machine consumers repointed to the shared non-admin identity. Core consumer functions PASS (canary 38/38, residue 0). Zero admin authentication by machine consumers, proven at runtime. No unexpected container/DB drift.
Disclosure (read section 4): the Nuxt UI read degradation is broader than the three routes named in the mission — it extends to every UI route that reads a collection outside the measured grant (the same ~134-collection gap S2 measured). This is the same class of degradation the mission accepted (routes that "need full-schema read"), not a new failure mode, and it does not touch any core business path. It is documented below rather than hidden.
2. Repoint matrix
| # | Consumer | Was (auth) | Now (auth) | Mechanism | Verified |
|---|---|---|---|---|---|
| 1 | Nuxt (incomex-nuxt) |
admin static token (NUXT_DIRECTUS_SERVICE_TOKEN) |
machine-transition token | compose L174 value swap; recreate --no-deps --pull never --force-recreate; pinned image 72715a…fab30 |
effective env == mt, != admin |
| 2 | agent-data (incomex-agent-data) |
admin static token (DIRECTUS_ADMIN_TOKEN) |
machine-transition token | /etc/incomex/agent-data.env value swap; recreate --no-deps --no-build --pull never; pinned 9acd60503290-20260717 |
effective env == mt, != admin; healthy; kb/list OK |
| 3 | reconcile-tasks | admin password login | machine-transition token (Bearer) | wrapper → shared identity file, -e DIRECTUS_TOKEN; .py token short-circuit |
dry-run + real: "All in sync!" via static token |
| 4 | reconcile-knowledge | admin password login | machine-transition token (Bearer) | same as reconcile-tasks | dry-run + real: "All in sync!" |
| 5 | dot-collection-health | admin password login (via dot-auth) |
machine-transition token (static) | dot-auth static-token branch (DOT_STATIC_TOKEN); cron line uses shared identity + unset admin creds |
wiring: DOT_TOKEN == mt, no admin login |
| 6 | dot-apr-health | admin password login (via dot-auth) |
machine-transition token (static) | same as dot-collection-health | ran --local exit 0 via static token |
Identity model (fingerprint-verified; values never exposed): admin static token (== SYNC_SECRET) and admin password are two distinct secrets; the machine-transition token is a third. Post-repoint, no machine consumer holds either admin secret except the Directus server's own bootstrap ADMIN_PASSWORD (the human admin UI credential — explicitly allowed).
dot-auth is the shared broker for 54 scripts; the static-token branch is additive and gated (DOT_STATIC_TOKEN), so the 48 non-cron on-demand schema tools are behaviourally unchanged and still fall back to admin login when a human runs them (per-service decomposition = OPTIONAL_BACKLOG).
3. Core functional results (Section 5) — all PASS
- S2 canary harness (authoritative machine-consumer parity + safe-write proof): PASS 38 / FAIL 0 / residue 0.
- knowledge_documents CRUD (agent-data + reconcile-knowledge path) ✓
- system_issues CREATE via public HTTPS (DOT health create) ✓; transitional DELETE correctly DENIED 403 ✓
- meta_catalog UPDATE + exact restore (refresh-counts write-half) ✓
- full workflow family writes (workflows/steps/relations/wcr/tasks/task_comments) ✓
- negative out-of-scope writes all DENIED 403 (workflows create/delete, tasks delete, os_deals, directus_fields) ✓
- reconcile-tasks / reconcile-knowledge: authenticate as machine identity, "All in sync!" ✓
- dot-collection-health / dot-apr-health: run via static token, no admin login ✓
- agent-data: healthy,
/infoOK (langroid up),kb/list= 50 items ✓ - Nuxt: homepage 200; Directus
/server/health200; most registry routes 200 (counts, raw-counts, species-matrix, species-summary, composition, unmanaged, system-issues, knowledge) ✓ - Balo: bridge intact — operator-role env + socket path preserved through recreate;
/run/incomex/balo-reconcile.sockpresent;incomex-balo-reconcile.serviceactive. Balo is session-gated + socket-bridge and does not use the service token, so it is architecturally unaffected. (Full browser battery not run this session; offered on request.) - No unexpected 401/403 on any core business path.
4. Known temporary degradation (Section 2 + measured expansion)
The shared identity is a measured union of machine-consumer needs, not a full-schema reader. Any Nuxt UI route reading a collection outside that union returns 403/degraded. This was accepted by the mission (S2_FIX1_BROAD_READ_BRIDGE = CANCELLED; "routes need TOÀN-SCHEMA read"). Dual-token measurement (admin=200 vs mt=403) confirms these are token-scope, not bugs.
KNOWN_TEMPORARY_DEGRADATION = {
refresh-counts # POST; mt reads 21/155 registry collections (S2: 118-coll gap). REDUNDANT: PG-native
# refresh_meta_catalog_from_pivot() refreshes meta_catalog.record_count every 10 min,
# independent of route/token (max last_scan ≈ now). Only automated caller is the
# [DOT-REG] Count Refresh (6h) flow — non-critical, left active per owner decision.
registry-health # GET returns HTTP 200 but degraded internal counts.
discovery-relations # GET 400/0 rows (admin: 371). No automated consumer.
registry/matrix # NEWLY DOCUMENTED: 403 (mt lacks taxonomy / taxonomy_matrix / entity_labels /
# universal_edges). Was 200 under admin. One taxonomy dashboard.
homepage CMS blocks # /items/pages now 403 (was 200 under admin) → 0 blocks. Homepage already rendered
# 0 blocks PRE (deep-field malformed-perm fallback), so no NEW visible change; HTTP 200.
(general) # any other UI route reading a non-granted collection degrades identically.
}
Working UI routes on mt (not degraded): counts, raw-counts, species-matrix, species-summary, composition, unmanaged, system-issues, knowledge/list, health.
Owner decision (this mission): proceed, document degradation — the 6h count-refresh flow is non-critical (redundant with the 10-min PG cron) so AUTOMATED_CRITICAL_CONSUMERS_OF_THESE_ROUTES = 0; not treated as a HOLD.
Not used as operational truth: any 0 / 403 / ORPHAN from the degraded routes.
5. Zero-admin-dependency proof (Section 6)
BOOTSTRAP_ADMIN_MACHINE_PASSWORD_CONSUMERS = 0
BOOTSTRAP_ADMIN_MACHINE_TOKEN_CONSUMERS = 0
ADMIN_TOKEN_RUNTIME_FALLBACKS = 0
ADMIN_PASSWORD_LOGIN_JOBS = 0
Evidence (not a single grep):
- Effective container env scan (all 11 running containers, fingerprint match): only
incomex-nuxt(mt) andincomex-agent-data(mt) hold a Directus API token;incomex-directusholdsADMIN_PASSWORD= its own bootstrap / human admin UI credential (allowed). No running container holds the admin static token. - Runtime session invariance: admin sessions = 35, max-expires
2026-07-29 10:00— identical before and after running reconcile×2 + dot-apr-health for real. A machine admin login would have added a session expiring ~07-29 14:4x; none appeared. Machine jobs use stateless static tokens (no session created). - Cron: no job authenticates as admin. dot-collection-health/dot-apr-health use
DOT_STATIC_TOKEN+unsetadmin creds; reconcile wrappers use the shared identity file. - Fallbacks: Nuxt container has no
DIRECTUS_ADMIN_TOKEN/DIRECTUS_SERVER_TOKEN/DIRECTUS_TOKENvar (none to unset). - SYNC_SECRET (byte-identical to admin token): referenced only by the broken
dot-apr-execute(dies atlocalhost:8055before any auth) — no runtime consumer.
Documented residuals (decision: repoint 6 + document; not neutralized — minimal drift):
- Vestigial admin-cred cron exports that never authenticate (psql-direct):
dot-orphan-scanner,dot-misclass-scanner(ADMIN_TOKEN);dot-dot-health,dot-dot-coverage(ADMIN_EMAIL/PASSWORD). They inherit admin creds viacron-env.sh→docker/.envbut make no Directus API call. dot-apr-execute(*/5): broken (localhost:8055), exports admin pw + SYNC_SECRET, sourcesdot-auth— never reaches auth; creates no admin session.dot-authadmin-login path retained for 48 on-demand human-invoked schema tools./etc/incomex/reconcile/directus-admin.env(admin password): orphaned — 0 references from reconcile now; left in place (no cleanup).- Human admin UI credential: not rotated (out of scope, allowed).
6. Secret hygiene (Section 7)
- No token / prefix / suffix / MD5 / last4 written to this report, the KB, Git, command arguments, or logs. All credential comparisons used remote-only SHA-256 fingerprints that emitted equivalence labels only; token values never left the host.
- Token files:
/etc/incomex/c2b1/machine-transition.env,/etc/incomex/agent-data.env=root:root 0600(perms preserved through the swap). Container injection uses variable NAME only (docker exec -e), value never in argv. SECRET_PROPAGATION = 0.
7. Container / config delta (Section 8, no-drift)
UNEXPECTED_CONTAINER_MUTATION = 0 # only incomex-nuxt + incomex-agent-data recreated (env change); 9 others untouched; 11/11 healthy
UNEXPECTED_DATABASE_MUTATION = 0 # canary residue 0; meta_catalog restored EXACT; no stray rows
MALFORMED_PERMISSION_ROWS = 632 # unchanged (fields = '{"*"}')
NEW_PERMISSION_ROWS = 0 # total_perms 1244 unchanged
NEW_ADMIN_OR_APP_ACCESS = 0 # directus_access 10, policies 9, roles 10, users_with_token 14 — all unchanged
Files changed (all snapshotted to /root/c2b1s3/rollback/): docker-compose.yml (Nuxt token line only — redacted diff identical to pre), /etc/incomex/agent-data.env (token value), reconcile-tasks.{sh,py}, reconcile-knowledge.{sh,py}, dot-auth (additive static branch), crontab (2 lines: dot-collection-health, dot-apr-health). Vestigial cron lines left unchanged. docker compose reported a benign orphan warning for incomex-agent-api-executor (separate service, not in project) — not touched (no --remove-orphans).
8. Rollback state (Section 10)
Not invoked — no core consumer failed. Full rollback available:
- File snapshots:
/root/c2b1s3/rollback/*.pre(compose, agent-data.env, reconcile ×4, dot-auth, crontab, container ids). - Reverse recipe: restore
.prefiles →crontab rollback/crontab.pre→ recreate nuxt + agent-data with the same flags → they re-read the admin token.dot-authreverts by restoringdot-auth.pre. Recovery floor intact (B0 restore-proven backup, S1 ledger, S2 harness, H1 checkpoint, protected config checkpoint).
9. Exact next gate
BOOTSTRAP_ADMIN_MACHINE_CONSUMERS = 0 (achieved)
OPEN NEXT: C2B1-XV-SIMPLE
Do not open S3 sub-phases or credential rotation from this mission. Optional backlog (owner's call): per-service policy decomposition; neutralize the vestigial/broken admin-cred cron exports; fix or retire dot-apr-execute; delete the orphaned /etc/incomex/reconcile/directus-admin.env; decide whether registry/matrix + homepage CMS blocks warrant a narrow additional read grant (the broad-read bridge remains CANCELLED).