Authenticate with a seeded operator key; fold escalation and switches into TerdutTeam #12

Merged
niklas merged 3 commits from operator-key-and-team-config into main 2026-10-09 20:20:13 +00:00
Owner

What

Redesigns how the operator authenticates to terdut-server and how its CRDs are shaped. Depends on terdut-server#43 (the server's TERDUT_OPERATOR_KEY and external_id support): merge that first.

Credentials. The TerdutServer controller generates <name>-operator-key in the server's own namespace (owned by it) and hands it to the pods as TERDUT_OPERATOR_KEY; the server creates its instance-scoped account from it at every start. A replaced Secret rolls the pods. Gone: the bootstrap handshake, the checkpoint Secret, per-team service accounts and credentials Secrets, BootstrapStateLost, credentials.deletionPolicy.

CRDs. TerdutServer, TerdutTeam, TerdutAlertSource. TerdutEscalationRule and TerdutDeadmanSwitch become spec.escalation and spec.deadmanSwitches[] on the team (switches matched by name, extras removed). Team invites are removed.

Team identity. A team is created under <namespace>/<name> (external_id), so a retry, a lost status or a deleted team heal by repeating the same call, and a display name owned by another team is TeamNameTaken instead of an adoption. The server resolves escalation usernames (UnknownUser condition). OIDC claim names and trustEmail are spec fields.

Fixes. Query values are URL-escaped; every delete treats 404 as success; deleting a team no longer depends on allowedTeams consent; a switch or integration deleted on the server is recreated; unnamed switches take the CR's name.

Cleanup. Scaffold e2e test, AGENTS.md, devcontainer, unused config/ pieces and Client.Version() removed. DESIGN.md, README, ROADMAP and the demo are rewritten for the new design. CI image bumped to Go 1.26.9 and golang.org/x/net to v0.60.0 (govulncheck).

Breaking

CRD changes (two kinds removed, TerdutTeam and TerdutServer specs changed) and a server requirement (TERDUT_OPERATOR_KEY), so existing installs must be recreated. Secret RBAC stays cluster-wide (DESIGN.md §9, #8).

Checked

  • make fmt lint test helm-lint passes (47 envtest specs against a fake server).
  • make security-go security-secrets clean on Go 1.26.9.
  • The real terdut-server binary was exercised over curl with an operator key for every endpoint the controllers call.
  • Not run: the kind end-to-end pass and examples/demo/run-demo.sh (#7). Please run the demo before releasing.

Closes #1 and #3 (already closed as obsolete). Related: #7, #8, #9, #10, #11.

https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN

## What Redesigns how the operator authenticates to terdut-server and how its CRDs are shaped. Depends on terdut-server#43 (the server's `TERDUT_OPERATOR_KEY` and `external_id` support): **merge that first**. **Credentials.** The `TerdutServer` controller generates `<name>-operator-key` in the server's own namespace (owned by it) and hands it to the pods as `TERDUT_OPERATOR_KEY`; the server creates its instance-scoped account from it at every start. A replaced Secret rolls the pods. Gone: the bootstrap handshake, the checkpoint Secret, per-team service accounts and credentials Secrets, `BootstrapStateLost`, `credentials.deletionPolicy`. **CRDs.** `TerdutServer`, `TerdutTeam`, `TerdutAlertSource`. `TerdutEscalationRule` and `TerdutDeadmanSwitch` become `spec.escalation` and `spec.deadmanSwitches[]` on the team (switches matched by name, extras removed). Team invites are removed. **Team identity.** A team is created under `<namespace>/<name>` (`external_id`), so a retry, a lost status or a deleted team heal by repeating the same call, and a display name owned by another team is `TeamNameTaken` instead of an adoption. The server resolves escalation usernames (`UnknownUser` condition). OIDC claim names and `trustEmail` are spec fields. **Fixes.** Query values are URL-escaped; every delete treats 404 as success; deleting a team no longer depends on `allowedTeams` consent; a switch or integration deleted on the server is recreated; unnamed switches take the CR's name. **Cleanup.** Scaffold e2e test, `AGENTS.md`, devcontainer, unused `config/` pieces and `Client.Version()` removed. DESIGN.md, README, ROADMAP and the demo are rewritten for the new design. CI image bumped to Go 1.26.9 and `golang.org/x/net` to v0.60.0 (govulncheck). ## Breaking CRD changes (two kinds removed, `TerdutTeam` and `TerdutServer` specs changed) and a server requirement (`TERDUT_OPERATOR_KEY`), so existing installs must be recreated. Secret RBAC stays cluster-wide (DESIGN.md §9, #8). ## Checked - `make fmt lint test helm-lint` passes (47 envtest specs against a fake server). - `make security-go security-secrets` clean on Go 1.26.9. - The real terdut-server binary was exercised over curl with an operator key for every endpoint the controllers call. - **Not run:** the kind end-to-end pass and `examples/demo/run-demo.sh` (#7). Please run the demo before releasing. Closes #1 and #3 (already closed as obsolete). Related: #7, #8, #9, #10, #11. https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
niklas added 3 commits 2026-10-09 20:08:21 +00:00
Credentials: the TerdutServer controller generates <name>-operator-key in
the server's own namespace (owned by it) and hands it to the pods as
TERDUT_OPERATOR_KEY; the server creates its instance-scoped account from it
at every start. A replaced Secret rolls the pods. The bootstrap handshake,
the checkpoint Secret, per-team service accounts and credentials Secrets,
BootstrapStateLost and credentials.deletionPolicy are gone.

CRDs: TerdutServer, TerdutTeam and TerdutAlertSource. TerdutEscalationRule
and TerdutDeadmanSwitch become spec.escalation and spec.deadmanSwitches[]
on the team (matched by name, extras removed); team invites are removed.
A team is created under the identity <namespace>/<name> (external_id), so a
retry, a lost status or a deleted team heal by repeating the same call, and
a display name owned by another team is TeamNameTaken instead of an
adoption. The server resolves escalation usernames (UnknownUser condition).
OIDC claim names and trustEmail are spec fields.

Fixes: query values are URL-escaped; every delete treats 404 as success;
deleting a team no longer depends on allowedTeams consent; a switch or
integration deleted on the server is recreated; unnamed switches take the
CR's name.

Cleanup: scaffold e2e test, AGENTS.md, devcontainer, unused config/ pieces
and Client.Version() removed; DESIGN.md, README, ROADMAP and the demo
(run-demo.sh, manifests) rewritten for the new design. Secret RBAC stays
cluster-wide, now stated in DESIGN.md section 9.

Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
govulncheck in the security job reports ten standard-library
vulnerabilities (net/http, mime/multipart, crypto/tls), all fixed in
1.26.9. The workflows pinned golang:1.26.6-bookworm.

Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
Update golang.org/x/net to v0.60.0
CI / chart (pull_request) Successful in 2s
CI / security (pull_request) Successful in 1m16s
CI / test (pull_request) Successful in 7m4s
9b59e4bdbc
govulncheck reports five vulnerabilities (GO-2026-6603, 6610, 6611, 6612,
6617) in x/net v0.58.0 that the code reaches through net/http's HTTP/2
client. v0.60.0 fixes them; the other x/ modules move with it.

Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
niklas merged commit 7fb8042265 into main 2026-10-09 20:20:13 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: niklas/terdut-operator#12