Skip to content

Granting Logins & Access โ€‹

What a POC does for a new person, in order. One pass each, USERNAME / EMAIL being theirs.

Grant when โ€‹

GrantUnblocksWhen
Admin accountThe portal, the docs site that carries the onboarding page, and their app inviteFirst
GitHub inviteCloning at allBefore they start
Secret Managernpm run env:bootstrap, backend workWhen they touch server-side code
GCP console, read-onlyFirestore data, Auth users, logs, BigQueryWhen they need to see production-shaped data
GCP per-service writeThe specific job in front of themOn request, one role at a time
Vendor dashboardsCloudflare, Railway, Prelude, Resend, Anthropic, DiscordOnly when their work reaches that vendor

1. Admin account, which also hands you their app invite โ€‹

Do this first. It is how they read the onboarding page.

Create their account from the admin portal's Users tab, Create Admin. The success screen shows two links, and you want both:

  • Admin Portal Setup (?mode=adminReset&token=..., 24 hours, single use): where they set their admin portal password. A setup email goes out too; this link is the backup for when it does not arrive.
  • Main App Invite Link (#/admin-signup?token=..., 7 days, single use): their invite to the Lantern app itself. Signup is invite-gated, so without it the app dead-ends for them.

Copy the app invite while it is on screen. It is issued once, at creation, and the portal has no button to reissue it yet (#850).

Then send them the docs site: View docs site in the portal, and point them at Engineering > Guides > Onboarding. That is their whole set of instructions from here.

Say one thing when you send it: the admin portal password is separate from the Lantern app passphrase and has to stay that way. The app passphrase is also their encryption key, so a routine admin password reset would destroy their app data (why).

2. GitHub invite and Secret Manager โ€‹

One command does both:

bash
npm run onboard:grant -- --github USERNAME --email EMAIL

It shows you each command, asks before applying, and prints the remaining click-only steps. Add --dry-run to preview, or pass one flag to do one grant. Idempotent, so re-running after a partial failure is safe.

  • GitHub invite is the only grant that blocks them from cloning and running the app.
  • Secret Manager only matters when they reach backend work; it unblocks npm run env:bootstrap.

By hand, if you would rather:

bash
gh api -X PUT repos/cattreedev/lantern_app/collaborators/USERNAME -f permission=push
gcloud projects add-iam-policy-binding lantern-app-dev --member="user:EMAIL" --role="roles/secretmanager.secretAccessor"

3. Google Cloud console โ€‹

Needed to see Firestore data, Auth users, Cloud Run logs, and BigQuery. Read-only to start, then a per-service grant when a specific job needs write:

bash
gcloud projects add-iam-policy-binding lantern-app-dev --member="user:EMAIL" --role="roles/viewer"
gcloud projects add-iam-policy-binding lantern-app-dev --member="user:EMAIL" --role="roles/firebase.viewer"

roles/viewer deliberately does not include reading secret payloads, which is why step 2's secretAccessor is its own grant.

The per-service grants that actually come up, one at a time as the work arrives:

RoleFor
roles/datastore.userWriting Firestore documents (backfills, migrations)
roles/bigquery.dataEditorDataform and the billing pipeline
roles/secretmanager.secretAccessorAlready covered by step 2

Nobody needs a deploy role: deploys go through GitHub Actions, never a person.

4. Vendor dashboards โ€‹

No CLI for any of these, and none are needed on day one. Invite from the vendor's own dashboard when their work reaches it, at the narrowest role that dashboard offers.

VendorCoversGrant when
CloudflarePages deploys, DNS, Zero Trust Access policiesThey work on hosting, domains, or the docs host
RailwayHosts the Discord triage botThey work on the bot
PreludeOTP delivery. Test numbers only, never a real phoneThey start OTP work
ResendTransactional emailThey work on email flows
AnthropicAPI keys and billing for the assistant and triageThey work on an AI surface
DiscordThe triage bot and its webhooksThey work on the bot or alerting

Production access โ€‹

Anything production-connected needs sign-off from a security reviewer, not just your grant. Confirm they have done the security checklist in Part 4 of ONBOARDING.md first, and grant the narrowest role that unblocks the work in front of them. Same for vendors and contractors, who usually need one of these grants and none of the others.

Serving docs to someone WITHOUT an admin account

docs.dev.ourlantern.app carries the same content behind Cloudflare Access, so it needs an explicit email allow. Only worth it if you are skipping step 1.

The Zero Trust dashboard is the safe path: Access > Applications > the app covering docs.dev.ourlantern.app > Policies, add the email to the allow policy.

From the terminal, the Access API replaces a policy's whole include list rather than appending to it, so a one-liner has to read the current list, add the email, and write it back. With CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID in your .env.local:

bash
set -a && . ./.env.local && set +a
APP=$(curl -s "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/access/apps" -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | python3 -c "import json,sys;print([a['id'] for a in json.load(sys.stdin)['result'] if a.get('domain','').startswith('docs.dev')][0])")
curl -s "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/access/apps/$APP/policies" -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | python3 -c "import json,sys;[print(p['name'], p['id']) for p in json.load(sys.stdin)['result']]"

That prints the policy names and ids. Then fetch the policy you chose, append the email to include, and PUT it back. Check the result in the dashboard afterward: a malformed include list replaces who can reach the host. The repo's token is confirmed to READ Access apps and policies; its write scope has not been exercised.

Built with VitePress