Skip to content
Closed
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
4 changes: 4 additions & 0 deletions sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://fosterstack.com/verify-a-release/</loc>
<lastmod>2026-10-08</lastmod>
</url>
</urlset>
162 changes: 162 additions & 0 deletions verify-a-release/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Verify a FosterStack Cache release yourself: signed at every stage</title>
<meta name="description" content="DRAFT-HOLD v0.3.0 draft: how to check each stage signature, provenance, SBOM, dependency provenance and the inputs manifest of a FosterStack Cache release.">
<meta name="robots" content="noindex">
<link rel="canonical" href="https://fosterstack.com/verify-a-release/">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<style>
:root {
--bg: #ffffff; --fg: #16181d; --muted: #5b6472; --line: #e4e7ec;
--accent: #0d7a5f; --accent-fg: #ffffff; --card: #f6f8f9; --warn-bg: #fff7ed; --warn-line: #fdba74;
--mark: #0f4d66;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #101318; --fg: #e8eaf0; --muted: #98a2b3; --line: #262c36;
--accent: #2fbf95; --accent-fg: #08110e; --card: #171c23; --warn-bg: #241a10; --warn-line: #7c4a12;
--mark: #e8eaf0;
}
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg); color: var(--fg);
font: 16px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
-webkit-font-smoothing: antialiased;
}
main { max-width: 44rem; margin: 0 auto; padding: 0 1.25rem 4rem; }
header.site { max-width: 44rem; margin: 0 auto; padding: 1.25rem; display: flex; align-items: baseline; gap: .6rem; }
.logo { font-weight: 700; font-size: 1.05rem; letter-spacing: -.01em; }
.logo span { color: var(--accent); }
.logo .mark { width: 1.2em; height: 1.2em; vertical-align: -.24em; margin-right: .4em; }
.tag { color: var(--muted); font-size: .85rem; }
.notice {
background: var(--warn-bg); border: 1px solid var(--warn-line); border-radius: 8px;
padding: .7rem 1rem; font-size: .92rem; margin: 1.5rem 0 2.5rem;
}
h1 { font-size: 2rem; line-height: 1.2; letter-spacing: -.02em; margin-bottom: 1rem; }
.lede { font-size: 1.12rem; color: var(--muted); margin-bottom: 2rem; }
h2 { font-size: 1.25rem; margin: 3rem 0 .9rem; letter-spacing: -.01em; }
p + p { margin-top: .8rem; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: .8rem; margin-top: 1rem; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 1rem 1.1rem; }
.card h3 { font-size: .98rem; margin-bottom: .35rem; }
.card p { font-size: .9rem; color: var(--muted); }
ul.trust { list-style: none; margin-top: .5rem; }
ul.trust li { padding: .45rem 0 .45rem 1.6rem; position: relative; }
ul.trust li::before { content: "✓"; position: absolute; left: .2rem; color: var(--accent); font-weight: 700; }
code, pre { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .88em; }
code { background: var(--card); border: 1px solid var(--line); border-radius: 5px; padding: .1em .35em; }
pre code { background: none; border: 0; padding: 0; color: inherit; font-size: 1em; }
button {
padding: .7rem 1.3rem; font-size: 1rem; font-weight: 600; cursor: pointer;
background: var(--accent); color: var(--accent-fg); border: 0; border-radius: 8px;
}
button:disabled { opacity: .6; cursor: default; }
table { width: 100%; border-collapse: collapse; font-size: .92rem; margin-top: 1rem; }
th, td { text-align: left; padding: .55rem .6rem; border-bottom: 1px solid var(--line); vertical-align: top; }
th { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
pre { background: #0f172a; color: #e2e8f0; padding: .9rem 1rem; border-radius: 8px;
overflow-x: auto; font-size: .9rem; line-height: 1.5; }
.cta-row { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: 1.1rem; }
.btn { display: inline-block; padding: .55rem 1rem; border-radius: 8px; font-weight: 600;
text-decoration: none; background: var(--accent); color: #fff; }
.btn-secondary { background: transparent; color: inherit; border: 1px solid #cbd5e1; }
.muted-note { color: var(--muted); font-size: .93rem; margin-top: 1.1rem; }
footer { border-top: 1px solid var(--line); margin-top: 4rem; padding: 1.5rem 1.25rem 3rem; }
footer div { max-width: 44rem; margin: 0 auto; color: var(--muted); font-size: .82rem; }
a { color: var(--accent); }
</style>
</head>
<body>
<header class="site">
<div class="logo"><svg class="mark" viewBox="0 0 96 96" aria-hidden="true" focusable="false"><rect x="12" y="14" width="72" height="18" rx="5" fill="var(--mark)"/><rect x="12" y="39" width="48" height="18" rx="5" fill="var(--mark)"/><rect x="12" y="64" width="26" height="18" rx="5" fill="var(--accent)"/></svg>foster<span>stack</span></div>
<div class="tag">Infrastructure worth keeping — and kept patched.</div>
</header>
<main>
<!--
DRAFT-HOLD. v0.3.0 version of /verify-a-release/. Do not merge until the first tag has been released
through the new four-stage chain (matrix rev 2: chunk 2 AC28 and AC49 trigger). Every command and every
v0.3.0-only claim below is marked TO-VERIFY and must be run against that release before the mark is removed
(AC25: the guide is tested, not only written). Rules from matrix AC26, AC47, AC48:
- say "signed at every stage, verified together at release"; no single sentence may join that with an L3 claim;
- claim SLSA Build L3 ONLY if the Build-stage test of dossier 2d.8 has passed, and only for the Build stage;
- no build-tool, package-distribution, signing-tool or scanner-product names except the commands a customer must
run by name (cosign, gh, jq): AC47 excludes none of them explicitly, so ask the advisor whether they are allowed
here (the v0.2.1 page already runs them by name);
- never "NIST compliant", "SLSA certified", "FIPS certified".
Length targets (AC24, AC27): this guide at most 500 words and at most 10 commands, the trust-boundaries section
at most 400 words. The draft below is over on commands because it is a working outline.
-->
<h1>Verify a FosterStack Cache release yourself</h1>
<p class="lede">Each stage of a release is signed on its own, and all the signatures are verified together before anything is published. This page shows how to check that yourself, with commands you run.</p>
<p><strong>Draft for the next release. <strong>[TO-VERIFY]</strong> marks anything not yet run against a real release.</strong></p>

<h2>1. Signed at every stage, verified together</h2>
<p>The release is built, rebuilt independently, checked and then authorized, and each stage signs a statement under its own identity. The release step verifies all of them together. The image is built from signed packages, with no base image.</p>
<pre><code># {TV}: identities, workflow names and the exact verify command per stage are not final.
$ cosign verify ghcr.io/fosterstack/cache:${VER} \
--certificate-identity-regexp=&quot;&lt;per-stage identity&gt;&quot; \
--certificate-oidc-issuer=&#x27;https://token.actions.githubusercontent.com&#x27;</code></pre>

<h2>2. About the exact digests</h2>
<p>Every statement names the image by digest, never by tag. The digest you verified is the digest in the release manifest, at both registries. <strong>[TO-VERIFY]</strong></p>
<pre><code># {TV}: manifest layout may differ from 0.2.1.
$ jq -r &#x27;.images[] | &quot;\(.variant) \(.digest)&quot;&#x27; release-manifest.json</code></pre>

<h2>3. Build provenance</h2>
<pre><code># {TV}: signer workflow and --source-ref for the new chain.
$ gh attestation verify oci://ghcr.io/fosterstack/cache:${VER} \
--repo fosterstack/cache \
--signer-workflow &lt;build-stage workflow&gt; \
--source-ref &quot;refs/tags/v${VER}&quot;</code></pre>
<p><strong>[TO-VERIFY]</strong> Say here, in one sentence, what the build-stage record covers. Make no SLSA level claim unless the matrix condition for it has passed.</p>

<h2>4. The SBOM</h2>
<pre><code># {TV}: file name, format and what the SBOM lists for an image with no base image.
$ jq &#x27;{{spdxVersion, name, packages: (.packages | length)}}&#x27; &lt;sbom file&gt;</code></pre>

<h2>5. Where the Go dependencies came from</h2>
<p><strong>[TO-VERIFY]</strong> <code>dependency-provenance.json</code> records where each vendored Go dependency came from and lets you re-derive it. Describe the file and the one command that re-derives or checks it.</p>
<pre><code># {TV}: command not defined yet.
$ &lt;check dependency-provenance.json&gt;</code></pre>

<h2>6. The inputs the image was assembled from</h2>
<p><strong>[TO-VERIFY]</strong> The inputs manifest lists every package the image was assembled from, by digest. Describe it and show the one command that checks it.</p>
<pre><code># {TV}: command not defined yet.
$ &lt;check the inputs manifest&gt;</code></pre>

<h2>7. Trust boundaries</h2>
<p><strong>[TO-VERIFY]</strong> TO-FILL, at most 400 words, from the build-system dossier (section 2c and 2d): for each stage, who holds which key or credential, and what a compromise of that stage can and cannot do. The owner explains it back in his own words before this section ships.</p>

<h2>What these checks do and do not prove</h2>
<ul class="trust">
<li>A valid signature proves who signed these exact bytes.</li>
<li>Provenance proves which workflow and run produced them.</li>
<li>None of it proves the software has no bugs. It proves the release is the one we built, the way we describe.</li>
</ul>

<p class="muted-note">Related: <a href="/how-we-build/">how releases are built and signed</a> and <a href="/security/">security policy</a>.</p>
<div class="cta-row">
<a class="btn" href="https://github.com/fosterstack/cache/releases">Releases on GitHub</a>
<a class="btn btn-secondary" href="/">FosterStack home</a>
</div>
</main>
<footer>
<div>
<p>FosterStack is not affiliated with, endorsed by, or sponsored by Gradle Inc.
"Gradle" and "Develocity" are trademarks of Gradle Inc., used here only to identify
compatibility. FosterStack contains no Gradle Inc. code; it is a clean-room implementation
of the documented remote build cache HTTP protocol. Apache Maven is a trademark of the
Apache Software Foundation; the Maven Build Cache Extension is Apache's project, not
ours.</p>
<p style="margin-top:.6rem">© 2026 FosterStack · <a href="/regulated/">For regulated markets</a> · <a href="https://github.com/fosterstack/cache">github.com/fosterstack/cache</a> · <a href="mailto:hello@fosterstack.com">hello@fosterstack.com</a></p>
</div>
</footer>
</body>
</html>
Loading