zddc-server can now run as a downstream client of another zddc-server. Set --upstream <url> and the master-side machinery (archive index, apps server, watcher, OPA decider, ACL middleware, token store) is bypassed entirely; cmd/zddc-server/main.go short-circuits to runClient(cfg) which uses zddc/internal/cache/Cache as the entire request handler. Three modes via --mode <proxy|cache|mirror>: - proxy: forward upstream live, no disk persistence - cache (default): persist responses on access; subsequent hits serve from disk + background If-Modified-Since revalidate - mirror: accepted but currently behaves like cache; the access- triggered walker lands in phase 3 Cache directory layout is intentionally a normal ZDDC root: a file fetched from <master>/foo/bar.txt is stored at <root>/foo/bar.txt with no sidecar metadata. The local file's mtime is set to the upstream's Last-Modified header so revalidation reflects the master's notion of file age, not local fetch time. Running zddc-server --root <cache-dir> without --upstream serves the cached files as a plain master — useful for portable offline snapshots. A small .zddc-upstream marker is written once on first persist for provenance. Pipeline (GET/HEAD only — writes deferred): - Hit → http.ServeContent serves directly (range-aware, 304-aware) + background revalidate (304 no-op, 200 overwrite, 403/404 purge) - Miss → forward to upstream with the configured bearer; tee response body to client + tmp-file atomically renamed into the cache - Network error + cached → serve stale + X-ZDDC-Cache: offline - Network error + no cache → 503 + X-ZDDC-Cache: offline - Directories always proxy live (no listing cache yet — phase 3) - Cache-Control: no-store / private and non-200 responses bypass cache Range requests work end-to-end (Range/If-Range headers forwarded on miss; http.ServeContent handles them natively on hit). Hop-by-hop headers per RFC 7230 §6.1 are dropped from forwarded responses. New flags (also as ZDDC_* env vars), all ignored when --upstream is empty (so master deployments are untouched): - --upstream <url> - --mode proxy|cache|mirror (default cache) - --bearer-file <path> (0600 file with the master-issued token) - --skip-tls-verify (separate from --no-auth; for self-signed dev) Validation: --upstream must be http(s)://...; trailing / is trimmed. Mode validated to one of the three known values. The startup no-root-.zddc check is skipped in client mode (the cache directory starts empty by design). The plain-HTTP-on-non-loopback check is also skipped (the local instance never reads the email header to decide anything; auth is forwarded to upstream as a Bearer). Tests: zddc/internal/cache/cache_test.go runs httptest.NewServer as the upstream and covers miss-then-hit, proxy-mode-no-persist, directory-never-cached, HEAD-no-body, offline-with-cache, offline-no-cache → 503, bearer forwarding, query-string preservation, no-store bypass, path-traversal rejection, error-status forwarding, revalidate-on-403/404/200/304, range-on-hit, concurrent-same-URL, cache-path boundary cases. 23 new tests, full suite + go vet clean. Live two-instance smoke verified: master at 127.0.0.1:18443, client at :18444 with --mode cache, miss→hit→hit transitions work, file materialises under cache root with parent dirs created, marker file written once, range-on-hit returns 206, master sees background 304s on every hit, killing master leaves cached files serving from disk and never-cached files returning 503 + offline header. Doc updates: zddc/README.md gains a "Client mode" section with the modes table, flag reference, pipeline summary, two-instance recipe, and explicit list of phase-2 limitations; AGENTS.md adds the four new env vars to the reference table and a "Client mode" subsection with smoke-test recipe and a pointer to the cache package; ARCHITECTURE.md adds "Master + proxy/cache/mirror" before "Bearer token issuance," covering the topology, the persist/warm switches, the cache-IS-a-ZDDC-root invariant, the request pipeline, and the v1-out-of-scope multi-tenancy note; CLAUDE.md's zddc/ entry expanded to mention both deployment shapes so future agents pick it up by default. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo | ||
| archive | ||
| browse | ||
| classifier | ||
| form | ||
| helm | ||
| landing | ||
| mdedit | ||
| pandoc | ||
| shared | ||
| tables | ||
| tests | ||
| transmittal | ||
| zddc | ||
| .gitignore | ||
| AGENTS.md | ||
| ARCHITECTURE.md | ||
| build | ||
| CLAUDE.md | ||
| deploy | ||
| dev-server | ||
| freshen-channel | ||
| LICENSE.txt | ||
| package.json | ||
| playwright.config.js | ||
| README.md | ||
| SECURITY.md | ||
Zero Day Document Control (ZDDC)
The Universal Distributed Filing Cabinet
ZDDC is an information management convention plus a small set of single-file HTML tools. 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 archive — no server, no database, no software required to read it.
The name "Zero Day Document Control" comes from the convention itself — adopt it on day zero of a project, with no setup time. The tools are optional interfaces around the structure; the structure works without them.
For end users: https://zddc.varasys.io/ introduces the project, links to all tool channels (stable / beta / alpha), and prints copy-paste shell snippets to install on a self-hosted deployment.
Tools
| Tool | What it does |
|---|---|
| Archive Browser | Browse, search, and filter a project archive folder. Group by transmittal, export selections as ZIP. |
| Transmittal Creator | Self-contained HTML transmittal records with SHA-256 checksums and optional digital signatures. |
| Document Classifier | Spreadsheet-like bulk-renamer that copy/pastes with Excel and writes back to disk. |
| Markdown Editor | Browser-based markdown editor with YAML front matter, TOC, and direct local file access. |
| Form Renderer | Schema-driven *.form.yaml editor — every form spec auto-mounts an editable form at <name>.form.html. |
| Tables | Read-only grid view of a directory of YAML files with sort + filter; click row → edit in the form renderer. Declared per-directory in .zddc. |
Each tool is published in three channels (stable, beta, alpha) as static files served from https://zddc.varasys.io/releases/. Local use: download a .html file from releases/ and open it in a browser. Server use: run zddc-server — the current-stable build of every tool is baked into the binary at compile time, so a fresh deployment Just Works with zero config. Tools auto-appear at folder-name-driven paths (archive everywhere; classifier in Incoming/Working/Staging; mdedit in Working; transmittal in Staging). Override per-directory by writing an apps: entry in any .zddc file (channel/version/URL/path). URL overrides are fetched once and cached in <ZDDC_ROOT>/_app/; drop a real .html file at any path to override entirely.
File-naming convention
The full specification — filename format, tracking numbers, revision rules, status codes, folder naming, and the transmittal workflow — lives at https://zddc.varasys.io/reference.html.
Quick example: 123456-EL-SPC-2623_A (IFR) - Specification For Switchgear.pdf
Build & develop
git clone https://codeberg.org/VARASYS/ZDDC.git && cd ZDDC
sh build.sh # build all tools (writes to dist/ only)
sh archive/build.sh # build one tool
sh archive/build.sh --release # cut stable; auto-bumps patch from last tag
sh archive/build.sh --release 0.1.0 # explicit version
sh archive/build.sh --release alpha # cut alpha (mutable channel, no tag)
sh archive/build.sh --release beta # cut beta
npm install && npx playwright install chromium && npm test # tests
./dev-server start # cache-busting HTTP on :8000
Authoritative build/release docs are in AGENTS.md. Architecture notes (single-file rationale, JS module pattern, security model) are in ARCHITECTURE.md. zddc-server (optional Go HTTP server with ACL and a virtual archive index) is in zddc/README.md. Example Helm charts for deploying zddc-server (production + dev) are under helm/.
Contributing
ZDDC is an open source project hosted on Codeberg at https://codeberg.org/VARASYS/ZDDC. Bug reports, feature requests, and pull requests welcome.
ZDDC is designed for zero configuration to start and minimal configuration overall — feature proposals are filtered through that lens.
License
GNU Affero General Public License v3.0. Free to use, modify, and distribute, including commercially, under the terms of the license. Provided "as is" without warranty.