Roadmap¶
Phased delivery plan for MKurator. Each phase is shippable
on its own and keeps the tree green (build + lint + tests + verify pass). See
ARCHITECTURE.md for design, DEVELOPMENT.md for
conventions, NON_FUNCTIONAL_REQUIREMENTS.md for
quality bars, and CICD.md for the pipeline.
Guiding principles¶
- Small, atomic, fully-tested increments over big drops.
- Every external interaction sits behind the
MQAdminport so it can be mocked. - The build stays pure Go (
CGO_ENABLED=0); no native MQ client. - Generated artifacts are committed and verified fresh (
task verify). - NFRs (security, reliability, observability) are built in per phase, not bolted on at the end.
Phase 0 — Foundations¶
- [x] Contributor conventions and toolchain documented (
docs/DEVELOPMENT.md, doc map in README). - [x]
docs/ARCHITECTURE.md(runtime concerns, RBAC, error/requeue, security). - [x]
docs/NON_FUNCTIONAL_REQUIREMENTS.md,docs/DEVELOPMENT.md,docs/CICD.md. - [x]
docs/adr/with template, index, and initial decisions. - [x]
SECURITY.md,README.md,docs/ROADMAP.md. - [x] Local platform under
hack/kind-cluster(kind + Terraform + IBM MQ).
Exit criteria: design and local MQ platform documented and runnable — met.
Phase 1 — Scaffold & toolchain¶
- [x] Scaffold with Kubebuilder v4 (manager entrypoint,
PROJECT,api/v1alpha1group shell,internal/controllerpackage, structured logging). - [x]
Taskfile.yml+Taskfile.test.yml(install, format, lint, manifests, generate, verify, build, docker:build,cluster:*, deploy/undeploy, test:run, test:e2e), with Go tools pinned viago.modtooldirectives. - [x]
.golangci.yaml(v2),.mockery.yaml,.pre-commit-config.yaml,.editorconfig, distroless nonrootDockerfile. - [x] Manager wiring with leader election, health/readiness probes, and a protected metrics endpoint (NFR REL-3/OBS-3).
- [x] GitHub Actions per CICD.md:
verify+ lint + unit tests +govulncheck+ gitleaks on PRs; pinned action SHAs. - [x] Renovate —
renovate.json(Go, Actions, Docker, Terraform, pre-commit) and a weekly self-hosted.github/workflows/renovate.yaml(no Mend app required).
Also delivered in Phase 1:
- [x] ADR-0006 — original project name and
module identity (superseded by ADR-0018:
API group
messaging.mkurator.dev). - [x] ADR-0007 + LOGGING.md
—
logr/slog, redaction handler, manager flags/env. - [x]
hack/verify.sh(codegen drift check) andhack/goformat.sh. - [x] Secret scanning — gitleaks in pre-commit (
.pre-commit-config.yaml), CI (ci.yaml),task secrets:scan, and.gitleaks.tomlallowlists for local dev artifacts (references/, kind cluster state, terraform state). - [x]
.envrc—KUBECONFIG/TF_VAR_kubeconfigfor the local kind cluster.
Exit criteria: task build, task lint, task verify, and task test:run pass
locally and in CI — met.
Phase 2 — Core API, adapter & tests¶
- [x]
api/v1alpha1:QueueManagerConnectionandQueuetypes + generated deepcopy and CRD manifests; kubebuilder validation and print columns. - [x]
internal/mqadmin:Admin+Factoryports, domain types, sentinel errors. - [x]
internal/adapter/mqrest:mqwebclient (Ping,GetQueue,DefineQueue,DeleteQueue) +ClientFactory(Secret/credential resolution, TLS, client cache). - [x]
internal/adapter/mqrest:httptestunit tests (success, not-found, ping). - [x]
internal/controller: thin reconcilers — finalizers, drift detection, status conditions (Ready,Synced,observedGeneration); Queue waits for connectionReadybefore calling MQ. - [x] Tests: mockery mocks (
test/mocks/mqadmin),needsUpdateunit test, Ginkgo envtest suite (controller + API server, mockedAdmin). - [x] RBAC from reconciler markers (
controller-genpaths includeinternal/controller/...). - [x]
config/samples/(Kustomize) andconfig/crd/bases/.
Also delivered in Phase 2:
- [x] docs/schemas/ —
mqsc-runcommand.schema.json+ README; optionalscripts/fetch-mqweb-swagger.shfor full mqweb Swagger export. - [x]
task deploy—go tool kustomize, explicit CRD apply (no global kustomize). - [x]
charts/mkurator/— publishable Helm chart,helm:sync-crds, kindvalues-kind.yaml, sample Secret + CRs undercharts/mkurator/samples/resources/. - [x] Local workflow tasks:
deploy:helm,deploy:samples,local:up/local:deploy/local:info/local:down. - [x] README + DEVELOPMENT.md + LOCAL_SETUP.md
— local setup documented;
hack/kind-cluster/README.mdcross-linked. - [x] Optional local
docs/REFERENCES.md(from REFERENCES.md.example) +references/clones (both gitignored) for vendored IBM MQ sample trees — not published in the repository. - [x]
setup-envtestwired inTaskfile.test.yml(KUBEBUILDER_ASSETS). - [x] Manual validation on kind:
QueueManagerConnectionreaches Ready against liveQM1; operator reaches mqweb in-cluster. - [x] Fix DISPLAY QLOCAL on live MQ — drop
maxmsglenfrom display parameters (mqweb 9.4 returnsMQWB0120E); coerce numeric DEFINE attrs; Queue reaches Synced=True ontask local:up. - [x] Raise
internal/coverage to ≥90% (enforced intask test:run).
Exit criteria: envtest + adapter tests + live queue on kind — met.
Phase 3 — E2E, CI & release¶
- [x] e2e scaffold (
test/e2e, build tage2e) — controller pod, metrics, suite wiring on kind. - [x] MQ e2e scaffold (
test/e2e/mq_e2e_test.go,mq_helpers.go) gated byKURATOR_E2E_MQ=1— QueueManagerConnection + Queue CR apply, MQSC fixture apply via mqweb; assert real MQSC objects for create/update/delete and re-apply idempotency (NFR REL-1). Topic, Channel, and auth CR scenarios were added in Phase 4/5 (same test file). - [x]
test/e2e/fixtures/— MQSC bootstrap for channels/auth (from mq-gitops-samples); see PHASE5_AUTH_SKETCH.md. - [x] Wire e2e into CI (
.github/workflows/e2e.yaml: kind + IBM MQ +task test:e2e;task ci:e2efor local parity). - [x] Release workflow (
.github/workflows/release.yaml): multi-arch distroless image publish to GHCR + Trivy image scan + published Kustomize/Helm install manifests (hack/release-assets.sh,charts/mkurator/samples/values-release.yaml,.trivyignore) onv*.*.*tags (NFR OPS-1/OPS-2, SEC-4/SEC-6). - [x] Release supply chain — OCI SBOM + SLSA provenance (
docker/build-push-action), SPDX SBOM on GitHub Releases (anchore/sbom-action), cosign keyless signing (sigstore/cosign-installer), Helm chart OCI push to GHCR (helm push).
Also delivered in Phase 3:
- [x] Helm install path for local and release publish (
charts/mkurator,task helm:*). - [x]
RunMQSChelper onmqrestclient (runCommandplaintext) + unit test — groundwork for e2e fixtures and Phase 5 MQSC.
Exit criteria: task test:e2e green locally and in CI against a live Queue
Manager; release pipeline produces a scanned, signed image with SBOM and install
manifests — met (e2e in CI via e2e.yaml; signing/SBOM on release tags).
Phase 4 — Additional MQ objects (Topic, Channel)¶
Extend declarative management beyond local queues to other common MQSC object types before access-control work.
- [x]
TopicCRD — DEFINE/DISPLAY/DELETE topic (DEFINE TOPIC, drift detection, finalizers); map attributes per IBM_MQ_OBJECTS.md. - [x]
ChannelCRD —CHLTYPE(SVRCONN)in v1alpha1 (other channel types later). - [x] Extend
MQAdminport andmqrestadapter for topic/channel operations; table-driven adapter tests withhttptest. - [x] Thin reconcilers, RBAC, samples under
config/samples/andcharts/mkurator/samples/resources/. - [x] Unit + envtest coverage; [x] e2e scenarios on kind against live
QM1(Queue, Topic, Channel — seetest/e2e/mq_e2e_test.go). - [x] ATTRIBUTE_RECONCILIATION.md — DEFINE vs DISPLAY drift matrix per object; user tables in INSTALL_AND_USE.md.
- [x]
Queue.spec.typeOpenAPI aligned with reconcilers (local,alias,remote). - [x] Drift detection: case-insensitive
pub/sub/policies; channelmaxinst/maxinstc; topicpubscope/subscopewhere mqweb DISPLAY allows. - [x] Alias and remote queue types (
QALIAS,QREMOTE) with drift detection. - [x] TLS channel attrs (
sslciph,sslcauth) drift-checked (shipped; see ATTRIBUTE_RECONCILIATION.md). - [x]
sharedrift wired via runtime DISPLAY probe (#62 MQ-3; DISPLAY_CAPABILITY_PROBE.md). - [ ] Queue attrs
defopts,bothresh,boqname,usageremain DEFINE-only on mqweb 9.4 (MQWB0120Eon DISPLAY); drift deferred until capability probe extends beyondshare.
Exit criteria: at least Topic and one Channel kind reconcile end-to-end on
kind with the same quality bar as Phase 2 (verify, ≥90% internal/ coverage,
e2e green) — met (optional DISPLAY/TLS drift extensions above remain open).
Phase 4b — Validating admission webhooks (pre–Phase 5)¶
- [x] Validating webhooks (no mutating) for
QueueManagerConnection,Queue,Topic,Channel. - [x] cert-manager TLS for webhook serving; Kustomize + Helm wired.
- [x] Referential checks:
connectionRefexists, same namespace, not deleting. - [x] Queue: MQ name constraints; alias/remote required attributes; optional unknown-attribute warnings.
- [x] Topic/Channel: name constraints; channel
svrconnonly. - [x] Unit tests (
internal/validation) + envtest admission tests; optional e2e negative apply. - [x] Optional: deny
QueueManagerConnectiondelete while dependent CRs exist.
Exit criteria: met — invalid manifests rejected by kubectl apply on kind (Kustomize and Helm verified); task test:run includes webhook envtest suite.
Phase 5 — User & authority management¶
Planning doc: PHASE5_AUTH_SKETCH.md (CR sketch mapped from
reference MQSC; e2e fixture
test/e2e/fixtures/channel-auth-prereq.mqsc).
Shipped on main:
- [x]
ChannelAuthRuleandAuthorityRecordCRDs — API, CRDs,MQAdminport,mqrestadapter (SET CHLAUTH/SET AUTHREC), thin reconcilers, validating webhooks, samples, Docker integration tests (including auth delete/update paths). - [x] E2e on kind —
ChannelAuthRuleandAuthorityRecordreconcile and delete intest/e2e/mq_e2e_test.go; adapter GET helpers for auth assertions; admission negative tests for invalid Queue and ChannelAuthRule without a matching Channel. - [x] MQAdmin GET + drift —
GetChannelAuth/GetAuthority; replace-on-diff in auth reconcilers;status.desiredMQSCon auth CRs. - [x] Release tags
v0.5.0–v0.5.3andv0.6.0with GitHub Releases; publish only after the RELEASE.md gate is green on the tag SHA (historical note:v0.5.2was cut before e2e was consistently green onmain). - [x] CI ergonomics (Phase 5) —
preflight.yaml(fail-fastgo mod tidy+task verify),nightly.yaml(Mon 03:00 UTC full pyramid),release-gate.yaml(workflow_dispatchon SHA), Phase C PR e2e filter(smoke || mq) && !slow, JUnit artifacts (integration-junit.xml,e2e-junit.xml), composite caches under.github/actions/— see CICD.md.
Remaining:
- [x] Pipeline green on
main— CI, Integration, and E2E (kustomize) succeeded onmainbeforev0.6.0(evidenced 2026-06-03/04; use release-gate orgh run listbefore the next tag). - [ ]
task ci:e2egreen locally — maintainer verification of full kind + MQ stack (Kustomize deploy path); respectexclusive-test.lock. - [x] Helm ClusterRole includes auth CRDs;
hack/helm-verify-rbac.shintask helm:lint. - [x] E2e BLOCKUSER
ChannelAuthRuleon kind (test/e2e/mq_e2e_test.go). - [x] Optional: integration BLOCKUSER CHLAUTH
(
test/integration/mq/auth_integration_test.go). - [ ] Additional CHLAUTH rule types (
USERMAP,SSLPEERMAP, …) — schema present; extend API fields, integration, and e2e when needed. Resequenced after Phase 7 (2026-06-09 audit): production-hardening table stakes serve adopters deciding whether to commit; extended rule types serve users already committed.
Exit criteria: declarative channel auth and OAM authority records reconciled on
kind with e2e specs — met for core auth code and v0.6.0 pipeline
closure on main; extended CHLAUTH rule types remain optional; local task ci:e2e
verification remains a maintainer checklist item.
Repo visibility¶
- [x] README badges — CI, MIT license, Codecov, Go module / pkg.go.dev (platformrelay/MKurator).
- [x] User guide — INSTALL_AND_USE.md + annotated config/samples/README.md.
- [x] CI coverage export —
coverage.outartifact, job summary, Codecov upload (codecov.yml; first greenmainrun registers the project). - [x] Go Report Card — retired (service sunset 2026-07-01); badge removed from README.
Quality gates remain via
golangci-lintin CI. - [x] Release badge —
README.mdlinks GitHub Releases (latest tag). - [x] LOCAL_SETUP.md — tiered dev tool install (
Brewfile,task tools:check/task tools:install, updated.devcontainer/).
Phase 6 — OSS maturity (shipped, v0.7.0)¶
Meta-engineering wave per ADR-0019 / ADR-0020:
- [x] MkDocs Material docs site + GitHub Pages (
docs.yaml), README badge. - [x] CodeQL, OpenSSF Scorecard, RBAC audit job; SonarCloud scaffolded (disabled).
- [x] Release attestations (cosign sign-blob,
actions/attest, signed Helm OCI). - [x] Community docs (
CODE_OF_CONDUCT.md,GOVERNANCE.md, DCO), engineering standards split (docs/development/*), assurance docs. - [x] Grafana dashboard + PrometheusRule (0.6.0/0.7.0); metrics catalog in OBSERVABILITY.md.
Exit criteria: docs site live, posture workflows green — met. Further badge work is deprioritized in favour of Phase 7 (2026-06-09 audit litmus test: does the artifact help a user run the operator, or help the repo look run?).
Phase 7 — Production hardening & operator table stakes¶
Driven by the 2026-06-09 audit train (architecture, edge-case, test-quality, docs, release lanes + critical design review). These items serve adopters deciding whether to commit and therefore precede further MQ-surface depth. New decisions: ADR-0021 – ADR-0025.
7a — Reliability fixes (P0/P1, land first)¶
- [x] Deletion deadlocks (EC-P0-01/EC-P0-02): evaluate
DeletionTimestampbefore requiring a ready connection;ReleaseConnectiontolerates missing Secrets; envtest locks T1/T2. Per ADR-0022 / ADR-0023. (v0.7.1) - [x] QMC hot loop (ARCH-01/EC-P1-02): stop
ReadyFalse→True flapping on every reconcile; status-change-only patches + predicates; oneAvailableevent per transition (ADR-0015 compliance); envtest lock T4. (v0.7.1, refined v0.8.0) - [x] MQSC injection (EC-P1-04): enum/pattern validation for
userSource/checkClient/authorities[]+ shared quoting helper per ADR-0024; webhook envtest T6. (v0.7.1) - [x] Periodic drift resync (ARCH-04/EC-P1-01, ADR-0010 gap): configurable
jittered
RequeueAfteron successful syncs (default 5–10 min) + drift detection metric; makes/readyzMQ-health real again (EC-P2-06); envtest locks T3/T3b. (v0.7.1) - [x] Client cache lifecycle (ARCH-02/03, EC-P2-01): identity-keyed cache, replace-on-rotation with transport close, bounded size — per ADR-0023. (v0.7.1)
- [x]
RecoverPanicon all controllers (EC-P1-05); log swallowedListerrors in connection fan-out (EC-P2-02, ARCH-10); fix transientRequeueAfter+error conflict (EC-P3-02). (v0.7.1)
7b — Operator table stakes¶
- [x]
spec.suspend+ reconcile-now annotation (MKR-01; makes the FAQ claim true — previously documented a non-existent annotation, DOC-02). (v0.8.0) - [x] Watch referenced Secrets (MKR-02/EC-P1-03): credential rotation and fixed-Secret recovery become event-driven; envtest lock T5. (v0.8.0)
- [x]
spec.deletionPolicy(Delete/Orphan) + force-orphan annotation;spec.adoptionPolicy(Adopt/AdoptIfMatching/FailIfExists) — per ADR-0022; brownfield-safe semantics. (v0.8.0) - [x] Retry/backoff + circuit breaker around mqweb (MKR-03) with breaker state metric; per-request context deadlines distinct from the 60 s client cap. (v0.8.0)
- [x] Configurable, jittered requeue intervals (MKR-05): QMC health 30 s, connection-wait 15 s, transient 30 s, drift resync — manager flags. (v0.8.0)
- [x] CEL-first validation per ADR-0025:
stateless rules on CRDs; webhooks for referential checks only; golden + envtest
parity; cert-manager optional with
webhooks.enabled=false. - [x] Secret RBAC/cache scoping (ARCH-05): filtered informer cache for
Secrets; align ARCHITECTURE.md least-privilege claim. Warn on the
admindefault when username keys are absent (ARCH-12). (v0.8.0)
7c — Code & test health¶
- [x] Collapse the 5-way type switches (ARCH-06, critical review §2.6):
MQObjectinterface or generics acrossreconcile_shared.go/status_helpers.go/drift_policy.go; one generic workload reconcile skeleton. Precondition for any new CRD kind. - [x] Wrong-behavior fixes (test audit): observe-only CHLAUTH/AUTHREC must not SET missing objects (WB-01/F01); typed wrap errors replace substring event classification (WB-02/F02, ADR-0014 compliance); per-kind status-patch tests assert re-read state (WB-03/F03). (v0.8.0)
- [x] Delete dead helpers + padding tests (ARCH-09/F04); envtest gaps for
Channel/Topic/AuthorityRecord paths (F07) — lifts
internal/controllercoverage (87.6%) honestly. (v0.8.0) - [x] E2E flake triage (ARCH-07): parallel Ginkgo
AfterSuitedeploy race — fixed #57SynchronizedAfterSuite(v0.9.6); E2E green onbea6b2027723178744. - [x] Fix
task changelogclobberingCHANGELOG.md(release audit P1-2:cliff.tomloutputvs preview tasks). (v0.7.1)
7d — Docs truth wave¶
- [x] Fix drift-semantics contradiction in INSTALL_AND_USE.md (DOC-01);
remove/implement FAQ
suspendentry (DOC-02 — closes with 7b); cert-manager in prerequisites (DOC-03); uninstall covers auth CRs (DOC-09); broken ADR-0006 links (DOC-04); certReadywait in UPGRADE.md (DOC-07); version pins → current release (DOC-08); remaining link/anchor fixes (DOC-05/10/11/12); doc-map sync (DOC-13); CRD field comments (DOC-14); ADR-0018KURATOR_*prefix note (DOC-17).
Exit criteria: all EC-P0/P1 closed with envtest locks; suspend/deletion/ adoption/resync shipped and documented; CEL migration complete with golden parity; coverage floor intact without padding; e2e flake rate addressed.
Phase 8 — API maturation (v1beta1 readiness)¶
8a — Typed attribute fields¶
- [x] Typed attribute fields + escape hatch per ADR-0021: promote drift-checked keys to typed, CEL-validated spec fields; exclusivity rule; schema goldens. Queue/Topic/Channel drift keys complete (v0.9.3).
8b — API stability statement¶
- [x] Published API stability statement: API_STABILITY.md —
what
v1alpha1guarantees, what graduation tov1beta1requires (conversion webhook, deprecation policy).
8c — DISPLAY capability probing (optional, partial)¶
Per ADR-0024 §4; DISPLAY_CAPABILITY_PROBE.md.
- [x] Spike:
ProbeQueueLocalAttributeDisplayable+ client cache (#58 MQ-1). - [x]
sharewired into local-queue DISPLAY/drift via runtime probe (#62 MQ-3). - [x] Extend probe to remaining
QueueLocalDefineOnlyCandidates(defopts,bothresh,boqname,usage,maxmsglen) via client cache (MQ-4).
8d — v1beta1 graduation¶
Per ADR-0026; bake criterion met (v0.11.x).
- [x] 8d-0 graduation plan ADR — conversion scope, hub-spoke storage, deprecation policy (docs only; no webhook code).
- [x] 8d-1
api/v1beta1types; CRD multi-version (servedon both versions). - [x] 8d-2 conversion webhook + cert-manager wiring (Kustomize + Helm).
- [x] 8d-3 per-kind conversion unit tests (table-driven round-trip).
- [x] 8d-4 Helm/Kustomize CRD bundle serves both versions; samples default
v1beta1. - [x] 8d-5 UPGRADE.md migration guide + API_STABILITY graduation checklist sync;
v1beta1 validating admission (deprecated
attributeswarnings, referential checks). - [x] 8d-6 e2e: apply
v1alpha1→ upgrade CRDs → object converts → reconcile green. - [x] Exit: tagged minor
v0.12.0— 8d-5 and 8d-6 complete; optional etcd storage flip tov1beta1hub after e2e proof deferred.
Phase 9 — MQ surface depth (resequenced from Phase 5)¶
- [x]
SSLPEERMAPkind e2e (AUTH-5b) — #46 @b82e809; mirrors AUTH-4 USERMAP e2e. - [x]
QMGRMAPCHLAUTH —remoteQueueManager/mcaUserCRD fields, mqrest SET/DISPLAY/DELETE, reconciler + drift, Docker integration + kind e2e (AUTH-6). - [x] Observe-only auth e2e —
ChannelAuthRulewithdrift-policy=observe-onlyreports drift without SET on MQ (AUTH-7). - [x]
SSLPEERMAPCHLAUTH —sslPeerName/mcaUserCRD fields, mqrest SET/DISPLAY/DELETE, reconciler + drift, Docker integration (AUTH-5a). - [x]
USERMAPCHLAUTH —clientUser/mcaUserCRD fields, mqrest SET/DISPLAY, reconciler + drift (AUTH-3b), Docker integration (AUTH-3a #42), kind e2e (AUTH-4 #43). - [x] AuthorityRecord channel/namelist profile parity with queue profiles (AUTH-9).
- [x] BLOCKADDR integration + e2e coverage (AUTH-1/AUTH-2) — #40 Docker integration, #41 kind e2e.
- [x]
SDRsender channel —connName/xmitQueueCRD fields, mqrest SET/DISPLAY/DELETE, reconciler + drift, Docker integration (AUTH-8a #63), kind e2e (#66 Day 31). - [x]
RCVRreceiver channel — mqrest SET/DISPLAY/DELETE, reconciler + drift, Docker integration (AUTH-8b #64), kind e2e (#66 Day 31).
Exit criteria: CHLAUTH breadth (USERMAP/SSLPEERMAP/QMGRMAP/BLOCKADDR), SDR/RCVR
channels, AUTHREC channel/namelist profile parity, and kind e2e for new surface —
met (v0.11.0, #62–#66). Extended CHLAUTH rule types remain in Phase 5 backlog.
Later / candidate work¶
- PCF adapter behind
MQAdmin— parked per the 2026-06-09 note in ADR-0017: implemented only if a concrete no-mqweb adopter commits. Scaffold stays as the compile-time contract check. - Multi-tenancy / governance boundary (
MQProject-style allowlists, MKR-09) andQueueSet-style generators (MKR-12) — evaluate on demand signal only. - Property-based tests for MQSC/attribute reconciliation (MKR-10,
pgregory.net/rapid): idempotency and determinism properties. testcontainers-gofor the Docker MQ integration tier (MKR-07) — prototype and compare flake/runtime before replacinghack/mq-docker.- OpenTelemetry tracing
Reconcile → mqweb(MKR-08 tail). - Commit generated
docs/schemas/mqweb-swagger.jsonper target MQ version. - [x] Admission: envtest assertion for unknown-attribute warnings (Queue, Topic,
Channel) via
internal/webhook/v1alpha1/suite_test.go. - [x] e2e Helm deploy path (
KURATOR_E2E_DEPLOY=helm,task test:e2e:helm) — CI jobe2e (helm)onmainpush andworkflow_dispatch(e2e.yaml). - [x] Runtime cleanup: migrated to
mgr.GetEventRecorder(events.k8s.io API).