audit-labs/audit-labs.dev
The website for Audit Labs.
clone: git clone https://gitbay.org/audit-labs/audit-labs.dev.git
e96afa52f24bd6fe311bb30d0bcc9e20f9f6230f
verified · cmc
author: Christian Cleberg <hello@cleberg.net> · 2026-08-06T23:44:02Z
audit-report/index.html | 275 +++++++++++++++++++++++++++++++++++++++++++++++ evidence-seal/index.html | 257 +++++++++++++++++++++++++++++++++++++++++++ index.html | 26 ++++- 3 files changed, 556 insertions(+), 2 deletions(-) new file mode 100644 @@ -0,0 +1,275 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>audit-report | Audit Labs</title> + <meta name="description" content="Turn audit-tools evidence packages into control-mapped, auditor-ready reports (Markdown, HTML, JSON) with SOC 2, ISO 27001 and NIST mappings, plus diff and trend modes."> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet"> + <style> + *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + :root { + --black:#0a0a0a; --off-white:#f4f1eb; --warm-white:#faf8f4; + --amber:#d97706; --amber-light:#fbbf24; --green:#15803d; + --gray-1:#1c1c1c; --gray-2:#2e2e2e; --gray-3:#6b6b6b; --gray-4:#a3a3a3; --gray-5:#d4d4d4; + --border:#e5e1d8; --red:#c0392b; + } + body { font-family:'DM Sans',sans-serif; background:var(--warm-white); color:var(--black); line-height:1.6; } + .mono { font-family:'IBM Plex Mono',monospace; } + + /* NAV */ + nav { position:sticky; top:0; z-index:100; background:var(--warm-white); border-bottom:1px solid var(--border); padding:0 2rem; } + .nav-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; height:60px; } + .logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:1.1rem; letter-spacing:-.02em; color:var(--black); text-decoration:none; } + .logo span { color:var(--amber); } + .nav-links { display:flex; gap:2rem; align-items:center; list-style:none; } + .nav-links a { font-family:'IBM Plex Mono',monospace; font-size:.78rem; color:var(--gray-3); text-decoration:none; transition:color .15s; } + .nav-links a:hover { color:var(--black); } + .nav-links .btn-github { background:var(--black); color:var(--off-white); padding:.45rem 1rem; border-radius:4px; font-size:.75rem; } + .nav-links .btn-github:hover { background:var(--gray-2); } + + /* HERO */ + .hero { background:var(--black); color:var(--off-white); padding:5.5rem 2rem 4.5rem; position:relative; overflow:hidden; } + .hero::before { content:''; position:absolute; inset:0; pointer-events:none; + background-image: + repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px), + repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px); } + .hero-inner { max-width:1100px; margin:0 auto; position:relative; display:grid; grid-template-columns:1fr 1fr; gap:3.5rem; align-items:center; } + @media (max-width:820px){ .hero-inner{ grid-template-columns:1fr; gap:2.5rem; } } + .crumb { font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.15em; text-transform:uppercase; color:var(--amber-light); margin-bottom:1.4rem; display:flex; align-items:center; gap:.5rem; } + .crumb::before { content:''; width:1.5rem; height:1px; background:var(--amber-light); } + .crumb a { color:var(--amber-light); text-decoration:none; opacity:.8; } + h1 { font-family:'DM Serif Display',serif; font-size:clamp(2.4rem,5vw,3.9rem); font-weight:400; line-height:1.08; letter-spacing:-.02em; margin-bottom:1.3rem; } + h1 em { font-style:italic; color:var(--amber-light); } + .hero-desc { font-size:1.02rem; color:#a09a8e; margin-bottom:2rem; line-height:1.75; max-width:34rem; } + .hero-actions { display:flex; gap:1rem; flex-wrap:wrap; } + .btn-primary { background:var(--amber); color:#fff; text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; font-weight:500; transition:background .15s; } + .btn-primary:hover { background:var(--amber-light); color:#000; } + .btn-secondary { background:transparent; color:var(--gray-4); text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; border:1px solid var(--gray-2); transition:border-color .15s,color .15s; } + .btn-secondary:hover { border-color:var(--gray-4); color:var(--off-white); } + + /* TERMINAL */ + .terminal { background:#111; border:1px solid #2a2a2a; border-radius:8px; overflow:hidden; } + .terminal-bar { background:#1a1a1a; border-bottom:1px solid #2a2a2a; padding:.6rem 1rem; display:flex; gap:.4rem; align-items:center; } + .dot { width:10px; height:10px; border-radius:50%; } + .dot-red{background:#ff5f57;} .dot-yellow{background:#febc2e;} .dot-green{background:#28c840;} + .terminal-body { padding:1.2rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.95; } + .t-prompt{color:#5a9060;} .t-cmd{color:#e8e0d0;} .t-comment{color:#555;} .t-out{color:#7a9f7a;} .t-path{color:#d4a862;} .t-dim{color:#444;} .t-bad{color:#e06c5e;} .t-hash{color:#8a8a8a;} + + /* SECTIONS */ + section { padding:5rem 2rem; border-bottom:1px solid var(--border); } + .section-inner { max-width:1100px; margin:0 auto; } + .eyebrow { font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.14em; text-transform:uppercase; color:var(--amber); margin-bottom:.9rem; } + h2 { font-family:'DM Serif Display',serif; font-size:clamp(1.7rem,3vw,2.3rem); font-weight:400; line-height:1.2; margin-bottom:.6rem; } + .lede { color:var(--gray-3); font-size:1rem; max-width:44rem; line-height:1.7; } + + .guarantees { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:1.5rem; margin-top:2.6rem; } + .card { background:#fff; border:1px solid var(--border); border-radius:8px; padding:1.8rem; transition:border-color .15s,box-shadow .15s; } + .card:hover { border-color:var(--amber); box-shadow:0 4px 20px rgba(0,0,0,.06); } + .card .num { font-family:'IBM Plex Mono',monospace; font-size:.7rem; color:var(--amber); letter-spacing:.1em; } + .card h3 { font-family:'DM Serif Display',serif; font-weight:400; font-size:1.3rem; margin:.5rem 0 .6rem; } + .card p { font-size:.9rem; color:var(--gray-3); line-height:1.65; } + .card p .mono { color:var(--gray-1); } + + /* COMMANDS / CONTENTS */ + .cmds { background:#fff; } + .cmd-list { margin-top:2.4rem; border:1px solid var(--border); border-radius:8px; overflow:hidden; } + .cmd-row { display:grid; grid-template-columns:11rem 1fr; gap:1.5rem; padding:1.15rem 1.5rem; border-bottom:1px solid var(--border); align-items:baseline; } + .cmd-row:last-child { border-bottom:none; } + .cmd-row:hover { background:var(--warm-white); } + .cmd-name { font-family:'IBM Plex Mono',monospace; font-size:.85rem; font-weight:700; color:var(--black); } + .cmd-desc { font-size:.9rem; color:var(--gray-3); line-height:1.6; } + .cmd-desc .mono { color:var(--amber); } + @media (max-width:560px){ .cmd-row{ grid-template-columns:1fr; gap:.3rem; } } + + /* FRAMEWORKS STRIP */ + .frameworks { padding:3.5rem 2rem; background:var(--warm-white); } + .frameworks-inner { max-width:1100px; margin:0 auto; display:flex; align-items:center; gap:3rem; flex-wrap:wrap; } + .frameworks-label { font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.12em; text-transform:uppercase; color:var(--gray-4); white-space:nowrap; } + .frameworks-list { display:flex; gap:2.5rem; flex-wrap:wrap; align-items:center; } + .framework-tag { font-family:'IBM Plex Mono',monospace; font-size:.8rem; font-weight:700; color:var(--gray-3); letter-spacing:.05em; } + + /* INSTALL */ + .install { background:var(--warm-white); } + .install-grid { display:grid; grid-template-columns:1fr 1fr; gap:2.5rem; margin-top:2.4rem; align-items:start; } + @media (max-width:820px){ .install-grid{ grid-template-columns:1fr; } } + .install pre { background:#111; color:#e8e0d0; border-radius:8px; padding:1.25rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.9; overflow-x:auto; } + .install pre .c { color:#555; } .install pre .p { color:#5a9060; } + .badges { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1.2rem; } + .badge { font-family:'IBM Plex Mono',monospace; font-size:.65rem; background:#fff; border:1px solid var(--border); color:var(--gray-3); padding:.2rem .55rem; border-radius:3px; } + .exit { margin-top:1.4rem; display:flex; flex-direction:column; gap:.55rem; } + .exit .e { font-size:.85rem; color:var(--gray-3); display:flex; gap:.7rem; align-items:baseline; } + .exit .code { font-family:'IBM Plex Mono',monospace; font-weight:700; min-width:1.2rem; } + .exit .g{color:var(--green);} .exit .r{color:var(--red);} .exit .a{color:var(--amber);} + + /* FOOTER */ + footer { background:var(--black); color:var(--gray-4); padding:3rem 2rem; } + .footer-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1.5rem; } + .footer-logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:.9rem; color:var(--gray-4); text-decoration:none; } + .footer-logo span { color:var(--amber); } + .footer-left p { font-size:.78rem; color:var(--gray-2); margin-top:.4rem; } + .footer-links { display:flex; gap:1.5rem; flex-wrap:wrap; } + .footer-links a { font-family:'IBM Plex Mono',monospace; font-size:.75rem; color:var(--gray-3); text-decoration:none; transition:color .15s; } + .footer-links a:hover { color:var(--off-white); } + + @keyframes fadeUp { from{opacity:0;transform:translateY(16px);} to{opacity:1;transform:translateY(0);} } + .crumb{animation:fadeUp .5s ease both;} h1{animation:fadeUp .5s ease .1s both;} + .hero-desc{animation:fadeUp .5s ease .2s both;} .hero-actions{animation:fadeUp .5s ease .3s both;} .terminal{animation:fadeUp .5s ease .4s both;} + @media (prefers-reduced-motion:reduce){ *{animation:none!important;} } + @media (max-width:640px){ .nav-links a:not(.btn-github):not(:last-child){ display:none; } } + </style> +</head> +<body> + +<nav> + <div class="nav-inner"> + <a href="/" class="logo">AUDIT<span>LABS</span></a> + <ul class="nav-links"> + <li><a href="/">Home</a></li> + <li><a href="/evidence-seal/">evidence-seal</a></li> + <li><a href="https://github.com/audit-labs/audit-report" class="btn-github">View on GitHub →</a></li> + </ul> + </div> +</nav> + +<header class="hero"> + <div class="hero-inner"> + <div> + <div class="crumb"><a href="/">Audit Labs</a> / audit-report</div> + <h1>Turn raw evidence into<br><em>an audit-ready report.</em></h1> + <p class="hero-desc"> + A command-line tool that reads an audit-tools evidence package, applies declarative + rulesets, and maps every finding to SOC 2, ISO 27001, and NIST controls — + rendered as Markdown, self-contained HTML, or JSON. Diff and trend modes track drift over time. + </p> + <div class="hero-actions"> + <a href="https://github.com/audit-labs/audit-report" class="btn-primary">View on GitHub</a> + <a href="#install" class="btn-secondary">Install & quickstart</a> + </div> + </div> + <div class="terminal"> + <div class="terminal-bar"><div class="dot dot-red"></div><div class="dot dot-yellow"></div><div class="dot dot-green"></div></div> + <div class="terminal-body"> + <span class="t-comment"># Report on an evidence package</span><br> + <span class="t-prompt">$</span> <span class="t-cmd">audit-report ./aws_audit_prod_2026-08 --format md,html --out report/</span><br> + <span class="t-out"> wrote report/report.md</span><br> + <span class="t-out"> wrote report/report.html</span><br> + <span class="t-path"> aws/prod: 3 failing, 4 passing, 1 n/a</span><br> + <span class="t-dim">──────────────────────────────</span><br> + <span class="t-comment"># Gate CI on high-severity findings</span><br> + <span class="t-prompt">$</span> <span class="t-cmd">audit-report ./aws_audit_prod_2026-08 --fail-on high</span><br> + <span class="t-bad"> ✗ high-severity control unsupported (exit 1)</span> + </div> + </div> + </div> +</header> + +<section> + <div class="section-inner"> + <div class="eyebrow">Three modes</div> + <h2>Report, diff, and trend.</h2> + <p class="lede">One ruleset, three lenses — a point-in-time report, the drift between two runs, or a control’s history across many.</p> + <div class="guarantees"> + <div class="card"> + <div class="num">01 · REPORT</div> + <h3>Point in time</h3> + <p>Evaluate a package against a ruleset and render a control-coverage matrix plus per-finding evidence — each with a plain-language rationale and remediation. <span class="mono">--format md,html,json</span>.</p> + </div> + <div class="card"> + <div class="num">02 · DIFF</div> + <h3>What changed</h3> + <p>Compare a package to an earlier one with <span class="mono">--baseline</span>. Every control is classified <em>regressed</em>, <em>fixed</em>, <em>drifted</em>, or <em>unchanged</em>, showing the exact evidence rows that moved. Gate CI on regressions only.</p> + </div> + <div class="card"> + <div class="num">03 · TREND</div> + <h3>Over time</h3> + <p>Point <span class="mono">--trend</span> at a folder of dated packages for a heatmap of every control across every run, plus a failing-count trendline — compliance drift at a glance.</p> + </div> + </div> + </div> +</section> + +<section class="cmds"> + <div class="section-inner"> + <div class="eyebrow">What you get</div> + <h2>Built for the auditor on the other side.</h2> + <p class="lede">A report presents <em>evidence</em>, not a verdict — a failing row means a setting doesn’t support a control; the judgment stays with you and your auditor.</p> + <div class="cmd-list"> + <div class="cmd-row"><div class="cmd-name">Control coverage</div><div class="cmd-desc">Every cited control, its framework, a worst-wins status, and which rules checked it — the matrix an auditor scans first.</div></div> + <div class="cmd-row"><div class="cmd-name">Findings</div><div class="cmd-desc">Failures first, then by severity — each with the result, <span class="mono">why it matters</span>, remediation, and the exact evidence rows that failed.</div></div> + <div class="cmd-row"><div class="cmd-name">Rulesets</div><div class="cmd-desc">Declarative YAML mapping signals to controls. Bundled for <span class="mono">AWS</span>, <span class="mono">GitHub</span>, and <span class="mono">GitLab</span> — or write your own.</div></div> + <div class="cmd-row"><div class="cmd-name">CI gating</div><div class="cmd-desc"><span class="mono">--fail-on low|medium|high</span> exits non-zero when a finding — or, in diff mode, a regression — crosses the line.</div></div> + </div> + </div> +</section> + +<section class="frameworks"> + <div class="frameworks-inner"> + <span class="frameworks-label">Maps signals to controls for</span> + <div class="frameworks-list"> + <span class="framework-tag">SOC 2</span> + <span class="framework-tag">ISO 27001</span> + <span class="framework-tag">NIST 800-53</span> + <span class="framework-tag" style="color:var(--gray-4);">·</span> + <span class="framework-tag">AWS</span> + <span class="framework-tag">GitHub</span> + <span class="framework-tag">GitLab</span> + </div> + </div> +</section> + +<section class="install" id="install"> + <div class="section-inner"> + <div class="eyebrow">Get started</div> + <h2>Install & quickstart.</h2> + <div class="install-grid"> + <div> + <pre><span class="c"># Install from source</span> +pip install <span class="p">"audit-report"</span> \ + @ git+https://github.com/audit-labs/audit-report + +<span class="c"># Report on an audit-tools package</span> +audit-report ./output/aws_audit_prod_2026-08 \ + --format md,html,json --out report/</pre> + <div class="badges"> + <span class="badge">Python 3.10+</span> + <span class="badge">GPL-3.0</span> + <span class="badge">PyYAML only</span> + <span class="badge">SOC 2 · ISO 27001 · NIST</span> + </div> + </div> + <div> + <p class="lede">The exit-code contract, at a glance:</p> + <div class="exit"> + <div class="e"><span class="code g">0</span><span>Ran clean — no <span class="mono">--fail-on</span> threshold was crossed.</span></div> + <div class="e"><span class="code r">1</span><span>A finding — or a regression, in diff mode — met the severity threshold.</span></div> + <div class="e"><span class="code a">2</span><span>Usage error, e.g. a missing package or unknown format.</span></div> + </div> + <p class="lede" style="margin-top:1.4rem; font-size:.9rem;"> + Pairs with <a href="/evidence-seal/" style="color:var(--amber); text-decoration:none;">evidence-seal</a> + — seal a package for integrity, then report on it for compliance. + </p> + </div> + </div> + </div> +</section> + +<footer> + <div class="footer-inner"> + <div class="footer-left"> + <a href="/" class="footer-logo">AUDIT<span>LABS</span></a> + <p>© 2026 Audit Labs — a two-person team building for the community.</p> + </div> + <div class="footer-links"> + <a href="/">Home</a> + <a href="https://github.com/audit-labs/audit-report">audit-report</a> + <a href="/evidence-seal/">evidence-seal</a> + <a href="https://github.com/audit-labs/gh-attest">gh-attest</a> + <a href="https://github.com/audit-labs">GitHub</a> + </div> + </div> +</footer> + +</body> +</html> new file mode 100644 @@ -0,0 +1,257 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>evidence-seal | Audit Labs</title> + <meta name="description" content="Tamper-evident seals and chain of custody for audit evidence. SHA-256 Merkle manifests, seal chaining, optional ed25519 signing and RFC 3161 timestamping."> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet"> + <style> + *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + :root { + --black:#0a0a0a; --off-white:#f4f1eb; --warm-white:#faf8f4; + --amber:#d97706; --amber-light:#fbbf24; --green:#15803d; + --gray-1:#1c1c1c; --gray-2:#2e2e2e; --gray-3:#6b6b6b; --gray-4:#a3a3a3; --gray-5:#d4d4d4; + --border:#e5e1d8; --red:#c0392b; + } + body { font-family:'DM Sans',sans-serif; background:var(--warm-white); color:var(--black); line-height:1.6; } + .mono { font-family:'IBM Plex Mono',monospace; } + + /* NAV */ + nav { position:sticky; top:0; z-index:100; background:var(--warm-white); border-bottom:1px solid var(--border); padding:0 2rem; } + .nav-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; height:60px; } + .logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:1.1rem; letter-spacing:-.02em; color:var(--black); text-decoration:none; } + .logo span { color:var(--amber); } + .nav-links { display:flex; gap:2rem; align-items:center; list-style:none; } + .nav-links a { font-family:'IBM Plex Mono',monospace; font-size:.78rem; color:var(--gray-3); text-decoration:none; transition:color .15s; } + .nav-links a:hover { color:var(--black); } + .nav-links .btn-github { background:var(--black); color:var(--off-white); padding:.45rem 1rem; border-radius:4px; font-size:.75rem; } + .nav-links .btn-github:hover { background:var(--gray-2); } + + /* HERO */ + .hero { background:var(--black); color:var(--off-white); padding:5.5rem 2rem 4.5rem; position:relative; overflow:hidden; } + .hero::before { content:''; position:absolute; inset:0; pointer-events:none; + background-image: + repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px), + repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(255,255,255,.03) 39px, rgba(255,255,255,.03) 40px); } + .hero-inner { max-width:1100px; margin:0 auto; position:relative; display:grid; grid-template-columns:1fr 1fr; gap:3.5rem; align-items:center; } + @media (max-width:820px){ .hero-inner{ grid-template-columns:1fr; gap:2.5rem; } } + .crumb { font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.15em; text-transform:uppercase; color:var(--amber-light); margin-bottom:1.4rem; display:flex; align-items:center; gap:.5rem; } + .crumb::before { content:''; width:1.5rem; height:1px; background:var(--amber-light); } + .crumb a { color:var(--amber-light); text-decoration:none; opacity:.8; } + h1 { font-family:'DM Serif Display',serif; font-size:clamp(2.4rem,5vw,3.9rem); font-weight:400; line-height:1.08; letter-spacing:-.02em; margin-bottom:1.3rem; } + h1 em { font-style:italic; color:var(--amber-light); } + .hero-desc { font-size:1.02rem; color:#a09a8e; margin-bottom:2rem; line-height:1.75; max-width:34rem; } + .hero-actions { display:flex; gap:1rem; flex-wrap:wrap; } + .btn-primary { background:var(--amber); color:#fff; text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; font-weight:500; transition:background .15s; } + .btn-primary:hover { background:var(--amber-light); color:#000; } + .btn-secondary { background:transparent; color:var(--gray-4); text-decoration:none; padding:.75rem 1.5rem; border-radius:4px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; border:1px solid var(--gray-2); transition:border-color .15s,color .15s; } + .btn-secondary:hover { border-color:var(--gray-4); color:var(--off-white); } + + /* TERMINAL */ + .terminal { background:#111; border:1px solid #2a2a2a; border-radius:8px; overflow:hidden; } + .terminal-bar { background:#1a1a1a; border-bottom:1px solid #2a2a2a; padding:.6rem 1rem; display:flex; gap:.4rem; align-items:center; } + .dot { width:10px; height:10px; border-radius:50%; } + .dot-red{background:#ff5f57;} .dot-yellow{background:#febc2e;} .dot-green{background:#28c840;} + .terminal-body { padding:1.2rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.95; } + .t-prompt{color:#5a9060;} .t-cmd{color:#e8e0d0;} .t-comment{color:#555;} .t-out{color:#7a9f7a;} .t-path{color:#d4a862;} .t-dim{color:#444;} .t-bad{color:#e06c5e;} .t-hash{color:#8a8a8a;} + + /* SECTIONS */ + section { padding:5rem 2rem; border-bottom:1px solid var(--border); } + .section-inner { max-width:1100px; margin:0 auto; } + .eyebrow { font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.14em; text-transform:uppercase; color:var(--amber); margin-bottom:.9rem; } + h2 { font-family:'DM Serif Display',serif; font-size:clamp(1.7rem,3vw,2.3rem); font-weight:400; line-height:1.2; margin-bottom:.6rem; } + .lede { color:var(--gray-3); font-size:1rem; max-width:44rem; line-height:1.7; } + + .guarantees { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:1.5rem; margin-top:2.6rem; } + .card { background:#fff; border:1px solid var(--border); border-radius:8px; padding:1.8rem; transition:border-color .15s,box-shadow .15s; } + .card:hover { border-color:var(--amber); box-shadow:0 4px 20px rgba(0,0,0,.06); } + .card .num { font-family:'IBM Plex Mono',monospace; font-size:.7rem; color:var(--amber); letter-spacing:.1em; } + .card h3 { font-family:'DM Serif Display',serif; font-weight:400; font-size:1.3rem; margin:.5rem 0 .6rem; } + .card p { font-size:.9rem; color:var(--gray-3); line-height:1.65; } + .card p .mono { color:var(--gray-1); } + + /* COMMANDS */ + .cmds { background:#fff; } + .cmd-list { margin-top:2.4rem; border:1px solid var(--border); border-radius:8px; overflow:hidden; } + .cmd-row { display:grid; grid-template-columns:9rem 1fr; gap:1.5rem; padding:1.15rem 1.5rem; border-bottom:1px solid var(--border); align-items:baseline; } + .cmd-row:last-child { border-bottom:none; } + .cmd-row:hover { background:var(--warm-white); } + .cmd-name { font-family:'IBM Plex Mono',monospace; font-size:.85rem; font-weight:700; color:var(--black); } + .cmd-desc { font-size:.9rem; color:var(--gray-3); line-height:1.6; } + .cmd-desc .mono { color:var(--amber); } + @media (max-width:560px){ .cmd-row{ grid-template-columns:1fr; gap:.3rem; } } + + /* INSTALL */ + .install { background:var(--warm-white); } + .install-grid { display:grid; grid-template-columns:1fr 1fr; gap:2.5rem; margin-top:2.4rem; align-items:start; } + @media (max-width:820px){ .install-grid{ grid-template-columns:1fr; } } + .install pre { background:#111; color:#e8e0d0; border-radius:8px; padding:1.25rem 1.4rem; font-family:'IBM Plex Mono',monospace; font-size:.78rem; line-height:1.9; overflow-x:auto; } + .install pre .c { color:#555; } .install pre .p { color:#5a9060; } + .badges { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1.2rem; } + .badge { font-family:'IBM Plex Mono',monospace; font-size:.65rem; background:#fff; border:1px solid var(--border); color:var(--gray-3); padding:.2rem .55rem; border-radius:3px; } + .exit { margin-top:1.4rem; display:flex; flex-direction:column; gap:.55rem; } + .exit .e { font-size:.85rem; color:var(--gray-3); display:flex; gap:.7rem; align-items:baseline; } + .exit .code { font-family:'IBM Plex Mono',monospace; font-weight:700; min-width:1.2rem; } + .exit .g{color:var(--green);} .exit .r{color:var(--red);} .exit .a{color:var(--amber);} + + /* FOOTER */ + footer { background:var(--black); color:var(--gray-4); padding:3rem 2rem; } + .footer-inner { max-width:1100px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1.5rem; } + .footer-logo { font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:.9rem; color:var(--gray-4); text-decoration:none; } + .footer-logo span { color:var(--amber); } + .footer-left p { font-size:.78rem; color:var(--gray-2); margin-top:.4rem; } + .footer-links { display:flex; gap:1.5rem; flex-wrap:wrap; } + .footer-links a { font-family:'IBM Plex Mono',monospace; font-size:.75rem; color:var(--gray-3); text-decoration:none; transition:color .15s; } + .footer-links a:hover { color:var(--off-white); } + + @keyframes fadeUp { from{opacity:0;transform:translateY(16px);} to{opacity:1;transform:translateY(0);} } + .crumb{animation:fadeUp .5s ease both;} h1{animation:fadeUp .5s ease .1s both;} + .hero-desc{animation:fadeUp .5s ease .2s both;} .hero-actions{animation:fadeUp .5s ease .3s both;} .terminal{animation:fadeUp .5s ease .4s both;} + @media (prefers-reduced-motion:reduce){ *{animation:none!important;} } + @media (max-width:640px){ .nav-links a:not(.btn-github):not(:last-child){ display:none; } } + </style> +</head> +<body> + +<nav> + <div class="nav-inner"> + <a href="/" class="logo">AUDIT<span>LABS</span></a> + <ul class="nav-links"> + <li><a href="/">Home</a></li> + <li><a href="/audit-report/">audit-report</a></li> + <li><a href="https://github.com/audit-labs/evidence-seal" class="btn-github">View on GitHub →</a></li> + </ul> + </div> +</nav> + +<header class="hero"> + <div class="hero-inner"> + <div> + <div class="crumb"><a href="/">Audit Labs</a> / evidence-seal</div> + <h1>Prove your evidence<br><em>hasn’t changed.</em></h1> + <p class="hero-desc"> + A command-line tool that seals a directory of audit evidence into a tamper-evident + manifest. Later, it proves the package is byte-for-byte what was collected — and + names anything that moved. Signing and trusted timestamps prove <em>who</em> and <em>when</em>. + </p> + <div class="hero-actions"> + <a href="https://github.com/audit-labs/evidence-seal" class="btn-primary">View on GitHub</a> + <a href="#install" class="btn-secondary">Install & quickstart</a> + </div> + </div> + <div class="terminal"> + <div class="terminal-bar"><div class="dot dot-red"></div><div class="dot dot-yellow"></div><div class="dot dot-green"></div></div> + <div class="terminal-body"> + <span class="t-comment"># Seal an evidence package</span><br> + <span class="t-prompt">$</span> <span class="t-cmd">evidence-seal seal ./aws_audit_prod_2026-08</span><br> + <span class="t-out"> sealed 8 files</span><br> + <span class="t-out"> root </span><span class="t-hash">1265ef6f…</span><span class="t-out"> id </span><span class="t-hash">d096c7ed…</span><br> + <span class="t-dim">──────────────────────────────</span><br> + <span class="t-comment"># Months later — prove nothing changed</span><br> + <span class="t-prompt">$</span> <span class="t-cmd">evidence-seal verify ./aws_audit_prod_2026-08</span><br> + <span class="t-out"> ✓ intact — 8 files match the seal</span><br> + <span class="t-comment"># One byte edited after the fact?</span><br> + <span class="t-prompt">$</span> <span class="t-cmd">evidence-seal verify ./aws_audit_prod_2026-08</span><br> + <span class="t-bad"> ✗ TAMPERED — MODIFIED iam_users.csv</span> + </div> + </div> + </div> +</header> + +<section> + <div class="section-inner"> + <div class="eyebrow">Three guarantees</div> + <h2>Integrity, custody, and proof of origin.</h2> + <p class="lede">Each layer is optional and composes with the others — the core needs no dependencies at all.</p> + <div class="guarantees"> + <div class="card"> + <div class="num">01 · INTEGRITY</div> + <h3>Nothing changed</h3> + <p>Every file is hashed with SHA-256 and folded into a single Merkle <span class="mono">root</span>. Any change to any file, name, or byte flips the root — and <span class="mono">verify</span> names exactly what was modified, added, or removed.</p> + </div> + <div class="card"> + <div class="num">02 · CHAIN OF CUSTODY</div> + <h3>In order, unbroken</h3> + <p>Seal each new package against the last and every manifest links to the previous by hash. A reordered, missing, or spliced-out link is detectable — an append-only history of a package over time.</p> + </div> + <div class="card"> + <div class="num">03 · ATTRIBUTION & TIME</div> + <h3>Who and when</h3> + <p>Sign a seal with an <span class="mono">ed25519</span> key to attest who collected it. Add an <span class="mono">RFC 3161</span> timestamp from an independent authority to prove it existed by a certain time — not backdated.</p> + </div> + </div> + </div> +</section> + +<section class="cmds"> + <div class="section-inner"> + <div class="eyebrow">The commands</div> + <h2>Five verbs, one contract.</h2> + <p class="lede">Every command exits <span class="mono">0</span> when all is well, <span class="mono">1</span> on tamper, and <span class="mono">2</span> on a usage error — so a pipeline can gate on the difference.</p> + <div class="cmd-list"> + <div class="cmd-row"><div class="cmd-name">seal</div><div class="cmd-desc">Hash a directory into a canonical <span class="mono">manifest.json</span> — with provenance metadata, ignore globs, and an optional <span class="mono">--prev</span> link for chaining.</div></div> + <div class="cmd-row"><div class="cmd-name">verify</div><div class="cmd-desc">Recompute and compare. Reports every <span class="mono">MODIFIED</span>, <span class="mono">ADDED</span>, and <span class="mono">REMOVED</span> file, and catches a doctored manifest itself.</div></div> + <div class="cmd-row"><div class="cmd-name">chain</div><div class="cmd-desc">Verify a sequence of seals links oldest → newest, catching reordering or a removed link.</div></div> + <div class="cmd-row"><div class="cmd-name">sign</div><div class="cmd-desc">Attach an <span class="mono">ed25519</span> signature; <span class="mono">verify --pubkey</span> requires a named signer, proving identity, not just integrity.</div></div> + <div class="cmd-row"><div class="cmd-name">timestamp</div><div class="cmd-desc">Request, submit, apply, and verify an <span class="mono">RFC 3161</span> token — with <span class="mono">--tsa-cert</span> for full CMS signature verification.</div></div> + </div> + </div> +</section> + +<section class="install" id="install"> + <div class="section-inner"> + <div class="eyebrow">Get started</div> + <h2>Install & quickstart.</h2> + <div class="install-grid"> + <div> + <pre><span class="c"># Core is pure standard library.</span> +<span class="c"># Extras add signing + timestamping:</span> +pip install <span class="p">"evidence-seal[sign,timestamp]"</span> \ + @ git+https://github.com/audit-labs/evidence-seal + +<span class="c"># Seal, then verify</span> +evidence-seal seal ./evidence +evidence-seal verify ./evidence</pre> + <div class="badges"> + <span class="badge">Python 3.10+</span> + <span class="badge">GPL-3.0</span> + <span class="badge">stdlib core · 0 deps</span> + <span class="badge">SHA-256 · Merkle</span> + </div> + </div> + <div> + <p class="lede">The exit-code contract, at a glance:</p> + <div class="exit"> + <div class="e"><span class="code g">0</span><span>Intact / valid — the package matches its seal.</span></div> + <div class="e"><span class="code r">1</span><span>Tamper detected, chain broken, or an invalid signature.</span></div> + <div class="e"><span class="code a">2</span><span>Usage error, or an optional dependency isn’t installed.</span></div> + </div> + <p class="lede" style="margin-top:1.4rem; font-size:.9rem;"> + Distinguishing <span class="mono">1</span> from <span class="mono">2</span> lets CI separate + “the evidence was tampered with” from “the job is misconfigured.” + </p> + </div> + </div> + </div> +</section> + +<footer> + <div class="footer-inner"> + <div class="footer-left"> + <a href="/" class="footer-logo">AUDIT<span>LABS</span></a> + <p>© 2026 Audit Labs — a two-person team building for the community.</p> + </div> + <div class="footer-links"> + <a href="/">Home</a> + <a href="/audit-report/">audit-report</a> + <a href="https://github.com/audit-labs/evidence-seal">evidence-seal</a> + <a href="https://github.com/audit-labs/gh-attest">gh-attest</a> + <a href="https://github.com/audit-labs">GitHub</a> + </div> + </div> +</footer> + +</body> +</html> @@ -556,7 +556,7 @@ <section class="repos"> <div class="section-inner"> <div class="section-header"> - <h2>Three repos.<br>Pick what you need.</h2> + <h2>Five repos.<br>Pick what you need.</h2> <a href="https://github.com/audit-labs" class="section-link">View all on GitHub →</a> </div> <div class="repo-grid"> @@ -590,6 +590,26 @@ <span class="lang-badge">D1</span> </div> </a> + <a href="/audit-report/" class="repo-card"> + <div class="repo-tag">CLI</div> + <h3>audit-labs/audit-report</h3> + <p>Turns an audit-tools evidence package into a control-mapped, auditor-ready report — Markdown, self-contained HTML, or JSON. Declarative rulesets map findings to SOC 2, ISO 27001, and NIST, with diff and trend modes for tracking drift over time.</p> + <div class="repo-langs"> + <span class="lang-badge">Python</span> + <span class="lang-badge">YAML</span> + <span class="lang-badge">HTML</span> + </div> + </a> + <a href="/evidence-seal/" class="repo-card"> + <div class="repo-tag">CLI</div> + <h3>audit-labs/evidence-seal</h3> + <p>Tamper-evident seals and chain of custody for evidence packages. SHA-256 Merkle manifests catch any change to any file; sequential seals chain into a verifiable history; optional ed25519 signing and RFC 3161 timestamping prove who sealed it and when.</p> + <div class="repo-langs"> + <span class="lang-badge">Python</span> + <span class="lang-badge">ed25519</span> + <span class="lang-badge">RFC 3161</span> + </div> + </a> </div> </div> </section> @@ -656,8 +676,10 @@ </div> <div class="footer-links"> <a href="https://github.com/audit-labs/audit-tools">audit-tools</a> - <a href="https://github.com/audit-labs/tutorials">tutorials</a> + <a href="/audit-report/">audit-report</a> + <a href="/evidence-seal/">evidence-seal</a> <a href="https://github.com/audit-labs/gh-attest">gh-attest</a> + <a href="https://github.com/audit-labs/tutorials">tutorials</a> <a href="https://github.com/audit-labs">GitHub</a> </div> </div>