# App-owned Cloudflare API ingress

Provision the app's Pages/Workers route and its per-app ingress token before deploying the backend.
The remote deployment helpers support Python 3.8 and newer; upgrading the deploy host is not required.
`BACKEND_API_DOMAIN` remains a distinct infrastructure hostname pointing to the deploy host; never
set it to a Pages/Workers hostname. Set these repository values for edge delivery:

- `BACKEND_PUBLIC_BASE_URL`: the client API base, for example `https://app.pages.dev/api`.
- `BACKEND_PUBLIC_HEALTH_URL`: that base plus the backend health path, for example `/healthz`.
- `BACKEND_INGRESS_REQUIRED`: `true`.
- Secret `BACKEND_INGRESS_TOKEN`: the same 43–128 character URL-safe token the edge sends in
  `X-App-Robot-Backend-Token`; never ship it in clients or app source.

The workflow supplies the exact commit SHA, and the public health endpoint must return JSON
with `build_sha` equal to that SHA. A completed HTTPS 2xx is required; redirects, partial transfers,
missing identity and another build fail deployment. The same check rejects missing/incorrect tokens
at the infrastructure hostname, verifies authenticated origin health and probes the public URL
without passing the token. The edge must add it itself.

The action adds `BACKEND_PUBLIC_BASE_URL` to Compose interpolation through a separate host-side
dotenv file, after `.env` and `.runtime.env`. The app's Compose service must explicitly consume it:

```yaml
environment:
  BACKEND_PUBLIC_BASE_URL: ${BACKEND_PUBLIC_BASE_URL:?required}
```

Use that value for redirects and generated API links. Preserve the action's private runtime files;
the ingress token is transported on SSH stdin and used in a mode-0600 nginx include, not CLI arguments.
Ingress configuration and public dotenv live in `/opt/gowalk-backend-ingress/<app>/`, outside the
application's Docker build context; broad application COPY instructions cannot include the token.
The new protected vhost is `backend-<app>-edge.conf`. An existing `backend-<app>.conf` keeps its
legacy domain and TLS configuration, and both upstream ports follow Compose on every deployment.
The old public hostname is health-checked without authentication so released clients remain usable.
An edge alias matching the existing legacy hostname is refused; provision a new alias instead.
Missing ingress settings on an already protected app cannot reopen its origin.

Managed backend locations forward WebSocket upgrades and disable response buffering so SSE and
streaming responses arrive incrementally. The Connection header becomes `upgrade` only when the
request carries an Upgrade header; ordinary HTTP requests use `close`. Each vhost owns a distinct
connection map, so protected and legacy domains coexist. Deployment updates existing locations
while preserving their domains, TLS settings and ingress checks.

These options are also named backend settings in `.gowalk-cicd.yml`: `public-base-url`,
`public-health-url`, `expected-build-sha`, `ingress-required` and `ingress-token`. Reference secrets
by name. Deployments without these options retain public origin access, certificate handling and health checks.
