From 0f8c419c51e5ab3844f795b5f6a7c5ba0c9b3965 Mon Sep 17 00:00:00 2001 From: Simon Koudijs Date: Fri, 4 Sep 2026 09:07:42 +0000 Subject: [PATCH] docs: close the API wave and placement-visibility issues, and drop three items #294 and #296 have shipped except for six small additive items, now tracked as one issue (#339). Three things that lived only in the docs are dropped rather than deferred, and every page that promised them says so: the corev1.Event on the GitTarget for a canonical fall-back (metric plus status.placement suffice), the TooManyStreams cap (the fan-out it bounded was deleted by #330; it was never in code), and the movable destination of consumer ask #6 (the destination stays immutable). Also retires the TODO entry for the scope field, which #333 removed. Co-Authored-By: Claude Fable 5.1 --- docs/INDEX.md | 4 +- docs/TODO.md | 27 ++++------- docs/design/gittarget-api-wave.md | 38 +++++++-------- docs/design/open-asks-priority.md | 48 +++++++++---------- docs/design/source-scope-simplification.md | 6 +-- ...ernetes-impersonation-and-flux-identity.md | 4 +- docs/layout/new-file-placement-rules.md | 9 ++-- 7 files changed, 61 insertions(+), 75 deletions(-) diff --git a/docs/INDEX.md b/docs/INDEX.md index 0d6719d5..361e55b5 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -116,8 +116,8 @@ so you never have to read a proposal to find out it already shipped. | Doc | Open question | |---|---| | [`open-asks-priority.md`](design/open-asks-priority.md) | **the work queue.** Merges three overlapping backlogs — the gitops-api consumer asks, the API-surface block left unbuilt by the status and configuration-model review, and the config-surface proposal (B1–B6) — into one ordered queue under four stated tests, and says where we deliberately do **not** do what was asked. The standing caveat narrowed once the layout model reversed: a Tier 2 entry belongs to postponed [#294](https://github.com/ConfigButler/gitops-reverser/issues/294) only if it breaks a `GitTarget` field, and everything else is independently schedulable. Makes one design call against what was asked: **delete Option C sibling inference** rather than ship an off-switch for it, because it let a human's edit to the repository change operator behavior with nothing in status recording the move. That deletion has shipped, and "what the deletion taught" records what building it found. **F9 is Tier 1**: the only item whose answer is unknown rather than whose work is unscheduled, and it gates planning the enum work | -| [`placement-visibility-and-declared-defaults.md`](design/placement-visibility-and-declared-defaults.md) | **design, half built.** The three questions the inference deletion left, decided and then built in two goes. PR #291 shipped the deletion and none of the eight items queued behind it; the residue was filed as [#295](https://github.com/ConfigButler/gitops-reverser/issues/295) — **which shipped in 0.42.1 via [#319](https://github.com/ConfigButler/gitops-reverser/pull/319) and is what reversed the layout model** — and [#296](https://github.com/ConfigButler/gitops-reverser/issues/296), whose largest half then shipped in [#326](https://github.com/ConfigButler/gitops-reverser/pull/326): `status.layout` became `status.placement`, and the ambiguous render root came with it as a refusal rather than a third counter outcome. The `declared` metric value has since split into `by_type`/`default` too, which was the one row with an external consumer because it changes a label a dashboard may select on. What still stands and is still unbuilt is the rest of the legibility set: the canonical path as a template constant, and `{kindLower}`. Its Question 2, a CRD default for `placement.default`, is **re-opened rather than superseded** and now lives as an open question in [`layout/model.md`](layout/model.md); the argument against it is legibility, since #319 removed the correctness objection | -| [`gittarget-api-wave.md`](design/gittarget-api-wave.md) | **partly built**, filed as [#294](https://github.com/ConfigButler/gitops-reverser/issues/294). One breaking wave on `GitTarget`, of which steps 2 to 7 have **shipped**: `spec.suspend`, `status.placement` and the reconcile-request annotation in [#326](https://github.com/ConfigButler/gitops-reverser/pull/326), and B4's `commitWindow`/`commit.message` move plus the source-scope deletion in [#330](https://github.com/ConfigButler/gitops-reverser/pull/330). Organizing principle: **the folder is described on the GitTarget, the connection describes only the connection** — and this is where that became a struct boundary rather than a sentence, since grouping a field is free only in a release that is already breaking. `spec.mode` and `GitTarget.spec.interval` are both **dropped**, with re-open triggers, and `status.lastHandledReconcileAt` was dropped in the build for a stated reason. What is left is **step 8, the riders** — asserted `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole, `meta.LocalObjectReference` for our six reference shapes, the `TooManyStreams` cap, the `default` `ClusterProvider` message — so #294 wants narrowing to those rather than closing. Also records that staying `v1alpha3` on loud rejections is a **one-consumer countdown**, and that the residue this pattern has actually left is one field: `ClusterWatchRule.spec.rules[].scope`, whose "removed one release from now" has stood since 0.39.0 | +| [`placement-visibility-and-declared-defaults.md`](design/placement-visibility-and-declared-defaults.md) | **design, half built.** The three questions the inference deletion left, decided and then built in two goes. PR #291 shipped the deletion and none of the eight items queued behind it; the residue was filed as [#295](https://github.com/ConfigButler/gitops-reverser/issues/295) — **which shipped in 0.42.1 via [#319](https://github.com/ConfigButler/gitops-reverser/pull/319) and is what reversed the layout model** — and [#296](https://github.com/ConfigButler/gitops-reverser/issues/296), whose largest half then shipped in [#326](https://github.com/ConfigButler/gitops-reverser/pull/326): `status.layout` became `status.placement`, and the ambiguous render root came with it as a refusal rather than a third counter outcome. The `declared` metric value has since split into `by_type`/`default` too, which was the one row with an external consumer because it changes a label a dashboard may select on. What still stands and is still unbuilt is the rest of the legibility set: the canonical path as a template constant, and `{kindLower}`, tracked on [#339](https://github.com/ConfigButler/gitops-reverser/issues/339) now that #296 is closed; the Event on the GitTarget was dropped. Its Question 2, a CRD default for `placement.default`, is **re-opened rather than superseded** and now lives as an open question in [`layout/model.md`](layout/model.md); the argument against it is legibility, since #319 removed the correctness objection | +| [`gittarget-api-wave.md`](design/gittarget-api-wave.md) | **partly built**, filed as [#294](https://github.com/ConfigButler/gitops-reverser/issues/294). One breaking wave on `GitTarget`, of which steps 2 to 7 have **shipped**: `spec.suspend`, `status.placement` and the reconcile-request annotation in [#326](https://github.com/ConfigButler/gitops-reverser/pull/326), and B4's `commitWindow`/`commit.message` move plus the source-scope deletion in [#330](https://github.com/ConfigButler/gitops-reverser/pull/330). Organizing principle: **the folder is described on the GitTarget, the connection describes only the connection** — and this is where that became a struct boundary rather than a sentence, since grouping a field is free only in a release that is already breaking. `spec.mode` and `GitTarget.spec.interval` are both **dropped**, with re-open triggers, and `status.lastHandledReconcileAt` was dropped in the build for a stated reason. What is left is **step 8, the riders** — asserted `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole, the `default` `ClusterProvider` message — tracked on [#339](https://github.com/ConfigButler/gitops-reverser/issues/339); #294 is closed. The reference collapse and the `scope` removal shipped in [#333](https://github.com/ConfigButler/gitops-reverser/pull/333); the `TooManyStreams` cap and the Event on a changed resolution were dropped. Also records that staying `v1alpha3` on loud rejections is a **one-consumer countdown** | | [`target-watch-plan.md`](design/target-watch-plan.md) | **partly built.** The diff is built and applied; removal semantics are not. The companion to [`watch-manager-ownership.md`](design/watch-manager-ownership.md): the ownership page says WHO applies a plan, this one says WHAT a plan is and what changing it may touch. A cell — group, resource, namespace, deliberately no served version — is the one identity the watch stream, the render-fidelity scope and the mark-and-sweep boundary all agree on, because a key that does not round-trip to the scope it sweeps under is the class of error that deletes user data. The plan is diffed into `keep`/`start`/`restart`/`stop` and applied per cell, so adding one WatchRule stops replaying every unrelated cell into a queue shared with other tenants; a `restart` is a served-version change, which is why the version is spec DATA rather than identity. Readiness and the fidelity revision are per scope, so a KEPT cell holds the result its own replay produced rather than being asked to prove itself again over an unrelated edit. `stop` never touches files — removal is a Git-side sweep under the target's existing `spec.prune.mode`, not a watch-layer delete. "Cut at the producer" is the accepted consequence: nothing fences the queue, so a deselected cell may leave a short tail of writes, bounded by the queue and converged afterwards. Still open: the `stop` classification wants a settled `TypeRemoved` from `typeset` (see TODO), and removal on INTENT is undecided. | | [`attribution-removal-wait-options.md`](design/attribution-removal-wait-options.md) | a removal now waits for evidence about the DELETION rather than accepting the object's last write, which stopped it naming whoever last edited the object as the author of a deletion they did not perform. Enumerates the eight situations a resolution can be in and shows the cost is concentrated in exactly one: a removal for which no delete fact will ever arrive (a graceful pod delete, a status-only removal, a type the audit policy skips) spends the whole grace to return the answer it had at t=0, measured at ~3.1s against ~70ms when evidence is present. Prices five options against that, and recommends a per-route watermark — stop waiting once the fact stream has demonstrably moved past this event — over a second timeout flag whose right value lives in the API server's config rather than ours. Open: the decision, and how common the case is outside the e2e suite | | [`watch-and-catalog-architecture.md`](design/watch-and-catalog-architecture.md) | the target three-layer watch model — **needs a human call before building** | diff --git a/docs/TODO.md b/docs/TODO.md index ce836257..1da4ca5b 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -83,25 +83,14 @@ This file is meant to track the smaller current backlog, not historical notes. `placement.default` (legibility only, since #319 removed the correctness objection), and a namespace-local `GitProvider` so three targets in three namespaces need not copy one credential. -- [ ] Remove `ClusterWatchRule.spec.rules[].scope`. It is the **whole** deprecation graveyard in the - CRDs: everything else this project has removed was removed outright, with - [`UPGRADING.md`](UPGRADING.md) as the migration. The field is retained purely so that re-applying - a manifest still saying `Namespaced` fails, and its own doc comment says "Removed one release from - now" — written for 0.39.0, and it has now stood through 0.40, 0.41 and 0.42. Delete the field, the - `DeclaresNamespacedScope` compile-path refusal that backs it, and the `Deprecated:` line in the - CRD. Breaking, so it wants a release that is breaking anyway; the reasoning is in - [`design/gittarget-api-wave.md`](design/gittarget-api-wave.md#version-strategy-stay-v1alpha3). - -- [ ] Build the riders that are all that is left of the `GitTarget` API wave - ([`design/gittarget-api-wave.md`](design/gittarget-api-wave.md), filed as - [#294](https://github.com/ConfigButler/gitops-reverser/issues/294), which wants narrowing to - them): an asserted `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole, - `meta.LocalObjectReference` for our six reference shapes, the `TooManyStreams` cap, and the - `default` `ClusterProvider` message. **Only the reference-shape collapse is breaking**, and it is - breaking in the quiet way: `GitProviderReference`, `ClusterProviderReference`, - `LocalSecretReference` and friends each carry a defaulted, enum-of-one `group`/`kind`, so every - stored object has those persisted and collapsing the shape prunes them with no error. It belongs - in a breaking release or in none. +- [ ] Build what is left of the `GitTarget` API wave and the placement-visibility set, tracked as + [#339](https://github.com/ConfigButler/gitops-reverser/issues/339): an asserted + `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole, the `default` `ClusterProvider` + message, the canonical path as a template constant, and `{kindLower}`. All + additive. The `scope` field, the reference-shape collapse and the metric split shipped in + [#333](https://github.com/ConfigButler/gitops-reverser/pull/333); the `TooManyStreams` cap, a + `corev1.Event` on the GitTarget for a canonical fall-back, and a movable destination were + **dropped**, with the reasons on that issue. - [ ] Reduce duplication between `WatchRule` and `ClusterWatchRule` code paths where it makes sense. diff --git a/docs/design/gittarget-api-wave.md b/docs/design/gittarget-api-wave.md index a8253c0e..b756a2a0 100644 --- a/docs/design/gittarget-api-wave.md +++ b/docs/design/gittarget-api-wave.md @@ -3,11 +3,12 @@ > **partly built**: a sequencing proposal. Steps 2 to 7 have all **shipped** — `spec.suspend`, > `status.placement` and the reconcile-request annotation in > [#326](https://github.com/ConfigButler/gitops-reverser/pull/326), B4 and the source-scope deletion -> in [#330](https://github.com/ConfigButler/gitops-reverser/pull/330) on 2026-09-01. **Step 8, the -> riders, is the only unbuilt member**, trimmed under this page's own rule; step 5 (an Event on a -> changed resolution) is additive and also unbuilt. What that leaves of -> [#294](https://github.com/ConfigButler/gitops-reverser/issues/294) is the riders alone, so the -> issue wants narrowing rather than closing. +> in [#330](https://github.com/ConfigButler/gitops-reverser/pull/330) on 2026-09-01, and the +> reference collapse in [#333](https://github.com/ConfigButler/gitops-reverser/pull/333). **Step 8, +> the riders, is the only unbuilt member**, trimmed under this page's own rule to three items. Step 5 +> (an Event on a changed resolution) and the `TooManyStreams` cap were **dropped**, not deferred. +> [#294](https://github.com/ConfigButler/gitops-reverser/issues/294) is closed; the riders are +> tracked on [#339](https://github.com/ConfigButler/gitops-reverser/issues/339). > Index: [`../INDEX.md`](../INDEX.md) > Date: 2026-08-28 (originally 2026-07-30). > @@ -33,7 +34,7 @@ |---|---|---| | **B4**: `commitWindow` and `commit.message` move off the connection | `GitProvider` → `GitTarget` | fields change object | | The source-scope deletion ([`source-scope-simplification.md`](source-scope-simplification.md)) | `GitTarget`, `ClusterProvider`, `WatchRule` | one removal, two renames, one redefinition | -| The riders: **#5** asserted `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole, `meta.LocalObjectReference` for our six reference shapes, the `TooManyStreams` cap, the `default` `ClusterProvider` message | various | shape changes | +| The riders: **#5** asserted `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole, the `default` `ClusterProvider` message; `meta.LocalObjectReference` for our six reference shapes shipped in #333 | various | shape changes | Additive, and therefore **not** wave members even though they are discussed here: `spec.suspend`, `status.placement` and the post-scan pass, the reconcile-request annotation, and the two placement @@ -148,14 +149,14 @@ review's central complaint: *this controller writes to a Git repository and ther it stop that is not deleting the object.* So `suspend` is not a rider here, it is a precondition — and it must stop bootstrap creation specifically, not only resource writes. -### 4. The Events question is answered by the recorder that shipped +### 4. The Events question is closed: no Event [`open-asks-priority.md`](open-asks-priority.md) left open whether a fall-back to canonical -should raise an Event, and reasoned it was expensive because placement runs on the branch worker with -no recorder. An `EventRecorder` now ships on every reconciler, and the roll-up seam projects -data-plane facts into status with an enqueue on change. So the Event is: emit when `status.placement` -changes in a way a human should know about — `LayoutResolved` becoming `Ambiguous`, or a type falling -back for the first time. One Event per persisted change, the pattern already established for `Ready`. +should raise a `corev1.Event` on the GitTarget. Decided against on 2026-09-04 +([#339](https://github.com/ConfigButler/gitops-reverser/issues/339)). The metric already names the +target and the exact `byType` key that is missing, and `status.placement` is the +durable record a bug report contains. A third surface for the same fact would be one more thing to +keep consistent, for a notification that is deduplicated and expires within the hour anyway. ### 5. The source-scope deletion is the only member that shrinks the API @@ -172,11 +173,10 @@ Two interactions worth naming, because they change what gets built rather than m you would do before you do it". They are separate conditions on separate objects and neither depends on the other, so the SAR work stays additive and can ship after the wave — but whoever writes the second should read the first. -- **`TooManyStreams` is sized by the `*` decision** +- **The `TooManyStreams` cap is dropped by the `*` decision** ([definition of record](source-scope-simplification.md#sourcenamespace--needs-its-own-decision)), - which removes the fan-out the cap was queued for. What is left to bound is explicit enumeration, - so the cap is still worth a `Stalled` reason and a bound — sized against enumerated rules, and not - planned before the `*` change lands. + which removes the fan-out the cap was queued for. Explicit enumeration is bounded by whoever + writes the rules; a cap on it would be a guard against a list a human typed. It was never in code. ### 6. Two facts kept from arguments that dissolved @@ -316,13 +316,13 @@ Dependencies first, then the things that only need the object to be breaking. write that already happened, rather than previewing one that has not. 4. **`requestedAt`.** On-demand refresh of step 3. Shipped without the `lastHandledReconcileAt` echo, for the reason recorded above. -5. **Events on a changed resolution**, over the existing recorder. +5. ~~**Events on a changed resolution**, over the existing recorder.~~ Dropped; see interaction 4. 6. **B4**, as `spec.commit`. Last of the principle items, and the one that makes the object coherent. 7. **The source-scope deletion.** Independent of every step above, so it can be written in parallel; placed here because a deletion reviews better once the additions it is not entangled with are settled. -8. **The riders.** `TooManyStreams` must come after step 7, which removes the fan-out it was written - to bound. +8. **The riders.** Three remain: `CommitRequest.spec.author`, the `CommitRequest` lifecycle hole and + the `default` `ClusterProvider` message. The `TooManyStreams` cap was dropped by step 7. Steps 2 to 5 are additive and need no bump. Steps 6 to 8 are one release; step 1 gates the planning; step 8 can be trimmed if the wave gets too big to review, since nothing else depends on it. The diff --git a/docs/design/open-asks-priority.md b/docs/design/open-asks-priority.md index 18c2537d..9645008a 100644 --- a/docs/design/open-asks-priority.md +++ b/docs/design/open-asks-priority.md @@ -13,9 +13,10 @@ > and #10 are gone**: the `permanent` doc comment was rewritten, the two encoders became one > (`internal/yamlstyle`, which is why a create and an update now emit identical bytes), and sibling > inference — the thing #10 was about — was deleted outright. What is left of the consumer list is -> **#15** (a declared `auditRoute` that has received zero facts should say so), **#23** (which actor -> deletion-as-intent picks when a controller clears a finalizer), and **#6** (a movable -> `GitTarget` destination), and of the wave, the riders. The tiers below have not been re-ordered +> **#15** (a declared `auditRoute` that has received zero facts should say so) and **#23** (which +> actor deletion-as-intent picks when a controller clears a finalizer); **#6** (a movable `GitTarget` +> destination) is **refused**, the destination stays immutable. Of the wave, three riders remain, +> tracked on [#339](https://github.com/ConfigButler/gitops-reverser/issues/339). The tiers below have not been re-ordered > against that; read them as the argument, and [`../TODO.md`](../TODO.md) as the queue. > > **Where this stands as of the sweep.** `0.41.0` is the attribution release: the fact stream, the @@ -197,10 +198,11 @@ and the word *Event* meant a real `corev1.Event` through later. Good enough for a durable condition, weak for a notification. Events are also deduplicated and expire (`--event-ttl` defaults to 1h), so an Event is never the record. -**The shape that follows is a split, not one of the three.** An **Event on the GitTarget** for -timeliness, over the existing refusal seam plus an enqueue; and **`status.layout` (B2)** for -durability, because "what the operator understood about this folder" is where someone looks a day -later. The log line stays. +**The shape that followed was a split**, an **Event on the GitTarget** for timeliness and +**`status.layout` (B2)** for durability. The durable half shipped as `status.placement`. **The Event +half was dropped on 2026-09-04** ([#339](https://github.com/ConfigButler/gitops-reverser/issues/339)): +with the metric naming the target and the missing key, a deduplicated, expiring third surface bought +nothing a reader could not already get. The log line stays. **What shipped, and where this paragraph was wrong.** A Prometheus counter was the one this document argued *against* leading with, on the grounds that `placement_fell_back_total` says it happened @@ -210,9 +212,8 @@ group, version, resource}` names the target and the exact `byType` key, so one s that is missing. It shipped with two companions the argument had not asked for and should have — `placement_refusals_total{reason}`, because a resource the writer *declined* to place had no countable trace at all, and `placement_kustomization_entries_total{outcome}`, whose `failed` value is -a file committed outside every render. The Event and `status.layout` are still the right split for -timeliness and durability, and neither is built; what is no longer true is that there was nothing -actionable in a metric. +a file committed outside every render. `status.placement` is built and carries the durable half; the +Event is dropped; what is no longer true is that there was nothing actionable in a metric. ### What the deletion taught @@ -258,7 +259,7 @@ and is not independently schedulable. | 5 | `CommitRequest.spec.author`, SAR-guarded | gitops-api (#220) | **2** | wave | | B4 | `commitWindow` / `commit.message` move to GitTarget | config surface | **2** | wave | | ~~B1~~ | ~~`GitTarget.spec.mode: Observe\|Write`~~ **dropped**: `suspend` already stops the writes, and `mode` buys only a declared posture over a pause | config surface | — | [`gittarget-api-wave.md`](gittarget-api-wave.md) | -| 6 | Movable destination via `status.observedDestination` | gitops-api (#220) | **2** | wave | +| 6 | Movable destination via `status.observedDestination` | gitops-api (#220) | **refused** | the destination stays immutable; a folder moves by delete-and-recreate | | F10 | CommitRequest TTL / ownerRef + the `delete` verb | maintainer review | **2** | wave | | n/a | The blocking resolve is head-of-line on the shard goroutine | [`../spec/attribution.md`](../spec/attribution.md#the-wait) | **2** | — | | B2 | `GitTarget.status.placement` (was `status.layout`) | config surface | **3** | [#296](https://github.com/ConfigButler/gitops-reverser/issues/296) | @@ -521,13 +522,12 @@ carry, and an aggregated-API create is logged with no name and no response body `#220` shape — honored only against an admission record carrying an authorized verdict, fail-closed independent of the webhook's `failurePolicy` — remains the right one, on the first argument alone. -**B4, #6, F10** as written in their source documents. **B1 has left the wave**: `suspend` already +**B4 and F10** as written in their source documents. **B1 has left the wave**: `suspend` already stops a target writing without deleting it, so `mode` buys only the difference between a pause and a declared permanent posture — a distinction in intent, not in behavior. The re-open trigger is in the wave -document. #6 is explicitly a lower priority than -when it was filed: the consumer downgraded it themselves, because branch and folder are now -chosen once per repository on an object that exists because the user picked that repository. -It rides the wave because it is in the wave, not because it is urgent. +document. **#6 is refused.** The consumer had already downgraded it themselves, because branch and +folder are chosen once per repository on an object that exists because the user picked that +repository; the destination stays immutable and a folder moves by delete-and-recreate. ### Tier 3: legibility @@ -561,13 +561,11 @@ bytes reach a mirror. One style authority for Git output, not one library for th after the inference deletion. `ambiguousDocuments` in particular is a correctness-relevant fallback that is currently a debug-level store diagnostic. -It also carries the durable half of the inference deletion's notification question, argued above: -**the Event says a fall-back to canonical happened, `status.layout` says what the operator -understood.** An Event is deduplicated and expires; a status field is what someone reads a day later, -and it is the only one of the two a `kubectl get -o yaml` in a bug report will contain. So the two are -not alternatives, and B2 should carry the per-target record of which types resolved by declaration and -which fell back — which is why this is worth doing in the same change as the deletion rather than -after it. +It carries the durable half of the inference deletion's notification question, argued above: +**`status.placement` says what the operator understood.** A status field is what someone reads a day +later, and it is what a `kubectl get -o yaml` in a bug report contains. The Event half is dropped, so +this is the record, and it carries the per-target statement of which types resolved by declaration +and which fell back. **B6** as filed: one error message that will otherwise be the most likely first-run support ticket. F9 has moved to Tier 1. @@ -607,8 +605,8 @@ defects. the reason to batch it was never only the consumer's bump, it was that four of the items are one decision and deciding it four times is how the object stops reading as one idea. 2. ~~A behavior change (inference removal) that needs its own UPGRADING entry and a decision on the - fall-back-to-canonical Event.~~ **Done for the removal and the entry**; the Event is still - undecided, and the metric now carries the actionable part in the meantime. + fall-back-to-canonical Event.~~ **Done for the removal and the entry**; the Event was decided + against, and the metric carries the actionable part. 3. ~~Rewriting Option C's sections in [`../layout/new-file-placement-rules.md`](../layout/new-file-placement-rules.md).~~ **Done**: the ladder is documented as three steps, the kustomize-root fallback keeps its section diff --git a/docs/design/source-scope-simplification.md b/docs/design/source-scope-simplification.md index dd4cb010..a0e4acda 100644 --- a/docs/design/source-scope-simplification.md +++ b/docs/design/source-scope-simplification.md @@ -177,9 +177,9 @@ silent empty set. right.** A `*` rule over a type in a hundred-namespace cluster is a hundred watch connections and a hundred list calls at warm-up today, one per namespace, each with its own cursor, its own retry schedule and its own share of apiserver watch cache. Cluster-wide makes it one of each, and the -saving grows with the cluster, which is exactly the direction the enumeration got worse in. The -`TooManyStreams` cap was queued for the fan-out this deletes; see -[`gittarget-api-wave.md`](gittarget-api-wave.md), where that rider is now smaller than it was. +saving grows with the cluster, which is exactly the direction the enumeration got worse in. A +stream-count cap had been queued to bound that fan-out; with the fan-out deleted, the cap was dropped +rather than resized ([`gittarget-api-wave.md`](gittarget-api-wave.md)). ## Consequences, including two breaking semantic changes diff --git a/docs/facts/kubernetes-impersonation-and-flux-identity.md b/docs/facts/kubernetes-impersonation-and-flux-identity.md index 7901a3eb..e5c4e58a 100644 --- a/docs/facts/kubernetes-impersonation-and-flux-identity.md +++ b/docs/facts/kubernetes-impersonation-and-flux-identity.md @@ -102,5 +102,5 @@ Recorded so the cost is not re-estimated: carry `system:serviceaccounts` and `system:serviceaccounts:` as groups or it answers narrower than reality. That needs `create subjectaccessreviews` on a credential users have already issued. -- Identity joins cluster, GVR, and namespace in the informer key, so it multiplies the resource the - `TooManyStreams` cap exists to bound. +- Identity joins cluster, GVR, and namespace in the informer key, so it multiplies the number of + informers a rule set opens, one per distinct identity. diff --git a/docs/layout/new-file-placement-rules.md b/docs/layout/new-file-placement-rules.md index 7131e005..56beb232 100644 --- a/docs/layout/new-file-placement-rules.md +++ b/docs/layout/new-file-placement-rules.md @@ -1452,11 +1452,10 @@ Integration/e2e tests: operator understood about the folder, and it expires with the scrape window. That is what `status.layout` (B2 in the config-surface doc) is for, and the two are complements: a status field is what a `kubectl get -o yaml` in a bug report contains. -- Whether the first canonical fall-back for a (target, type) should also raise a - `corev1.Event` on the GitTarget for timeliness. Placement runs on the branch worker, which - has no recorder and no reconcile context, so this is a hand-back over the existing - refusal→condition seam rather than a one-line addition — see the same section of - [`open-asks-priority.md`](../design/open-asks-priority.md). +- ~~Whether the first canonical fall-back for a (target, type) should also raise a + `corev1.Event` on the GitTarget for timeliness.~~ **Closed, no Event** + ([#339](https://github.com/ConfigButler/gitops-reverser/issues/339)): the metric names the + target and the missing key, and `status.placement` is the durable record. - Should the Validated gate learn about operator-configured *additional* sensitive types (beyond core Secrets) so a bundling `default` that could catch one is rejected up front, instead of relying on the write-time guards to skip those