Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .coverage-baseline
Original file line number Diff line number Diff line change
@@ -1 +1 @@
75.2
75.3
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Stage 1: CI base image with essential build tools
# Pinned by digest (Scorecard "pinned dependencies"); Dependabot's docker
# ecosystem keeps version + digest current together.
FROM golang:1.26.4-bookworm@sha256:b305420a68d0f229d91eb3b3ed9e519fcf2cf5461da4bef997bf927e8c0bfd2b AS ci
FROM golang:1.26.5-bookworm@sha256:18aedc16aa19b3fd7ded7245fc14b109e054d65d22ed53c355c899582bbb2113 AS ci

# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Build the manager binary
# Base images are pinned by digest (Scorecard "pinned dependencies");
# Dependabot's docker ecosystem keeps version + digest current together.
FROM golang:1.26.4@sha256:f96cc555eb8db430159a3aa6797cd5bae561945b7b0fe7d0e284c63a3b291609 AS builder
FROM golang:1.26.5@sha256:079e59808d2d252516e27e3f3a9c003740dee7f75e55aa71528766d52bcfc16a AS builder

# Automatic platform arguments provided by Docker BuildKit
ARG TARGETOS
Expand Down
6 changes: 6 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ func main() {
// The registry is a stable pointer the watch manager refreshes in place.
workerManager.SetMapper(watchMgr.TypeRegistry())

// Give the workers a way to surface a refused live write plan. Live events are committed
// off a timer with no result channel, so without this a refusal (acceptance gate or a
// write-boundary precondition) would abort the commit and leave the GitTarget looking
// healthy; the resync path already reports its own refusals through the router.
workerManager.SetPathRefusalReporter(watchMgr.ReportGitPathRefusal)

// WatchRule controller (with WatchManager reference for dynamic reconciliation)
fatalIfErr((&controller.WatchRuleReconciler{
Client: mgr.GetClient(),
Expand Down
19 changes: 16 additions & 3 deletions docs/design/gitops-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,13 @@ The scoping move that keeps this launchable: **F2 + F4 are day-one
Kustomize support; F3 is the deferred hard part.** Adding overlay-local KRM
and bumping governed versions do not need patch authoring. A per-environment
edit of a base-owned *field* (the `kubectl set env` case) has no destination
until F3 — at launch it is honestly reported as unreflected and reverted by
hydration
until F3. Today such an edit is *prevented* — the write-boundary preconditions
refuse it and fail the GitTarget (`WriteBoundaryRefused`), so it is never written
into the base. Turning that target-level refusal into a per-edit report,
reverted by hydration and never silently lost, is the **designed but unbuilt**
unreflected-set accounting
([unreflectable-edits-and-write-gating.md](unreflectable-edits-and-write-gating.md)),
never silently lost. Tier-2 metrics on how often users hit that wall are
a launch prerequisite. Tier-2 metrics on how often users hit that wall are
exactly what prices F3.

## Feature ladder
Expand Down Expand Up @@ -150,6 +153,16 @@ base"), and the mirror-mode vs. intent-cluster topology — live in
surface with terminal `Pushed=True` + SHA.
- Refusals: unsupported kustomize features, duplicate identities, impure or
foreign content — refuse-first, never mis-edit.
- The two-layer **write boundary**, enforced as write-plan preconditions before
any byte is written: **L1** — no write leaves `spec.path` (reads may, writes
never); **L2** — no in-place edit of a source file that more than one kustomize
render path reaches with override entries at stake (write-fan-in = 1). A
violation aborts the whole flush, commits nothing, and fails the GitTarget with
`GitPathAccepted=False` / reason `WriteBoundaryRefused` — on the live-event path
as well as on resync. Specified in
[gittarget-granularity-and-cross-environment-edits.md §1](gittarget-granularity-and-cross-environment-edits.md).
The refusal is target-level; the per-edit `FullyReflected` accounting that would
name each dropped edit is designed and unbuilt.
- Higher-level KRM documents (Flux `HelmRelease`, Argo CD `Application`, KRO
resources) mirror and edit exactly like core resources — the pipeline is
kind-agnostic, now pinned by F7's corpus + HelmRelease e2e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ component is applied to its supplier:
Distinct chains from multiple roots emit an `ambiguous-kustomize-overrides`
diagnostic and fall back to today's write-through (no behavior regression;
F2's render-root scoping resolves this case properly).

> **Superseded (Track-1 write boundary).** The write-through fallback is gone.
> A planned write into a file flagged `ambiguous-kustomize-overrides` now
> refuses the flush (`write-fan-in`) and fails the GitTarget with
> `WriteBoundaryRefused`; nothing is committed. See
> [../gittarget-granularity-and-cross-environment-edits.md §1](../gittarget-granularity-and-cross-environment-edits.md).
> F2 render-root scoping still generalizes the check.
3. **Acceptance tightens only for garbage.** A kustomization whose `images:`
or `replicas:` value is present but not structurally parseable (not a list
of maps, missing `name`, non-string image fields, non-integer count) is
Expand Down
Loading