Provision Engineer Auth Users
Landmark's row-level security policies admit a request based on
the JWT's email claim. Supabase Auth only issues a
JWT for an auth.users row that already exists — so
before any engineer can read their own activity rows, their roster
entry needs a paired auth.users row.
fit-map people provision reconciles
auth.users against the
activity.organization_people roster: it creates rows
for new engineers, restores rows that were previously
decommissioned, and bans rows whose roster entry has been removed.
This guide is for operators — anyone running the verb against a production Supabase instance. Engineers do not run it.
Prerequisites
-
MAP_SUPABASE_URLandMAP_SUPABASE_SERVICE_ROLE_KEYexported in your shell. The service-role key is the same credentialfit-map people pushconsumes —provisionis operator-only by virtue of which env var it reads. It is registered onfit-map, notfit-landmark, because Landmark's read path no longer holds the service-role key. -
activity.organization_peoplepopulated. Runfit-map people push <roster.yaml>first if it isn't.
Run it
fit-map people provision
The verb reports a per-action summary:
Provisioning auth.users from organization_people
created: 4
restored: 0
decommissioned: 1
unchanged: 22
Reconciliation complete
The four counters cover every reachable transition:
| Counter | Meaning |
|---|---|
created |
Roster row had no matching auth.users row; one
was created.
|
restored |
auth.users row was banned; it has been unbanned
because the roster brought the engineer back.
|
decommissioned |
Roster row was removed; the matching
auth.users row has been banned (banned_until
≥100 years out).
|
unchanged |
Roster row and auth.users row already paired and
active; no change.
|
Idempotency
Running provision twice in a row against the same
roster leaves the auth.users rowset unchanged: the
count, the id per email, and the active-state per row
are all stable. This is the contract the test harness and CI
fixtures rely on; production operators can run it from cron without
fear of churning state.
Decommissioning
When an engineer leaves and their roster row is removed, the next
provision run bans their auth.users row by
setting banned_until to ≈100 years out (ban_duration: "876000h"). Banned users cannot issue JWTs, so no new Landmark reads land
for them.
The id is preserved across decommission — if the same
engineer rejoins and the roster row reappears, a subsequent
provision run unbans the same row (ban_duration: "none"), preserving any audit trail that referenced the original
id.
What this does not do
-
Issue JWTs to engineers. A
fit-landmark loginverb, magic-link delivery, password-reset flow, or SSO bridge — any of which would turn a provisionedauth.usersrow into a JWT in the engineer's CLI environment — is a follow-up.provisiononly ensures the row exists; getting a JWT into engineer hands remains a separate concern. -
Delete user data. Decommissioning bans the row;
it does not remove the engineer's history from
activity.*. That is governed by the retention windows declared in the migration metadata and surfaced viafit-landmark sources --email <e>. -
Provision against a remote Supabase from your laptop.
provisionrequires the service-role key. Keep it confined to your operator environment; never expose it to engineer-side tooling.