Skip to content
Merged
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
5 changes: 5 additions & 0 deletions data/audit/catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,11 @@
"$type": "body",
"$description": "extracted prose — index.html"
},
"index.html#7cf0ba906692": {
"$value": "The hand-graded claims above are also published as a signed graph — claims.jsonld — each carrying its grade, its gap, and the evidence link, secured by the same build signature",
"$type": "body",
"$description": "extracted prose — index.html"
},
"index.html#7ff944b86a94": {
"$value": "Bounded Systems scopes that down",
"$type": "body",
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ <h2>Every claim here is graded against the running code.</h2>
<p class="honesty__stamp" style="font-family:var(--bs-font-mono);font-size:12px;margin:14px 0 0;color:var(--site-on-dark-mono);opacity:.85;letter-spacing:.02em;">
<!-- stamp:start -->graded against the latest commit<!-- stamp:end -->
</p>
<p class="honesty__lead" style="margin-top:18px;">Beyond the hand-graded claims, the build runs a battery of fail-closed gates: <a href="https://github.com/bounded-systems/lone">lone</a> blesses each rendered page's DOM for semantic HTML and accessibility, the JSON-LD is checked against SHACL shapes, an SPDX SBOM is generated and completeness-checked, a signed whole-site manifest and RFC&nbsp;9530 content digests cover the served bytes, and the nix build is reproducible. Each verdict folds into one honest <a href="/conformance">conformance projection</a> &mdash; lone's web-build model, which emits the strong WCAG&nbsp;2.2&nbsp;AA / OWASP&nbsp;ASVS claim only when every gating criterion passes, so manual and unsupplied criteria stay not assessed rather than overclaimed.</p>
<p class="honesty__lead" style="margin-top:18px;">Beyond the hand-graded claims, the build runs a battery of fail-closed gates: <a href="https://github.com/bounded-systems/lone">lone</a> blesses each rendered page's DOM for semantic HTML and accessibility, the JSON-LD is checked against SHACL shapes, an SPDX SBOM is generated and completeness-checked, a signed whole-site manifest and RFC&nbsp;9530 content digests cover the served bytes, and the nix build is reproducible. Each verdict folds into one honest <a href="/conformance">conformance projection</a> &mdash; lone's web-build model, which emits the strong WCAG&nbsp;2.2&nbsp;AA / OWASP&nbsp;ASVS claim only when every gating criterion passes, so manual and unsupplied criteria stay not assessed rather than overclaimed. The hand-graded claims above are also published as a signed graph &mdash; <a href="/claims.jsonld">claims.jsonld</a> &mdash; each carrying its grade, its gap, and the evidence link, secured by the same build signature.</p>

<div class="legend">
<div class="legend__card">
Expand Down
93 changes: 93 additions & 0 deletions integrity/claims/claims.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"//": "The bounded.tools honesty-section claims, as a nanopublication-shaped, Sigstore-securable graph. Mirrors the visible grade chips (same claims, same grades) so the page's honesty is also machine-checkable data. Grades/gaps/evidence are verified against the linked repos (see content/grounding.json for the per-term evidence). @@DATE@@ is substituted at build by scripts/gen-claims.mjs. Validated by validate-claims.mjs (brand-checks CI).",
"@context": {
"schema": "https://schema.org/",
"prov": "http://www.w3.org/ns/prov#",
"np": "http://www.nanopub.org/nschema#",
"bt": "https://bounded.tools/ns/claims#",
"claim": "bt:claim",
"grade": "bt:grade",
"gap": "bt:gap",
"evidence": { "@id": "bt:evidence", "@type": "@id" },
"subject": { "@id": "schema:subjectOf", "@type": "@id" },
"wasDerivedFrom": { "@id": "prov:wasDerivedFrom", "@type": "@id" },
"generatedAtTime": { "@id": "prov:generatedAtTime", "@type": "schema:DateTime" },
"wasAttributedTo": { "@id": "prov:wasAttributedTo", "@type": "@id" },
"securedBy": { "@id": "bt:securedBy", "@type": "@id" }
},
"@id": "https://bounded.tools/claims#",
"@graph": [
{
"@id": "https://bounded.tools/claims#assertion",
"@graph": [
{
"@id": "https://bounded.tools/claims#c1",
"@type": "bt:Claim",
"claim": "Docs generate from source and fail CI on drift.",
"grade": "enforced",
"evidence": "https://github.com/bounded-systems/site"
},
{
"@id": "https://bounded.tools/claims#c2",
"@type": "bt:Claim",
"claim": "guest-room's behaviour specs execute against the engine.",
"grade": "enforced",
"evidence": "https://github.com/bounded-systems/guest-room"
},
{
"@id": "https://bounded.tools/claims#c3",
"@type": "bt:Claim",
"claim": "A git-write carries a verifiable in-toto / SLSA provenance derivation — signed per-actor, content-addressed in a derivation ledger, checked fail-closed at the merge gate.",
"grade": "partial",
"gap": "Emission and enforcement are opt-in (a signer plus require-signed) until Sigstore lands; without them the push is bare. Verified mechanisms: ocap-provenance/slsa.ts, prx verify.ts/merge-guard.ts, anchored-chain.",
"evidence": "https://github.com/bounded-systems/ocap-provenance"
},
{
"@id": "https://bounded.tools/claims#c4",
"@type": "bt:Claim",
"claim": "The agent never holds the credential — a broker daemon does.",
"grade": "partial",
"gap": "On macOS the door is TCP loopback — weaker than unix-socket possession; isolation is the container plus daemon discipline, not a hardened sandbox. Verified: keeperd/daemon.ts holds the key; claude-box is credential-free.",
"evidence": "https://github.com/bounded-systems/prx"
},
{
"@id": "https://bounded.tools/claims#c5",
"@type": "bt:Claim",
"claim": "prx and claude-box converge onto one guest-room door runtime.",
"grade": "aspirational",
"gap": "Convergence is in progress — prx wires the seams in-process today; the out-of-process door runtime is the direction, not yet at scale.",
"evidence": "https://github.com/bounded-systems/prx"
},
{
"@id": "https://bounded.tools/claims#c6",
"@type": "bt:Claim",
"claim": "Contracts stay honest between components as they evolve.",
"grade": "aspirational",
"gap": "Inter-contract enforcement is the open problem this whole project is aimed at — a bet, stated as direction, not a solved result.",
"evidence": "https://github.com/bounded-systems/prx"
}
]
},
{
"@id": "https://bounded.tools/claims#provenance",
"@graph": [
{
"@id": "https://bounded.tools/claims#assertion",
"subject": "https://bounded.tools",
"wasDerivedFrom": "https://github.com/bounded-systems/site",
"generatedAtTime": "@@DATE@@"
}
]
},
{
"@id": "https://bounded.tools/claims#pubinfo",
"@graph": [
{
"@id": "https://bounded.tools/claims#",
"wasAttributedTo": "https://github.com/bounded-systems/site",
"securedBy": "https://bounded.tools/provenance.json"
}
]
}
]
}
1 change: 1 addition & 0 deletions integrity/structure-audit/structure.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"readerOk": null,
"internalLinks": [
"/blog/",
"/claims.jsonld",
"/conformance",
"/conformance",
"/provenance.json",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"description": "The bounded.tools website. Static HTML built on the @bounded-systems/brand design system.",
"type": "module",
"scripts": {
"build": "node build.mjs && node scripts/gen-blog.mjs && node scripts/gen-conformance.mjs && node scripts/gen-sitemap.mjs && node scripts/gen-sbom.mjs && node vendor/conformance-kit/gates/sbom/check-sbom.mjs && node scripts/gen-stamp.mjs && node scripts/emit-catalog.mjs",
"build": "node build.mjs && node scripts/gen-blog.mjs && node scripts/gen-conformance.mjs && node scripts/gen-sitemap.mjs && node scripts/gen-sbom.mjs && node vendor/conformance-kit/gates/sbom/check-sbom.mjs && node scripts/gen-stamp.mjs && node scripts/gen-claims.mjs && node scripts/emit-catalog.mjs",
"conformance": "node scripts/gen-conformance.mjs",
"check": "node scripts/verify-vendor.mjs && node brand/tokens/build-tokens.mjs --check && node scripts/gen-seams.mjs --check && node scripts/gen-blog.mjs --check && node scripts/emit-catalog.mjs --check && node scripts/check-reader.mjs && node scripts/check-seo.mjs",
"check": "node scripts/verify-vendor.mjs && node brand/tokens/build-tokens.mjs --check && node scripts/gen-seams.mjs --check && node scripts/gen-blog.mjs --check && node scripts/gen-claims.mjs --check && node scripts/emit-catalog.mjs --check && node scripts/check-reader.mjs && node scripts/check-seo.mjs",
"seams": "node scripts/gen-seams.mjs",
"blog": "node scripts/gen-blog.mjs",
"copy": "node scripts/emit-catalog.mjs",
Expand Down
29 changes: 29 additions & 0 deletions scripts/gen-claims.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env node
// Emit dist/claims.jsonld — the served, build-dated copy of the honesty-section
// claims graph (integrity/claims/claims.jsonld). The served file is covered by
// the site's content-digest manifest (its `securedBy`), so the graph the page
// links to is the one the build signature attests. @@DATE@@ → build date (date
// granularity, matching gen-stamp, to keep the build reproducible day-to-day).
//
// node scripts/gen-claims.mjs # write dist/claims.jsonld
// node scripts/gen-claims.mjs --check # validate the source graph only
import { readFile, writeFile, mkdir } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { execSync } from "node:child_process";

const root = dirname(dirname(fileURLToPath(import.meta.url)));
const SRC = join(root, "integrity", "claims", "claims.jsonld");
const CHECK = process.argv.includes("--check");

const src = await readFile(SRC, "utf8");
// Validate structure via the same checker CI runs (throws/exits non-zero on bad graph).
execSync(`node ${join(root, "integrity", "claims", "validate-claims.mjs")} ${SRC}`, { stdio: "inherit" });

if (CHECK) process.exit(0);

const date = new Date().toISOString().slice(0, 10);
const out = src.replace(/@@DATE@@/g, date);
await mkdir(join(root, "dist"), { recursive: true });
await writeFile(join(root, "dist", "claims.jsonld"), out);
console.log(`✓ claims: 6 graded claims → dist/claims.jsonld (${date})`);
Loading