16 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 97ffaac13b |
feat(server): self-issued bearer tokens + --no-auth flag
zddc-server now issues its own bearer tokens for non-browser callers (CLI tools, scripts, downstream proxy/cache/mirror instances). No external IDP, no JWKS rotation. Self-service flow: sign in via the browser, visit /.tokens, click "Create token," paste the resulting plaintext into a 0600 file, and pass --bearer-file <path> to whatever calls back into the server. Storage is <ZDDC_ROOT>/.zddc.d/tokens/<sha256-hex>, YAML per token with email/created/expires/description. Filename is the *hash* of the plaintext, never the plaintext itself — a leak of the tokens directory exposes hashes, not credentials. Mode 0600 / 0700, atomic writes via temp+rename. Already shielded from public serving by the existing dot-prefix guards in dispatch and fs.ListDirectory. ACLMiddleware now recognises Authorization: Bearer <token>. On valid token, sets the request email from the token file and falls through to the existing ACL chain. On any failure (unknown / expired / store unavailable / Bearer with no validator), returns 401 — no silent fallback to anonymous, so a misconfigured client fails loudly. JSON API at /.api/tokens (GET list, POST create, DELETE /<id> revoke) backs a small inline HTML self-service page at /.tokens. Users can only see and revoke their own tokens; cross-user revoke returns 404 to avoid leaking ownership. --no-auth (ZDDC_NO_AUTH=1) skips ACL enforcement entirely on this instance. On master: anyone reads everything (dev / trusted-LAN / public-read deployments). On a downstream proxy/cache/mirror: trust upstream's filtering, don't re-evaluate ACLs locally. Implemented as a swap to policy.AllowAllDecider; all existing handlers keep calling AllowFromChain unchanged. Distinct from --insecure, which only relaxes the no-root-.zddc startup check. WARN-level startup log when --no-auth is active so accidental enablement is visible. 33 new tests covering token storage, validation/expiry/revocation, the JSON API end-to-end, the HTML page, and the middleware-Bearer integration including the case-insensitive prefix and expired-token paths. Full suite + go vet clean. Doc updates: zddc/README.md "Authentication" rewritten to cover both auth paths and the token UI/API; AGENTS.md gains ZDDC_NO_AUTH and a "Bearer tokens" subsection flagging the dot-prefix-shielding pre- condition; ARCHITECTURE.md adds "Bearer token issuance" and "--no-auth" subsections under "Server security model" with the hash-as-filename rationale and dispatch-shielding regression- sensitivity called out; CLAUDE.md adds a one-line summary of the new auth topology so future agents pick it up by default. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 3115e388fc |
feat(server): authenticated CRUD + verb-based RBAC with WORM archive folders
Replaces the binary acl.allow/deny model with five permission verbs
(r/w/c/d/a) and first-class roles, and adds an authenticated file API
(PUT/DELETE/POST move/mkdir) so the HTML tools can edit-in-place over
HTTP. Closes the AC-3(7) and AC-6 federal-readiness gaps.
File API (zddc/internal/handler/fileapi.go)
- PUT <new> → action c
- PUT <existing> → action w
- PUT <.zddc> → action a (CanEditZddc strict-ancestor rule)
- DELETE → action d
- POST mkdir → action c (auto-writes creator-owned .zddc when the
parent is Incoming/Working/Staging)
- POST move → action w on src + c on dst, atomic via os.Rename
- Optional If-Match for optimistic concurrency, --max-write-bytes cap,
audit log emits a structured file_write event per operation.
Permission model (zddc/internal/zddc/{acl,file,roles,cascade_mode}.go)
- acl.permissions: { principal → verb-set } map; principals are email
patterns or role names. Empty verb set is an explicit deny.
- roles: { name → members } definitions, available at the level they
declare and all descendants. Closer-to-leaf shadows ancestor.
- Legacy acl.allow/deny still work; they fold into permissions at
parse time (allow → "rwcd", deny → "").
- Cascade walks leaf→root; first level with any matching entry wins;
the union of matching verb sets at that level decides.
- --cascade-mode=strict adds a root→leaf ancestor-deny pre-pass so an
ancestor explicit-deny is absolute (NIST AC-6). Default delegated
preserves the existing commercial behavior.
Special folders (zddc/internal/zddc/special.go)
- Incoming / Working / Staging: mkdir auto-writes a .zddc into the new
subdir granting created_by + that email rwcda directly. Same form
operators write by hand; creator can edit it later to add others.
- Issued / Received: server-enforced WORM split. Cascade grants
inherited from above the WORM folder are masked to r only; grants
placed at-or-below the WORM folder retain r,c. Operators grant
write-once (cr) to the doc controller via an explicit .zddc at the
Issued/Received folder. Admins exempt — only escape hatch.
Browser polyfill (shared/zddc-source.js)
- HttpDirectoryHandle + HttpFileHandle implement the FS Access API
surface (values, getFileHandle, createWritable, removeEntry,
queryPermission/requestPermission) over zddc-server's listing JSON
and file API. Existing tools written against showDirectoryPicker
work unchanged.
- detectServerRoot() returns { handle, status }: tools auto-load on
HTTP, surface a clear "no permission to list" message on 403, and
fall back to the welcome screen on 0.
- classifier renames take the atomic POST move path on HTTP-backed
handles; mdedit and transmittal route reads/writes through the
polyfill so prior FS-API code paths cover both modes.
Tests
- zddc/internal/zddc/{cascade_mode,roles,special,acl}_test.go cover
delegated vs strict, role membership / shadowing / legacy fallback,
WORM split semantics, verb-set parser round-trip.
- zddc/internal/handler/fileapi_test.go now also covers role-based
vendor scenarios, WORM blocking vendor & doc controller writes,
explicit Issued .zddc unlocking the cr drop-box, admin bypass,
auto-ownership on mkdir, and strict-mode lockouts.
Docs
- ARCHITECTURE.md + zddc/README.md document the verb model, role
syntax, special-folder behaviors, cascade-mode flag, and full file
API surface. Federal-readiness gap analysis strikes AC-3(7) and
AC-6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 5c33c8a821 |
docs: ACL/security overhaul (cascade rules, OPA, caching)
Three docs aligned with the preceding three feature commits. zddc/README.md -------------- Major overhaul of the access-control narrative. The previous "three- tier" example table was misleading: it claimed a project-level allow-list "restricts" access under a parent wildcard, when actually the cascade is additive (a non-team employee falls up to root and matches *@company.com). Operators reading the old docs would build deployments that looked locked-down but leaked across the company. New sections under "Access control: the .zddc cascade": * Step 1: starter .zddc — leads with the public-by-default warning and the --insecure escape hatch * How a request is evaluated — bottom-up walk with code citations * Glob patterns — @-boundary rule * When the cascade helps and when it fights you — the asymmetry between adding strangers (easy) and excluding insiders (hard) * Pick your layout — decision matrix for common shapes * Worked example: paired open/closed projects + third-party archive — full layout with trace table for two representative users * Patterns that look secure but aren't — anti-patterns including same-level allow+deny shadow, leaf-allow-doesn't-restrict, apps:-as-UI-mount * Trust model and invariants — auth boundary, subtree authority, root-only escalation gate * Trust boundary — network isolation requirement, anonymous information disclosure on /, audit-log integrity * Debugging permissions — manual cascade trace * Directory visibility / Reserved hidden segments * How to verify in 5 minutes — recipe with negative anti-pattern test * Federal-readiness gap analysis — bulleted with NIST control refs * External policy decider — OPA wire format, deployment shapes, failure modes * OPA decision cache — TTL semantics, knobs * Reference Rego policy — --print-rego, parity test rationale * Caching and ETags — content-hash story, why not server-side * Future work Plus env-var table updates for ZDDC_INSECURE, ZDDC_OPA_URL, ZDDC_OPA_FAIL_OPEN, ZDDC_OPA_CACHE_TTL; CORS narrative reflects default-empty. ARCHITECTURE.md --------------- New "Server security model" section between Form Renderer and CSS: cooperating layers (auth / policy decider / cascade / tool-rooted view / reserved prefixes / audit log), commercial-vs-federal trust model side-by-side, why the tool-rooted view matters for third-party containment. AGENTS.md --------- Two new env-var rows (ZDDC_OPA_URL, ZDDC_OPA_CACHE_TTL); ACL line sharpened with cascade rules + cross-reference; ZDDC_CORS_ORIGIN description updated for default-empty. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| a02a26d3c2 |
feat: form-data system v0 (sixth tool + zddc-server endpoints)
All checks were successful
Build + deploy releases / build-and-deploy (push) Successful in 8s
Schema-driven form renderer plus zddc-server endpoints that turn any
<name>.form.yaml into a working data-collection form at <path>/<name>.form.html.
Submissions land in <path>/<name>/<YYYY-MM-DD>-<email-sanitized>.yaml,
ACL-gated by the existing .zddc cascade. The form posts back to its own URL;
the server strips ".html" and routes by what's underneath, so create and
update use the same client-side code path.
Form spec dialect: JSON Schema 2020-12 + RJSF-style ui:* hints, written in
YAML. Chosen for LLM authorability — it's the canonical structured-output
target for OpenAI/Anthropic, and the ui:* convention is the most-trained UI
hint vocabulary. Supported subset for v0: type (string/number/integer/boolean/
array/object), enum, min/max, minLength/maxLength, required, additionalProperties:
false, properties, items, format (date, email). Round-trip mode is form-as-truth:
submission YAML is regenerated each save, comments are not preserved (the v1
file-as-truth mode for hand-edited files like .zddc itself is deferred).
New components:
* form/ — sixth single-file HTML tool, vanilla JS renderer (~760 LoC)
* zddc/internal/jsonschema/ — focused JSON Schema validator covering only
the v0 keyword subset. Match-implementation-cost-to-surface-used: a full
library brings 70%+ surface we don't use; revisit when v1 adds $ref +
oneOf + if/then/else.
* zddc/internal/handler/formhandler.go — RecognizeFormRequest / ServeForm,
capability-URL re-edit, atomic submission writes via the new
zddc.WriteAtomic helper extracted from writer.go.
* dispatch() in zddc-server/main.go now intercepts *.form.html and
*.yaml.html before the static-file path; spec existence is the trigger.
Build pipeline: form joins ZDDC_RELEASE_TOOLS in lockstep, gets its own
embedded copy in handler/form.html (separate from the apps cascade —
the form renderer is fixed, not subject to per-folder version overrides).
Tests: 5 new Playwright specs (form-safety) + 14 new Go tests across the
validator and handler. All 172 Playwright tests + 10 Go packages green.
End-to-end manual verification: GET empty → POST 201 + capability URL →
GET re-edit (pre-filled) → POST update → 200, raw YAML browsable, ACL
deny → 403.
Docs: form/ section added to AGENTS.md and ARCHITECTURE.md. AGENTS.md
also documents the implementation-vs-dependency policy. CLAUDE.md repo-shape
list extended.
Deferred (v1+): .zddc editor migration onto this system, file-as-truth
lossless YAML round-trip, ui:show-when conditional visibility, oneOf/anyOf,
apps-cascade preview hook, cascade-fetched form definitions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 7570fb7494 |
refactor: separate website repo + deploy-host model
Migrates from in-repo orphan `website` branch + LFS to a two-repo +
deploy-host model so source editing is fully decoupled from live state.
- Source code stays here (codeberg.org/VARASYS/ZDDC).
- Hand-edited website content moves to a separate Codeberg repo
(codeberg.org/VARASYS/ZDDC-website, cloned at ~/src/zddc-website/).
- Live site is /srv/zddc/ on the deploy host (Caddy bind-mount),
populated by ./deploy from this repo's dist/release-output/ plus
~/src/zddc-website/.
- Releases are no longer in any git history — reproducible from
<tool>-vX.Y.Z tags via `./build release X.Y.Z`. No LFS, no
Codeberg release assets.
Build/deploy split:
- ./build (no arg) is source-only; nothing in dist/release-output/
or /srv/zddc/ is touched.
- ./build alpha|beta|release seeds dist/release-output/ from
/srv/zddc/releases/ (preserving symlinks), then mutates the
channel(s) being cut on top. The bundle is always a complete
intended-live snapshot, so the verifier sees a complete world
and ./deploy --releases (rsync --delete-after) replaces live
state cleanly.
- New ./deploy wraps the rsync flow with --content / --releases
subcommands.
Docs updated to reflect the new model: CLAUDE.md, AGENTS.md,
ARCHITECTURE.md, zddc/README.md, README.md, .gitignore, shared/
build-lib.sh comments, deprecated zddc/release.sh message.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 6167e99f3a |
chore: simplify CLI to ./build / ./build beta / ./build release
Renames build.sh → build and replaces the --release flag form with
subcommands:
./build cut alpha (default; active dev iteration)
./build beta cut beta (cascades alpha → beta)
./build release cut stable (coordinated next version)
./build release X.Y.Z cut stable at explicit version
./build help
The contract shift: there's no longer a "plain dev build that doesn't
touch channels" at the top level. Every full-stack build is a publish
action — running ./build IS active dev iteration, which is what alpha
already meant. To iterate on one tool without writing to the website
worktree, use the per-tool sh tool/build.sh (unchanged).
Output continues to land in ${ZDDC_DEPLOY_RELEASES_DIR:-$HOME/src/zddc-website/releases}
and nothing is pushed automatically. Commit + push the website branch
yourself when you want to publish. Stable cuts still tag locally on
main; tags push separately too.
Behind the scenes: the export of ZDDC_DEPLOY_RELEASES_DIR is moved
above the per-tool build.sh invocations so children inherit it. The
prior "if RELEASE_CHANNEL else write_zddc_server_stubs_all" branch is
collapsed since RELEASE_CHANNEL is always set under the new CLI.
Docs (CLAUDE.md, AGENTS.md, ARCHITECTURE.md, zddc/README.md) updated
to reference ./build everywhere; the per-tool sh tool/build.sh refs
stay (they're a separate, narrower entry point).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 76820fa8dd |
chore: split website out into orphan branch + worktree
Moves website source + release artifacts off `main` and into a new
orphan branch named `website` in this same Codeberg repo. A `git worktree`
of that branch — typically at ~/src/zddc-website/ — is what the system
Caddy now bind-mounts and serves at zddc.varasys.io. Decoupling source
from the live site means editing source can no longer accidentally
affect what's published.
Layout going forward:
- ~/src/zddc/ — main worktree (this branch, source only).
- ~/src/zddc-website/ — git worktree of the `website` branch:
hand-edited content + LFS-tracked release
artifacts (server binaries) + regular-git
HTML tool releases + symlinks.
- Caddy bind-mount swapped: ~/src/zddc/website → ~/src/zddc-website
(quadlet at /etc/containers/systemd/caddy.container, restarted).
Build pipeline now writes releases to
${ZDDC_DEPLOY_RELEASES_DIR:-$HOME/src/zddc-website/releases}.
- build.sh: RELEASES_DIR points at the env var
- shared/build-lib.sh: promote_release honors the env var, falls
back to the legacy in-repo path so any
standalone single-tool release on a checkout
that still has website/ keeps working
- freshen-channel: passes ZDDC_DEPLOY_RELEASES_DIR through to
the worktree-based build
Docs (CLAUDE.md, AGENTS.md, ARCHITECTURE.md, .gitignore) updated for
the new layout. The 51 MB of website/ blobs stays in main's history
(no force-push); over time Codeberg's GC will pack them down.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 9fce18cd45 |
feat: lockstep release infra + cascade/.archive fixes + profile perf + page redesign
Four entangled change-sets from one session, committed together because
their file-level overlap (build.sh, docs, embedded/, watcher.go, …) makes
post-hoc separation noisy:
* fix(archive): nested-party + folder-type cascade
transmittalIsUnderVisibleParty short-circuited on the first matched
party segment, only checking the immediately-next segment for a
folder-type marker. Paths like BM/sub/Issued/<txn> bypassed the Issued
toggle entirely. Replaced with isUnderHiddenFolderType (full-path) +
any-segment party match. Eight new Playwright cases pin the contract
in tests/archive-cascade.spec.js.
* refactor(zddc-server): scope .archive index by project
archive.Index now buckets by top-level segment
(.ByProject[<project>].ByTracking[<tracking>]). Resolve and AllEntries
take a project parameter; handler extracts it from contextPath's first
segment. /.archive/ at root returns 404 — stable refs must be
project-rooted. Within-project (tracking, rev) collisions emit a WARN
with both paths. Cross-project tracking-number duplicates no longer
collide.
* perf(zddc-server): lazy-load expensive bits of the profile page
serveProfilePage now ships a minimal shell: Email, EmailHeader,
IsSuperAdmin (root .zddc only). Visible projects + admin subtrees +
editable scaffolds populate client-side via /.profile/access. Subtree-
admin scaffolds live in <template id="tmpl-subtree-admin">; pure
non-admins receive no live admin form. ScanZddcFiles now memoized,
invalidated on .zddc events by the watcher and writer helpers.
* feat: lockstep release + redesigned releases page
sh build.sh --release [version|alpha|beta] is the canonical lockstep
cut: every tool (5 HTML + zddc-server) bumps to the same coordinated
version. zddc-server binaries now committed under website/releases/
with the same cascade chain as HTML tools (no more Codeberg release-
asset publication). zddc/release.sh deprecated (kept as a guard);
shared/publish-codeberg-release.sh removed.
Releases page redesigned as an action-first install guide: hero +
version dropdown that rewires every download link, channel chips for
always-visible alpha/beta access (state-aware labels: "tracks stable"
vs "active dev"), Path A (zddc-server with platform auto-detect from
UA), Path B (5 standalone tool HTMLs), version-pinning empowerment
narrative (drop-a-copy vs .zddc apps: cascade), channels explainer.
Channel-link verifier asserts every <tool>_{stable,beta,alpha}.html
resolves at the end of every build. Bootstrap-friendly: zddc-server
artifact checks skip until the first lockstep cut anchors the chain.
Tests: 167 Playwright + all Go packages green.
Docs: CLAUDE.md, AGENTS.md, ARCHITECTURE.md, zddc/README.md updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| adb6904397 |
docs: rewrite for embedded + cascade install model
Updates every repo doc to reflect the simplified install model:
- Local install is just a download from /releases/.
- Server install is just running zddc-server (current-stable HTMLs
embedded at compile time).
- Customize via .zddc apps: cascade entries (channel/version/URL/path,
with default + per-app composition); editor at /.profile/zddc/.
Removes references to the old install scripts, level-1/level-2 stubs,
admin UI at /.profile/apps, SHA-256 verification, TOFU writes, refresh
worker, and ZDDC_APPS_* env vars.
zddc/README.md: replaces "Landing Page and Tool Install" section with
"Apps: virtual tool HTMLs" — covers the folder-name availability rules,
the resolution chain (real-file override / cascade / embedded), spec
syntax cheat sheet, cache layout under <ZDDC_ROOT>/_app/, the ?v=
cache-only override, and the X-ZDDC-Source response header.
ARCHITECTURE.md: install-distribution-model section rewritten to
describe the embed-first / cascade-override model with one canonical
example.
AGENTS.md, CLAUDE.md: short-form summaries pointing at the same model.
README.md: install bullet rewritten.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 7365e94cac |
docs: align with simplified release model
Updates to all six top-level docs to describe the new flow:
- Storage: HTML tools live in website/releases/ as committed static
files. Per-version files are real bytes; partial-version pins and
channel mirrors are checked-in symlinks. No manifest.json, no Codeberg
indirection, no Caddy regex-rewrite.
- URL scheme: <tool>_v<X.Y.Z>.html (exact), <tool>_v<X.Y>.html (latest
patch), <tool>_v<X>.html (latest minor), <tool>_<channel>.html
(channel mirror). All resolve via the symlink chain.
- Cascade rule: stable cut → beta + alpha symlinks reset to stable;
beta cut → alpha resets to beta. Channels are never stale.
- No -alpha.N / -beta.N counter tags. Channel URLs are stable URLs by
design; counters defeat that. The on-page <date> · <sha> label is
enough for traceability.
- bootstrap/install.sh is the canonical install path. The four hand-
rolled snippets are gone; one script handles all three deployment
patterns + both target shapes.
- Helm charts under helm/ (zddc-server-{prod,dev}/) build from source
via init container; documented as the recommended k8s deployment
path.
- zddc-server now publishes binaries on stable cuts only — no alpha/
beta channel for binaries. Active dev runs through the dev helm chart
which builds from source on each rollout.
Files updated:
- CLAUDE.md — Repo shape, Most-used commands, Things that bite if you
forget. Drops mentions of manifest.json, the Codeberg-as-canonical
model, and -alpha.N/-beta.N tags.
- AGENTS.md — website/ tree, Releasing — channels and layout, Channel
discipline rules (renumbered to add coordinated minor/major bump
rule), Freshen helper, Bootstrap stubs, zddc-server Release tagging.
- ARCHITECTURE.md — website/ tree, build.sh step 5, Channels section,
level-2 bootstrap description.
- README.md — tool publishing description, link to helm/.
- bootstrap/README.md — install path is install.sh now; pin URL table
uses static symlinks; CORS check uses release-asset URLs (not
manifest.json).
- zddc/README.md — Quick Start uses Codeberg URLs directly (no proxy);
Release tagging is stable-only; Distribution / Versioning sections
rewritten.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| bdac8dc4fb |
docs: clean up drift left over from the Codeberg release-assets refactor
The
|
|||
| 916e53d873 |
feat(install): replace .zip downloads with copy-paste shell snippets
The "Install on your server" section of the home page now prints four
short shell snippets — copy-paste into a terminal, files land in CWD.
Each uses curl to fetch the relevant bootstrap files; nothing else to
install:
1. Self-contained: fetches the 5 current-stable tool HTMLs into CWD
plus a _template/ directory of level-1 stubs.
~1.8 MB on disk; no runtime dependency on the
site after install.
2. Track stable: fetches 5 tiny level-2 stubs (~10 KB total)
that fetch zddc.varasys.io's stable channel
on every page load.
3. Track beta: same, for beta.
4. Track alpha: same, for alpha.
Each snippet card explains when/why to use that option directly inline.
Implementation:
- build.sh now produces website/bootstrap/level1/<tool>.html and
website/bootstrap/track-{alpha,beta,stable}/<tool>.html as
standalone files (rather than packaging them into zips).
- install.zip and track-{alpha,beta,stable}.zip are removed; the
snippets curl the per-channel stubs directly.
- Docs updated: README, ARCHITECTURE, CLAUDE, AGENTS, bootstrap/README,
zddc/README, landing/build.sh comment.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 91d6e61e22 |
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>
|
|||
| 67f794e6d0 |
refactor: rename channel 'latest' to 'stable' across all artifacts
The 'latest' label for the current-stable channel was inconsistent
with the channel set we use elsewhere (alpha / beta / stable). Rename
to 'stable' so URLs, file names, zip names, and image tags all line
up with the channel terminology used in the bootstrap, AGENTS.md
discipline rules, and chart consumers.
File / artifact renames
- website/releases/<tool>_latest.html → <tool>_stable.html (5 files)
- website/track-latest.zip → track-stable.zip
- shared/build-lib.sh: promote_release writes/refreshes _stable.html
- bootstrap/level{1,2}.html.tmpl: channels map drops 'latest', keeps
'stable' as the canonical name. ?v=stable is now the explicit way
to switch to current-stable for one request (alongside ?v=alpha,
?v=beta, and ?v=X.Y.Z).
- build.sh: install.zip sources from <tool>_stable.html; emits
track-stable.zip instead of track-latest.zip.
Container image (.woodpecker.yml rewritten)
- Tag publishing now cascades:
zddc-server-vX.Y.Z → :X.Y.Z, :stable, :beta, :alpha, :latest
zddc-server-vX.Y.Z-beta.N → :X.Y.Z-beta.N, :beta, :alpha
zddc-server-vX.Y.Z-alpha.N → :X.Y.Z-alpha.N, :alpha
- :stable, :beta, :alpha are now first-class channel pointers; chart
consumers (e.g. tnd-zddc-chart) can FROM :beta for dev and FROM
:stable for prod.
- :latest kept as an alias for :stable per Docker convention.
Documentation sweep
- AGENTS.md, ARCHITECTURE.md, CLAUDE.md, README.md
- bootstrap/README.md, zddc/README.md
- website/index.html, website/zddc-server.html
- transmittal/template.html, transmittal/README.md
all updated to reference _stable.html / track-stable.zip / the
'stable' channel name. ARCHITECTURE.md's manual freshen example
points at ./freshen-channel instead of the old git-checkout snippet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 699069e538 |
docs: add zddc-server.html — local vs online mode, what the server adds
The intro page's "zddc-server" link previously pointed at a Codeberg
blob URL (which uses /src/branch/main/, not GitHub's /blob/main/, so
the link 404'd anyway). Replace with a hand-edited concept page on
the website itself.
The page is structured around two access modes:
- Local directory mode — open a tool, point it at a folder, work
via the File System Access API. No upload, no server.
- Online mode — take that same local directory and put it behind
any web server (nginx, Caddy, Apache, even python -m http.server).
The Archive Browser tool works against the server's directory
listings the same way it works against a local folder.
zddc-server is then introduced as a Go binary that gives you online
mode out of the box, plus four conveniences a generic web server
can't: ACL via .zddc YAML files (gated on email-header trust),
virtual /.archive/ URL space, per-request access logging, and the
mundane glue (TLS, ETags, conditional GET, CORS).
Closing section: the on-disk layout is the same in both modes — the
server doesn't transform the archive, it serves it. Stop the server
and the directory is still a valid ZDDC archive. The "Zero Day"
promise: server is convenience, not lock-in.
Also:
- Add Server nav link to website/index.html and reference.html.
- Fix the bootstrap/README.md link that used GitHub's /blob/main/
pattern (Codeberg uses /src/branch/main/).
- Update ARCHITECTURE.md doc-ownership table: new row for the concept
page, clarify that zddc/README.md is the operations reference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| ea385b5366 |
Initial commit
ZDDC — Zero Day Document Control. A file-naming convention plus five single-file HTML tools (archive, transmittal, classifier, mdedit, landing) and an optional Go HTTP server (zddc-server) with ACL and a virtual archive index. Self-contained, offline-capable, dependency-free. See README.md for an overview, AGENTS.md and ARCHITECTURE.md for the build/release/architecture detail, bootstrap/README.md for the two-level deployment install pattern, and zddc/README.md for the HTTP server. |