feat(web): releases index, alpha+beta channel builds, inline server section

Three things on the public website:

1) Cut alpha and beta channel builds for all five tools, so each tool
   now has stable + beta + alpha actually published — previously
   beta and alpha were vapor for archive (which had been freshened
   earlier) and missing entirely for the others. The intro page's
   tool cards now point at real artifacts on every channel.

2) New website/releases/index.html — a generated index of every
   version + channel of every tool, with stable/beta/alpha pill
   links per tool and a "Pin to version" row of every concrete
   v0.0.X build. Regenerated by build.sh's new build_releases_index
   function (reads the filesystem so it is always consistent with
   what is actually under releases/). Linked from the intro page nav
   (Releases), from the bottom of the Try the tools section
   ("Browse all versions"), and from the Learn more list.
   reference.html's nav gets the same Releases link.

3) Folded website/zddc-server.html into website/index.html as a new
   inline section ("zddc-server (optional)") below the tool cards.
   The earlier separate page is removed; the broken Server nav link
   that pointed at it is gone too. The new section leads with the
   dual-mode insight (the tools work locally on a folder OR via any
   web server, including the optional zddc-server) and frames
   zddc-server as a small Go binary that adds things a generic web
   server cannot: ACL via .zddc files, virtual .archive URL space,
   per-request access logging, mundane glue. The What is it?
   paragraph also mentions the dual-mode story up front so users
   reading top-to-bottom get the framing before they hit the cards.

Also caught two stale _latest.html refs missed by the earlier
rename sweep: 8 tool links in reference.html and a comment line in
CLAUDE.md. Verified with a full link audit — every relative href in
index.html, reference.html, and releases/index.html now resolves to
an existing file under website/.

ARCHITECTURE.md doc-ownership table updated: zddc-server.html row
removed; new row added for the regenerated releases/index.html.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-04-28 10:00:10 -05:00
parent 67f794e6d0
commit 91d6e61e22
21 changed files with 45216 additions and 186 deletions

View file

@ -59,11 +59,11 @@ Each topic has exactly one authoritative home; everything else links to it.
| Topic | Single home | Linked from |
|---|---|---|
| What ZDDC is + tool channel links + install bundles | `website/index.html` (hand-edited intro for `zddc.varasys.io/`) | repo `README.md`, `bootstrap/README.md` |
| What ZDDC is + tool channel links + dual-mode (local/server) overview + install bundles | `website/index.html` (hand-edited intro for `zddc.varasys.io/`) | repo `README.md`, `bootstrap/README.md` |
| File-naming convention spec (status codes, modifiers, folder format) | `website/reference.html` | repo `README.md`, in-tool help text |
| Local-mode vs online-mode concept; what `zddc-server` adds | `website/zddc-server.html` | website intro |
| Customer-deployment install (install.zip, level-1/2 stubs, `?v=`, audit) | `bootstrap/README.md` | website intro, `zddc/README.md`, `zddc-server.html` |
| zddc-server operations: env vars, ACL syntax, `.archive` URLs, container vs binary | `zddc/README.md` | `AGENTS.md`, `bootstrap/README.md`, `zddc-server.html` |
| Versions + channel builds index of every tool | `website/releases/index.html` (regenerated by `build.sh`) | website intro nav, "Browse all versions" link |
| Customer-deployment install (install.zip, level-1/2 stubs, `?v=`, audit) | `bootstrap/README.md` | website intro, `zddc/README.md` |
| zddc-server operations: env vars, ACL syntax, `.archive` URLs, container vs binary | `zddc/README.md` | `AGENTS.md`, `bootstrap/README.md`, website intro |
| Build / release / channel commands | `AGENTS.md` | repo `README.md` ("see AGENTS.md") |
| Architecture & internal patterns | `ARCHITECTURE.md` (this file) | `AGENTS.md` |
| Per-tool internal design quirks | `<tool>/README.md` | (linked from website intro tool cards) |

View file

@ -26,7 +26,7 @@ This is a **monorepo of independent tools**, not one application:
```bash
sh build.sh # build all five HTML tools (dist/ only)
sh tool/build.sh # build one (archive|transmittal|classifier|mdedit|landing)
sh tool/build.sh --release [version] # cut stable; tag, write website/releases/<tool>_v<ver>.html, refresh _latest symlink
sh tool/build.sh --release [version] # cut stable; tag, write website/releases/<tool>_v<ver>.html, refresh _stable symlink
sh tool/build.sh --release alpha|beta # cut channel build; overwrites website/releases/<tool>_<channel>.html (mutable, no tag)
npm test # all Playwright specs (build first!)
npx playwright test <tool> # one spec

107
build.sh
View file

@ -134,12 +134,117 @@ EOF
rm -rf "$_staging"
}
# Regenerate website/releases/index.html — a static directory listing of
# all tool releases with channel rows + per-version archive links. Read
# from the filesystem so the page is always consistent with what's there.
build_releases_index() {
_out="$RELEASES_DIR/index.html"
{
cat <<'HEAD'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Releases — ZDDC</title>
<meta name="description" content="All released versions and channel builds of every ZDDC tool.">
<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>
.rel-tool { margin-top: var(--spacing-xl); padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; }
.rel-tool h2 { margin-top: 0; }
.rel-channels { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0 1.25rem 0; }
.rel-channels a { padding: 0.25rem 0.625rem; border-radius: 999px; text-decoration: none; border: 1px solid var(--color-border); color: var(--color-text); font-size: 0.9rem; }
.rel-channels a.stable { border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
.rel-channels a.beta, .rel-channels a.alpha { color: var(--color-text-muted); }
.rel-channels a:hover { background: var(--color-bg-subtle); }
.rel-versions { font-size: 0.875rem; color: var(--color-text-muted); }
.rel-versions a { margin-right: 0.5rem; color: var(--color-text); text-decoration: none; padding: 0.1rem 0.4rem; border-radius: 4px; }
.rel-versions a:hover { background: var(--color-bg-subtle); text-decoration: underline; }
.rel-meta { font-size: 0.85rem; color: var(--color-text-muted); margin-top: 0.5rem; }
</style>
</head>
<body>
<header class="site-header">
<div class="container header-content">
<a href="/" class="brand">
<div class="brand-logo">
<svg viewBox="0 0 24 24"><path d="M3 5h18v2H3V5zm0 6h12v2H3v-2zm0 6h6v2H3v-2z" /></svg>
</div>
<span class="brand-name">ZDDC</span>
</a>
<nav class="header-nav">
<a href="/" class="nav-link">Home</a>
<a href="../reference.html" class="nav-link">Docs</a>
<a href="index.html" class="nav-link active">Releases</a>
</nav>
</div>
</header>
<section class="hero">
<div class="container">
<h1>Releases</h1>
<p class="hero-subtitle">All published versions and channel builds of every ZDDC tool. Stable releases are immutable; alpha and beta channels are rebuilt without notice.</p>
</div>
</section>
<main class="container" style="margin-bottom: var(--spacing-2xl);">
HEAD
printf '%s\n' "$TOOL_TABLE" | while IFS='|' read -r _tool _file _title; do
_stable_target=""
if [ -L "$RELEASES_DIR/${_tool}_stable.html" ]; then
_stable_target=$(readlink "$RELEASES_DIR/${_tool}_stable.html")
fi
printf ' <section class="rel-tool">\n'
printf ' <h2>%s</h2>\n' "$_title"
printf ' <div class="rel-channels">\n'
[ -e "$RELEASES_DIR/${_tool}_stable.html" ] && printf ' <a class="stable" href="%s_stable.html">stable</a>\n' "$_tool"
[ -e "$RELEASES_DIR/${_tool}_beta.html" ] && printf ' <a class="beta" href="%s_beta.html">beta</a>\n' "$_tool"
[ -e "$RELEASES_DIR/${_tool}_alpha.html" ] && printf ' <a class="alpha" href="%s_alpha.html">alpha</a>\n' "$_tool"
printf ' </div>\n'
_versions=$(ls -1 "$RELEASES_DIR" 2>/dev/null | grep -E "^${_tool}_v[0-9]" | sort -V -r)
if [ -n "$_versions" ]; then
printf ' <div class="rel-versions"><strong>Pin to version:</strong>\n'
printf '%s\n' "$_versions" | while read -r _v; do
_ver=${_v#${_tool}_v}; _ver=${_ver%.html}
printf ' <a href="%s">v%s</a>\n' "$_v" "$_ver"
done
printf ' </div>\n'
fi
if [ -n "$_stable_target" ]; then
printf ' <div class="rel-meta">stable currently → %s</div>\n' "$_stable_target"
fi
printf ' </section>\n'
done
cat <<'TAIL'
<section style="margin-top: var(--spacing-2xl); color: var(--color-text-muted); font-size: 0.9rem;">
<p>Append <code>?v=alpha</code>, <code>?v=beta</code>, <code>?v=stable</code>, or <code>?v=0.0.1</code> to any deployment URL to switch versions for a single request — see <a href="../">the home page</a>.</p>
</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>
</body>
</html>
TAIL
} > "$_out"
echo "Wrote $_out"
}
echo ""
echo "=== Building install.zip and track-*.zip ==="
echo "=== Building install.zip, track-*.zip, releases/index.html ==="
build_install_zip
build_track_zip alpha
build_track_zip beta
build_track_zip stable
build_releases_index
echo ""
echo "=== All tools built successfully ==="

View file

@ -24,7 +24,13 @@
@media (min-width: 720px) { .install-grid { grid-template-columns: repeat(2, 1fr); } }
.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; }
.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>
@ -69,7 +75,7 @@
</div>
</div>
<a href="reference.html" class="nav-link">Docs</a>
<a href="zddc-server.html" class="nav-link">Server</a>
<a href="releases/" class="nav-link">Releases</a>
</nav>
</div>
</header>
@ -87,7 +93,7 @@
<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 four tools below are <em>optional</em> interfaces around this structure. Each is a single self-contained HTML file. Save it locally and it works forever, without internet, updates, or a subscription.</p>
<p>The four 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>
@ -139,7 +145,38 @@
</div>
<p style="margin-top: var(--spacing-lg); color: var(--color-text-muted);">Append <code class="inline">?v=alpha</code> (or <code class="inline">?v=0.0.4</code>, etc.) to any URL to switch versions 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).</p>
<p style="margin-top: var(--spacing-lg); color: var(--color-text-muted);">Append <code class="inline">?v=alpha</code> (or <code class="inline">?v=0.0.4</code>, etc.) to any URL to switch versions 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>Access control via <code class="inline">.zddc</code> files.</strong> Behind a reverse proxy that authenticates users and sets an <code class="inline">X-Email</code> request header, <code class="inline">zddc-server</code> consults YAML <code class="inline">.zddc</code> files in directories — cascading bottom-up; deeper rules override. No database, no admin UI.</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>Per-request access logging</strong> keyed to the authenticated user.</li>
<li><strong>TLS, ETags, conditional GET, CORS, autoindex.</strong> The mundane glue.</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, container image, 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 image at <code class="inline">codeberg.org/varasys/zddc-server</code> (channel-tagged <code class="inline">:stable</code>, <code class="inline">:beta</code>, <code class="inline">:alpha</code>).</p>
</section>
<section style="margin-top: var(--spacing-2xl);">
@ -176,8 +213,8 @@
<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="releases/">All releases</a> — every version and channel build 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="zddc-server.html">zddc-server</a> — how the local-mode and online-mode tools relate, and what the optional Go HTTP server adds (access control, virtual archive index, audit logging).</li>
</ul>
</section>

Binary file not shown.

View file

@ -37,19 +37,19 @@
</button>
<div class="dropdown-menu">
<div class="dropdown-menu__inner">
<a href="releases/archive_latest.html">
<a href="releases/archive_stable.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/transmittal_latest.html">
<a href="releases/transmittal_stable.html">
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
Transmittal Creator
</a>
<a href="releases/classifier_latest.html">
<a href="releases/classifier_stable.html">
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
Document Classifier
</a>
<a href="releases/mdedit_latest.html">
<a href="releases/mdedit_stable.html">
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
Markdown Editor
</a>
@ -57,7 +57,7 @@
</div>
</div>
<a href="reference.html" class="nav-link active">Docs</a>
<a href="zddc-server.html" class="nav-link">Server</a>
<a href="releases/" class="nav-link">Releases</a>
</nav>
</div>
</header>
@ -979,25 +979,25 @@ project/
<p>Four single-file HTML applications — each is complete and self-contained. Save them locally and they work forever, without internet, without updates, without a subscription.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--spacing-lg); margin-top: var(--spacing-lg);">
<a href="releases/archive_latest.html" class="tool-card" style="text-decoration: none; display: block;">
<a href="releases/archive_stable.html" class="tool-card" style="text-decoration: none; display: block;">
<div class="tool-card__title">Archive Browser</div>
<div class="tool-card__desc">Browse, search, filter your project folder. Filter by tracking number, discipline, revision, status, or free text. Group by transmittal. Download selected files as ZIP.</div>
<div class="tool-card__link">Open Archive Browser</div>
</a>
<a href="releases/transmittal_latest.html" class="tool-card" style="text-decoration: none; display: block;">
<a href="releases/transmittal_stable.html" class="tool-card" style="text-decoration: none; display: block;">
<div class="tool-card__title">Transmittal Creator</div>
<div class="tool-card__desc">Fill in metadata, drag in files, publish a self-contained HTML transmittal record with SHA-256 checksums. Supports digital signatures. The published file IS the transmittal record.</div>
<div class="tool-card__link">Create Transmittal</div>
</a>
<a href="releases/classifier_latest.html" class="tool-card" style="text-decoration: none; display: block;">
<a href="releases/classifier_stable.html" class="tool-card" style="text-decoration: none; display: block;">
<div class="tool-card__title">Document Classifier</div>
<div class="tool-card__desc">Spreadsheet-like interface for bulk-renaming files to ZDDC format. Copy/paste with Excel. Point it at a folder, fill in the columns, save all at once.</div>
<div class="tool-card__link">Run Classifier</div>
</a>
<a href="releases/mdedit_latest.html" class="tool-card" style="text-decoration: none; display: block;">
<a href="releases/mdedit_stable.html" class="tool-card" style="text-decoration: none; display: block;">
<div class="tool-card__title">Markdown Editor</div>
<div class="tool-card__desc">Browser-based markdown editor with live preview, YAML front matter support, and table of contents. Direct local file access via File System Access API.</div>
<div class="tool-card__link">Open Editor</div>

View file

@ -2078,7 +2078,7 @@ td[data-field="trackingNumber"] {
<div class="header-left">
<div class="header-title-group">
<span class="app-header__title">ZDDC Archive</span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">alpha · 2026-04-27 · ea385b5</span></span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">alpha · 2026-04-28 · 67f794e</span></span>
</div>
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh Data" style="font-size:1.1rem;"></button>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

124
website/releases/index.html Normal file
View file

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Releases — ZDDC</title>
<meta name="description" content="All released versions and channel builds of every ZDDC tool.">
<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>
.rel-tool { margin-top: var(--spacing-xl); padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; }
.rel-tool h2 { margin-top: 0; }
.rel-channels { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0 1.25rem 0; }
.rel-channels a { padding: 0.25rem 0.625rem; border-radius: 999px; text-decoration: none; border: 1px solid var(--color-border); color: var(--color-text); font-size: 0.9rem; }
.rel-channels a.stable { border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
.rel-channels a.beta, .rel-channels a.alpha { color: var(--color-text-muted); }
.rel-channels a:hover { background: var(--color-bg-subtle); }
.rel-versions { font-size: 0.875rem; color: var(--color-text-muted); }
.rel-versions a { margin-right: 0.5rem; color: var(--color-text); text-decoration: none; padding: 0.1rem 0.4rem; border-radius: 4px; }
.rel-versions a:hover { background: var(--color-bg-subtle); text-decoration: underline; }
.rel-meta { font-size: 0.85rem; color: var(--color-text-muted); margin-top: 0.5rem; }
</style>
</head>
<body>
<header class="site-header">
<div class="container header-content">
<a href="/" class="brand">
<div class="brand-logo">
<svg viewBox="0 0 24 24"><path d="M3 5h18v2H3V5zm0 6h12v2H3v-2zm0 6h6v2H3v-2z" /></svg>
</div>
<span class="brand-name">ZDDC</span>
</a>
<nav class="header-nav">
<a href="/" class="nav-link">Home</a>
<a href="../reference.html" class="nav-link">Docs</a>
<a href="index.html" class="nav-link active">Releases</a>
</nav>
</div>
</header>
<section class="hero">
<div class="container">
<h1>Releases</h1>
<p class="hero-subtitle">All published versions and channel builds of every ZDDC tool. Stable releases are immutable; alpha and beta channels are rebuilt without notice.</p>
</div>
</section>
<main class="container" style="margin-bottom: var(--spacing-2xl);">
<section class="rel-tool">
<h2>Archive</h2>
<div class="rel-channels">
<a class="stable" href="archive_stable.html">stable</a>
<a class="beta" href="archive_beta.html">beta</a>
<a class="alpha" href="archive_alpha.html">alpha</a>
</div>
<div class="rel-versions"><strong>Pin to version:</strong>
<a href="archive_v0.0.1.html">v0.0.1</a>
</div>
<div class="rel-meta">stable currently → archive_v0.0.1.html</div>
</section>
<section class="rel-tool">
<h2>Transmittal</h2>
<div class="rel-channels">
<a class="stable" href="transmittal_stable.html">stable</a>
<a class="beta" href="transmittal_beta.html">beta</a>
<a class="alpha" href="transmittal_alpha.html">alpha</a>
</div>
<div class="rel-versions"><strong>Pin to version:</strong>
<a href="transmittal_v0.0.1.html">v0.0.1</a>
</div>
<div class="rel-meta">stable currently → transmittal_v0.0.1.html</div>
</section>
<section class="rel-tool">
<h2>Classifier</h2>
<div class="rel-channels">
<a class="stable" href="classifier_stable.html">stable</a>
<a class="beta" href="classifier_beta.html">beta</a>
<a class="alpha" href="classifier_alpha.html">alpha</a>
</div>
<div class="rel-versions"><strong>Pin to version:</strong>
<a href="classifier_v0.0.1.html">v0.0.1</a>
</div>
<div class="rel-meta">stable currently → classifier_v0.0.1.html</div>
</section>
<section class="rel-tool">
<h2>Markdown Editor</h2>
<div class="rel-channels">
<a class="stable" href="mdedit_stable.html">stable</a>
<a class="beta" href="mdedit_beta.html">beta</a>
<a class="alpha" href="mdedit_alpha.html">alpha</a>
</div>
<div class="rel-versions"><strong>Pin to version:</strong>
<a href="mdedit_v0.0.1.html">v0.0.1</a>
</div>
<div class="rel-meta">stable currently → mdedit_v0.0.1.html</div>
</section>
<section class="rel-tool">
<h2>ZDDC</h2>
<div class="rel-channels">
<a class="stable" href="landing_stable.html">stable</a>
<a class="beta" href="landing_beta.html">beta</a>
<a class="alpha" href="landing_alpha.html">alpha</a>
</div>
<div class="rel-versions"><strong>Pin to version:</strong>
<a href="landing_v0.0.1.html">v0.0.1</a>
</div>
<div class="rel-meta">stable currently → landing_v0.0.1.html</div>
</section>
<section style="margin-top: var(--spacing-2xl); color: var(--color-text-muted); font-size: 0.9rem;">
<p>Append <code>?v=alpha</code>, <code>?v=beta</code>, <code>?v=stable</code>, or <code>?v=0.0.1</code> to any deployment URL to switch versions for a single request — see <a href="../">the home page</a>.</p>
</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>
</body>
</html>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -2191,7 +2191,7 @@ dialog.modal--narrow {
<span id="no-js-notice" class="text-gray-400 text-xs italic">JavaScript not available</span>
<div class="header-title-group">
<span class="app-header__title">ZDDC Transmittal</span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">beta · 2026-04-27 · ea385b5</span></span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">beta · 2026-04-28 · 67f794e</span></span>
</div>
<div class="app-header__spacer"></div>
<div class="app-header__icons">
@ -2509,7 +2509,7 @@ dialog.modal--narrow {
<li><strong>Digital signatures</strong> &mdash; ECDSA signatures bind the digest to a signer&rsquo;s private key. Any change invalidates the signature, preventing undetected tampering. Add signatures after publishing via <em>Add Signature</em>.</li>
<li><strong>Independent verification</strong> &mdash; A tampered HTML file could ship modified JavaScript that always says &ldquo;Verified.&rdquo; To rule this out, the recipient opens the sender&rsquo;s file in their <em>own</em> trusted copy of the tool using <em>Import HTML</em>. This extracts the raw data and re-verifies it with the recipient&rsquo;s own code. Use this level for anything that matters.</li>
</ol>
<p class="text-sm text-gray-500">Level&nbsp;4 assumes the recipient&rsquo;s tool is trustworthy (downloaded from a known source or built from source). A reference instance is at <a href="https://zddc.varasys.io/releases/transmittal_latest.html" target="_blank" rel="noopener">zddc.varasys.io</a>.</p>
<p class="text-sm text-gray-500">Level&nbsp;4 assumes the recipient&rsquo;s tool is trustworthy (downloaded from a known source or built from source). A reference instance is at <a href="https://zddc.varasys.io/releases/transmittal_stable.html" target="_blank" rel="noopener">zddc.varasys.io</a>.</p>
<h3>Menu Actions</h3>
<p>Actions available from the dropdown button. <span class="help-badge help-badge--draft">draft</span> items appear only while editing. <span class="help-badge help-badge--published">published</span> items appear only after publishing. Unmarked items appear in both modes.</p>
@ -10548,7 +10548,7 @@ When you open a transmittal, it may display "✓ Signature Valid" - but **this d
**For Document Controllers / Official Verification:**
1. **Use a trusted tool instance** - Download the official transmittal tool from a trusted source (e.g., your organization's approved version or https://zddc.varasys.io/releases/transmittal_latest.html)
1. **Use a trusted tool instance** - Download the official transmittal tool from a trusted source (e.g., your organization's approved version or https://zddc.varasys.io/releases/transmittal_stable.html)
2. **Export JSON from the transmittal** - Open the transmittal → Click "Download Data"
3. **Import JSON into trusted tool** - Open your trusted tool → Click "Load JSON" → Paste the exported data
4. **Verify file hashes** - Click "Select Directory" and point to the actual files
@ -10777,7 +10777,7 @@ When viewing a published transmittal, signature status is displayed above the fi
**Verification Actions**:
- **Verify Externally** — Opens a trusted tool instance for independent verification
- Copies JSON data to clipboard
- Opens https://zddc.varasys.io/releases/transmittal_latest.html in validation mode
- Opens https://zddc.varasys.io/releases/transmittal_stable.html in validation mode
- Paste JSON and select directory to verify file hashes independently
- Only trust verification results from the trusted tool, not this document

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,162 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>zddc-server — Zero Day Document Control</title>
<meta name="description" content="ZDDC has two access modes: local directory mode (tools work directly on a folder) and online mode (any web server can host it). zddc-server is an optional Go binary that adds access control, a virtual archive index, and audit logging on top of online mode.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://zddc.varasys.io/zddc-server.html">
<meta property="og:title" content="zddc-server — Zero Day Document Control">
<meta property="og:description" content="ZDDC has two access modes: local directory mode (tools work directly on a folder) and online mode (any web server can host it). zddc-server is an optional Go binary that adds access control, a virtual archive index, and audit logging on top of online mode.">
<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>
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; }
.feature-list li strong { color: var(--color-text); }
.ascii-tree { background: var(--color-bg-subtle); padding: var(--spacing-md); border-radius: 6px; font-family: ui-monospace, monospace; font-size: 0.85rem; line-height: 1.5; overflow-x: auto; color: var(--color-text); white-space: pre; }
.mode-card { padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; }
.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; } }
</style>
</head>
<body>
<!-- Header -->
<header class="site-header">
<div class="container header-content">
<a href="/" class="brand">
<div class="brand-logo">
<svg viewBox="0 0 24 24">
<path d="M3 5h18v2H3V5zm0 6h12v2H3v-2zm0 6h6v2H3v-2z" />
</svg>
</div>
<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_stable.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/transmittal_stable.html">
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
Transmittal Creator
</a>
<a href="releases/classifier_stable.html">
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
Document Classifier
</a>
<a href="releases/mdedit_stable.html">
<svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
Markdown Editor
</a>
</div>
</div>
</div>
<a href="reference.html" class="nav-link">Docs</a>
<a href="zddc-server.html" class="nav-link active">Server</a>
</nav>
</div>
</header>
<!-- Hero -->
<section class="hero">
<div class="container">
<h1>zddc-server</h1>
<p class="hero-subtitle">ZDDC has two access modes over the same on-disk archive. <strong>Online mode</strong> is what you get when you put a local directory behind a web server. <code class="inline">zddc-server</code> is an optional Go binary that adds access control, a virtual archive index, and audit logging on top.</p>
</div>
</section>
<main class="container" style="margin-bottom: var(--spacing-2xl);">
<section style="margin-top: var(--spacing-xl);">
<h2>Two modes, one archive</h2>
<div class="mode-grid">
<div class="mode-card">
<h3 style="margin-top: 0;">Local directory mode</h3>
<p>Open a tool, click <em>Add Directory</em>, point it at a folder. The tool reads files directly 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 style="margin-top: 0;">Online mode</h3>
<p>Take the same local directory and put it behind any web server (nginx, Caddy, Apache, even <code class="inline">python -m http.server</code>). The Archive Browser tool talks to the server's directory listings instead of the local filesystem.</p>
<p>Read-only, no special server software, works in any browser.</p>
</div>
</div>
<p style="margin-top: var(--spacing-md);">That's it. Same on-disk layout, two access mechanisms. The convention is the contract; the mode is an access decision.</p>
</section>
<section style="margin-top: var(--spacing-2xl);">
<h2>What zddc-server adds</h2>
<p><code class="inline">zddc-server</code> is a small Go binary built specifically to serve ZDDC archives. It <em>is</em> a web server, so it gives you online mode out of the box — but it adds things a generic web server can't:</p>
<ul class="feature-list">
<li><strong>If the server reads email headers, it can enforce access control.</strong> Behind any reverse proxy that authenticates users (Authelia, oauth2-proxy, your own SSO) and sets an <code class="inline">X-Email</code> request header, zddc-server consults <code class="inline">.zddc</code> YAML files in directories. Cascading bottom-up; deeper rules override shallower ones. No database, no admin UI — edit the files with any text editor.</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 (the one in the chronologically earliest transmittal that contains it). Computed from filenames at request time — no cache, no separate index file. Restart the server and it rebuilds.</li>
<li><strong>Per-request access logging</strong> keyed to the authenticated user's email — method, path, status, bytes, duration.</li>
<li><strong>TLS, ETags, conditional GET, CORS, autoindex.</strong> The mundane glue that makes a directory pleasant to serve.</li>
</ul>
<p>In short: any web server can do online mode for reads. <code class="inline">zddc-server</code> adds ACL, a virtual archive index, and audit logging while remaining a thin wrapper around the same directory.</p>
</section>
<section style="margin-top: var(--spacing-2xl);">
<h2>Still just files in folders</h2>
<p>The on-disk layout is the same whether you access locally or online. The server doesn't transform the archive — it serves it. Stop the server and the directory is still a perfectly valid ZDDC archive that opens in local-directory mode.</p>
<pre class="ascii-tree">ZDDC_ROOT/
index.html ← landing tool
archive.html ← archive browser
transmittal.html
Project-001/
.zddc ← ACL (optional, YAML)
2025-10-31_123456-EM-MDL-0001 (IFR) - Master Deliverables List/
123456-EM-MDL-0001_A (IFR) - Master Deliverables List.pdf
2025-11-12_123456-EL-SPC-2623 (IFR) - Specification For Switchgear/
123456-EL-SPC-2623_A (IFR) - Specification For Switchgear.pdf
Project-002/
</pre>
<p>This keeps the "Zero Day" promise: <strong>the server is convenience, not lock-in</strong>. Walk away from <code class="inline">zddc-server</code> tomorrow and the archive is still a perfectly valid convention-named folder tree, fully usable with nothing more than a file manager.</p>
</section>
<section style="margin-top: var(--spacing-2xl);">
<h2>Get it</h2>
<p>The server lives at <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc"><code class="inline">codeberg.org/VARASYS/ZDDC</code> under <code class="inline">zddc/</code></a>. Operations and configuration — environment variables, TLS modes, the <code class="inline">.zddc</code> ACL syntax, the virtual archive index URL patterns, container vs native binary deployment — are documented in <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/zddc/README.md">zddc/README.md</a>.</p>
<p>Quick start (with <code class="inline">podman</code> available):</p>
<pre class="ascii-tree">git clone https://codeberg.org/VARASYS/ZDDC.git
cd ZDDC/zddc
ZDDC_DATA_DIR=/path/to/your/archive podman-compose up --build</pre>
<p>For the deployment-side install of the tools onto a <code class="inline">zddc-server</code> instance — including the level-1/level-2 bootstrap pattern, <code class="inline">install.zip</code>, and the channel-tracking <code class="inline">track-*.zip</code> bundles — see <a href="https://codeberg.org/VARASYS/ZDDC/src/branch/main/bootstrap/README.md">bootstrap/README.md</a>.</p>
</section>
</main>
<!-- Footer -->
<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>