Draft

ADR-0002: Zero-Trust Access Perimeter for @@G1G@@

Status: TBDDate: 2026-07-17Deciders: Propel CloudOpsRelated: ADR-0001.1
Why this matters

one login gates every internal tool, new tools protected the day they ship, and $0 at our size — nothing to self-host or patch. Surfaced by ADR-0001.1, but an org-wide perimeter decision in its own right.

Context

Every internal tool needs the same thing: "only Propel humans, MFA'd." Building that per app (a Cognito gate here, a Lambda@Edge there) is duplicated, inconsistent, and slow. We already front our domain with Cloudflare and run a global Cognito IdP for application identity.

Decision TBD

Suggested decision — not yet agreed, expand to review

Adopt Cloudflare Access as the org-wide zero-trust edge over *.propellabs.io. One policy set gates every internal subdomain; the existing Cognito IdP stays the application identity layer.

flowchart LR
    U([Propel engineers]) -->|Google SSO + MFA| ACC[Cloudflare Access
*.propellabs.io] ACC --> D[docs.propellabs.io] ACC --> O[grafana.propellabs.io] ACC --> A[admin.propellabs.io] ACC -.signed JWT = identity.-> BE[app backends
reuse Cognito for authZ] style ACC fill:#EDEDFF,stroke:#3B54F7
  • One perimeter, every tool. A new internal app = a new subdomain → instantly protected. No per-app gate.
  • Managed-HA proxy mode, not a cloudflared tunnel — resolves the tunnel-reliability concern.
  • Two layers stay separate: Access = edge gate + coarse identity (email/groups in a signed JWT); Cognito = fine-grained app identity/authZ. Origins are locked to Cloudflare and still validate the JWT (never trust network position alone).

Consequences

Positive — one consistent zero-trust layer; MFA, device posture, and audit centralized; new tools protected for free; nothing to self-host or patch; $0 at our size (Access free ≤50 users; we're ~10–12). Negative / risks — Cloudflare becomes the critical path for internal access → mitigate with a documented break-glass route and origin-side JWT validation; every internal tool must sit behind the proxied domain.

Alternatives considered (with cost)

Option Cost Why not
Cloudflare Access $0 ≤50 users (then ~$7/user) — chosen
Per-app gates (Cognito + Lambda@Edge each) ~$0 infra but N× build/maintain Duplicated, inconsistent, slow to add tools
AWS Verified Access ~$200/mo per app ($0.27/hr/endpoint + $0.02/GB) AWS-native zero-trust, but priced per app-endpoint — expensive across many tools
VPN VPN infra + ops Not zero-trust; clunky for browser tools and external-ish access

Open questions

  • Which subdomains are in scope first (docs, Grafana), and group-based policies (who sees what)?
  • Break-glass procedure if Cloudflare Access is unavailable.
  • Client-facing surfaces stay out of this perimeter (they use per-client access, per the observability model).

Discussion

#cloudops. This ADR gates ADR-0001.1 — the docs crawl rides on adopting it.