diff --git a/.agents/architecture.md b/.agents/architecture.md index c6bd3d0..e6ad8f6 100644 --- a/.agents/architecture.md +++ b/.agents/architecture.md @@ -70,7 +70,9 @@ operational invariants that template changes must preserve. callback paths must remain on the API before broader console prefixes. A generated console Ingress or HTTPRoute requires the matching server resource so those core-owned paths cannot disappear. Split mode rejects a - path-prefixed server public URL. + path-prefixed server public URL. The server catch-all is load-bearing: it + carries every path outside `/console`, including the hosted page GETs and + `/device_authorization`, so Authup can add one without a chart change. 16. **HTTPRoute flags are strict.** `route.enabled` accepts a boolean or a template-rendered boolean string. `authup.flag` validates every role even when that role is disabled, because a non-empty string `"false"` is truthy diff --git a/.agents/references/authup.md b/.agents/references/authup.md index 4c0002b..d4b58c0 100644 --- a/.agents/references/authup.md +++ b/.agents/references/authup.md @@ -1,17 +1,31 @@ # authup application mapping Repository: https://github.com/authup/authup. A local checkout commonly exists -at `/opt/projects/authup/authup`. This mapping is pinned to v1.0.0-beta.65, the +at `/opt/projects/authup/authup`. This mapping is pinned to v1.0.0-beta.66, the chart `appVersion`. -beta.64 to beta.65 changed no image entrypoint, CLI, port or environment-variable -contract: `Dockerfile` and `entrypoint.sh` are unchanged. The one new config -field, `querySchemaDiscoveryEnabled` (`QUERY_SCHEMA_DISCOVERY_ENABLED`, -`packages/server-config/src/sections/core/schema.ts`), is already reachable -through the long tail (`server.config.core.querySchemaDiscoveryEnabled`) and -does not need a first-class value. Identity-provider secret encryption -(`feat(server-core): encrypt identity-provider secrets at rest`, #3569) reuses -the existing `SECRETS_ENCRYPTION_KEY`; it adds no new chart-managed secret. +beta.65 to beta.66 changed no image entrypoint, CLI role, port or +environment-variable contract: `Dockerfile` and `entrypoint.sh` are unchanged, +`packages/server-config/src` gained no field, and `apps/authup/src/module.ts` +only adds operator-side commands (`login`, `logout`, `whoami`, `api `, +a CLI that signs itself in through the device grant) beside the unchanged +`start` tree. Three deployment-facing facts, none of which needs a chart value: + +- The device authorization grant (RFC 8628, #3587) adds `/device_authorization` + and the hosted `/device` page. Both sit outside `/console`, so they ride the + server catch-all, and the `/device` redirect target `/console/auth/device` + rides the auth console's `/console/auth` prefix + (`docs/src/guide/deployment/console-replicas.md`). The grant is opt-in per + client through the provisioning field `grantTypes`; an omitted `grantTypes` + does not enable it. +- The `@authup/client-auth-console` render contract is version 5 (was 3). A + bundle substituted through `AUTH_CONSOLE_PATH` and built against an older + contract is refused at boot and must be rebuilt + (`docs/src/guide/deployment/theming.md`). +- Console permission gating, token client narrowing, realm-gated entity reads + and the new `permission_check` permission are API and provisioning behavior. + They change which grants an operator hands out, not what the chart renders + (`docs/src/guide/deployment/upgrading.md`). ## Image and CLI @@ -91,3 +105,9 @@ clients and must not be declared as user provisioning entries. - Split console prefixes must be removed before requests reach their listeners. Admin/account login start and callback endpoints are core API routes, not console asset routes. +- Paths outside `/console` belong to the API set: the hosted page GETs + (`/authorize`, `/register`, `/activate`, `/password-forgot`, + `/password-reset`, `/logout`, `/device`), which answer with a redirect into + the auth console, and the endpoints behind them (`/token`, + `/device_authorization`). The chart's server catch-all carries them, so a new + hosted page needs no chart change while that catch-all exists. diff --git a/charts/authup/Chart.yaml b/charts/authup/Chart.yaml index 7247637..194d197 100644 --- a/charts/authup/Chart.yaml +++ b/charts/authup/Chart.yaml @@ -5,7 +5,7 @@ description: Authup is an authentication & authorization system. This chart built-in PostgreSQL, MySQL and Valkey instances. type: application version: 0.4.1 -appVersion: "1.0.0-beta.65" +appVersion: "1.0.0-beta.66" kubeVersion: ">=1.25.0-0" home: https://authup.org icon: https://raw.githubusercontent.com/authup/helm/master/assets/icon.svg @@ -32,6 +32,8 @@ annotations: url: https://github.com/authup/helm artifacthub.io/changes: | - kind: changed - description: Track Authup v1.0.0-beta.65; no image entrypoint, CLI or environment-variable contract changes - - kind: fixed - description: Fix ArgoCD first-sync deadlock when server.migration.enabled and a built-in database are both enabled with useHelmHooks=false + description: Track Authup v1.0.0-beta.66; no image entrypoint, CLI or environment-variable contract changes + - kind: added + description: The device authorization grant endpoints and the hosted /device page route through the existing server catch-all and auth console prefix; no new routing values + - kind: changed + description: A console bundle substituted through AUTH_CONSOLE_PATH must be rebuilt against auth console render contract version 5 diff --git a/charts/authup/README.md b/charts/authup/README.md index 0c5af00..7e6d656 100644 --- a/charts/authup/README.md +++ b/charts/authup/README.md @@ -7,10 +7,10 @@ # authup ![Version](https://img.shields.io/badge/Version-0.4.1?style=flat-square&color=informational) -![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.0.0-beta.65](https://img.shields.io/badge/AppVersion-1.0.0--beta.65-informational?style=flat-square) +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.0.0-beta.66](https://img.shields.io/badge/AppVersion-1.0.0--beta.66-informational?style=flat-square) -Authup is an authentication & authorization system. This chart deploys its combined or split API, console and worker roles, with optional built-in PostgreSQL, MySQL and Valkey instances. It runs Authup v1.0.0-beta.64's role-based -CLI topology: +Authup is an authentication & authorization system. This chart deploys its combined or split API, console and worker roles, with optional built-in PostgreSQL, MySQL and Valkey instances. It runs Authup v1.0.0-beta.66's +role-based CLI topology: - one combined API and console workload by default (`start`) - optional split API (`start core`) plus auth, admin and account console diff --git a/charts/authup/README.md.gotmpl b/charts/authup/README.md.gotmpl index b879d95..6ee02b9 100644 --- a/charts/authup/README.md.gotmpl +++ b/charts/authup/README.md.gotmpl @@ -22,8 +22,8 @@ ![Version](https://img.shields.io/badge/Version-{{ template "chart.version" . }}?style=flat-square&color=informational) {{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} -{{ template "chart.description" . }} It runs Authup v1.0.0-beta.64's role-based -CLI topology: +{{ template "chart.description" . }} It runs Authup v{{ template "chart.appVersion" . }}'s +role-based CLI topology: - one combined API and console workload by default (`start`) - optional split API (`start core`) plus auth, admin and account console diff --git a/scripts/check-beta64-contract.py b/scripts/check-beta64-contract.py index 880fb36..724b94e 100644 --- a/scripts/check-beta64-contract.py +++ b/scripts/check-beta64-contract.py @@ -321,6 +321,15 @@ def check_routing(): ): assert exact_backend(server_ingress, path) == "test-authup-server" + # Everything outside /console belongs to the API set: the hosted page GETs + # that redirect into the auth console (/authorize, /device, ...) and the + # endpoints behind them (/token, /device_authorization). They ride the + # catch-all, which therefore has to stay last and stay on the server. + catch_all = ingress_paths(server_ingress)[-1] + assert catch_all["path"] == "/" + assert catch_all["pathType"] == "Prefix" + assert catch_all["backend"]["service"]["name"] == "test-authup-server" + route_values = { "server": { "publicUrl": "https://auth.example.com", @@ -365,6 +374,15 @@ def check_routing(): assert [rule["matches"][0]["path"]["value"] for rule in rules[:4]] == expected_paths assert all(rule["matches"][0]["path"]["type"] == "Exact" for rule in rules[:4]) + # Same catch-all rule for Gateway API: a rule with no matches, last, on the + # API Service. The auth console prefix above covers /console/auth/device, + # the page the API redirects /device to. + catch_all_rule = rules[-1] + assert "matches" not in catch_all_rule + assert [ref["name"] for ref in catch_all_rule["backendRefs"]] == [ + "test-authup-server" + ] + def check_policy(): documents = render(chart / "ci" / "split-values.yaml")