KB-1958

C2B1-S3-R1-SIMPLE — Repoint All Machine Consumers · Zero Admin Dependency (2026-07-22)

12 min read Revision 1
current-statec2b1-s3-r1directusmachine-transitionrepointzero-admin-dependencynon-admin-identitymachine-consumerscanaryknown-temporary-degradationsecret-hygieneno-drift2026-07-22PASS_C2B1_S3_R1_ALL_MACHINE_CONSUMERS_REPOINTED

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, /info OK (langroid up), kb/list = 50 items ✓
  • Nuxt: homepage 200; Directus /server/health 200; 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.sock present; incomex-balo-reconcile.service active. 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) and incomex-agent-data (mt) hold a Directus API token; incomex-directus holds ADMIN_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 + unset admin creds; reconcile wrappers use the shared identity file.
  • Fallbacks: Nuxt container has no DIRECTUS_ADMIN_TOKEN / DIRECTUS_SERVER_TOKEN / DIRECTUS_TOKEN var (none to unset).
  • SYNC_SECRET (byte-identical to admin token): referenced only by the broken dot-apr-execute (dies at localhost:8055 before 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 via cron-env.shdocker/.env but make no Directus API call.
  • dot-apr-execute (*/5): broken (localhost:8055), exports admin pw + SYNC_SECRET, sources dot-auth — never reaches auth; creates no admin session.
  • dot-auth admin-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 .pre files → crontab rollback/crontab.pre → recreate nuxt + agent-data with the same flags → they re-read the admin token. dot-auth reverts by restoring dot-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).

Back to Knowledge Hub knowledge/current-state/reports/c2b1-s3-r1-simple-repoint-zero-admin-dependency-2026-07-22.md