key-cape/docs
tegwick d568b79223
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 41s
Give the runtime real readiness, graceful shutdown and stated limits
Closes gap G08. /healthz returned a constant without probing anything, the server
called ListenAndServe with no signal handling, and the operational limits of
in-memory state, startup-loaded keys and local-only logout lived in code comments
rather than anywhere an operator would look.

/readyz probes LLDAP, Authelia and privacyIDEA; /healthz stays liveness and
probes nothing. Keeping them distinct matters: wiring liveness to dependency
health means an orchestrator restarts KeyCape when a dependency blinks, and a
restart also discards every in-flight login, so the reaction is worse than the
condition it reacts to.

LLDAP is probed with a bind rather than a dial, since a rotated or revoked
service password leaves the port open and every lookup failing -- exactly what
readiness should catch and exactly what a dial would miss. The response names the
failing check but never the reason: the endpoint is unauthenticated and upstream
error text carries hostnames and sometimes credentials-in-URLs. Results are
cached for 2s so an unauthenticated endpoint cannot be used to drive unbounded
upstream traffic, and probes run concurrently under a 3s bound so a hung
dependency makes the endpoint answer rather than hang with it.

SIGTERM and SIGINT now drain in-flight requests for 15s, under the 30s read/write
timeouts so a stuck request cannot outlive the window before SIGKILL.

docs/operations.md states the single-replica topology and why, and three limits
easy to get wrong: the constant key-1 key ID makes same-kid rotation a trap for
consumers caching JWKS, removing a client does not revoke its issued tokens, and
/logout is local only. No throughput figures are given, since nothing here
benchmarks KeyCape. Shared storage and refresh tokens stay excluded, as G08
allows.

Verified in the running executable: 503 naming all three checks failed while
/healthz returned 200, the LLDAP check flipping to ok once started, and 40/40
requests succeeding across a SIGTERM.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NV9oijZukGyGbRQGGKnK4P

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 713576@bnt-lap001
Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
2026-09-08 09:43:49 +02:00
..
adr feat: implement T01-T04 — Go module, canonical model, LDAP validator, error taxonomy 2026-03-13 01:27:54 +01:00
approval-engine-auth-contract.md Add bounded resource audiences and enforce browser scope grants 2026-09-05 00:41:17 +02:00
approval-engine-provisioning-request.yaml Align approval registrations to the tenant:platform decision 2026-09-06 22:30:32 +02:00
authorization-code-bindings.md Document the authorization-code bindings for relying parties 2026-09-07 00:17:56 +02:00
native-authentication.md Add native verified login and service-token commands 2026-09-05 01:08:58 +02:00
openbao-service-auth-contract.md Implement KeyCape provider and service identity contracts 2026-08-23 13:10:13 +02:00
operations.md Give the runtime real readiness, graceful shutdown and stated limits 2026-09-08 09:43:49 +02:00
qonto-runtime-identity-contract.md Define Qonto runtime identity contract 2026-07-26 13:34:56 +02:00
tenant-claim-contract.md Align approval registrations to the tenant:platform decision 2026-09-06 22:30:32 +02:00