rastrillo / fiesta Public

_headers for CARLOS: releases a year, /1/ five minutes, hashed assets immutable; red then green open

On branch fiesta-1-1

Implementer: Claude Opus 5.5 (claude-opus-5-5), default reasoning setting.

Commits: b1e5fd0 (site.Build writes _headers), 326efa0 (the www test server applies it), 378b68d (the approved CHANGELOG line). Hub CI passed on 378b68d: gofmt, no-rastrillo, size, history and 50-suite@49, 49 of 49 shards, no FAIL lines.

What ships

site.Build now takes site.Rules{Redirects, Immutable} instead of variadic redirects. www.Rules(pages) supplies both, so fiesta site, the www tests and the cmd test can't keep one and drop the other. The built _headers has 24 paths, 3,278 bytes, and its longest line is 71 characters:

  • /1/*: public, max-age=300, Access-Control-Allow-Origin: *, Cross-Origin-Resource-Policy: cross-origin.
  • /1.0.0/* and /1.1.0/*: public, max-age=31536000, immutable and the same two cross-origin headers.
  • 21 hashed gallery assets under /design-system/assets/, each listed exactly: a year and immutable, with no CORS headers.
  • Everything else has no rule, so it keeps no-cache.

gallery.Fingerprinted lists a hashed name only when its plain twin sits beside it with the same bytes. A name that only looks hashed is not listed.

Build refuses each of these with a message:

  • more than 90 paths: it says to give the hashed assets a directory of their own, or to ask CARLOS for a higher limit
  • a line over 2,048 characters
  • any header outside the five the edge allows, or a value the edge refuses
  • an immutable address that is not a page, or that holds :, *, %, ?, # or white space
  • a page named _headers

Red, then green

The first red run used a stub: Build wrote no _headers and Fingerprinted returned nothing.

--- FAIL: TestOneServesTheNewestOneX            the site holds 13 files, want 14
--- FAIL: TestPagesCannotShadowAVersion/_headers Build accepted the page _headers
--- FAIL: TestTheHeadersCacheAReleaseForAYearAndAMajorForMinutes  _headers is "" (want the whole file)
--- FAIL: TestANewReleaseAddsItsOwnHeadersRule  with 1.0.0, _headers names ; want /1/* /1.0.0/*
--- FAIL: TestAnImmutableAddressMustBeAPage     Build accepted the immutable address "/a/missing.css" (and 9 more)
--- FAIL: TestTheHeadersStopShortOfTheEdgesLimit Build wrote 91 paths into _headers
--- FAIL: TestTheHeadersSetOnlyWhatTheEdgeAllows Set-Cookie: a=b was accepted; the edge refuses it (and 8 more)
--- FAIL: TestFingerprintedNamesTheHashedTwinsOnly Fingerprinted is [] want [3 names]
--- FAIL: TestTheSitesHeaders                    the site has no _headers

The second red run used the old test server, with the handler commit stashed and the new tests kept:

--- FAIL: TestTheSitesHeaders/served_as_the_edge_serves_them
    /1/fiesta.css gets Cache-Control "no-store"; want "public, max-age=300"
    /1.1.0/fiesta.css gets Cache-Control "no-store"; want "public, max-age=31536000, immutable"
    /_headers answers 200; the edge never serves it
--- FAIL: TestServeSiteSendsHeadersLikeTheEdge
    GET /1/fiesta.css: 200, Cache-Control "no-store" ...; want ["public, max-age=300" "" "*"]
    GET /gone/x: 404, Cache-Control "no-store" ...; want 404 ["" "" ""]

Green, run locally:

  • go test ./internal/site ./internal/www ./cmd/fiesta ./internal/gallery -run Fingerprinted
  • the root package, with the role tests, TestVersionIsTheChangelogsNewestRelease and the release tests
  • -tags browser ./internal/www, in 305s
  • staticcheck on the touched packages

Each mutation below was applied, failed, and was reverted:

| | Mutation | Fails | |---|---|---| | M1 | releases get five minutes | TestTheHeadersCache..., TestTheSitesHeaders/exactly, /immutable | | M2 | /M/ gets a year | TestTheHeadersCache..., TestTheSitesHeaders/exactly | | M3 | plain assets listed too | TestFingerprinted..., TestTheSitesHeaders/exactly | | M4 | any name with two dots listed | TestFingerprinted... | | M5 | www.Rules drops Immutable | TestTheSitesHeaders/exactly (21 missing rules) | | M6 | stop at 100 instead of 90 | TestTheHeadersStopShortOfTheEdgesLimit | | M7 | any origin accepted | TestTheHeadersSetOnlyWhatTheEdgeAllows | | M8 | any header name accepted | TestTheHeadersSetOnlyWhatTheEdgeAllows | | M9 | no line limit | TestTheHeadersStopShortOfTheEdgesLimit | | M10 | immutable address not checked against the pages | TestAnImmutableAddressMustBeAPage | | M11 | CORS headers on the hashed assets | TestTheHeadersCache..., TestTheSitesHeaders/exactly | | D1 | headers on every status | TestServeSiteSendsHeadersLikeTheEdge (/gone/x 404) | | D2 | rules matched after the rewrite | TestTheSitesHeaders/served (/1/fiesta.css immutable), TestServeSite... | | D3 | _headers served as a file | both | | D4 | first rule wins | TestServeSiteSendsHeadersLikeTheEdge | | P1 | parser mirror takes any header | TestServeSiteRefusesAHeadersFileCarlosWouldRefuse | | P2 | parser mirror takes any origin | the same |

Validation with CARLOS's own code

carlos v0.31.1 cannot validate a static tree without shipping it:

  • carlos ship --check is for rootfs images only.
  • carlos vet checks a release that has already shipped.

Instead I ran edge.PackDir, the function carlos ship --kind static calls, together with parseHeaders and lookup. They ran from a carlos/platform checkout whose internal/edge is identical to v0.31.1. The test file was added with go test -overlay, so nothing was written to that checkout. The tree was fiesta site -releases releases -site site at 378b68d.

PackDir(.../site/public): ok
parseHeaders: 24 rules
/1/fiesta.css                                        map[Access-Control-Allow-Origin:[*] Cache-Control:[public, max-age=300] Cross-Origin-Resource-Policy:[cross-origin]]
/1.1.0/fiesta.css                                    map[Access-Control-Allow-Origin:[*] Cache-Control:[public, max-age=31536000, immutable] Cross-Origin-Resource-Policy:[cross-origin]]
/1.0.0/i18n/es.json                                  map[Access-Control-Allow-Origin:[*] Cache-Control:[public, max-age=31536000, immutable] Cross-Origin-Resource-Policy:[cross-origin]]
/design-system/assets/gallery.fc83762b4ec7573c.css   map[Cache-Control:[public, max-age=31536000, immutable]]
/design-system/assets/gallery.css                    map[]
/design-system/                                      map[]
/index.html                                          map[]
/static/site.css                                     map[]
--- PASS: TestZZFiestaSiteTree (1.35s)

Nothing was shipped.

Decisions

  • The test server applies _headers. It parses the file with a mirror of the edge's grammar, sends no-cache and then the matching rules on 200s only, and never serves either rules file. The browser drives still get no-store, so a second load reaches the handler and Delay and Seen see it.
  • The _redirects limit test changed. _headers now stops a site at 45 majors, so the test can no longer build 2,000 majors. It reaches 2,000 _redirects rules through the pages' rules instead.
  • No release rebuild. CHANGELOG.md is not embedded or copied into any release or page, so releases/1.1.0 is unchanged.