# StormTrust gateway

`stormtrust-gateway` is the coarse request policy layer for StormTrust public hostnames. Cloudflare Worker Routes invoke it for the origins listed in its hostname registry. The gateway forwards approved requests through explicit service bindings.

## Application reference

| Property              | Value                                                               |
| --------------------- | ------------------------------------------------------------------- |
| Source                | org/apps/gateway/                                                   |
| Worker                | stormtrust-gateway                                                  |
| Public hostnames      | Hostnames declared in the gateway registry                          |
| Origin dispatch       | Fixed Worker service bindings                                       |
| Coarse authorization  | D1 binding AUTHORIZATION                                            |
| Authentication RPC    | Private AuthService binding to stormtrust-auth                      |
| Authentication issuer | https://auth.stormtrust.net                                         |
| Verification          | make app-verify APP=gateway                                         |
| Route ownership check | GET /.well-known/stormtrust-gateway on each managed public hostname |

## Request flow

```txt
Public request
      ↓
Exact hostname lookup
      ↓
Longest matching path policy
      ↓
Public ───────────────────────────────┐
      or                             │
Session or bearer-token validation   │
      ↓                              │
Active StormTrust principal          │
      ↓                              │
Role and permission lookup in D1     │
      ↓                              │
Sanitized identity context           │
      └──────────────────────────────┤
                                     ↓
                         Fixed service binding
                                     ↓
                            Application Worker
```

The request cannot select a Worker name. The gateway uses a source-controlled hostname registry. Unknown hostnames return `404`.

This design does not use a Workers for Platforms dispatch namespace. Dispatch namespaces target large collections of customer-authored Workers. StormTrust currently routes a small set of first-party services, so fixed bindings keep the trust boundary smaller and easier to audit.

## Current access policy

The website, developer documentation, UI workshop, shared assets, and public storm workspace remain public. The `/dashboard` path requires a verified, active principal with the ` member`, ` operator`, or ` admin` role and the ` dashboard:read` permission. Cookie-authenticated state changes also require an exact same-origin request; bearer-token requests use scoped abilities.

The gateway removes inbound `X-StormTrust-*` identity headers. It adds trusted identity headers only after successful checks. Origin Workers are responsible for tenant, record, and action authorization.

## Authentication boundary

The authentication service uses authorization code with Proof Key for Code Exchange (PKCE). The gateway validates opaque sessions through a private Worker service binding. Both Workers run in the StormTrust Cloudflare account.

Each protected hostname has source-controlled client configuration. The website uses client `stormtrust-web`, audience ` stormtrust.net`, and the exact redirect ` https://stormtrust.net/auth/callback`. Protected routes return ` 503`instead of bypassing policy when auth or authorization state is unavailable.

The gateway implements these host-local endpoints:

| Route              | Behavior                                                           |
| ------------------ | ------------------------------------------------------------------ |
| GET /auth/login    | Starts a five-minute PKCE transaction                              |
| GET /auth/callback | Consumes the transaction and stores an opaque host-only session    |
| POST /auth/logout  | Destroys the service session and clears the local cookie           |
| GET /auth/session  | Returns minimal, cache-free session state without exposing a token |

Each callback uses an exact issuer, client ID, redirect URI, audience, and one-time state record. Session and transaction cookies use the `__Host-` prefix, `Secure`, ` HttpOnly`, and ` SameSite=Lax` attributes.

## Authorization data

D1 stores principal status, scoped role assignments, role permissions, and short-lived PKCE transactions. The initial permission mapping is:

| Role     | Permissions                   |
| -------- | ----------------------------- |
| member   | dashboard:read                |
| operator | dashboard:read, storm:operate |
| admin    | \*                            |

After auth returns a verified principal, the gateway creates that principal and assigns the baseline `member` role once. The one-time marker prevents a removed role from reappearing at the next sign-in. Operator and administrator grants remain explicit.

## Ownership

Terraform owns the gateway Worker identity and authorization D1 database. Wrangler owns code, service bindings, Worker Routes, D1 migrations, deployments, and observability. Origin applications continue to own their Custom Domains.

The trusted workflow applies Terraform and D1 migrations before deploying the gateway. It verifies that the gateway route owns every configured hostname.

## Local development

Use [Run the local application stack](/stormtrust/engineering/operations/local-development/) for startup, gateway URLs, local sign-in, and verification. The local topology preserves the production binding and authorization boundaries with generated `.localhost` configuration. Wrangler supervises the processes; Durable Objects retain their application-state role.

## Operational guides

Use the shared [validation and deployment guides](/stormtrust/engineering/operations/) and [health evidence by app](/stormtrust/engineering/operations/health/#evidence-by-application). For a failed release, follow [recovery procedures](/stormtrust/engineering/operations/recover/) with this application's state and access boundaries.
