Skip to content

WORKSPACE-OPERATOR-LOGIN-BOOTSTRAP-01 — Close Report

Brief: Bootstrap the operator login to the canonical identity model on both environments, reopen workspace login, and close the deferred SSG-01 operator-pass live test. Narrowed from WORKSPACE-ALLOWLIST-MIGRATION-COMPLETION-01 after Gate 1 found the old allowlist still has live writers (§4). Filed by: Tim, 2026-05-29. Executed: 2026-05-29, single session — audit (Alex), dev writes (Alex, CF MCP), prod write (Tim-delegated to Alex via CF MCP — single reviewed reversible INSERT), verification (Tim login + Claude read-only browser smoke).

Status: Closed. Operator login reopened on both envs; operator-pass runtime-confirmed both sides. Table retirement + /org writer disposition split to ACCESS-ALLOWLIST-RETIREMENT-01 (§4).


1. What landed

  • Prod rto-identity-db (8f0ba518…): one magic_link_allowlist row — admin@rtopacks.com.au (id d5223e63-f19b-430e-bea5-2e986449de7a, type email, added_by …001, active). Operator users row + T3 tier_grants (65163496…) already present from a prior migration, so the gate row was the only gap.
  • Dev rto-identity-db-staging (462b970b…): full operator bootstrap, FK order — users (…001 / admin@rtopacks.dev / Tim Rignold / verified / active), tier_grants (d6ddd4cc-33fb-4b03-8000-90f52f170785 / T3 / client_id NULL / granted_by self), magic_link_allowlist (000f1063-135a-44ba-9e8f-4e9ee3ce8017 / email / admin@rtopacks.dev). Restored from dormant (post-SSG-01 sweep) to operator-ready.
  • All three carries are a documented bootstrap exception to CANONICAL-IDENTITY-VIA-UI-ONLY — the first login cannot be created through a UI that requires login to reach. Durable replacement: identity-bound provisioning via portal_invites when the IM lands; these gate rows are knowingly interim.

2. Verification — the deferred SSG-01 operator-pass leg, now live

  • Prod: Tim magic-linked into my.rtopacks.com.au as admin@rtopacks.com.au — succeeds (was masked-reject / "invitation only" against the empty allowlist). GET /api/studio/scope200, rto.org_id: org_rtopacks_ops (org "United Central Colleges of Australia Pty Ltd", RTO 45329; 3 on-scope + 2 proposed quals).
  • Dev: Tim logged in as admin@rtopacks.dev on my.rtopacks.dev. GET /api/studio/scope200, rto.org_id: org_rtopacks_ops (empty content: org_name "Unknown", rto_code "", 0 quals — expected for the swept dev env; the "Unknown" is the empty-state default, not a fault).
  • Both envs resolve T3 → OPERATOR_SCOPEorg_rtopacks_ops → no wall → 200, identical structure. The operator-pass leg SSG-01 could only code-read is now runtime-confirmed on both sides.
  • By-product confirmation: the tile difference first observed on dev was client@rtopacks.dev (lower tier) vs the operator — i.e. permissioning working (reduced surface for a lower tier), not a fence or config artefact. Structure parity holds; content parity is not required and differs by env data.
  • Smoke method note: the operator-pass reads were run read-only via Claude-in-Chrome on Tim's authenticated session. /api/auth/me was redacted by the browser tool's own sensitive-key filter (token in payload); the 200 + org_rtopacks_ops from /api/studio/scope is sufficient — an unscoped user would have returned 403 not_provisioned.

3. Gates

  1. Audit (Alex, read-only) — reader confirmed repointed to canonical magic_link_allowlist; STOP condition surfaced (live /org writers, §4); dev schema mirror + dormancy confirmed.
  2. Dev bootstrap (Alex, CF MCP) — 3 INSERTs, changes: 1 each; post-state users 1 / tier_grants 1 / magic_link_allowlist 1; gate-match + T3 tier verified at query level.
  3. Prod carry (Tim-delegated, Alex CF MCP) — pre-write fence check anchored the target to prod (8f0ba518…, operator email reads .com.au not .dev); INSERT changes: 1, count 0→1.
  4. Verify — login + operator-pass 200/org_rtopacks_ops both envs (§2).
  5. Close — this report.

4. Scope change recorded (Gate 1 finding → follow-up)

ops-db.access_allowlist is read by nothing (reader repointed in IMM-01 Phase 3c) but still written by two live /org paths: workers/internal-api/src/orgs.ts:134 (inviteMember) and :342 (provisionOrg) — INSERT OR IGNORE, try/catch-swallowed, both endpoints live. Consequence: the /org invite/provision flow is silently broken (it writes a table the gate no longer reads, so invited members never get gated in) — fails closed (cannot grant access wrongly). The table therefore cannot be dropped without leaving dead-writing code (decommission-and-leave, which MIGRATION-COMPLETION-DISCIPLINE forbids).

Retirement and writer disposition split to ACCESS-ALLOWLIST-RETIREMENT-01, sequenced with the first-client-onboarding arc — because it is a rebuild question, not a repoint: writing a gate row with no users/tier_grants behind it would resurrect the gate-without-identity anti-pattern, so a proper invite/provision must build identity + permissioning, which is the onboarding arc's portal_invites work. Dev ops-db-staging (6ee420d6…) also holds an orphaned access_allowlist (3 rows: admin@rtopacks.dev, phase3a-test-invite@rtopacks.dev, rtopacks.dev catch-all) — retires in the same follow-up.

5. Banked observations

  • org_rtopacks_ops dual-role surfaces in the operator view: prod scope shows UCCA's real RTO (45329) data → ORGS-DUPLICATE-UCCA-RECORD-CLEANUP-01 (the operator-scope constant and the UCCA org record are the same id). Dev resolves the same constant but is unpopulated.
  • Dead write behind bare try/catch: the orgs.ts writes go silently to an unread table — same failure shape as the dead-by-construction-behind-bare-try/catch pattern tracked at 2/3 (provisioning, not telemetry — judge as a third sighting or a cousin).
  • CF Access "Create new self-hosted application" flow was observed open in a browser tab during the session. If aimed at the workspace it cuts against the locked magic-link-only decision; flagged, not actioned (echoes the "RTOpacks Dev — Admin Copy" create-app previously backed out of).

6. Forward

  • ACCESS-ALLOWLIST-RETIREMENT-01 — disposition the two /org writers, then drop access_allowlist (prod + dev), with the onboarding arc.
  • First-client-onboarding arc — the durable portal_invites provisioning path that supersedes these bootstrap gates and rebuilds /org invite/provision properly.

Operator login is live on both envs; the operator-pass leg is runtime-confirmed. The allowlist migration's write side (the /org writers + table retirement) remains the parked completion, sequenced with onboarding.