All checks were successful
Deploy content to live site / deploy (push) Successful in 2s
Catches the website up to the v0.0.21 server contract:
- Project structure (reference.html §9): archive/ is the only
physical project-root directory; the in-flight lifecycle
(working/staging/reviewing) now lives PER-PARTY under
archive/<party>/. Six top-level URLs (ssr/mdl/rsk/working/
staging/reviewing) are virtual aggregators synthesised from
each party's content.
- Retired the staging↔working mirror language — drafting a
response transmittal now walks the in-flight ratchet through
Plan Review's scaffold at archive/<party>/reviewing/<tracking>/.
- Role descriptions (§10): document_controller is no longer
subtree-admin anywhere. Authority cascades from the auto-own
.zddc written at each archive/<party>/ folder, which grants
both the creator email AND the document_controller role
`rwcda` (via auto_own_roles in the defaults). Multi-DC
deployments work without admin status because the role itself
is named in every party's auto-own grant.
- Added the `observer` role (third standard role) with a
pure-read-only intent for external auditors.
- Documented the in-flight ratchet (working → staging → issued)
as a one-way handoff that downgrades the prior role's modify
rights at each step.
- Clarified that the `a` verb is the .zddc-edit verb, distinct
from the elevation-bypass sudo channel (root admins: list).
- Dropped `on_plan_review:` from the cascade-keys reference (the
key was retired when Plan Review hardcoded the scaffold
convention); added `auto_own_roles:` and `auto_own_fenced:`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
219 lines
21 KiB
HTML
219 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>ZDDC — Zero Day Document Control</title>
|
|
<meta name="description" content="A file-naming convention and two single-file HTML tools — archive and browse — for managing project deliverables. Self-contained, offline-capable, dependency-free.">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:url" content="https://zddc.varasys.io/">
|
|
<meta property="og:title" content="ZDDC — Zero Day Document Control">
|
|
<meta property="og:description" content="A file-naming convention and two single-file HTML tools — archive and browse — for managing project deliverables. Self-contained, offline-capable, dependency-free.">
|
|
<meta name="theme-color" content="#2a5a8a">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="css/style.css">
|
|
<style>
|
|
.install-grid { display: grid; grid-template-columns: 1fr; gap: var(--spacing-md); margin-top: var(--spacing-md); }
|
|
.install-card { padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-bg-subtle); }
|
|
.install-card h3 { margin-top: 0; margin-bottom: 0.25rem; }
|
|
.install-card .when { color: var(--color-text-muted); font-size: 0.92em; margin: 0.1rem 0 0.6rem 0; }
|
|
.install-card pre { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 6px; padding: 0.6rem 0.8rem; overflow-x: auto; font-size: 0.82em; line-height: 1.45; margin: 0; }
|
|
.install-card pre code { font-family: "SF Mono", Menlo, Consolas, monospace; }
|
|
.install-points { margin: 0.4rem 0 0.4rem 1.4rem; padding: 0; line-height: 1.65; }
|
|
.install-points li { margin-bottom: 0.15rem; }
|
|
.mode-grid { display: grid; grid-template-columns: 1fr; gap: var(--spacing-md); margin-top: var(--spacing-md); }
|
|
@media (min-width: 720px) { .mode-grid { grid-template-columns: 1fr 1fr; } }
|
|
.mode-card { padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; }
|
|
.mode-card h3 { margin-top: 0; }
|
|
code.inline { background: var(--color-bg-subtle); padding: 0.1rem 0.35rem; border-radius: 4px; font-size: 0.9em; }
|
|
.feature-list { line-height: 1.8; padding-left: 1.5rem; color: var(--color-text); }
|
|
.feature-list li { margin-bottom: 0.4rem; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Header -->
|
|
<header class="site-header">
|
|
<div class="container header-content">
|
|
<a href="/" class="brand">
|
|
<svg class="brand-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" aria-hidden="true">
|
|
<rect width="64" height="64" rx="12" fill="#1e3a5f"/>
|
|
<g fill="#fff">
|
|
<rect x="14" y="18" width="36" height="7"/>
|
|
<polygon points="43,25 50,25 21,43 14,43"/>
|
|
<rect x="14" y="43" width="36" height="7"/>
|
|
</g>
|
|
</svg>
|
|
<span class="brand-name">ZDDC</span>
|
|
</a>
|
|
<nav class="header-nav">
|
|
<div class="dropdown">
|
|
<button class="dropdown-toggle" type="button" aria-haspopup="true">
|
|
<span>Tools</span>
|
|
<svg viewBox="0 0 24 24" style="width: 14px; height: 14px; fill: currentColor;">
|
|
<path d="M7 10l5 5 5-5z"/>
|
|
</svg>
|
|
</button>
|
|
<div class="dropdown-menu">
|
|
<div class="dropdown-menu__inner">
|
|
<a href="releases/archive.html">
|
|
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M20 6H4a2 2 0 00-2 2v10a2 2 0 002 2h16a2 2 0 002-2V8a2 2 0 00-2-2zm0 12H4V8h16v10zM4 2h16v2H4z"/></svg>
|
|
Archive Browser
|
|
</a>
|
|
<a href="releases/browse.html">
|
|
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg>
|
|
Browse
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<a href="reference.html" class="nav-link">Docs</a>
|
|
<a href="releases/" class="nav-link">Releases</a>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Hero -->
|
|
<section class="hero">
|
|
<div class="container">
|
|
<h1>Zero Day Document Control</h1>
|
|
<p class="hero-subtitle">A file-naming convention and two single-file HTML tools — archive and browse — for managing project deliverables. Self-contained, offline-capable, dependency-free.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<main class="container" style="margin-bottom: var(--spacing-2xl);">
|
|
|
|
<section style="margin-top: var(--spacing-xl);">
|
|
<h2>What is it?</h2>
|
|
<p>ZDDC is a convention, not a platform. Every deliverable's filename encodes its tracking number, revision, status, and title; every transmittal folder is date-prefixed and self-describing. A plain shared folder becomes a fully searchable, auditable information-management system — no server, no database, no software required to read the archive.</p>
|
|
<p>The two tools below are <em>optional</em> interfaces around this structure. Each is a single self-contained HTML file that works two ways: open it locally and point it at a folder on your disk, or put it behind any web server (including the optional <code class="inline">zddc-server</code> described below) and use it over the network. Same on-disk layout either way.</p>
|
|
<p style="margin-top: var(--spacing-md);"><a href="reference.html">Read the full specification →</a></p>
|
|
</section>
|
|
|
|
<section style="margin-top: var(--spacing-2xl);">
|
|
<h2>Try the tools</h2>
|
|
<p>Each tool is a single self-contained HTML file. The link below always tracks the current stable; pin to a specific version on the <a href="releases/">releases page</a> for reproducibility.</p>
|
|
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--spacing-lg); margin-top: var(--spacing-lg);">
|
|
|
|
<a href="releases/archive.html" class="tool-card" style="text-decoration: none; display: block;">
|
|
<div class="tool-card__title">Archive Browser</div>
|
|
<div class="tool-card__desc">Search the formal record. Filter by tracking number, discipline, revision, status, or free text; group rows by transmittal to see each deliverable's lifecycle; export the current selection as a ZIP. Read-only — the archive is preserved as-issued.</div>
|
|
<div class="tool-card__link">Open Archive Browser →</div>
|
|
</a>
|
|
|
|
<a href="releases/browse.html" class="tool-card" style="text-decoration: none; display: block;">
|
|
<div class="tool-card__title">Browse</div>
|
|
<div class="tool-card__desc">File-tree navigator for the whole project. Edit markdown in place with live preview, YAML front matter, and a table of contents pane; download any markdown source as DOCX, HTML, or PDF on demand; classify inbound files to ZDDC names, draft transmittals, and manage the project tree end-to-end.</div>
|
|
<div class="tool-card__link">Open Browse →</div>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<p style="margin-top: var(--spacing-lg); color: var(--color-text-muted);">Append <code class="inline">?v=v0.0.4</code> to any URL to load a specific version for a single request — useful for sharing a link to an exact build. Direct local-folder access requires a Chromium-based browser (the File System Access API is unavailable in Firefox / Safari). <a href="releases/">Browse all versions →</a></p>
|
|
</section>
|
|
|
|
<!-- zddc-server (inline, replaces the previous separate page) -->
|
|
<section style="margin-top: var(--spacing-2xl);">
|
|
<h2>zddc-server (optional)</h2>
|
|
<p>The tools work two ways over the same on-disk archive. Pick whichever fits your team:</p>
|
|
|
|
<div class="mode-grid">
|
|
<div class="mode-card">
|
|
<h3>Local directory mode</h3>
|
|
<p>Open a tool, click <em>Add Directory</em>, point it at a folder. The tool reads files via the File System Access API. No upload, no server, no account.</p>
|
|
<p>Enough for individual users and small teams on a shared drive (network share, Dropbox, OneDrive, syncthing).</p>
|
|
</div>
|
|
<div class="mode-card">
|
|
<h3>Online mode</h3>
|
|
<p>Take the same local directory and put it behind any web server (nginx, Caddy, Apache, or <code class="inline">zddc-server</code>). The Archive Browser tool talks to the server's directory listings instead of the local filesystem — read-only, works in any browser.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<p style="margin-top: var(--spacing-md);"><strong><code class="inline">zddc-server</code></strong> is a small Go binary purpose-built to serve ZDDC archives. <em>Any</em> web server gives you online mode; <code class="inline">zddc-server</code> adds things a generic web server can't:</p>
|
|
|
|
<ul class="feature-list">
|
|
<li><strong>Lazy folder creation, case-fold matching.</strong> Drop a <code class="inline">.zddc</code> file into an empty directory and the canonical project layout (<code class="inline">archive/<party>/{mdl,rsk,incoming,received,issued,working,staging,reviewing}/</code>) materialises on the first write into each path — never on bare reads. <code class="inline">archive/</code> is the only physical project-root child; <code class="inline">ssr</code>, <code class="inline">mdl</code>, <code class="inline">rsk</code>, <code class="inline">working</code>, <code class="inline">staging</code>, <code class="inline">reviewing</code> sit beside it as virtual aggregators that synthesise listings across parties. Folder names are matched case-insensitively, so an existing <code class="inline">Working/</code> is reused rather than shadowed by a new <code class="inline">working/</code> sibling. Each authenticated viewer sees a virtual <code class="inline">archive/<party>/working/<your-email>/</code> entry; first write makes it real.</li>
|
|
<li><strong>Virtual <code class="inline">.archive</code> URL space.</strong> <code class="inline">GET /Project/.archive/123-XYZ.html</code> resolves to the canonical revision file at request time. Computed from filenames; no cache, no separate index file.</li>
|
|
<li><strong>Access control via <code class="inline">.zddc</code> files.</strong> Behind a reverse proxy that authenticates users and sets an <code class="inline">X-Auth-Request-Email</code> request header, <code class="inline">zddc-server</code> consults YAML <code class="inline">.zddc</code> files at every directory along the path. The cascade walks root→leaf; the closest match wins. Five verbs (<code class="inline">r</code> read, <code class="inline">w</code> overwrite, <code class="inline">c</code> create, <code class="inline">d</code> delete, <code class="inline">a</code> admin / edit ACL) gate every operation. An empty grant (e.g. <code class="inline">"*@vendor.com": ""</code>) is an explicit deny. A subtree that wants to start fresh — vendor folder, regulated workspace — can declare <code class="inline">inherit: false</code> to fence off ancestor grants and roles, then list the principals it does want. Common shapes (paired open/closed projects, third-party-restricted vendor folders) are documented with worked examples in the <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc/README.md#access-control-the-zddc-cascade">access-control reference</a>. No database, no admin UI.</li>
|
|
<li><strong>Roles for human-readable grants.</strong> A <code class="inline">.zddc</code> may declare named roles whose members are email patterns; permissions then reference the role name instead of pasting the same wildcard everywhere:
|
|
<pre style="margin: 0.4rem 0;"><code>roles:
|
|
qc-reviewers:
|
|
members: ["*@quality.org", "alice@example.com"]
|
|
acl:
|
|
permissions:
|
|
qc-reviewers: rwd
|
|
"*@example.com": r</code></pre>
|
|
Role definitions cascade like everything else; a child <code class="inline">.zddc</code> redefining the same role name shadows the ancestor for that subtree.</li>
|
|
<li><strong>WORM archive folders.</strong> Anything under <code class="inline">archive/<party>/issued/</code> or <code class="inline">archive/<party>/received/</code> enforces write-once via a verb mask: ancestor grants are reduced to <code class="inline">r</code> only, while a <code class="inline">.zddc</code> placed at the WORM folder itself can still grant <code class="inline">rc</code> (create-but-not-overwrite) to specific principals — that's how a doc controller drops a fresh transmittal into the immutable record. Root admins (the <code class="inline">admins:</code> list in the root <code class="inline">.zddc</code>) bypass the mask as the deliberate escape hatch for mis-filed documents.</li>
|
|
<li><strong>Cascade tracer for operators.</strong> Admins can hit <code class="inline">/.profile/effective-policy?path=<url></code> to see the resolved ACL chain at any path — every level's grants, the role evaluation, the final verb-set. Useful when a permission isn't behaving the way the operator expected.</li>
|
|
<li><strong>Per-request access logging</strong> keyed to the authenticated user; conservative HTTP timeouts; optional file-tee for offline audit (production deployments typically leave logs on stdout for the orchestrator's pipeline to handle).</li>
|
|
<li><strong>TLS, ETags, conditional GET, CORS, autoindex.</strong> The mundane glue.</li>
|
|
<li><strong>OPA-compatible policy decider.</strong> Federal and other regulated customers can swap the built-in evaluator for an external <a href="https://www.openpolicyagent.org/" rel="noopener">Open Policy Agent</a> server with their own audited Rego policies — set <code class="inline">ZDDC_OPA_URL</code> and the server POSTs the request's user, path, action, and the full <code class="inline">.zddc</code> cascade chain to <code class="inline">/v1/data/zddc/access/allow</code>. Decisions are cached per (user, path, action) with a configurable TTL (<code class="inline">ZDDC_OPA_CACHE_TTL</code>); failures fail closed by default (<code class="inline">ZDDC_OPA_FAIL_OPEN=1</code> flips it). The bundled NIST AC-6 strict-cascade preset is dumpable via <code class="inline">--print-rego=federal</code>. Default mode adds zero new dependencies; external mode is a configuration flip.</li>
|
|
<li><strong>Designed for regulated environments.</strong> Hardened TLS (NIST SP 800-52 Rev. 2 cipher allowlist + HSTS), pluggable policy engine, federal-mode strict-least-privilege Rego shipping out of the box, structured audit logging, documented vulnerability-disclosure process. Specific federal-track work (FIPS-validated build, signed-token proxy↔server channel, code-signed tool fetches) is on a clear roadmap — see the <a href="federal.html">federal compliance page</a> for the supported deployment shape and what an integrator adds during ATO.</li>
|
|
</ul>
|
|
|
|
<p style="margin-top: var(--spacing-md);">The on-disk layout is the same in both modes. Stop the server and the directory is still a perfectly valid ZDDC archive that opens in local-directory mode. <strong>The server is convenience, not lock-in.</strong></p>
|
|
|
|
<p style="margin-top: var(--spacing-md);">Source, environment-variable contract, and ACL syntax: <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc">codeberg.org/VARASYS/ZDDC <code class="inline">zddc/</code></a>. Pre-built binaries are published as Codeberg release assets; example Helm charts (production + dev) live under <code class="inline">helm/</code> in the repo and compile from source at deploy time.</p>
|
|
</section>
|
|
|
|
<section style="margin-top: var(--spacing-2xl);">
|
|
<h2>Install on your server</h2>
|
|
<p>Two paths, no install scripts. The server has built-in fetch-and-cache for the tool HTMLs; the local-file path needs nothing more than a download.</p>
|
|
|
|
<div class="install-grid">
|
|
<div class="install-card">
|
|
<h3>Server: just run zddc-server</h3>
|
|
<p class="when">The binary has the current-stable build of both tools baked in at compile time. They appear automatically at the right paths in the served tree:</p>
|
|
<ul class="install-points">
|
|
<li><strong>archive.html</strong> at every <code class="inline">archive/</code> path — the read-only search-and-export view of the formal record</li>
|
|
<li><strong>browse.html</strong> at every directory (the slash form of any path) — the file-tree navigator, in-place markdown editor, and inbound-file handling surface</li>
|
|
<li><strong>index.html</strong> (the project picker) at the deployment root</li>
|
|
</ul>
|
|
<p class="when" style="margin-top: 0.6rem;">Which tool serves at a given URL is decided by the <code class="inline">.zddc</code> cascade — the embedded defaults map <code class="inline">archive/</code> subtrees to the archive tool and everything else to browse, but operators can override per folder via <code class="inline">default_tool:</code>. Folder names are case-insensitive — <code class="inline">Working/</code>, <code class="inline">working/</code>, and <code class="inline">WORKING/</code> all match the same rule.</p>
|
|
<pre><code>./zddc-server</code></pre>
|
|
<p class="when" style="margin-top: 0.6rem;">No flags needed for a quick start. The served tree defaults to the current working directory; the listener defaults to <code class="inline">https://localhost:8443/</code> with a self-signed certificate. <code class="inline">--root</code>, <code class="inline">--addr</code>, and <code class="inline">--tls-cert</code> / <code class="inline">--tls-key</code> override each. <code class="inline">--help</code> prints the full flag list.</p>
|
|
<p class="when" style="margin-top: 0.6rem;"><strong>To override a tool</strong> at any path: drop a real <code class="inline">.html</code> file there — that file wins over the baked-in version. <strong>To pin a different version</strong>, write an <code class="inline">apps:</code> entry in any <code class="inline">.zddc</code> file along the path:</p>
|
|
<pre><code># <project>/.zddc
|
|
apps:
|
|
browse: stable # latest stable, or v0.0.4 to pin an exact version
|
|
archive: https://my-fork.example/archive.html</code></pre>
|
|
<p class="when" style="margin-top: 0.6rem;">URL sources are fetched once and cached in <code class="inline"><ZDDC_ROOT>/_app/</code>. To force a re-fetch, delete the cache file. Closer-to-leaf <code class="inline">.zddc</code> entries override parent ones.</p>
|
|
</div>
|
|
|
|
<div class="install-card">
|
|
<h3>Local: just download the .html file</h3>
|
|
<p class="when">No server, no install — open in any modern browser.</p>
|
|
<ul class="install-points">
|
|
<li><a href="releases/archive.html">archive.html</a></li>
|
|
<li><a href="releases/browse.html">browse.html</a></li>
|
|
</ul>
|
|
<p class="when" style="margin-top: 0.6rem;">Right-click → Save As. Each tool is a self-contained HTML file with everything inlined; works from <code class="inline">file://</code> or any static host.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section style="margin-top: var(--spacing-2xl);">
|
|
<h2>Learn more</h2>
|
|
<ul style="line-height: 1.9;">
|
|
<li><a href="reference.html">Technical Reference</a> — the full ZDDC convention: filename format, tracking numbers, revisions, status codes, folder naming, transmittal workflow.</li>
|
|
<li><a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc/README.md#access-control-the-zddc-cascade">Access control reference</a> — cascade rules, common deployment shapes (paired open/closed projects + third-party-vendor folders), anti-patterns, a five-minute verify-it-works recipe, the federal-readiness gap analysis with NIST control references, and the OPA-compatible decider configuration.</li>
|
|
<li><a href="federal.html">For federal evaluators</a> — non-technical walk-through of what's already in place, the supported deployment shape, what an integrator adds during ATO, and the two-track build plan. Procurement-friendly entry point that links back to engineering detail.</li>
|
|
<li><a href="releases/">All releases</a> — every version of every tool, with per-version pin URLs.</li>
|
|
<li><a href="https://codeberg.org/VARASYS/ZDDC">codeberg.org/VARASYS/ZDDC</a> — source code, issue tracker, contributor docs.</li>
|
|
</ul>
|
|
</section>
|
|
|
|
</main>
|
|
|
|
<footer class="site-footer">
|
|
<div class="container footer-content">
|
|
<span>ZDDC is open source — <a href="https://codeberg.org/VARASYS/ZDDC">codeberg.org/VARASYS/ZDDC</a></span>
|
|
</div>
|
|
</footer>
|
|
|
|
<script src="js/layout.js"></script>
|
|
</body>
|
|
</html>
|