Rolls back the HTML-tool side of the Codeberg-as-canonical refactor
(commits 2dc9ad2, b28c4ae, bdac8dc) in favor of a simpler model:
per-version HTML files committed under website/releases/ as immutable
real files; partial-version pins (<tool>_v<X.Y>.html, <tool>_v<X>.html)
and channel mirrors (<tool>_<channel>.html) are checked-in symlinks.
Docker-tag pattern: :1.2.3 is pinned, :1.2 floats, :1 floats further,
:stable floats furthest.
URL scheme — every URL resolves to actual HTML via the symlink chain;
no JS indirection, no manifest.json, no Caddy regex-rewrite:
/releases/<tool>_v<X.Y.Z>.html exact version (real file)
/releases/<tool>_v<X.Y>.html latest patch within X.Y.* (symlink)
/releases/<tool>_v<X>.html latest within X.*.* (symlink)
/releases/<tool>_stable.html current stable (symlink)
/releases/<tool>_beta.html current beta (symlink to stable when no
active beta; real file when beta is in flight)
/releases/<tool>_alpha.html current alpha (similar — symlink to beta
or stable when no active alpha)
Cascade rule (in shared/build-lib.sh promote_release):
--release [version] (stable cut) → write per-version file; refresh 5
symlinks (_v<X.Y>, _v<X>, _stable,
_beta, _alpha) → new versioned file;
tag <tool>-v<X.Y.Z>.
--release beta → overwrite <tool>_beta.html with real
bytes; cascade _alpha.html → _beta.html
(symlink). No tag — channel URLs are
stable URLs by design; counters defeat
that.
--release alpha → overwrite <tool>_alpha.html with real
bytes. No tag, no other side-effects.
Plain `sh tool/build.sh` → dist/ only. No website/releases/
side-effect, no commit.
Code changes:
- .gitignore — drop website/releases/*.html and website/releases/zddc-server-*
exclusions; HTML tool files are tracked again. Replace the comment with
the new model description.
- shared/build-lib.sh — drop next_prerelease (no -alpha.N / -beta.N counter
tags). Drop the Codeberg-upload path for HTML tools (no longer sourcing
publish-codeberg-release.sh from build-lib). promote_release rewritten
with two helpers: _promote_stable (per-version file + 5 symlinks + tag)
and _promote_channel (overwrite mirror + cascade alpha→beta on beta cut).
- zddc/release.sh — drop alpha/beta channel path entirely; binaries publish
only on stable cuts. zddc-server's beta/alpha builds-from-source via the
helm charts (next phase) — no binary distribution needed for those channels.
- bootstrap/level2.html.tmpl — drop manifest.json fetch; resolve ?v= to a
static URL via the symlink chain. New suffixFor() handles channel names,
exact versions, and partial-version pins (?v=0.0, ?v=0). Same logic in
level1.html.tmpl already works because the local-staging files (e.g.
../<tool>_v0.0.html) exist via the same symlink scheme.
- build.sh build_releases_index — revert to filesystem scan of
website/releases/ instead of Codeberg API call. Drop manifest.json
generation. Per-tool sections list channel chips + per-version pin links;
zddc-server section links to Codeberg release pages directly.
- tests/build-label.spec.js — fix the channel-label regex to match the
pre-release-semver format introduced in commit 9459139 ("v0.0.3-alpha · ...").
Pre-existing test failure that wasn't caught at the time.
Storage:
- 30 new committed files under website/releases/ — 10 real (per-version) +
20 symlinks (5 tools × 4 partial/channel variants, plus alpha as a real
file by default).
- Initial state: stable v0.0.2 across all 5 tools; alpha/beta/v0.0/v0
symlinks all point at <tool>_v0.0.2.html.
- manifest.json deleted (no longer needed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the codeberg.org/varasys/zddc-server registry image, which had
no remaining consumer outside this shop. The two chart Dockerfiles
(tnd-zddc-chart) now compile zddc-server from source at build time,
fetching the right tag from a Codeberg release. release-image.sh,
zddc/Containerfile, and zddc/podman-compose.yaml are gone.
Build artifacts (HTML tools + zddc-server binaries) move from
website/releases/ in this repo to Codeberg release assets attached to
git tags. The website at zddc.varasys.io serves them by reverse-
proxying /releases/<tag>/<asset> to the corresponding Codeberg URL,
so consumers (zddc-use, level-2 bootstrap stubs, the chart
Dockerfiles) only ever talk to zddc.varasys.io.
Releases page becomes server-rendered static HTML regenerated on each
build via a single Codeberg API call. A small website/releases/manifest.json
maps <tool>-<channel> → tag for runtime channel resolution by zddc-use
and the level-2 stubs.
Files added:
- shared/publish-codeberg-release.sh — POSIX-sh helper that creates a
Codeberg release for a tag (sets prerelease flag from tag suffix)
and uploads/replaces release assets idempotently. Sourced by
build-lib.sh and zddc/release.sh.
- zddc/release.sh — replaces release-image.sh. Tags + cross-compiles
binaries via native Go (no podman needed; install Go) + uploads to
Codeberg release assets. No image build, no registry push.
Files modified:
- shared/build-lib.sh — promote_release tags + uploads via the helper
for stable AND alpha/beta now (alpha/beta were untagged before).
update_alpha removed; per-tool build.sh files no longer mirror to
website/releases/<tool>_alpha.html on plain dev builds.
- build.sh — prefers native go build over the old podman-based
cross-compile (which is gone with Containerfile). build_releases_index
queries the Codeberg API once and writes static HTML + manifest.json,
with graceful fallback when the API is unreachable.
- bootstrap/level2.html.tmpl — fetches manifest.json to resolve
channel → tag, then fetches the asset from /releases/<tag>/<asset>
(Caddy proxy). Replaces the old /releases/<tool>_<channel>.html flat
URL pattern. Operators with curl'd level-2 stubs need to re-issue
them — this is a breaking change.
- AGENTS.md, CLAUDE.md — rewritten to describe the new flow.
- .gitignore — releases/ artifacts now expected to be on Codeberg, not
committed locally.
NOT in this commit (deferred until $CODEBERG_TOKEN is provisioned):
- Backfilling existing tags as Codeberg releases.
- Cleanup commit: git rm-ing the existing artifacts in website/releases/.
Until backfill happens, those files are how operators with old
bootstrap stubs still get content. Once Codeberg has the assets,
drop them.
- The Caddy reverse-proxy config on zddc.varasys.io.
Operator-side changes (not in this repo):
- tnd-zddc-chart Dockerfile.prod and Dockerfile (dev) need updating
to compile from source rather than `FROM codeberg.org/...:stable`.
Done in a separate commit on that repo.
- Caddyfile rule for the /releases/<tag>/<asset> reverse-proxy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The releases index already enumerated HTML tools by channel and
version. Add a parallel section for zddc-server with two artifact
families:
- Standalone binaries: a channel × platform table linking to
website/releases/zddc-server-{linux,darwin,windows}-{amd64,arm64}-<channel>
(the files release-image.sh now mirrors there). Empty cells render
as em-dashes; the table only renders when at least one binary
exists locally so freshly-cloned repos don't show a ghost section.
- Container images: pull-snippet, channel chips linking to the
codeberg package page, and a "Pin to version" row of historical
tags (clean stables first, recent pre-releases listed separately
with a "recent pre-releases:" label so the pre-release noise
doesn't drown out the stable list).
Recent pre-releases capped at 10 entries to keep the list scannable
as alpha cuts proliferate over time.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Bundles a stretch of in-progress work across the SPA tools so the
tree returns to a coherent shippable state ahead of cutting a new
zddc-server stable image:
- landing: substantial rework of the project picker (sortable/filterable
table, presets refactor, ?projects= filter, ?v= channel propagation,
loading/error states)
- archive: presets cleanup, source.js refactor, filtering/url-state
alignment with the landing page
- mdedit: file-system module split, resizer, file-tree improvements,
base/toc styling tweaks
- transmittal/classifier: small template touch-ups for shared chrome
- shared: build-lib.sh helpers, new favicon.svg
- bootstrap, build.sh: pick up the channel-aware install/track zip
generation
- tests: new landing.spec.js, expanded archive/mdedit/build-label specs
- docs: CLAUDE.md picks up the zddc-server section and freshens the
alpha-build exception note
- regenerated artifacts: install.zip, track-{alpha,beta,stable}.zip,
*_alpha.html — these are produced by `sh build.sh` and per project
convention are committed alongside the source changes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- release-image.sh now defaults to alpha (was stable). Active dev no
longer silently advances :stable; that tag only moves on a deliberate
`sh release-image.sh <ver> stable`. Same cascade logic, reordered
default. Updated AGENTS.md and zddc/README.md sections accordingly.
- zddc/Containerfile: dropped the "see .woodpecker.yml" comment since
that file no longer exists; pointed the docs to release-image.sh.
- build.sh: dropped the "CI builds the runtime container directly"
parenthetical; the cross-compiled host-binaries build is the only
thing that step actually produces.
Why alpha as the default: caught it during active development —
:stable kept advancing every release because the script defaulted
there. Solo workflow + alpha default = `:stable` is a deliberate
gesture, not a side-effect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
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>
Batch 1 of the chart-vs-project split. The project now ships a
hardened runtime image as part of every zddc-server release; downstream
deployments (e.g. the Burns & McDonnell Helm chart) will FROM this
image instead of cloning and building from source.
zddc/Containerfile (target: server)
- Tag the runtime stage `server` so `podman build --target server`
is unambiguous (the existing `binaries` target still works).
- Bake the bundled landing + archive tool HTML at /opt/zddc-server/web.
Useful for self-contained demos (`ZDDC_ROOT=/opt/zddc-server/web`)
and as a fallback web root when no external mount is supplied.
- Set fixed UID/GID 1000 for the non-root zddc user so volume
permissions are predictable across hosts.
- Add ENV ZDDC_ROOT=/srv default so a `podman run -v data:/srv` works
with no further config; explicit ZDDC_ROOT overrides.
- Declare VOLUME /srv to make the data-mount expectation explicit.
- Add OCI image labels (title, description, source, documentation,
license, vendor).
- Install ca-certificates so any future outbound HTTPS works.
- Add a HEALTHCHECK for `docker run` users (Kubernetes overrides).
build.sh
- Make the cross-platform podman binary build conditional on `podman`
being present. CI doesn't need it (the runtime container image's
own builder stage produces linux/amd64 internally), but having
build.sh sh-only-runnable means CI doesn't have to do nested
containers just to assemble dist/web.
- Reorder so `zddc/dist/web/` is assembled before the binary build
(allows the binary build to be skipped without breaking the bundle).
.woodpecker.yml (new)
- Triggers on tag push matching `zddc-server-v*`.
- Step 1 (alpine + sh): runs `sh build.sh` to assemble dist/web,
computes the image tag (`${TAG#zddc-server-v}` plus `latest`).
- Step 2 (docker-buildx plugin): builds and publishes
codeberg.org/varasys/zddc-server:{X.Y.Z, latest}. Auth via the
codeberg_user / codeberg_token Woodpecker secrets — these need
one-time setup in repo Settings; documented in zddc/README.md.
zddc/README.md
- New "Container image" section: pull URL, image properties (alpine,
non-root UID 1000, EXPOSE 8443, VOLUME /srv, baked web bundle),
example `podman run` invocation.
- New "Env-var contract (for chart consumers)" table: the variables
Helm charts and Compose files should set explicitly when running
behind a TLS-terminating reverse proxy with SSO. This is the
documented interface between project and downstream charts.
- "Release Tagging" section now points at .woodpecker.yml and lists
the two Woodpecker secrets that must be configured.
Validated locally:
podman build --target server -t zddc-server-test .
podman run -e ZDDC_ROOT=/opt/zddc-server/web -e ZDDC_TLS_CERT=none \
-e ZDDC_INSECURE_DIRECT=1 -e ZDDC_ADDR=:8080 \
-p 18080:8080 zddc-server-test
curl http://localhost:18080/ → HTTP 200, bundled landing tool.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.