Skip to content

Latest commit

 

History

History
219 lines (195 loc) · 15.2 KB

TODO.md

File metadata and controls

219 lines (195 loc) · 15.2 KB

TODO

The open work, in one list. Each item is one or two lines with a code pointer or the design page that argues it. Ranked within each group, most urgent first. Before the next release marks what should land before the next tag is cut (the last release is v0.53.0). Checked against main at 1bc97904 on 2026-10-24.

Before the next release

Nothing open. The 0.54.0 release PR's changelog was checked against what ships on 2026-10-24.

Applier claims and bi-directional editing

  • Reopen the render-fidelity gate after a Git repair, automatically. Today a target on RenderMatchesLive=False clears only on an explicit recheck (the reconcile.configbutler.ai/requestedAt annotation, which restarts every scope; the render fidelity e2e spec proves it recovers a repaired folder), a re-declaration or a restart. Doing it on an incoming Git revision is more than calling Invalidate and RequestRecheckForGitTarget from a new place: it first needs the retained-intent ordering barrier, so the source refresh cannot discard or race an open commit window or pending live edits (render-fidelity.md §6b).
  • Watch the held applier, so a switch-on or a flux resume is undone at once instead of within the one-minute heldClaimSteadyInterval. Also makes apply_claimed_resource_reconciled_total (ask #31) count at the moment of the resume. applier-claim-held-applier-watch.md.
  • F3: a Flux fetch is made before the hold is checked, so a Kustomization resumed by hand applies the fetched artifact at once (internal/applier/flux.go, Request).
  • The apply window's remaining clock limits (internal/git/apply_window.go, file comment). A server clock ahead by more than the time between an earlier apply and the send dates an undo of an edit published before the send after it, so the undo is not mirrored and the next apply reverts it. With an edit carried from the window before, the check against the send still mixes the two clocks, and a server clock behind can withhold this attempt's own apply and ask for an unneeded Repair. Only comparing the event's content with Git separates them.
  • F-h: small leaks and races. The 5-minute hold can restart; the Initial flag races settlement; snapshotHeldSince, applierState.named and dropped collections in settledSnapshots leak.
  • Check Argo CD sync windows in Configured. The guide says a sync window must not block GitOps Reverser's syncs; nothing checks it.
  • Refuse or flag overrides that are not in Git (Argo spec.source.kustomize; Flux spec.images, patches, targetNamespace): they change what is applied where the fidelity check cannot see. applicationMismatch checks only repo and revision. Needs a decision; render-fidelity.md §8.
  • One holder per applier across KubeProviders (cluster identity or an object-local stamp). idea-applier-claim-ownership.md.
  • A targeted review of internal/applier/. CodeRabbit skipped #420 (over its 100-file limit), so the largest new package has had no bot review.
  • Later: claim an Argo CD ApplicationSet (idea-argocd-applicationset-claim.md); a webhook applier, a third claim kind (apply-trigger.md, "Where this goes next").

The gitops-api team's asks

Their argument for each is in gitops-api-open-asks.md.

  • #34: an e2e with an in-cluster applier and a remote source cluster, provoking one apply window collision.
  • #10: consider the namespace when placement follows siblings. Cosmetic.
  • #28 (two instances sharing one cluster) is deferred, not open work: one instance serving many namespaces is the tenancy model, and the restart cost behind the ask is the durable queue's.

Attribution

  • Option F: stop waiting for a fact a (route, type) has never produced. A removal on a type the audit policy drops spends the full grace for nothing. attribution-removal-wait-options.md.
  • Release attribution per object, not per watch (head-of-line). One slow lookup delays every later event on its stream. Before relying on per-object order, check three places: the watch cursor may advance only to the oldest unreleased event; the producerGate handoff on retire and replace, and the snapshot-before-live boundary; and the apply window, which classifies an edit by when it reaches the worker. The ordering spec.
  • Two doc sentences: no condition detects an API server's 30s default --audit-webhook-batch-max-wait (say so in the KubeProvider docs), and a relist after a watch gap ships its changes as the configured author (say so in the operator docs).
  • Optional: capture CommitRequest authors without Redis in single-pod mode, with an in-memory CommandAuthorStore. The only thing that still forces Redis on one replica. Low priority, and only useful until HA.

Branch worker and CommitRequests

  • expireWaitingCommitRequests ranges over a map, so empty commits for saves that expire in the same pass land in random order; sort by seq (internal/git/commit_request_attach_loop.go).
  • buildRequestRecordWrite keeps only the username (UserInfo{Username: pcr.author}); carry the full UserInfo so a record commit has the same author identity as a window commit.
  • A record commit skips requestTemplate, though its doc comment says it is phrased like every other commit; fix the code or the comment.
  • Nits: a doubled doc comment on commitWindowFor; "close-delay" in the test names in internal/controller/commitrequest_kstatus_test.go.
  • Parent observation, step 1: keep parent availability and its timestamp after the write branch exists, from existing advertisements, with no extra connections. gittarget-parent-observation.md.
  • Finish making a GitTarget turn red quickly and say why no commit was made: the broader reason and status contract table remains. gittarget-red-status-plan.md.
  • Transition boundary in the branch worker, the prerequisite for the durable queue. branch-worker-event-model.md.
  • Make the worker queue durable, and advance the watch cursor only after a durable worker acknowledgment. Today a crash after cursor advancement and before the write lands in Git can skip work on restart.
  • High availability: leader or ownership coordination so two replicas never write the same GitTarget, plus the durable queue, plus whether a replica warms its fact index before starting a watch it took over. Redis becomes required in this mode. ha-gittarget-distribution-plan.md.
  • Re-assess unifying the pending-write kinds (idea-unify-pending-write-kinds.md, now four kinds, not two). Deferred.
  • Improve queue and worker observability, with more high-load tests.

Watch plane

  • Subscribe the watch plane to typeset.Registry lifecycle events. Registry.Subscribe has no production observer, so nothing sweeps the manifests of an uninstalled CRD, and since #419 the operator asks Flux or Argo CD to apply that folder. Its consumer is the stop classification in target-watch-plan.md, "What a collection leaving means".
  • Pin with a test that an unforced retention pass keeps a scope's revision, so only Invalidate re-issues one (internal/git/render_fidelity_gate.go), and close the retention revision-mismatch question in watch-plane-status-convergence-failures.md §3.
  • Filter more cluster-generated noise, such as kube-root-ca.crt; decide which objects and whether a user can opt back in (resource_policy.go is a type-level denylist only).
  • A manifest whose CRD is missing refuses the whole folder (IssueUnresolvedKRM, manifestanalyzer/acceptance.go): keep that, or defer only that document. The scan already records unresolved-mapping instead of failing.
  • Decide whether the settle window should be configurable (settleWindow 2s, maxSettleWait 10s in internal/watch/owner.go). Revisit only on a report that config changes feel slow.
  • Reduce duplication between the WatchRule and ClusterWatchRule code paths where it makes sense.
  • Later: a namespace selector in a KubeProvider grant's scope (idea-source-namespace-selector.md).

Support boundary and Git content

  • Scalar strategic-merge patch authoring: an env var or a limit edited in one overlay is still refused, and since #419 the user sees the edit reverted. Decide "we author patches", then about two weeks. patch-authoring.md.
  • Decide how SOPS rules cover sensitive custom resources that are not Secret-shaped (fields such as spec.credentials): an explicit field policy, or full-file encryption.
  • Should comments survive a SOPS re-encrypt? (e2e Test C in e2e-coverage-gaps-and-improvements-plan.md).
  • Decide the three open layout questions in layout/model.md: nested roots per directory, refusing rather than reporting when a governing root disappears, and a CRD default for placement.default. (The fourth, a shared GitProvider, is answered by GitBranch and grants.)
  • Preserve more user-facing file structure: comments, ordering and other low-noise formatting.
  • Values Move 2, the editable values projection (values-file-projection.md).
  • Least privilege: never mirror Secrets, permission-aware followability, an RBAC generator (least-privilege-remaining-work.md).
  • Support-boundary gaps: the Generated{path} claim, Argo directory.exclude, paths written by ImageUpdateAutomation, the provenance and ownerReference gate, a Helm chart skipped as a unit, the Overlay-Diverged trailer.

E2E and CI

  • Fix the recurring full-e2e flakes around WatchRule and snapshot convergence (SOPS bootstrap, signing snapshot messages). Notes in the e2e serial registry. Address before the next feature that widens commit-message, snapshot or write-window behavior.
  • Run image-refresh only when its inputs change, a path filter in ci.yml; it removes a 14–18 minute leg from most PRs. e2e-suite-trim.md.
  • F-f: E6 can leak its editing goroutine: close(stop) runs only after the Eventually succeeds. Use DeferCleanup (test/e2e/bi_directional_echoes_e2e_test.go).
  • The e2e detail gaps and redundancy tables in e2e-suite-trim.md: four specs that look tested and are not, then the moves and merges.
  • SetDefaultEventuallyTimeout is global and set in 17 e2e files, so the last Describe body built wins; use per-spec timeouts (Eventually(...).WithTimeout).
  • e2e Test A: a delete missed while the controller is scaled to 0; then Tests B and C. e2e-coverage-gaps-and-improvements-plan.md.
  • Re-enable goconst with a path-scoped exclusion (test/, internal/git/commit.go) instead of the repo-wide disable in .golangci.yml.
  • Release-image reuse PRs 2, 3 and 5 (release-image-reuse-plan.md).
  • Metrics Phase 5: dashboard JSON, recording and alert rules (metrics-observability-plan.md §7).
  • Use bestpractices.dev as a maturity checklist, and turn the useful items into concrete work.

Docs and vocabulary

Future directions

  • A Writable condition on GitProvider. A push session that sends nothing proves the server opens one for the credential, not that a write is accepted (branch protection and pre-receive hooks apply at ref update), so a green probe is necessary and not sufficient. False only on an explicit refusal; a failed probe never clears a proven denial. Gating Ready on it is a separate release. (GitBranch now opens a push session before it holds a branch, which covers part of this.)
  • Simpler setup flows, including more Git provider bootstrap automation.
  • Constrained reverse actions for simple, known Kustomize-style mutations.
  • Better branching and promotion strategies.

Research: