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…): onemagic_link_allowlistrow —admin@rtopacks.com.au(idd5223e63-f19b-430e-bea5-2e986449de7a, type email,added_by …001, active). Operatorusersrow + T3tier_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_inviteswhen 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.auasadmin@rtopacks.com.au— succeeds (was masked-reject / "invitation only" against the empty allowlist).GET /api/studio/scope→ 200,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.devonmy.rtopacks.dev.GET /api/studio/scope→ 200,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_SCOPE→org_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/mewas redacted by the browser tool's own sensitive-key filter (token in payload); the200+org_rtopacks_opsfrom/api/studio/scopeis sufficient — an unscoped user would have returned 403not_provisioned.
3. Gates¶
- Audit (Alex, read-only) — reader confirmed repointed to canonical
magic_link_allowlist; STOP condition surfaced (live/orgwriters, §4); dev schema mirror + dormancy confirmed. - Dev bootstrap (Alex, CF MCP) — 3 INSERTs,
changes: 1each; post-stateusers1 /tier_grants1 /magic_link_allowlist1; gate-match + T3 tier verified at query level. - Prod carry (Tim-delegated, Alex CF MCP) — pre-write fence check anchored the target to prod (
8f0ba518…, operator email reads.com.aunot.dev); INSERTchanges: 1, count 0→1. - Verify — login + operator-pass 200/
org_rtopacks_opsboth envs (§2). - 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_opsdual-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.tswrites 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/orgwriters, then dropaccess_allowlist(prod + dev), with the onboarding arc.- First-client-onboarding arc — the durable
portal_invitesprovisioning path that supersedes these bootstrap gates and rebuilds/orginvite/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.