Why
Part of the self-service kubeconfig bootstrap initiative (tracking issue TBD, linked once created). Need a controller-owned primitive that issues, hashes, expires, and resends bootstrap tokens before any HTTP surface (gateway) or email sending exists — testable in isolation by inspecting the Secret directly.
Scope
- New package
internal/controller/bootstrap, following the existing style of internal/controller/renewal / internal/controller/rbac.
- On
User reconcile, if spec.email is set and status.bootstrapPhase is NotConfigured: generate a random token, store only its SHA-256 hash + expiry (15–30 min TTL) + used: false in a new <username>-bootstrap-token Secret, owned via OwnerReference (reuse the fixed-TypeMeta pattern so garbage collection works correctly), set status.bootstrapPhase = Pending.
- Detect a
kubeuser.io/resend-bootstrap annotation: invalidate any existing unused token, issue a fresh one, reset phase to Pending, clear the annotation.
- TTL sweep: expired, unused tokens get their Secret deleted (reuse timing/requeue patterns already established in
internal/controller/renewal).
- Does not send email yet or expose any HTTP endpoint — that's separate sub-issues.
Acceptance criteria
Depends on
#102 (CRD fields), #101 (secret-naming conventions this package should follow)
Why
Part of the self-service kubeconfig bootstrap initiative (tracking issue TBD, linked once created). Need a controller-owned primitive that issues, hashes, expires, and resends bootstrap tokens before any HTTP surface (gateway) or email sending exists — testable in isolation by inspecting the Secret directly.
Scope
internal/controller/bootstrap, following the existing style ofinternal/controller/renewal/internal/controller/rbac.Userreconcile, ifspec.emailis set andstatus.bootstrapPhaseisNotConfigured: generate a random token, store only its SHA-256 hash + expiry (15–30 min TTL) +used: falsein a new<username>-bootstrap-tokenSecret, owned viaOwnerReference(reuse the fixed-TypeMeta pattern so garbage collection works correctly), setstatus.bootstrapPhase = Pending.kubeuser.io/resend-bootstrapannotation: invalidate any existing unused token, issue a fresh one, reset phase toPending, clear the annotation.internal/controller/renewal).Acceptance criteria
<username>-bootstrap-tokenwith only a hash at rest, never plaintextDepends on
#102 (CRD fields), #101 (secret-naming conventions this package should follow)