Commit Graph

16 Commits

Author SHA1 Message Date
Niklas Ye ffc2e6441e ROADMAP.md Stage 1: scope down to bring-your-own only, defer self-registration to Stage 5
CI / test (push) Successful in 1m23s
Stage 1's own setup (chart bootstraps before the CR exists) never
exercises the self-registration fallback, and the narrowed spec has
nowhere to put the username/email /api/bootstrap needs anyway. Matches
DESIGN.md's §6 rewrite (bring-your-own is now the primary path, not an
equal alternative).
2026-09-30 22:22:09 +02:00
Niklas Ye 5f93a530fa DESIGN.md §4.1/§6: drop namespace from credentialsSecretRef, add key
CI / test (push) Has been cancelled
It's always the operator's own namespace by construction now (§6), never
anything else, so there was nothing for the field to vary -- key varies
instead (fixed 'token' when self-generated, whatever a human chose when
adopted from spec.credentialsSecretRef).
2026-09-30 22:21:28 +02:00
Niklas Ye 7f439605c4 DESIGN.md §4.1/§6: fix the bootstrap self-registration deadlock
CI / test (push) Has been cancelled
Traced the actual flow against terdut-server's real source before writing
any Stage 1 controller code, rather than trusting this section's own prior
description of it:

- internal/api/middleware.go's AuthMiddleware hard-rejects with 401 any
  request carrying neither a Bearer token nor a session cookie, before
  handleListServiceAccounts' own (more permissive) internal check ever
  runs. So "on 403, self-lookup via GET /api/service-accounts?name=" --
  this section's described fallback -- cannot work unauthenticated; an
  earlier draft of this section assumed otherwise.
- That only actually matters in the rare case where this TerdutServer's
  own controller loses the /api/bootstrap race... except Stage 1's own
  setup (ROADMAP.md) guarantees it loses every time: terdut-server is
  deployed via its existing chart, which runs its own bootstrap Job,
  before the TerdutServer CR or its controller exist at all. The
  self-registration flow was never going to complete for the one scenario
  Stage 1 actually exercises.

Fix: spec.credentialsSecretRef (§4.1), bring-your-own -- a human mints an
instance-scoped service account once, manually, with their own admin
session, and hands the controller that Secret directly. This is now the
primary, expected path; self-registration on a genuinely fresh install
(where this controller might actually win the race) stays as the
fallback it was always meant to be, not the only path.

Also corrected: this section's opening paragraph still said "v1-blocking,
not v1-shippable" pending SERVICE-ACCOUNTS.md landing -- confirmed shipped
(internal/api/service_accounts.go, migration 014) since Stage 0's work on
this repo; stale framing removed.
2026-09-30 22:20:31 +02:00
Niklas Ye dd955bbf1a CI: update comment -- second MTU fix resolves the github.com timeout
CI / test (push) Successful in 1m17s
Confirmed via the actual job log (run 857, job 1931), not just the exit
code: setup-envtest fetches envtest-v1.37.0-linux-amd64.tar.gz from
github.com in ~4s now, where it previously TLS-handshake-timed-out every
time. golangci-lint's own git-clone-to-github.com (the confound from the
first fix attempt) also went through fine in the same run.

Stage 0 is now fully green end to end: fmt, lint, test (envtest included).
2026-09-30 21:41:29 +02:00
Niklas Ye 0e89816ad4 CI: revert temporary test-only isolation; MTU fix ruled out
CI / test (push) Successful in 7m59s
Clean result, isolated from lint's own unrelated github.com flakiness:
post-MTU-fix (Ryuvia/charts#272), `make test` alone hits the exact same
"TLS handshake timeout" fetching envtest-v1.37.0-linux-amd64.tar.gz as
before the fix. Byte-for-byte identical error. The dind sidecar's MTU
mismatch was real (measured 1450 vs 1500 per the other session's report)
but it was not (solely) the cause of this specific failure.

Separately and incidentally: golangci-lint's own custom-gcl build also
does a plain `git clone https://github.com/...` and that is now failing
too (2/2, ~2.5min hang then generic exit 128) where it briefly succeeded
in an earlier pre-fix run -- noted in the comment but not chased further
here; worth someone's attention if it keeps recurring, since it'll block
`lint` regardless of the envtest question.
2026-09-30 21:26:29 +02:00
Niklas Ye a55489c7a9 CI: temporarily isolate make test from lint to probe the envtest fetch alone
CI / test (push) Failing after 3m23s
lint is currently blocked by an unrelated github.com git-clone failure
(golangci-lint's custom-gcl build), which means the last two runs never
reached setup-envtest -- the step the act-runner MTU fix (Ryuvia/charts#272)
was meant to affect. Narrowing to `make test` alone to get a clean signal;
will revert to `make fmt lint test` right after.
2026-09-30 21:22:10 +02:00
Niklas Ye a241007135 CI: revert to container-based test job; correct the NetworkPolicy claim
CI / test (push) Failing after 2m42s
Host-mode (previous commit) fails earlier and differently: "go: command not
found" -- the runner host has no Go, so that path is dead.

Checked Ryuvia/charts' act-runner/templates/networkpolicy.yaml directly
rather than assuming: it's the only NetworkPolicy in the cluster, and it is
explicitly deny-ingress only -- its own comment states egress is
deliberately untouched, "CI pulls from registries and package indexes that
are not enumerable here" (issue #128). So my earlier claim that this needs
"allowlisting github.com on the runner's NetworkPolicy" was wrong: there is
no in-repo egress rule governing this at all. Whatever blocks github.com
from the dind bridge is outside anything Ryuvia/charts or Ryuvia/k8s
expresses in a Kubernetes object -- back to container-based (matching every
other Go job in this org) as the known-good shape, with `make test` left
red on the envtest fetch until that's actually found.
2026-09-30 19:49:23 +02:00
Niklas Ye 372fbe0660 CI: try running test job on host, not in a container
CI / test (push) Failing after 1s
Confirmed the hard way (run 852, attempt 2): setup-envtest v0.25 fetches the
envtest kube-apiserver/etcd tarball from github.com's release CDN, not the
legacy GCS kubebuilder-tools bucket (that bucket 403s now for any object --
no fallback there for k8s 1.37 either). github.com is unreachable from this
job's container the same way terdut-server's ci.yaml already documents for
get.helm.sh -- TLS handshake timeout.

Dropping `container:` on this job is the same fix terdut-server's `chart` job
already uses for that exact class of problem (it reaches get.helm.sh only by
running on the host). Unproven for a Go job specifically -- no workflow in
this org has run Go outside a container before, so this also bets the runner
host has Go installed. If it fails on a missing `go` instead of the envtest
fetch, that bet was wrong and the real fix is allowlisting github.com's
release CDN on the runner's NetworkPolicy instead (Ryuvia/charts or
Ryuvia/k8s, outside this repo).
2026-09-30 19:41:08 +02:00
Niklas Ye e118a8e70d Ignore coverage output (cover.out) from make test
CI / test (push) Failing after 7m4s
2026-09-30 19:22:28 +02:00
Niklas Ye ba253b7bf7 Add CI, repo CLAUDE.md, and finish Stage 0
- .gitea/workflows/ci.yaml: fmt/lint/test, same no-actions/checkout-and-manual-clone
  shape as terdut-server's ci.yaml, and the same reasoning for why (Node/ES2022
  incompatibility on the runner image). No chart/security jobs yet -- nothing for
  either to check until Stage 6 / real controller code exists.
- CLAUDE.md: Checks + Release sections, matching the sibling repos' convention from
  the workspace-level CLAUDE.md ("each repo has its own CLAUDE.md... read it before
  working in that repo"). Release is explicitly marked not-wired-yet rather than
  copying terdut-server's, since there's no chart to release against until Stage 6.
- ROADMAP.md: moved the .release.conf bullet out of Stage 0 (it names a HELM_CHART
  this repo doesn't have yet) -- it was already duplicated into Stage 6, which is
  where it actually belongs.

Stage 0 done: `make fmt lint test` verified green locally. Real open question the CI
workflow's comments flag rather than assume past: whether storage.googleapis.com
(envtest's binary source) is reachable from this Gitea runner's container network the
way proxy.golang.org is -- terdut-server's own ci.yaml notes get.helm.sh/github.com are
not. Only running the workflow for real will confirm; the comment names the fallback
(move the job out of `container:`, like terdut-server's chart job) if it isn't.
2026-09-30 19:22:19 +02:00
Niklas Ye c97571c4c4 Scaffold project with Kubebuilder v4
kubebuilder init --domain ryuvia.com --repo git.ryuvia.com/niklas/terdut-operator
(--license none, no per-file header boilerplate -- terdut-server's source carries
none either). Go 1.26.0/controller-runtime v0.25.0/controller-tools v0.22.0, whatever
the current kubebuilder CLI (v4.16.0) scaffolds -- not pinned back to terdut-server's
go 1.25.9, since this is a separate module with its own toolchain.

Verified locally: build, vet, fmt all clean; `make lint` (golangci-lint, fetched into
bin/) 0 issues; `make test` (controller-gen + setup-envtest, fetched into bin/,
downloads real envtest binaries from storage.googleapis.com) passes.

Dropped kubebuilder's default .github/workflows/* -- this org runs on Gitea, not
GitHub; ci.yaml (next commit) is the only CI this repo gets.
2026-09-30 19:22:09 +02:00
Niklas Ye 1feffd791a Housekeeping: gitignore, and finish the webhook-Secret-loss/RBAC fix
- Add .gitignore (build artifacts, editor swapfiles, envtest testbin).
- Remove the stray .DESIGN.md.swp that was sitting untracked in the repo.
- Carries the DESIGN.md §5/§9/§13 edits from the secret-loss discussion:
  fail-closed (not self-healed) TerdutAlertSource webhook Secret loss, and
  the corrected RBAC section (the webhook Secret lives in the CR's tenant
  namespace, not the operator's own namespace as an earlier draft claimed).
2026-09-30 19:16:37 +02:00
Niklas Ye ee39b8e668 Add build roadmap
Stages the operator's implementation: TerdutServer stays bootstrap/credentials-only
(no Deployment/Service takeover) until Stage 5, so every earlier stage targets a
hand-deployed terdut-server in a disposable dev namespace instead of forcing the
chart-migration decision (§10) up front.
2026-09-30 19:16:21 +02:00
Niklas Ye 94989e2c87 Rework §6 bootstrap/credentials against confirmed server behavior
/api/bootstrap is single-shot per install (gated on COUNT(*) FROM
users, confirmed against internal/api/users.go and the chart's
bootstrap-job.yaml), not per identity — the two-identity bootstrap
plan and the delete-Secret-to-rotate runbook this section described
don't work against that. Rewrites §6 points 1/5/6 around a dedicated,
repeatable service-account credential instead (proposed server-side in
terdut-server's new SERVICE-ACCOUNTS.md), notes in §9 that Secret
mirroring is RBAC-sound but still hands out a server-admin-equivalent
credential per consenting namespace, and flags in §10 that chart-vs-
operator bootstrap ownership blocks §6 and needs deciding first.

Updates §13 to mark the service-account type as v1-blocking rather
than a someday improvement, and adds a version-discovery endpoint to
the same list (both this operator and terdut-tui currently detect
server capability by route-probing).
2026-09-29 20:35:15 +02:00
Niklas Ye 5f728a556b Switched from referencegrant the ligther parentRef 2026-09-29 16:19:06 +02:00
Niklas Ye ef5d8fcb5d First draft for design 2026-09-29 15:16:15 +02:00