You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pinned legacy source builds are byte-for-byte reproducible across separate clean workspaces and processes. This unblocks the generated-source freshness gate for Studio → Courses without weakening provenance or accepting a wall-clock/random-order snapshot.
Incident evidence
Independent #115 QA found scripts/build_pinned_legacy_sources.py --check stale after the current-main integration. Regenerating aligned the two checked artifacts only temporarily: two consecutive full builds changed them again.
The repeat-build delta is exactly 209 generated paths:
203 main-site podcast pages whose season JSON-LD endDate inherits the current build time from an undated collection item;
docs and podwiki feed.xml timestamps;
main-site sitemap.xml ordering; and
the three .rustkyll-manifest.json map orderings.
The affected builds use pinned Rustkyll 0.4.6 and 0.5.0 code paths. Local source inspection found no existing SOURCE_DATE_EPOCH or reproducible-build flag. Rustkyll uses Utc::now/Local::now in collection fallback dates, site.time, feed fallback, and future-post filtering; sitemap input and manifest maps originate from Rust HashMap iteration/serialization. The manifest also records source mtimes.
Required implementation
Rustkyll compatibility lanes
Add standard SOURCE_DATE_EPOCH support to compatible 0.4.x and 0.5.x releases/backports; do not force an unrelated renderer upgrade.
Parse the value once and fail closed on invalid, negative, overflow, or ambiguous input.
Thread one frozen UTC instant through collection default dates, site.time, empty-feed fallback, and future-post cutoff.
In reproducible mode, use UTC when the source has no explicit timezone; preserve an explicit configured timezone.
Sort final sitemap entries deterministically, root first and then lexicographically by final loc, without changing membership.
Canonically serialize manifest map keys. Preserve the manifest rather than excluding it from checked output.
Website wrapper
Derive SOURCE_DATE_EPOCH from each already-verified pinned commit's committer timestamp with an exact revision-bound git query.
Pass only the minimal deterministic environment to Rustkyll and record source-date-epoch=<value> in checked deterministic-override provenance.
Normalize copied tracked source-file mtimes to that same epoch before rendering so manifest values are stable across clean clones.
Reject missing, malformed, mismatched, or out-of-range revision/epoch/mtime data with bounded diagnostics.
Regenerate generated-path-baseline.jsonl and source-build-provenance.json only after deterministic rendering is proven.
Current pinned epoch reference values, to be independently derived rather than hard-coded as authority:
main: 1785872368
docs: 1786017922
podwiki: 1785736104
Acceptance criteria
Two full builds of every pinned source in separate fresh workspaces/processes are byte-identical for the complete generated trees and all checked artifacts.
A third full build followed by scripts/build_pinned_legacy_sources.py --check remains green without changing tracked bytes.
The exact generated path membership and route contract remain unchanged; main sitemap retains the same 811-URL multiset in documented deterministic order.
All 203 affected podcast pages retain valid JSON-LD shape with stable source-derived/frozen dates; docs/podwiki feeds have stable timestamps.
All three manifest files have stable key order and stable source-mtime values across clean clones.
Tests cover one frozen instant shared by every Rustkyll time consumer, invalid epoch inputs, explicit timezone behavior, deterministic sitemap membership/order, and canonical manifest serialization in both compatibility lanes.
Normal uv-backed compatibility/Django/quality/Playwright gates pass, with no secret, credential, private source row, or production mutation.
Process
This is a technical blocker for #115. Rustkyll changes require their own review/release evidence, after which website pins must be updated and the #115 candidate refreshed to current main before a new independent QA pass. Do not bypass the generator, post-process volatile output as an unexplained mask, or weaken the freshness check.
Parent: #115
Outcome
Pinned legacy source builds are byte-for-byte reproducible across separate clean workspaces and processes. This unblocks the generated-source freshness gate for Studio → Courses without weakening provenance or accepting a wall-clock/random-order snapshot.
Incident evidence
Independent #115 QA found
scripts/build_pinned_legacy_sources.py --checkstale after the current-main integration. Regenerating aligned the two checked artifacts only temporarily: two consecutive full builds changed them again.The repeat-build delta is exactly 209 generated paths:
endDateinherits the current build time from an undated collection item;feed.xmltimestamps;sitemap.xmlordering; and.rustkyll-manifest.jsonmap orderings.The affected builds use pinned Rustkyll 0.4.6 and 0.5.0 code paths. Local source inspection found no existing
SOURCE_DATE_EPOCHor reproducible-build flag. Rustkyll usesUtc::now/Local::nowin collection fallback dates,site.time, feed fallback, and future-post filtering; sitemap input and manifest maps originate from RustHashMapiteration/serialization. The manifest also records source mtimes.Required implementation
Rustkyll compatibility lanes
SOURCE_DATE_EPOCHsupport to compatible 0.4.x and 0.5.x releases/backports; do not force an unrelated renderer upgrade.site.time, empty-feed fallback, and future-post cutoff.loc, without changing membership.Website wrapper
SOURCE_DATE_EPOCHfrom each already-verified pinned commit's committer timestamp with an exact revision-bound git query.source-date-epoch=<value>in checked deterministic-override provenance.generated-path-baseline.jsonlandsource-build-provenance.jsononly after deterministic rendering is proven.Current pinned epoch reference values, to be independently derived rather than hard-coded as authority:
178587236817860179221785736104Acceptance criteria
scripts/build_pinned_legacy_sources.py --checkremains green without changing tracked bytes.--artifacts-onlyor an immediate--checkis not accepted as reproducibility proof because neither independently proves a clean full rebuild./cadminsource mappings, access matrix, current-main Import historical registration totals safely and show aggregate event counts #112/Recover fail-closed ECR manifest verification for active release capture #117/Ship real public content on the final editorial route map #105 behavior, CMP adoption, and public route inventory remain unchanged.Process
This is a technical blocker for #115. Rustkyll changes require their own review/release evidence, after which website pins must be updated and the #115 candidate refreshed to current main before a new independent QA pass. Do not bypass the generator, post-process volatile output as an unexplained mask, or weaken the freshness check.