INFD-WP-0001-T07 has been blocked since 2026-09-08 on an OIDC redirect URI it cannot publish without a real deployed origin, which in turn blocks key-cape's KEY-WP-0013-T02. The operator assigned decisions.coulomb.social; DNS already resolves to the cluster address. Adds the Ingress + letsencrypt-prod certificate for the host and a placeholder nginx backend, so the origin answers before the approver UI itself exists (INFD-WP-0001-T08 is still gated on approval-engine and on intake INFD-IN-0003). A redirect URI matches byte-exactly at /authorize, so a host that resolves but does not complete a TLS handshake fails closed at first login and presents as a rejected approval rather than a registration defect. The Ingress carries one path rule on purpose: reuse-surface reported on 2026-07-07 that an Exact rule alongside a catch-all Prefix rule on the same host was swallowed by the catch-all. That trap is worth avoiding on a host whose entire purpose is exact-match redirect handling. Dry-run clean against the live API; deliberately not applied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJbh7o7UWF4tQ5jxygnNGu Assistant: claude-code Assistant-Model: opus Assistant-Process: 2072522@bnt-lap001 Assistant-Session: 46173adf-7302-4ede-99d6-963b61359928
4.4 KiB
decisions.coulomb.social — origin for the informed-decision approver surface
Status: manifests written and dry-run clean; not applied. Last reviewed: 2026-09-10
Why this host exists before the app does
informed-decision owns the browser-facing approver UI that approval-engine
deliberately does not contain. Its workplan task INFD-WP-0001-T07 must publish
two strings to key-cape — an OIDC client_id and a full callback URI — and
close KEY-WP-0013-T02, which has been blocked on them since 2026-09-08.
Both strings are now fixed except for the host:
| Field | Value |
|---|---|
client_id |
informed-decision-approver |
| Redirect URI | https://decisions.coulomb.social/auth/callback |
| Flow | authorization code + S256 PKCE, public client |
| Scopes | openid, approval:read, approval:approve |
Redirect URIs match byte-exactly at /authorize. A registration pointing at a
host that does not answer fails closed at first login and presents as a rejected
approval rather than as a registration defect — which is exactly the failure
approval-engine avoided by refusing to invent these strings. So the origin has
to be real before the registration is submitted, and that is S5 work here rather
than in informed-decision.
The approver UI itself is INFD-WP-0001-T08, still gated on approval-engine
APPROVAL-WP-0002-T01 and on intake INFD-IN-0003 (the evidence copy must reach
audit-core independently of this component). This host therefore ships a
placeholder first and the real surface later.
What is in the repo
| File | Contents |
|---|---|
manifests/informed-decision-origin.yaml |
Namespace, placeholder nginx ConfigMap/Deployment/Service on informed-decision:80 |
manifests/informed-decision-ingress.yaml |
Traefik Ingress + letsencrypt-prod certificate for decisions.coulomb.social |
The placeholder is nginxinc/nginx-unprivileged, read-only root filesystem,
non-root, noindex. When the real surface lands it takes over the same Service
name and the origin file shrinks to the Namespace.
Deliberate single path rule
The Ingress carries exactly one rule: / Prefix to one backend.
reuse-surface reported on 2026-07-07 that an Ingress declaring an Exact
/health rule alongside a catch-all / Prefix rule on the same host had the
exact match swallowed by the catch-all — the public health URL returned 404 from
the landing container while the pod was 1/1 Ready and its own probes passed.
Splitting /auth, /api and / across backends here would reproduce that on a
host whose whole purpose is an exact-match redirect URI. If a second backend ever
becomes necessary, set traefik.ingress.kubernetes.io/router.priority
explicitly rather than relying on rule order.
Preconditions verified 2026-09-10
- DNS
decisions.coulomb.social→92.205.62.239(same A record asreuse). letsencrypt-prodClusterIssuerReady=True.- No existing Ingress claims
decisions.coulomb.social. - Server-side dry-run of all five objects against the live API is clean.
The namespaced four were validated against an existing namespace, since a
server dry-run cannot create the new one first; see
DRY_RUN_CREATE_NAMESPACESintools/k8s-server-dry-run.sh.
To deploy (operator approval required — not yet given)
export KUBECONFIG=$HOME/.kube/config-hosteurope
kubectl apply -f manifests/informed-decision-origin.yaml
kubectl apply -f manifests/informed-decision-ingress.yaml
kubectl -n informed-decision get pods,svc,ingress
kubectl -n informed-decision get certificate informed-decision-tls -w
curl -sSI https://decisions.coulomb.social/ | head -1
Only when that curl succeeds does informed-decision submit
docs/keycape-client-registration.md to key-cape.
Note on the kubeconfig: ~/.kube/config-hosteurope names port 16443, but
the k3s-api-railiance01 ops-bridge tunnel currently listens on 16444.
Override with --server https://127.0.0.1:16444 or fix the kubeconfig; bridge check reports the tunnel healthy either way, so it does not surface the
mismatch.
HTTP → HTTPS
The Ingress is websecure-only, following the forgejo and coulomb-social
pattern, so port 80 stays free for cert-manager HTTP-01 solvers. Plain
http://decisions.coulomb.social/ will not redirect. reuse-surface adds a
separate -http-redirect Ingress for this; add one here if a bare-host redirect
is wanted. It is not required for the OIDC flow, which is always https.