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>
156 lines
7.3 KiB
Markdown
156 lines
7.3 KiB
Markdown
# Deployment bootstrap
|
|
|
|
ZDDC tools (archive, transmittal, classifier, mdedit, landing) are single-file
|
|
HTML bundles. The bootstrap pattern lets you install once on a deployment and
|
|
update by editing a few lines, without re-uploading multi-megabyte HTML files.
|
|
|
|
End users install via the unified [`install.sh`](install.sh) script, served at
|
|
`https://zddc.varasys.io/install.sh`. The script handles all three deployment
|
|
patterns (self-contained / channel-tracking / pin-to-version) plus both target
|
|
shapes (deployment root or project subdirectory) via a single command:
|
|
|
|
```sh
|
|
sh -c "$(curl -fsSL https://zddc.varasys.io/install.sh)" -- [options]
|
|
```
|
|
|
|
The published stubs live under `https://zddc.varasys.io/bootstrap/`:
|
|
|
|
- `bootstrap/level1/<tool>.html` — same-origin level-1 stubs (4 tools, no
|
|
landing — landing only lives at deployment root).
|
|
- `bootstrap/track-{stable,beta,alpha}/<tool>.html` — per-channel level-2
|
|
stubs (5 tools each).
|
|
|
|
Both directories are produced by the project's top-level `build.sh` from
|
|
`bootstrap/level{1,2}.html.tmpl`. `install.sh` orchestrates which stubs to
|
|
fetch and where to put them based on `--mode` / `--target` / `--channel`.
|
|
|
|
## The two-level model
|
|
|
|
A typical `zddc-server` deployment looks like this:
|
|
|
|
```
|
|
<ZDDC_ROOT>/
|
|
index.html # landing tool (or bootstrap)
|
|
archive.html # archive tool (or bootstrap; site-wide channel switch lives here)
|
|
transmittal.html
|
|
classifier.html
|
|
mdedit.html
|
|
<project-A>/
|
|
archive.html # level-1 bootstrap → fetches ../archive.html
|
|
transmittal.html
|
|
classifier.html
|
|
mdedit.html
|
|
<project files…>
|
|
<project-B>/
|
|
archive.html # level-1 bootstrap (or pinned to a specific version)
|
|
…
|
|
```
|
|
|
|
- **Level-1 stubs** at `<project>/<tool>.html` always fetch the same-origin
|
|
`../<tool>.html`. They never touch `zddc.varasys.io`. Install them once;
|
|
they don't need to change.
|
|
- **At deployment root** (`<ZDDC_ROOT>/<tool>.html`), put either:
|
|
- the actual built tool HTML — fully self-contained install, no external
|
|
dependencies; or
|
|
- a level-2 bootstrap — fetches `<source>/releases/<tool>_<channel>.html`
|
|
directly (that path is a checked-in symlink on the upstream that resolves
|
|
to the current channel mirror). No manifest lookup, no version arithmetic,
|
|
no Codeberg proxy magic — every URL is a real static file or a static
|
|
symlink chain.
|
|
|
|
The site administrator switches the whole site to a channel by re-running
|
|
`install.sh --mode track --channel <name>` — that overwrites the root
|
|
`<tool>.html` files with the matching level-2 stubs. A single project can
|
|
override one tool by editing just `<project-X>/<tool>.html` (replace the
|
|
relative `upstream` URL with an absolute zddc.varasys.io URL pointing at
|
|
the desired version, channel mirror, or partial-version pin).
|
|
|
|
## Why two levels
|
|
|
|
The level-1 stubs let projects share a single source of truth for "which
|
|
build of the archive tool runs here." Switching channels is one file change
|
|
at the root; pinning a single project is one file change in that directory.
|
|
|
|
`document.write()` chains across both levels: level-1 fetches and writes,
|
|
the new document's level-2 script runs and writes again, the third write
|
|
is the actual tool. Origin stays at the deployment domain throughout, so
|
|
File System Access API, `crypto.subtle`, and `localStorage` all work and
|
|
preferences stay scoped to the deployment.
|
|
|
|
## Pinning options
|
|
|
|
There are two ways to choose a version: edit the stub for a permanent
|
|
pin, or pass a `?v=` URL parameter for a per-request override.
|
|
|
|
### 1. Permanent pin (point the stub at a fixed URL)
|
|
|
|
The default level-2 stub fetches `<source>/releases/<tool>_<channel>.html` —
|
|
which is itself a symlink on the upstream that resolves to the current
|
|
channel mirror. To pin permanently, change the URL inside the stub:
|
|
|
|
| Target stability | URL the stub should fetch |
|
|
|----------------------------------|------------------------------------------------------------------------|
|
|
| Exact stable version | `https://zddc.varasys.io/releases/<tool>_vX.Y.Z.html` |
|
|
| Latest patch within `<X.Y>.*` | `https://zddc.varasys.io/releases/<tool>_v<X.Y>.html` (symlink) |
|
|
| Latest within `<X>.*.*` | `https://zddc.varasys.io/releases/<tool>_v<X>.html` (symlink) |
|
|
| Track stable channel (default) | `https://zddc.varasys.io/releases/<tool>_stable.html` (symlink) |
|
|
| Track beta / alpha channel | `https://zddc.varasys.io/releases/<tool>_<channel>.html` |
|
|
|
|
### 2. Per-request `?v=` parameter
|
|
|
|
Both stub levels honor a `?v=` URL parameter. The parameter survives the
|
|
`document.write()` chain, so it flows through level-1 → level-2 →
|
|
upstream automatically.
|
|
|
|
| URL parameter | Resolves to |
|
|
|--------------------------------|-------------------------------------------------------|
|
|
| `?v=0.0.4` (or `?v=v0.0.4`) | `<tool>_v0.0.4.html` (exact) |
|
|
| `?v=0.0` (or `?v=v0.0`) | `<tool>_v0.0.html` (latest 0.0.x patch — symlink) |
|
|
| `?v=0` (or `?v=v0`) | `<tool>_v0.html` (latest 0.x — symlink) |
|
|
| `?v=stable` | `<tool>_stable.html` |
|
|
| `?v=beta` | `<tool>_beta.html` |
|
|
| `?v=alpha` | `<tool>_alpha.html` |
|
|
| (omitted) | the default channel baked into the stub at install time |
|
|
|
|
When level-1 has `?v=…`, it tries `../<tool>_<suffix>.html` first (useful
|
|
when the admin has staged specific versions locally — the upstream's
|
|
symlink layout works the same locally) and falls back to `../<tool>.html`
|
|
if 404 — which then forwards the parameter via level-2 if one is installed.
|
|
|
|
Stable per-version files are immutable. The `<tool>_stable.html`,
|
|
`<tool>_beta.html`, and `<tool>_alpha.html` symlinks (or real bytes when a
|
|
channel has active dev) get updated whenever the relevant channel
|
|
advances upstream — expect them to change. The build label rendered on
|
|
the tool page tells you exactly which build you're seeing
|
|
(`v<next-stable>-{alpha,beta} · <date> · <sha>` for channel mirrors,
|
|
`v<X.Y.Z>` for pinned stables).
|
|
|
|
## Auditing what's installed
|
|
|
|
Every stub contains a `fallback` (level-1) or `upstream` (level-2)
|
|
constant. To see what each tool / project on the deployment points at:
|
|
|
|
```sh
|
|
grep -rn "fallback\|upstream" <ZDDC_ROOT>
|
|
```
|
|
|
|
## CORS prerequisite (level-2 only)
|
|
|
|
A level-2 fetch is cross-origin (deployment → `zddc.varasys.io`). The
|
|
upstream must serve `Access-Control-Allow-Origin: *` (or a list including
|
|
your deployment origin) on each released asset. Verify with:
|
|
|
|
```sh
|
|
curl -I https://zddc.varasys.io/releases/archive_stable.html | grep -i access-control
|
|
curl -I https://zddc.varasys.io/releases/archive_v0.0.2.html | grep -i access-control
|
|
```
|
|
|
|
Level-1 fetches are same-origin so no CORS is involved.
|
|
|
|
## Templates
|
|
|
|
`level1.html.tmpl` and `level2.html.tmpl` are the source of truth. The
|
|
project's top-level `build.sh` substitutes `{{TOOL}}`, `{{TOOL_TITLE}}`,
|
|
`{{CHANNEL}}`, and `{{FAVICON}}` to produce the per-tool stubs published
|
|
under `website/bootstrap/level1/` and `website/bootstrap/track-<channel>/`,
|
|
which the install snippets curl from `https://zddc.varasys.io/bootstrap/`.
|