Rewrite changelog registry docs for scrubber Lambda ownership - #3761
Conversation
Phase 1 of elastic/docs-eng-team#688. The public registry.json was a log of upload operations (client-written, pass-through copied); every known consistency gap followed from that. The scrubber Lambda now derives it from the public bucket's actual state: registry = f(state), never f(event). - Extract the Lambda's top-level handler logic into testable classes in Elastic.Changelog: ScrubberProcessor (batch coalescing by key and group, object-level reconcile with post-write source validation) and RegistryReconciler (delimited/paginated group listing, ETag reuse with amends always recomputed, semantic idempotence, conditional PUT/DELETE with bounded jittered retries on 412/409, newer-schema refusal). Program.cs is now a thin adapter. - Retire the registry pass-through in the same deploy: registry-key events only schedule a group reconcile, so client-authored JSON no longer reaches the public bucket uninspected. - Add a producer (algorithm version) field to the manifest; a mismatch — including legacy pass-through manifests — forces a full metadata recompute and a write even when entries are identical. - Emit per-invocation reconcile metrics as CloudWatch EMF (the Phase 0 observability item that could only land with the reconciler). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 2 of elastic/docs-eng-team#688. The cutover/heal tooling for the
Lambda-owned public registry:
- `changelog registry reconcile` plans groups (one scope, or the union of
both buckets so orphan public groups are covered) and sends one versioned,
discriminated reconcile message per group to the scrubber queue —
{kind, version, scope, group, correlation_id}, validated through
ChangelogKeys on both ends. The CLI never mutates S3; the Lambda stays the
public bucket's single writer. --dry-run prints the plan; the non-dry-run
path asks for confirmation (--yes for CI). Each run stamps one correlation
id and prints a ledger line per group.
- On a reconcile message the Lambda performs a full group heal:
object-level reconcile over the union of both buckets' listings (copy
what's live, delete what isn't), then the group reconcile — recovering
lost/DLQ-expired scrub events. Requires the new optional
PRIVATE_BUCKET_NAME Lambda env var; malformed messages are rejected to
the DLQ where the Phase 0 alarm surfaces them.
- `changelog registry verify` is the read-only sibling and cutover gate:
compares each public manifest against what a reconcile would write (same
listing spec and entry rules by construction) and reports divergence as
missing/stale/corrupt/object-divergent, with unsupported schemas reported
distinctly.
- Fix the manifest ETag wire format: the snake_case policy serialized the
producer-side field as "e_tag" while consumers and the documented format
read "etag" — recorded ETags were invisible to every consumer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same suppression RegistryBuilderTests carries: xUnit owns the test class lifetime and TestDiagnosticsCollector needs no disposal in these tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The scrubber Lambda is the sole producer of the public registry.json, reconciled from public bucket state on the S3 events every upload already emits (elastic/docs-eng-team#688 Phase 3). Uploads now write YAML objects only; RegistryBuilder and the private-manifest write path are removed, and the amend end-to-end test exercises RegistryReconciler instead.
4cefbe5 to
cc65ecf
Compare
The registry docs still described the retired model: client-side refresh, registry pass-through, pre-scrub ETags, a 1 h CloudFront TTL (caching is disabled), and a refresh "skipped for --artifact-type changelog". Documents the reconciler as sole producer, the public-object ETag, convergence semantics, absent-vs-empty manifests, the reconcile message contract, and the registry reconcile/verify operator commands (docs-eng-team#688 Phase 4).
7af75b0 to
9bebf38
Compare
|
Converting to draft: these docs describe the per-product registry model that's being dropped per the review on #3738. I'll rewrite them once the thin folder→ETag registry shape lands there. |
95b64ed to
5695678
Compare
ba57fc6 to
31d19e6
Compare
The draft predated the #3738 review rework: RegistryReconciler is now BundleRegistryReconciler and reconciles the bundle/{product}/ tree only, the changelog/ pool manifests remain legacy client-authored pass-through (changelog bundle still enumerates pools through them, RFC #698 replaces that), the registry reconcile/verify operator CLI was dropped with #3741, and the scrubber now also maintains the shallow per-tree folder-to-token maps (consumer side: #3801). Infra bullets match the applied docs-infra#360 IAM (no registry-operator grant, no private ListBucket) and observability as it exists (metric stream to docs-o11y; alerts and runbook tracked in docs-eng-team#692).
|
Un-drafted and caught up with |
* Scrubber Lambda owns the public changelog registry via state reconcile Phase 1 of elastic/docs-eng-team#688. The public registry.json was a log of upload operations (client-written, pass-through copied); every known consistency gap followed from that. The scrubber Lambda now derives it from the public bucket's actual state: registry = f(state), never f(event). - Extract the Lambda's top-level handler logic into testable classes in Elastic.Changelog: ScrubberProcessor (batch coalescing by key and group, object-level reconcile with post-write source validation) and RegistryReconciler (delimited/paginated group listing, ETag reuse with amends always recomputed, semantic idempotence, conditional PUT/DELETE with bounded jittered retries on 412/409, newer-schema refusal). Program.cs is now a thin adapter. - Retire the registry pass-through in the same deploy: registry-key events only schedule a group reconcile, so client-authored JSON no longer reaches the public bucket uninspected. - Add a producer (algorithm version) field to the manifest; a mismatch — including legacy pass-through manifests — forces a full metadata recompute and a write even when entries are identical. - Emit per-invocation reconcile metrics as CloudWatch EMF (the Phase 0 observability item that could only land with the reconciler). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Add changelog registry reconcile and verify commands Phase 2 of elastic/docs-eng-team#688. The cutover/heal tooling for the Lambda-owned public registry: - `changelog registry reconcile` plans groups (one scope, or the union of both buckets so orphan public groups are covered) and sends one versioned, discriminated reconcile message per group to the scrubber queue — {kind, version, scope, group, correlation_id}, validated through ChangelogKeys on both ends. The CLI never mutates S3; the Lambda stays the public bucket's single writer. --dry-run prints the plan; the non-dry-run path asks for confirmation (--yes for CI). Each run stamps one correlation id and prints a ledger line per group. - On a reconcile message the Lambda performs a full group heal: object-level reconcile over the union of both buckets' listings (copy what's live, delete what isn't), then the group reconcile — recovering lost/DLQ-expired scrub events. Requires the new optional PRIVATE_BUCKET_NAME Lambda env var; malformed messages are rejected to the DLQ where the Phase 0 alarm surfaces them. - `changelog registry verify` is the read-only sibling and cutover gate: compares each public manifest against what a reconcile would write (same listing spec and entry rules by construction) and reports divergence as missing/stale/corrupt/object-divergent, with unsupported schemas reported distinctly. - Fix the manifest ETag wire format: the snake_case policy serialized the producer-side field as "e_tag" while consumers and the documented format read "etag" — recorded ETags were invisible to every consumer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Suppress CA1001 on ChangelogRegistryServiceTests Same suppression RegistryBuilderTests carries: xUnit owns the test class lifetime and TestDiagnosticsCollector needs no disposal in these tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Retire the client-side registry refresh from changelog upload The scrubber Lambda is the sole producer of the public registry.json, reconciled from public bucket state on the S3 events every upload already emits (elastic/docs-eng-team#688 Phase 3). Uploads now write YAML objects only; RegistryBuilder and the private-manifest write path are removed, and the amend end-to-end test exercises RegistryReconciler instead. * Rewrite changelog registry docs for scrubber Lambda ownership The registry docs still described the retired model: client-side refresh, registry pass-through, pre-scrub ETags, a 1 h CloudFront TTL (caching is disabled), and a refresh "skipped for --artifact-type changelog". Documents the reconciler as sole producer, the public-object ETag, convergence semantics, absent-vs-empty manifests, the reconcile message contract, and the registry reconcile/verify operator commands (docs-eng-team#688 Phase 4). * Align registry docs with the merged #3738 rework and #3760 The draft predated the #3738 review rework: RegistryReconciler is now BundleRegistryReconciler and reconciles the bundle/{product}/ tree only, the changelog/ pool manifests remain legacy client-authored pass-through (changelog bundle still enumerates pools through them, RFC #698 replaces that), the registry reconcile/verify operator CLI was dropped with #3741, and the scrubber now also maintains the shallow per-tree folder-to-token maps (consumer side: #3801). Infra bullets match the applied docs-infra#360 IAM (no registry-operator grant, no private ListBucket) and observability as it exists (metric stream to docs-o11y; alerts and runbook tracked in docs-eng-team#692). --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Why
Phase 4 of elastic/docs-eng-team#688. After Phases 1–3 the registry docs described a retired system: client-side refresh, registry pass-through everywhere, an ETag "documented as useless", a CloudFront "1 h TTL" that hasn't existed since caching was disabled, and a claim that the refresh was "skipped for
--artifact-type changelog".Note
Un-drafted 2026-08-13: the original draft predated the #3738 review rework, so it documented the dropped per-product operator tooling. It now documents the merged end state (#3738, #3760, docs-infra#360). The branch was brought up to date by merging
main; everything outsidedocs/resolves tomain, so the diff is docs-only.What
docs/development/changelog-bundle-registry.mdnow documents the end state:bundle/{product}/registry.jsonis produced solely by the scrubber Lambda'sBundleRegistryReconciler(registry = f(state)); thechangelog/{org}/{repo}/{branch}/pool manifests remain legacy client-authored pass-through —changelog bundlestill enumerates a pool through its manifest — until PR-list-driven discovery (RFC elastic/docs-eng-team#698) replaces them.producerfield (changelog-scrubber-reconcile/1, null on legacy manifests) andbundles[].etagas the public object's ETag, finally usable for CDN cache revalidation.bundle/registry.json,changelog/registry.json): folder → opaque digest token, cache opt-out only; consumer side tracked in Changelog CDN fetchers: skip unchanged folders via shallow registry maps #3801.registry reconcile/verifycommand pages were removed (Add changelog registry reconcile and verify commands #3741 closed unmerged); out-of-band drift repair rides the normal event path (--skip-etag-checkre-upload).ListBucketfor the Lambda) and observability as it exists today (SQS metric stream to docs-o11y; alert rules + runbook tracked in elastic/docs-eng-team#692).The scrubber README's event-handling section and
cmd-upload.md's registry paragraph are aligned with the same model.Part of elastic/docs-eng-team#688 (Phase 4).