All guides

Deployment & rollout

First client — preflight checklist (role-based)

Vendor-neutral version: describes roles (gate controller, reader, pass issuance mode) without tying the checklist to a specific single-board computer, relay, or reader SKU. Use with any hardware that fills the same role.

For a variant that names concrete products where helpful, see first-client-preflight-checklist.md.

Calendar planning for sponsors (typical rollout duration and what drives it): org-platform-decision-guide.md#implementation-timeline.

Go-live handover (what receiving teams should confirm): new-organization-handover-package.md.

Run this in order before go-live. Record pass/fail and who verified (name + date).


How this checklist varies by org profile

Requirements are not identical for every client. Before you chase every row, agree the payment path, approval vs trusted activation, brand footprint, pass issuance mode, and physical entry model with the sponsor. Use the How this checklist varies by org profile section in the detailed checklist—including which sections matter most. Mark checklist rows N/A when they describe hardware or flows this deployment does not use.


0. On-site physical requirements (what must exist at the facility)

Profile: This entire section may be N/A when there is no unattended lane or on-site reader in scope (credentials-only from phone, desk-only ops, etc.).

This section is separate from cloud configuration: it is the hardware and environment at the door or desk where members tap in.

#ItemPass/failVerified by / dateNotes
0.1Credential reader (NFC/RFID or equivalent) installed and cabled to on-site computer or staff PC, or integrated per your deployment guideModel + serial recorded
0.2On-site gate controller (small PC, industrial box, or staff workstation) running the reader client, mounted and powered (not loose on a shelf)Hardware class + OS recorded
0.3Power: reader + controller on reliable outlets; consider surge protection; note if UPS is required for your SLA
0.4Network: Ethernet to gate controller preferred over Wi‑Fi for unattended lanes; if Wi‑Fi only, document SSID constraints and who owns password rotation
0.5Internet reachability: site can reach your production API host (HTTPS outbound); no captive portal blocking the controllerTest from same VLAN as reader
0.6Physical placement: reader at correct height/line-of-tap; cable strain relief; enclosure if exposed to dust/moisturePhoto optional
0.7Labeled assets: controller, reader, and power brick labeled (facility name + support contact); MAC address or mesh VPN node name recorded off-site
0.8Spares / plan: spare credential for tests; local contact who can power-cycle or reseat reader cable during business hours

Distinction: Automatic welcome emails and portal configuration are not “on-site.” Items 0.x are what a technician must touch at the building.


1. Infrastructure & environment

#ItemNotes
1.1Production deploy is current (known-good commit / tag)
1.2DATABASE_URI / DATABASE_URL points at production Postgres
1.3All db-infra migrations applied to production (including entry_channel, vetting, wallet fields as needed)
1.4Supabase project linked; SUPABASE_* and service role / admin keys match production
1.5NEXT_PUBLIC_ROOT_DOMAIN (or default) matches live hostname (e.g. pass host)
1.6Object storage (e.g. R2) configured; payment proof bucket works

2. Email (Resend)

#ItemNotes
2.1RESEND_API_KEY set in production
2.2RESEND_FROM_DOMAIN verified in Resend; sending domain aligned with product
2.3Test: member receives confirm / magic link after join
2.4Test: org owner/manager receives pending member alert (facility must have organization_id)
2.5Test: after approval (or trusted auto-activate), member receives key activated email
2.6Test: member payment proof upload notifies admins (non-trusted path)

3. Auth & accounts

#ItemNotes
3.1Login / logout / session on production domain (no loops, correct redirects)
3.2At least one org owner (or manager) can open /portal/{facility-slug}/admin
3.3Member can open /portal/{facility-slug}/dashboard after verify
3.4Password / magic link flow matches what you communicate to the client

4. Facility & org data model

#ItemNotes
4.1Facility exists with correct slug (used in URLs and gate payloads)
4.2Facility linked to organization (organization_id set) — required for admin alert emails
4.3At least one owner or manager on user_organizations for that org
4.4Payment instructions / currency / promos (if used) set under portal admin Packages as needed

5. Member lifecycle (end-to-end)

#ItemNotes
5.1Join (/portal/{slug}/join): creates pending user + pass + optional payment row
5.2Member sees pending state on dashboard; can upload proof (if applicable)
5.3Approvals queue shows pending member; Approve activates pass + payment
5.4Reject path works and member state is coherent
5.5If using trusted members: proof upload → auto-activate without manual approve

6. Digital membership pass (phone wallets)

#ItemNotes
6.1Pass issuance mode matches intent: direct signing (your keys/certs) vs hosted template service (vendor mints passes from your templates)
6.2Direct signing: secrets and signing material in env; member obtains install link and adds pass to Apple or Google wallet on device
6.3Hosted template: external template IDs, vendor API credentials, and mint route return success (no 4xx from your integration)
6.4Google wallet pass (if used): issuer / service account / template config aligned with the same architectural choice as Apple
6.5Express phone tap at reader (if used): reader/controller credentials exercised end-to-end; entry_channel: vas in data; Organization → Gate activity shows Wallet tap (and Manual Gate Recent admits matches)

7. Unattended entry (first client: single reader)

#ItemNotes
7.1GATE_INGEST_SECRET set in production; reader sends Authorization: Bearer <secret>
7.2Portal admin → Reader (/portal/{slug}/admin/access-point): register one access point (name + unique serial)
7.3Copy facilityId and accessPointId into reader config
7.4Reader/controller env sets relay target: LAN IP preferred when both IP and hostname are configured (offline resilience); hostname-only for mesh VPN / mDNS-only sites; API mode for your relay firmware (RPC vs legacy coil URL per vendor docs)
7.5Remote deploy pipeline copies the staged device env and regenerates runtime .env on the controller
7.6Controller maintains a local credential/pass-state cache so tap authorization works without internet in the hot path
7.7Test members have nfc_uid set (matches value reader sends as uid)
7.8Active pass + active account test: access granted and relay triggers
7.9Inactive account (or unknown token) test: access denied, relay does not trigger
7.10Wrong accessPointId for facility → 400 (no bogus linkage)
7.11Organization → Gate activity shows Unattended reader for standard reader path, Wallet tap for entry_channel: vas (phone tap path), Staff admit for Manual Gate (legacy unlabeled rows acceptable)

Edge runtime — unattended controller (Linux gate host)

Confirm on the gate OS via SSH (not from a developer laptop shell unless using remote SSH):

ItemNotes
Access-engine service startsLogs show no crash loop from missing Python deps — runtime pip install -r requirements.txt must satisfy sync_service (Member Access OS supabase client). First venv install on low-power ARM hardware often needs 20 to 30 minutes; run in staging, then retest end-to-end before production.
Relay protocol matches hardwareGen2/Gen3 relays often require vendor RPC-style URLs; legacy /relay/0-style triggers may return HTTP success but not energize the coil — validate with a curl smoke test from the controller to the relay IP.
Separate reader daemonsIf both a plain NFC UID stack and a phone-wallet tap daemon run, they may be different systemd units — tail the unit that matches the integration under test.

7.12 On-site gate controller — remote access for support

The unattended stack usually only needs outbound HTTPS to your app; you do not need to expose the controller to the public internet for normal operation. Remote access is for SSH (or equivalent), updates, log checks, and troubleshooting without a site visit.

Recommended (default): Tailscale

  • Install Tailscale on the gate controller and on each support engineer laptop (same tailnet).
  • Why: Encrypted mesh VPN, no router port-forwarding, works behind NAT, ACLs can restrict which machines reach the controller.
  • Ops checklist: Document the controller’s Tailscale name (e.g. facility-a-gate-01) in your runbook; use SSH over Tailscale; keep OS and Tailscale agent patched on a defined cadence.

Alternatives (when Tailscale is not acceptable)

ApproachBest forCaveat
WireGuard to a small VPSFull control, no third-party control planeYou operate keys, firewall rules, and monitoring
Cloudflare Tunnel (cloudflared)Expose SSH or a local debug HTTP endpoint without opening inbound portsRequires Cloudflare account; scope access carefully
Reverse SSH (autossh)Very small deploymentsFragile if middle host changes; document recovery
Router port-forward (SSH → controller)Legacy sitesHigh risk unless combined with VPN, fail2ban, key-only SSH, non-default port; many ISPs use CGNAT

Baseline hardening (any method)

  • SSH: key-based auth, disable password login if possible; non-default SSH port optional.
  • Dedicated deploy/support user; document who has keys.
  • Host firewall on controller: allow only what you need (often: nothing inbound if using mesh VPN only).
  • Time sync so logs correlate with cloud.
#ItemNotes
7.12.1Remote path chosen (Tailscale recommended) and documented in client runbook
7.12.2Test SSH (or agreed remote shell) from support laptop without being on-site LAN
7.12.3Controller hostname / mesh VPN name and OS image version recorded

Fleet inventory: For device_id, hostname, Tailscale metadata, reader serial, and a deployment log (who deployed where and when), use fleet-checkin-device-registry.md.


8. Optional: manual gate

Skip if client is unattended only.

#ItemNotes
8.1Staff can open /facility/{slug}/gate (or rely on portal staff URLs per your IA)
8.2Search → Admit / Deny writes entry_channel: staff_manual
8.3Recent entries may show Wallet for entry_channel: vas (not staff-initiated)

9. Observability & support

#ItemNotes
9.1Production logs / alerts reachable (Vercel, Supabase, Resend dashboards)
9.2Escalation contact and rollback plan documented for the client
9.3Backup admin account exists (not only one person’s email)

10. Security & compliance (minimum)

#ItemNotes
10.1No service role or DB URLs in client-visible code or public repos
10.2Gate ingest URL + secret treated as sensitive (rotate if leaked)
10.3Privacy: confirm what you log (PII in entry_logs, retention) with the client

Known gaps to track (not blockers for all pilots)

  • Several portal admin server actions historically relied on UI-only gating; prioritize smoke-testing critical paths and consider a follow-up authorization audit on mutations.
  • GET /api/gate-events in-memory lastScan is for demo / credential registration polling only — not reliable on multi-instance; unattended decisions must use POST response allowed.

Sign-off

RoleNameDateSignature / note
Engineering
Client / ops