docs: simplify to three local-first tools (actual content)
All checks were successful
Deploy content to live site / deploy (push) Successful in 2s

Follow-up to c3ba81a, which deleted federal.html but missed the file
edits (the prior git add aborted on a pathspec error). This commit
carries the real changes: remove the zddc-server + install sections and
all server discussion from the landing page; lead with "runs in your
browser, files never leave your machine, start with Browse now"; give
each tool card a bulleted feature list; lay the three cards out
all-across or all-stacked via a shared .tools-grid. In the reference,
remove Section 10 (server bootstrap), renumber Tools to 10, and
de-couple Section 9's layout/workflow from server machinery.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-06-11 12:03:59 -05:00
parent c3ba81a59b
commit 48a4e357f2
3 changed files with 86 additions and 314 deletions

View file

@ -514,6 +514,19 @@ html[data-theme="dark"] .filename-parts__dot--status {
background: var(--color-accent-hover);
}
/* Three tool cards: all three side by side on wide screens, all three
stacked on narrow screens never a 2-then-1 wrap. */
.tools-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-lg);
margin-top: var(--spacing-lg);
align-items: start;
}
@media (min-width: 860px) {
.tools-grid { grid-template-columns: repeat(3, 1fr); }
}
/* ── Steps List ── */
.steps {
margin: var(--spacing-xl) 0;

View file

@ -15,23 +15,11 @@
<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; }
.tool-card--featured { border-color: var(--color-accent); box-shadow: 0 0 0 1px var(--color-accent) inset; }
.tool-card__tag { display: inline-block; font-size: 0.72em; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: #fff; background: var(--color-accent); border-radius: 4px; padding: 0.1rem 0.45rem; margin-bottom: 0.5rem; }
.tool-card__list { margin: 0.6rem 0 0 0; padding-left: 1.15rem; line-height: 1.55; color: var(--color-text); font-size: 0.95em; }
.tool-card__list li { margin-bottom: 0.35rem; }
</style>
</head>
<body>
@ -84,7 +72,8 @@
<section class="hero">
<div class="container">
<h1>Zero Day Document Control</h1>
<p class="hero-subtitle">A file-naming convention plus a few single-file HTML tools for managing project deliverables. Start with <strong>Browse</strong> — open any folder, no setup. Self-contained, offline-capable, dependency-free.</p>
<p class="hero-subtitle">Three small tools for managing project deliverables, plus a simple file-naming convention. Each tool is one HTML file that runs entirely in your browser — open it, point it at a folder on your computer, and go. Nothing to install, no account, no server. Your files never leave your machine.</p>
<p style="margin-top: var(--spacing-md);"><a href="releases/browse.html" class="tool-card__link">Open Browse now →</a></p>
</div>
</section>
@ -92,117 +81,65 @@
<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 tools below are <em>optional</em> interfaces around this structure, and each needs nothing to run. Every one is a single self-contained HTML file: open it 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. The extra niceties — friendly labels, per-folder tools, permissions — come from optional <code class="inline">.zddc</code> files you can add later, or never.</p>
<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 folder on your computer or a shared drive becomes a fully searchable, auditable record — no server, no database, no software required to read it.</p>
<p>The three tools below are <em>optional</em> helpers around this structure. Each is a single HTML file that works entirely on your own machine: open it, pick a folder, and you're working. They run offline and never upload anything. You can start with <strong>Browse</strong> on your existing files right now — there's nothing to set up first.</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>
<h2>The tools</h2>
<p>Three single-file apps. Click one to open it now, or right-click → <em>Save As</em> to keep your own copy — each works offline forever, with no install and no updates.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--spacing-lg); margin-top: var(--spacing-lg);">
<div class="tools-grid">
<a href="releases/browse.html" class="tool-card tool-card--featured" style="text-decoration: none; display: block;">
<span class="tool-card__tag">Start here</span>
<div class="tool-card__title">Browse</div>
<div class="tool-card__desc">Open any folder on your disk — that's the whole setup. A file-tree navigator with live preview for the things you actually have: PDFs, Office docs, images, markdown. Edit markdown in place and download it as DOCX, HTML, or PDF on demand. Add optional <code class="inline">.zddc</code> files and the same tool gains friendly folder labels, per-folder tools, permissions, and transmittal actions — leave them out and it's still a complete browser.</div>
<div class="tool-card__link">Open Browse →</div>
<div class="tool-card__desc">Look at any folder — no setup at all.</div>
<ul class="tool-card__list">
<li>Open files on your computer and preview them instantly — PDFs, Word, Excel, images, markdown</li>
<li>Move through your folders the way you already think about them</li>
<li>Edit markdown in place and save it as Word, PDF, or HTML</li>
<li>Works completely offline; your files stay on your machine</li>
</ul>
<div class="tool-card__link" style="margin-top: var(--spacing-lg);">Open Browse →</div>
</a>
<a href="releases/classifier.html" class="tool-card" style="text-decoration: none; display: block;">
<div class="tool-card__title">Classify</div>
<div class="tool-card__desc">Turn a pile of incoming files into properly named ZDDC deliverables. Drop files onto a tree to assign each one a tracking number, revision, and status, then organize them into dated transmittal folders ready to issue. Spreadsheet-style editing; writes the renamed, sorted copies straight back to disk. No server needed.</div>
<div class="tool-card__link">Open Classify →</div>
<div class="tool-card__desc">Name and sort a pile of incoming files.</div>
<ul class="tool-card__list">
<li>Rename messy files into clean, consistent names</li>
<li>Give each file a tracking number, revision, and status just by dropping it into place</li>
<li>Group deliverables into dated transmittal folders, ready to send</li>
<li>Edit like a spreadsheet; saves the organized copies back to your folder</li>
</ul>
<div class="tool-card__link" style="margin-top: var(--spacing-lg);">Open Classify →</div>
</a>
<a href="releases/archive.html" class="tool-card" style="text-decoration: none; display: block;">
<div class="tool-card__title">Archive</div>
<div class="tool-card__desc">The read-only window into 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. The archive is preserved exactly as-issued.</div>
<div class="tool-card__link">Open Archive →</div>
<div class="tool-card__desc">Find anything in your record.</div>
<ul class="tool-card__list">
<li>Search and filter by tracking number, status, discipline, or plain text</li>
<li>See every revision of a deliverable and where it is in its lifecycle</li>
<li>Group by transmittal to see what was sent, and when</li>
<li>Download any selection as a ZIP — read-only, nothing gets changed</li>
</ul>
<div class="tool-card__link" style="margin-top: var(--spacing-lg);">Open Archive →</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 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 an optional web-server app, purpose-built to serve a ZDDC archive over the network. <em>Any</em> web server gives you read-only online mode; <code class="inline">zddc-server</code> adds the things a generic one can't:</p>
<ul class="feature-list">
<li><strong>Access control, no database.</strong> Drop optional <code class="inline">.zddc</code> files along the tree to say who can read, write, create, or delete each folder — by email, wildcard, or named role. Write-once (WORM) archive folders keep the issued record immutable. <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc/README.md#access-control-the-zddc-cascade">How the cascade works →</a></li>
<li><strong>Less to set up.</strong> The canonical project layout appears on first use, the tools are baked in and served at the right paths automatically, and a virtual <code class="inline">.archive</code> URL always resolves to the current revision of any document.</li>
<li><strong>Built for regulated environments.</strong> Hardened TLS, per-request audit logging, and a pluggable policy engine (swap in <a href="https://www.openpolicyagent.org/" rel="noopener">Open Policy Agent</a> with your own Rego). See the <a href="federal.html">federal compliance page</a> for the supported deployment shape.</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, configuration, and the full ACL reference: <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc">codeberg.org/VARASYS/ZDDC <code class="inline">zddc/</code></a>.</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 app has the current-stable build of the tools baked in. They appear automatically at the right paths in the served tree:</p>
<ul class="install-points">
<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>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>classifier.html</strong> wherever a folder opts into it — assign tracking numbers and build transmittals</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># &lt;project&gt;/.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">&lt;ZDDC_ROOT&gt;/_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/browse.html">browse.html</a></li>
<li><a href="releases/classifier.html">classifier.html</a></li>
<li><a href="releases/archive.html">archive.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>
<p style="margin-top: var(--spacing-lg); color: var(--color-text-muted);">To open a folder straight from your computer, use a Chromium-based browser — Chrome, Edge, or Brave. That one feature isn't available in Firefox or Safari yet. <a href="releases/">Browse all versions →</a></p>
</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>
<li><a href="reference.html">Technical Reference</a> — the full ZDDC convention: filename format, tracking numbers, revisions, status codes, folder naming, and transmittal workflow.</li>
<li><a href="releases/">All releases</a> — every version of every tool.</li>
<li><a href="https://codeberg.org/VARASYS/ZDDC">codeberg.org/VARASYS/ZDDC</a> — source code and issue tracker.</li>
</ul>
</section>

View file

@ -84,8 +84,7 @@
<div class="ref-toc__item"><a href="#status-codes" class="ref-toc__link">7. Status codes</a></div>
<div class="ref-toc__item"><a href="#folder-naming" class="ref-toc__link">8. Folder naming</a></div>
<div class="ref-toc__item"><a href="#transmittal-workflow" class="ref-toc__link">9. Transmittal workflow</a></div>
<div class="ref-toc__item"><a href="#bootstrap" class="ref-toc__link">10. zddc-server bootstrap</a></div>
<div class="ref-toc__item"><a href="#tools" class="ref-toc__link">11. Tools</a></div>
<div class="ref-toc__item"><a href="#tools" class="ref-toc__link">10. Tools</a></div>
</nav>
</aside>
@ -223,10 +222,10 @@ status = "IFA" / "IFB" / "IFC" / "IFD" / "IFI" / "IFP" / "IFR" / "IFU" / "
</div>
<div class="highlight-box" style="margin-top: var(--spacing-lg);">
<p><strong>zddc-server defaults.</strong> The schemas above are deployment-agnostic — any of them is a valid tracking number. The <code>zddc-server</code> reference implementation ships the <strong>Basic</strong> schema by default (<code>originator-project-discipline-type-sequence</code>), plus the optional per-deliverable <code>[suffix]</code> (a hyphenated part marker such as <code>-A</code> for an appendix). Two deployment behaviours are worth knowing:</p>
<p><strong>A sensible default profile.</strong> The schemas above are all valid tracking numbers; pick the one that fits your project. A common starting point is the <strong>Basic</strong> schema (<code>originator-project-discipline-type-sequence</code>), plus the optional per-deliverable <code>[suffix]</code> (a hyphenated part marker such as <code>-A</code> for an appendix). Two conventions are worth knowing:</p>
<ul style="margin: var(--spacing-md) 0; padding-left: 1.5rem; color: var(--color-text-muted); line-height: 1.65;">
<li><strong>originator is bound to the party folder.</strong> Under <code>archive/&lt;party&gt;/</code>, the server sets <code>originator</code> from the party-folder name and renders it read-only — the folder is its single source of truth, so it can't drift from where the deliverable is filed.</li>
<li><strong>phase and area are off by default.</strong> Because they are project-wide (all-or-nothing across a project), the default omits them; a project that needs them enables them on <em>every</em> deliverable by extending the schema in its <code>.zddc</code> configuration.</li>
<li><strong>originator follows the party folder.</strong> When deliverables are filed under a per-party folder, the <code>originator</code> matches that folder's name — the folder is the single source of truth, so the code can't drift from where the document is filed.</li>
<li><strong>phase and area are off by default.</strong> Because they are project-wide (all-or-nothing across a project), most projects omit them; a project that needs them adds them to <em>every</em> deliverable.</li>
</ul>
</div>
@ -1013,75 +1012,33 @@ date = 4DIGIT "-" 2DIGIT "-" 2DIGIT
<!-- Section 9: Project layout & transmittal workflow -->
<section id="transmittal-workflow">
<h2>9. Project layout &amp; transmittal workflow</h2>
<p>A ZDDC project mirrors the natural lifecycle of an engineering deliverable: <strong>drafted in private, lined up for issue, formally exchanged, kept as record</strong>. Each canonical folder maps to one of those stages, so file location alone tells you where a document is in its lifecycle. An operator only needs to create one file — a <code>.zddc</code> in an empty directory — and the rest of the layout populates as work happens.</p>
<p>A ZDDC project mirrors the natural lifecycle of an engineering deliverable: <strong>drafted in private, lined up for issue, formally exchanged, kept as record</strong>. Each folder maps to one of those stages, so file location alone tells you where a document is in its lifecycle. You only create the folders you need, when you need them.</p>
<div class="code-block">
project/
.zddc ← the only file an operator must create
archive/ ← The only PHYSICAL project-root directory.
Everything party-scoped (records, lifecycle,
immutable archives) lives uniformly under
archive/&lt;party&gt;/.
{party-name}/ ← One per counterparty; one for ourselves.
We treat our own organisation as just another
party so internal deliverables get the same
tracking treatment as external ones.
mdl/ ← The party's Master Deliverables List —
what they're going to produce. Opens as
a grid editor; rows are individual .yaml
files, one per deliverable.
rsk/ ← Risk register for this party. Same grid
editor as mdl/.
incoming/ ← Where the counterparty drops things for us.
A quality-check buffer before content
becomes part of the permanent record.
received/ ← What we've accepted from that party.
Immutable (WORM); the historical record
of inbound documents.
issued/ ← What we sent to that party. Immutable
(WORM); the historical record of outbound
documents.
working/ ← Where this party's staff draft. Each
person has a private subfolder here
(named by email) and iterates until ready
to commit. The browse tool handles
everything here.
&lt;your-email&gt;/ ← Your private workspace under THIS
party. Fenced (inherit:false) by the
auto-own .zddc, so other team members
only see what you explicitly share.
staging/ ← The "about to issue" lane for this party.
Drop files here and the project_team
gives them up — only the doc-controller
can change a file after it lands. Each
sub-folder declares a planned outbound
transmittal (name carries the date +
tracking number).
reviewing/ ← One place per party to see everything we
owe a response on. Folders are scaffolded
by Plan Review, each pairing an inbound
submittal in received/ with the in-progress
response draft.
ssr/ ← Virtual aggregator: tables rollup of every
party's ssr.yaml row, with a synthesised
$party column. Never on disk.
mdl/ ← Virtual aggregator: tables rollup of every
party's mdl/*.yaml deliverables.
rsk/ ← Virtual aggregator: tables rollup of every
party's rsk/*.yaml risk rows.
working/ ← Virtual aggregator: browse folder-nav listing
parties with non-empty content in working/.
Per-party clicks 302-redirect to the canonical
archive/&lt;party&gt;/working/.
staging/ ← Same shape as working/ for the staging slot.
reviewing/ ← Same shape as working/ for the reviewing slot.
archive/ ← Holds everything, organised by party.
{party-name}/ ← One folder per organisation you exchange
with — and one for yourselves. Your own
deliverables get the same treatment as
anyone else's.
mdl/ ← Master Deliverables List for this party —
what they are going to produce.
rsk/ ← Risk register for this party.
incoming/ ← Where this party drops things for you;
a checking buffer before you accept them.
received/ ← What you have accepted from that party.
A permanent, write-once record.
issued/ ← What you have sent to that party.
A permanent, write-once record.
working/ ← Where your team drafts. Each person works
in their own subfolder until a file is ready.
staging/ ← The "about to issue" lane: drop finished
files here to line up an outbound transmittal.
reviewing/ ← One place to track everything you owe a
response on.
</div>
<p style="margin-top: var(--spacing-md); font-size: 0.95em; color: var(--color-text-soft);"><em>Mechanics:</em> folders materialise on first write, names match case-insensitively, the WORM zones (<code>received/</code>, <code>issued/</code>) enforce write-once via an ACL mask, and the six top-level aggregators (<code>ssr</code>/<code>mdl</code>/<code>rsk</code>/<code>working</code>/<code>staging</code>/<code>reviewing</code>) are virtual — they never materialise on disk but show up in listings, computed from <code>archive/&lt;party&gt;/&hellip;</code> at request time. Mkdir at the project root is restricted to <code>archive</code> + system names (<code>_</code>/<code>.</code>-prefixed) so the virtual names can never be shadowed by a physical folder. Drop files where the lifecycle says they go and the layout takes care of itself.</p>
<p style="margin-top: var(--spacing-md); font-size: 0.95em; color: var(--color-text-soft);"><em>The in-flight ratchet.</em> <code>working/</code><code>staging/</code><code>issued/</code> is a one-way handoff. <code>project_team</code> iterates freely in <code>working/</code> (the auto-own-fenced subfolder gives each user a private <code>rwcda</code> workspace). When they drop a file into <code>staging/</code> their access downgrades to <code>cr</code> — they can drop more, but only the <code>document_controller</code> can change what's already there. When DC publishes to <code>issued/</code>, the WORM mask downgrades even DC to <code>cr</code> (write-once). Each handoff is a commitment by permission-loss.</p>
<p style="margin-top: var(--spacing-md); font-size: 0.95em; color: var(--color-text-soft);"><em>How it flows.</em> <code>working/</code><code>staging/</code><code>issued/</code> is a one-way progression: your team drafts freely in <code>working/</code>, lines finished files up in <code>staging/</code> for the document controller to sign off, and the document controller publishes the package into <code>issued/</code> as the permanent record. Treat <code>received/</code> and <code>issued/</code> as write-once — once a document lands there, it stays exactly as filed.</p>
<p><strong>5-step transmittal workflow:</strong></p>
@ -1133,156 +1090,21 @@ project/
</div>
<h3>Drafting a response transmittal</h3>
<p>Submittals from counterparties (tracking numbers containing <code>-SUB-</code> at status <code>IFR</code> or <code>IFA</code>) require a response transmittal whose status starts with <code>RS</code> (RSA, RSB, RSC, …). The flow walks the ratchet:</p>
<p>Submittals from counterparties (tracking numbers containing <code>-SUB-</code> at status <code>IFR</code> or <code>IFA</code>) require a response transmittal whose status starts with <code>RS</code> (RSA, RSB, RSC, …). The flow follows the same lifecycle:</p>
<ol>
<li>Right-click the submittal in <code>archive/&lt;party&gt;/received/&lt;tracking&gt;/</code> and pick <strong>Plan Review</strong>. The server scaffolds a workflow folder at <code>archive/&lt;party&gt;/reviewing/&lt;tracking&gt;/</code> — its <code>.zddc</code> carries a <code>received_path</code> pointer back to the canonical submittal and a planned response date.</li>
<li>The party's working subfolder under <code>archive/&lt;party&gt;/working/&lt;your-email&gt;/</code> is where reviewer notes and the response payload are drafted. The <code>reviewing/</code> virtual aggregator at the project root surfaces all open reviews across parties.</li>
<li>When the response is ready, files move from <code>working/</code> into <code>archive/&lt;party&gt;/staging/</code> for sign-off. Project team's permission on staged files downgrades to <code>cr</code> — the doc controller takes over.</li>
<li>The doc controller cuts the package from <code>staging/</code> into <code>archive/&lt;party&gt;/issued/</code> via the standard 5-step transmittal flow. The reviewing scaffold is deleted at issue time.</li>
<li>For a submittal in <code>received/</code>, start a review folder under <code>reviewing/</code> that points back to it, so every open response is in one place.</li>
<li>Draft your reviewer notes and the response itself in <code>working/</code>.</li>
<li>When the response is ready, move the files into <code>staging/</code> for the document controller to sign off.</li>
<li>The document controller issues the package from <code>staging/</code> into <code>issued/</code> via the standard 5-step transmittal flow.</li>
</ol>
</section>
<!-- Section 10: zddc-server bootstrap -->
<section id="bootstrap">
<h2>10. zddc-server bootstrap</h2>
<div class="highlight-box">
<p><strong>A fresh <code>zddc-server</code> deployment grants no access to anyone until two config files are populated.</strong> Without them the server runs but every request returns 403. The embedded defaults ship with empty role members, so deployments must opt-in to authorize anyone — there is no default "anything goes" mode (except <code>--insecure</code>, which is explicitly for deliberately-public archives).</p>
</div>
<p>Two files, both named <code>.zddc</code>. YAML format. Hand-edited.</p>
<h3>Step 1 — root <code>/.zddc</code></h3>
<p>At <code>&lt;ZDDC_ROOT&gt;/.zddc</code>, name at least one admin:</p>
<div class="code-block">admins:
- cwitt@burnsmcd.com
</div>
<p><code>admins:</code> is honored only at the root file. Admins behave as normal users by default and elevate per-request via the <code>zddc-elevate=1</code> cookie (the header toggle visible in every tool) or implicitly when authenticating with a bearer token. This sudo-style model means an admin can't accidentally clobber files in their everyday browsing — elevation is opt-in.</p>
<p>Without this file the server refuses to start (the served tree would be publicly accessible to anonymous callers); pass <code>--insecure</code> to acknowledge a deliberately-public deployment.</p>
<h3>Step 2 — per-project <code>&lt;project&gt;/.zddc</code></h3>
<p>In each project, populate role members:</p>
<div class="code-block">title: "Project Phoenix"
roles:
document_controller:
members:
- dc1@burnsmcd.com
project_team:
members:
- '*@burnsmcd.com' # all internal staff
observer: # optional — external audit
members:
- auditor@external.com
</div>
<p>That's it. The embedded cascade does the rest:</p>
<ul style="margin: var(--spacing-md) 0; padding-left: 1.5rem; color: var(--color-text-muted); line-height: 1.65;">
<li><code>project_team</code> gets read across the project plus the in-flight ratchet (<code>cr</code> in <code>working/</code> + <code>reviewing/</code> + <code>staging/</code>, with <code>rwcda</code> inside each user's auto-own-fenced home under <code>working/</code>).</li>
<li><code>document_controller</code> creates party folders at <code>archive/</code>; when they do, the auto-own <code>.zddc</code> written at <code>archive/&lt;party&gt;/</code> grants both their email AND the <code>document_controller</code> role <code>rwcda</code> — so any DC in the role has full authority at every party a peer created. Explicit <code>rwcd</code> grants at <code>incoming/</code>/<code>staging/</code> for the QC + transfer workflows, and WORM <code>cr</code> at <code>received/</code>/<code>issued/</code> for write-once filing.</li>
<li><code>observer</code> is pure read-only across the project — intended for external auditors, regulators, and read-only viewers who must not contribute content.</li>
</ul>
<p style="margin-top: var(--spacing-md);">A DC is typically also a project team member (the <code>*@burnsmcd.com</code> glob catches them). The embedded defaults restate <code>document_controller: rwcda</code> at every slot that grants project_team a narrower verb — within-level union of all matched principals gives DCs <code>rwcda</code> <code>cr</code> = <code>rwcda</code>, preserving full authority. <strong>Document controllers are not subtree-admins anywhere.</strong> Their power comes purely from cascade grants; admin elevation is reserved for the root <code>admins:</code> list (the human escape hatch).</p>
<p>Add a new project team member with one line; revoke by removing the line. No need to restate the cascade's grants — they're already in the embedded defaults that ship with <code>zddc-server</code>.</p>
<h3>Schema essentials</h3>
<table>
<thead>
<tr>
<th scope="col">Key</th>
<th scope="col">Where</th>
<th scope="col">Shape</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>admins:</code></td>
<td>Root only</td>
<td>List of emails. Sudo-style; gates on <code>zddc-elevate=1</code>.</td>
</tr>
<tr>
<td><code>acl:</code></td>
<td>Anywhere; cascades</td>
<td><code>{ permissions: { &lt;principal&gt;: &lt;bits&gt; }, inherit: &lt;bool&gt;? }</code></td>
</tr>
<tr>
<td><code>roles:</code></td>
<td>Anywhere; members union across the cascade</td>
<td><code>{ &lt;name&gt;: { members: [...], reset: &lt;bool&gt;? } }</code></td>
</tr>
<tr>
<td><code>title:</code></td>
<td>Per-project only</td>
<td>String; surfaces on the landing-page picker.</td>
</tr>
</tbody>
</table>
<p><strong>Permission bits</strong> — any subset of:</p>
<ul style="margin: var(--spacing-md) 0; padding-left: 1.5rem; color: var(--color-text-muted); line-height: 1.65;">
<li><code>r</code> read</li>
<li><code>w</code> write (overwrite existing files)</li>
<li><code>c</code> create (new files, new directories)</li>
<li><code>d</code> delete</li>
<li><code>a</code> admin (modify the <code>.zddc</code> ACL at this level — distinct from the root <code>admins:</code> list, which is the elevation-bypass sudo channel)</li>
</ul>
<p>An empty bits string (<code>''</code>) is an explicit deny.</p>
<p><strong>Principals</strong> — three forms:</p>
<ul style="margin: var(--spacing-md) 0; padding-left: 1.5rem; color: var(--color-text-muted); line-height: 1.65;">
<li>Email address — must contain <code>@</code>, e.g. <code>alice@burnsmcd.com</code></li>
<li>Email glob — wildcard on the local part, e.g. <code>'*@acme.com'</code> (quote it in YAML so the leading <code>*</code> doesn't confuse the parser)</li>
<li>Role name — anything without an <code>@</code>, e.g. <code>document_controller</code>. The role's members are looked up via <code>roles:</code> at any cascade level.</li>
</ul>
<h3>Common footgun</h3>
<div class="highlight-box">
<p><strong>This is silently dropped:</strong></p>
<div class="code-block" style="margin: var(--spacing-sm) 0;">acl:
allow:
- '*@burnsmcd.com'
</div>
<p>The YAML parses cleanly but <code>ACLRules</code> only reads <code>permissions:</code>. The <code>allow:</code> block is discarded during unmarshal and you end up with zero grants. Correct form:</p>
<div class="code-block" style="margin: var(--spacing-sm) 0;">acl:
permissions:
'*@burnsmcd.com': r
</div>
</div>
<h3>Verifying the bootstrap</h3>
<p><code>zddc-server</code> prints a startup warning when the root <code>.zddc</code> grants nobody anything — watch for it on first boot:</p>
<div class="code-block">level=WARN msg="root .zddc grants nobody anything (no admins,
no acl.permissions, no role members). ZDDC will refuse every
request until you populate it..."</div>
<p>To dump the full annotated schema (every cascade key with documentation):</p>
<div class="code-block">zddc-server show-defaults</div>
<p>That prints the embedded <code>defaults.zddc.yaml</code> with comments explaining every option (<code>worm:</code>, <code>auto_own:</code>, <code>auto_own_roles:</code>, <code>auto_own_fenced:</code>, <code>drop_target:</code>, <code>apps:</code>, <code>convert:</code>, <code>records:</code>, <code>available_tools:</code>, <code>default_tool:</code>, <code>dir_tool:</code>, and more). Pipe it to a file and use it as the starting point for any deeper customization.</p>
</section>
<!-- Section 11: Tools -->
<!-- Section 10: Tools -->
<section id="tools">
<h2>11. Tools</h2>
<p>Single-file HTML applications — each is complete and self-contained. Save one locally and it works forever, without internet, without updates, without a subscription. None of them require any configuration to run; <code>.zddc</code> files and <code>zddc-server</code> only add to them. Together they cover the full ZDDC workflow: <strong>browse</strong> to look at anything; <strong>classify</strong> to name incoming files and build transmittals; <strong>archive</strong> to search and export the formal record.</p>
<h2>10. Tools</h2>
<p>Single-file HTML applications — each is complete and self-contained. Save one locally and it works forever, without internet, without updates, without a subscription. None of them require any configuration to run; optional <code>.zddc</code> files only add to them. Together they cover the full ZDDC workflow: <strong>browse</strong> to look at anything; <strong>classify</strong> to name incoming files and build transmittals; <strong>archive</strong> to search and export the formal record.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--spacing-lg); margin-top: var(--spacing-lg);">
<div class="tools-grid">
<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">Open any folder on your disk — no setup. A file-tree navigator with live preview, plus in-place markdown editing (YAML front matter pane, table of contents) and export to DOCX, HTML, or PDF. Optional <code>.zddc</code> files add friendly labels, per-folder tools, permissions, and transmittal actions; without them it is still a complete browser.</div>
@ -1302,7 +1124,7 @@ request until you populate it..."</div>
</a>
</div>
<p style="margin-top: var(--spacing-xl); color: var(--color-text-muted);">Local directory access relies on the <a href="https://www.chromium.org/Home/">Chromium</a>-based browser File System Access API. It does not work in Firefox or Safari. Run the tools through <code>zddc-server</code> for any browser, network access, and ACL enforcement.</p>
<p style="margin-top: var(--spacing-xl); color: var(--color-text-muted);">To open a folder directly from your computer, use a Chromium-based browser — Chrome, Edge, or Brave. That feature relies on the browser's <a href="https://www.chromium.org/Home/">File System Access API</a>, which Firefox and Safari do not yet support.</p>
</section>
</main>
</div>