TerdutTeam: mint and surface a real invite link (spec.invite) #5
Reference in New Issue
Block a user
Delete Branch "terdutteam-invite-minting"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stacked on #4 (still open) — this branches from it since it edits the same
run-demo.sh.The actual fix for the human-onboarding gap
niklas/terdut-server#23found — not aterdut-serverchange at all. A team-scoped credential is already owner-equivalent forPOST/GET/DELETE /api/teams/{teamID}/invites(requireTeamOwner's synthetic-membership mechanism, ratified not accidental per that repo'sSERVICE-ACCOUNTS.md), and invite redemption bypassessignup_modeentirely — thisTerdutTeamcontroller just never grew a feature to use either fact.What changed
spec.invite{enabled, role (member|owner, default member), maxUses (1-100, default 1)}andstatus.inviteSecretRefonTerdutTeam. The Secret lives in the TerdutTeam's own namespace, not the operator's — unlikestatus.credentialsSecretRef(a durable, high-privilege credential, kept operator-side perDESIGN.md§6), an invite is bounded and limited-use, meant for that namespace's own human operators to read and hand out. Same precedent asTerdutAlertSource'sstatus.webhookURLSecretRef: same-namespace,OwnerReference'd, garbage-collected automatically when theTerdutTeamis deleted.internal/controller/terdutteam_invite.go: mints on firstspec.invite.enabled, refreshes a day ahead of terdut-server's fixed 7-day TTL, revokes server-side + deletes the Secret when flipped back tofalse. A lost invite Secret is silently re-minted (not fail-closed likeTerdutAlertSource's webhook key) — nothing external depends on one specific invite link staying stable.tdclient.Invite/CreateInvite/RevokeInvite.handleTeamSubPathdispatcher got split further — dead man switches into their ownhandleDeadmanSubPath— to stay undergocyclo's threshold with the new route).Demo proof
examples/demo/02-team-platform.yamlturns onspec.invite;run-demo.sh'sbootstrap_login/join_demo_teams(thepsqlsignup_modeflip + a directteam_membersINSERT) are replaced byredeem_platform_invite(readsstatus.inviteSecretRef, a realPOST /api/signupwith the token) andjoin_payments_team(POST /api/teams/{teamID}/membersusing Payments' own credential + alice's user id viaGET /api/users— Payments deliberately has nospec.inviteof its own, so the demo shows both onboarding paths this unlocks). Zerokubectl exec/psqlcalls remain anywhere in the script.README.md's "First login" section rewritten to match — it no longer documents the admin-token curl call that 403s against current terdut-server.Sequencing
Depends on
niklas/terdut-server#24(thecallerMayManageServiceAccountfix for #3) being released before this is deployed for real — not required to build or test this change itself, since the envtest fake never modeled that authorization gap to begin with.Testing
make fmt lint test helm-lintgreen. New specs:spec.inviteDescribe block interdutteam_controller_test.go(3 cases: mint, refresh, revoke).