Trust page
A fact absent from the allowlist reaches neither HTML nor JSON, and the default page exposes aggregate posture without tenant or control detail.
What it is
trust-page is a pure generator that turns an EvidencePackManifest into self-contained HTML and JSON for a buyer-hosted trust page. flattenManifestFacts defines the only fields that can appear; generateTrustPage filters that universe through DEFAULT_TRUST_PAGE_ALLOWLIST before rendering either output and rejects prohibited readiness claims. It adds no auth, comments, sign-off, hosting, or runtime fetch.
What ships in the module
A finite fact ceiling before redaction
flattenManifestFacts() converts the evidence-pack manifest into the flat scalar key universe the generator can render. Tenant id, framework identity, chain-anchor values, summary counts, and per-control fields enter through this one function; a fabricated field outside that universe has no route into either output.
Aggregate-only defaults
DEFAULT_TRUST_PAGE_ALLOWLIST admits framework title and version plus aggregate posture, total, ready, and gap counts. It excludes tenantId, the raw chain-anchor hash, total evidence count, every per-control title and readiness value, and the crosswalk table unless the caller opts each field in.
Crosswalk rows require explicit opt-in
CROSSWALK_ROLLUP_ROWS_KEY is the sentinel that enables generateTrustPage() to render the crosswalk-rollup table. Without that exact allowlist entry, the HTML contains no table and the JSON crosswalk stays empty; opting in also exposes the cells' evidence pointers, so the choice is visible and deliberate.
HTML and JSON are independently self-contained
generateTrustPage() returns a TrustPage-shaped pair of complete static HTML and newline-terminated JSON. Neither output fetches the other at runtime, and sorted fact keys keep both stable across caller allowlist order, so a buyer can host either artifact anywhere without a Caisson service.
Readiness language is enforced
generateTrustPage() runs every rendered string through the shared readiness-language gate before returning. A prohibited compliant, certified, or verified claim throws instead of entering the artifact, while crosswalk rows pass through the same citation-row guard as the rest of the compliance render surface.
export function generateTrustPage(
manifest: EvidencePackManifest,
options: GenerateTrustPageOptions = {},
): TrustPage {
const allowlist = options.allowlist ?? DEFAULT_TRUST_PAGE_ALLOWLIST;
const facts = redactToAllowlist(flattenManifestFacts(manifest), allowlist);
for (const [key, value] of Object.entries(facts)) {
if (typeof value === "string") {
assertReadinessLanguage(value, `trust page fact "${key}"`);
}
}
const rows = allowlist.includes(CROSSWALK_ROLLUP_ROWS_KEY)
? crosswalkRollupRows(manifest)
: [];
return {
html: renderHtml(facts, rows),
json: renderJson(facts, rows),
};
}- generateTrustPage calls flattenManifestFacts and redactToAllowlist before either renderer receives data; a field missing from the allowlist never enters HTML or JSON.
- DEFAULT_TRUST_PAGE_ALLOWLIST is the fallback when the caller supplies no override, and generateTrustPage still runs every surviving string through the readiness-language gate.