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>
This commit is contained in:
ZDDC 2026-04-28 09:30:24 -05:00
parent 1da25eff3f
commit 67f794e6d0
26 changed files with 96 additions and 73 deletions

View file

@ -1,22 +1,30 @@
# Woodpecker CI for ZDDC. # Woodpecker CI for ZDDC.
# #
# This pipeline only runs on `zddc-server-v*` tag pushes — it builds the # Triggers on `zddc-server-v*` tag pushes. Builds the runtime container
# zddc-server runtime container image and publishes it to Codeberg's # image and publishes it to Codeberg's container registry with channel
# container registry. Other tags (archive-v*, transmittal-v*, etc.) and # tags that cascade downward, so that pinning to `:stable` always gets
# regular pushes are ignored here; the HTML tool releases happen by # the most recent stable, `:beta` always tracks the most recent beta-or-
# pushing static files to the website (no image involved). # stable, and `:alpha` always tracks the most recent alpha-or-newer.
# #
# To enable: in Codeberg → repo Settings → Woodpecker → set the secrets # Tag conventions
# codeberg_user = your Codeberg username (e.g. VARASYS) # ---------------
# codeberg_token = a personal token with package:write scope # zddc-server-vX.Y.Z → stable release
# Generate the token at https://codeberg.org/user/settings/applications. # zddc-server-vX.Y.Z-beta.N → beta release
# zddc-server-vX.Y.Z-alpha.N → alpha release
# #
# After setup, cut a release with: # Image tags applied (cascading)
# git tag zddc-server-v0.0.1 # ------------------------------
# git push --tags # stable release: :X.Y.Z + :stable, :beta, :alpha, :latest
# and the pipeline will publish: # beta release: :X.Y.Z-beta.N + :beta, :alpha
# codeberg.org/varasys/zddc-server:0.0.1 # alpha release: :X.Y.Z-alpha.N + :alpha
# codeberg.org/varasys/zddc-server:latest #
# `:latest` is kept as an alias for `:stable` (Docker convention).
#
# To enable: in the Woodpecker dashboard at https://ci.codeberg.org →
# repo → Settings → Secrets, add codeberg_user (your Codeberg username)
# and codeberg_token (a personal token with package:write scope from
# https://codeberg.org/user/settings/applications). Restrict both
# secrets to the `tag` event for safety.
when: when:
- event: tag - event: tag
@ -26,17 +34,32 @@ steps:
prepare-bundle: prepare-bundle:
image: docker.io/alpine:3.20 image: docker.io/alpine:3.20
commands: commands:
# build.sh assembles zddc/dist/web/ from landing and archive # 1. Assemble zddc/dist/web/ from the landing + archive built outputs.
# built outputs (which are committed force-tracked dist files). # build.sh now skips the (host-side) podman binary build when
# Falls back gracefully when podman isn't present — we don't # podman is absent, which is the case in CI — the runtime
# need the cross-compiled binaries here, the runtime container # container image's own builder stage produces linux/amd64.
# builds its own linux/amd64 binary internally.
- sh build.sh - sh build.sh
# Image tag = the bare semver after the "zddc-server-v" prefix. # 2. Compute the image tags. Grammar:
# Plus a "latest" tag for convenience. # zddc-server-vX.Y.Z → stable
- VERSION="${CI_COMMIT_TAG#zddc-server-v}" # zddc-server-vX.Y.Z-alpha.N → alpha (cascade: alpha)
- printf '%s\nlatest\n' "$VERSION" > .image-tags # zddc-server-vX.Y.Z-beta.N → beta (cascade: beta, alpha)
- echo "Will tag image with: $(cat .image-tags | tr '\n' ' ')" # Anything else is rejected by the `when:` filter; nothing to
# handle here.
- |
VERSION="${CI_COMMIT_TAG#zddc-server-v}"
case "$VERSION" in
*-alpha.*) CHANNEL=alpha ;;
*-beta.*) CHANNEL=beta ;;
*) CHANNEL=stable ;;
esac
case "$CHANNEL" in
stable) TAGS="$VERSION stable beta alpha latest" ;;
beta) TAGS="$VERSION beta alpha" ;;
alpha) TAGS="$VERSION alpha" ;;
esac
printf '%s\n' $TAGS > .image-tags
echo "Channel: $CHANNEL"
echo "Tags: $TAGS"
publish-image: publish-image:
image: woodpeckerci/plugin-docker-buildx image: woodpeckerci/plugin-docker-buildx

View file

@ -58,11 +58,11 @@ website/
index.html current stable landing (root URL) index.html current stable landing (root URL)
releases/ releases/
<tool>_v<X>.<Y>.<Z>.html immutable stable release archives <tool>_v<X>.<Y>.<Z>.html immutable stable release archives
<tool>_latest.html -> ... symlink to current stable (highest semver) <tool>_stable.html -> ... symlink to current stable (highest semver)
<tool>_alpha.html mutable; overwritten by --release alpha <tool>_alpha.html mutable; overwritten by --release alpha
<tool>_beta.html mutable; overwritten by --release beta <tool>_beta.html mutable; overwritten by --release beta
install.zip drop-in self-contained install (5 stable HTMLs + _template/ stubs) install.zip drop-in self-contained install (5 stable HTMLs + _template/ stubs)
track-latest.zip level-2 stubs that track the current-stable channel track-stable.zip level-2 stubs that track the current-stable channel
track-alpha.zip level-2 stubs that track the alpha channel track-alpha.zip level-2 stubs that track the alpha channel
track-beta.zip level-2 stubs that track the beta channel track-beta.zip level-2 stubs that track the beta channel
@ -163,7 +163,7 @@ Format: `trackingNumber_revision (status) - title.extension`
Three channels: Three channels:
- **Stable**: versioned, immutable. `sh tool/build.sh --release [version]` writes `website/releases/<tool>_v<version>.html`, refreshes the `<tool>_latest.html` symlink, and tags `<tool>-v<version>`. Skips automatically if source has not changed since the latest tag. Pass an explicit version to override auto-increment. - **Stable**: versioned, immutable. `sh tool/build.sh --release [version]` writes `website/releases/<tool>_v<version>.html`, refreshes the `<tool>_stable.html` symlink, and tags `<tool>-v<version>`. Skips automatically if source has not changed since the latest tag. Pass an explicit version to override auto-increment.
- **Beta**: mutable. `sh tool/build.sh --release beta` overwrites `website/releases/<tool>_beta.html` in place. No tag. The on-page label is `beta · <date> · <sha>` so the source is recoverable from git via the SHA. - **Beta**: mutable. `sh tool/build.sh --release beta` overwrites `website/releases/<tool>_beta.html` in place. No tag. The on-page label is `beta · <date> · <sha>` so the source is recoverable from git via the SHA.
- **Alpha**: mutable, analogous. `sh tool/build.sh --release alpha`. - **Alpha**: mutable, analogous. `sh tool/build.sh --release alpha`.
@ -214,7 +214,7 @@ Note: the build pipeline used is the one **at the tag**, not on `main`. That is
`build.sh` regenerates three downloadable zips into `website/` on every invocation: `build.sh` regenerates three downloadable zips into `website/` on every invocation:
- `install.zip` — 5 current-stable HTMLs at root + `_template/` directory containing 4 level-1 bootstrap stubs (per-project use). Skipped if any tool has no stable release yet. - `install.zip` — 5 current-stable HTMLs at root + `_template/` directory containing 4 level-1 bootstrap stubs (per-project use). Skipped if any tool has no stable release yet.
- `track-{alpha,beta,latest}.zip` — 5 level-2 stubs each, hardcoded to fetch the named channel from `zddc.varasys.io/releases/`. Drop one over a deployment root to switch the whole site to that channel. - `track-{alpha,beta,stable}.zip` — 5 level-2 stubs each, hardcoded to fetch the named channel from `zddc.varasys.io/releases/`. Drop one over a deployment root to switch the whole site to that channel.
See `bootstrap/README.md` for the install / pin / audit story. See `bootstrap/README.md` for the install / pin / audit story.

View file

@ -40,11 +40,11 @@ website/
index.html # current stable landing tool (root URL) index.html # current stable landing tool (root URL)
releases/ releases/
<tool>_v<X>.<Y>.<Z>.html # immutable stable release archives <tool>_v<X>.<Y>.<Z>.html # immutable stable release archives
<tool>_latest.html -> ... # symlink to the highest-versioned stable <tool>_stable.html -> ... # symlink to the highest-versioned stable
<tool>_alpha.html # mutable: overwritten on every --release alpha <tool>_alpha.html # mutable: overwritten on every --release alpha
<tool>_beta.html # mutable: overwritten on every --release beta <tool>_beta.html # mutable: overwritten on every --release beta
install.zip # current-stable HTMLs + project bootstrap stubs install.zip # current-stable HTMLs + project bootstrap stubs
track-{alpha,beta,latest}.zip # level-2 channel-tracking stubs track-{alpha,beta,stable}.zip # level-2 channel-tracking stubs
``` ```
There is no `website/dev/`. To preview a build locally, open `dist/tool.html` directly via the dev server. To publish on `zddc.varasys.io`, cut a release. There is no `website/dev/`. To preview a build locally, open `dist/tool.html` directly via the dev server. To publish on `zddc.varasys.io`, cut a release.
@ -68,7 +68,7 @@ Each topic has exactly one authoritative home; everything else links to it.
| Architecture & internal patterns | `ARCHITECTURE.md` (this file) | `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) | | Per-tool internal design quirks | `<tool>/README.md` | (linked from website intro tool cards) |
`website/index.html` is **hand-edited static content** (analogous to `reference.html`), not the landing-tool output. The landing tool ships only via `website/releases/landing_v<X>.html` and `install.zip``install.zip` copies `landing_latest.html` to `<deployment-root>/index.html` for customer sites where the project picker UI is actually useful (it queries `zddc-server` for the project list). The public website at `zddc.varasys.io/` has nothing to pick, so its root URL is the introduction page. `website/index.html` is **hand-edited static content** (analogous to `reference.html`), not the landing-tool output. The landing tool ships only via `website/releases/landing_v<X>.html` and `install.zip``install.zip` copies `landing_stable.html` to `<deployment-root>/index.html` for customer sites where the project picker UI is actually useful (it queries `zddc-server` for the project list). The public website at `zddc.varasys.io/` has nothing to pick, so its root URL is the introduction page.
When updating documentation, prefer linking over duplicating. If you find yourself rewriting the file-naming convention in a tool's README, link to `reference.html` instead. When updating documentation, prefer linking over duplicating. If you find yourself rewriting the file-naming convention in a tool's README, link to `reference.html` instead.
@ -86,17 +86,17 @@ Each tool's `build.sh`:
4. Writes the result to `dist/tool.html` 4. Writes the result to `dist/tool.html`
5. If `--release <channel-or-version>` was passed, calls `promote_release` to write the appropriate file under `website/releases/` 5. If `--release <channel-or-version>` was passed, calls `promote_release` to write the appropriate file under `website/releases/`
The top-level `build.sh` at the repository root calls all five tool build scripts in sequence and then regenerates the bootstrap zips (`install.zip`, `track-{alpha,beta,latest}.zip`) so they always match what's in `releases/`. The top-level `build.sh` at the repository root calls all five tool build scripts in sequence and then regenerates the bootstrap zips (`install.zip`, `track-{alpha,beta,stable}.zip`) so they always match what's in `releases/`.
### Channels ### Channels
Three release channels: Three release channels:
- **Stable** — versioned, immutable. `--release [version]` writes `website/releases/<tool>_v<version>.html`, refreshes the `<tool>_latest.html` symlink, and tags `<tool>-v<version>` in git. Skips automatically when there is no source change since the last tag. - **Stable** — versioned, immutable. `--release [version]` writes `website/releases/<tool>_v<version>.html`, refreshes the `<tool>_stable.html` symlink, and tags `<tool>-v<version>` in git. Skips automatically when there is no source change since the last tag.
- **Beta** — mutable. `--release beta` overwrites `website/releases/<tool>_beta.html` in place. No git tag; the on-page label is `beta · <date> · <sha>` so the source is recoverable from git history via the SHA. - **Beta** — mutable. `--release beta` overwrites `website/releases/<tool>_beta.html` in place. No git tag; the on-page label is `beta · <date> · <sha>` so the source is recoverable from git history via the SHA.
- **Alpha** — mutable, analogous to beta. - **Alpha** — mutable, analogous to beta.
Stable releases do not automatically clobber `<tool>_alpha.html` / `<tool>_beta.html` — those keep whatever was last built into them. To freshen alpha to current stable, `git checkout v<X>.<Y>.<Z> && sh tool/build.sh --release alpha`. Stable releases do not automatically clobber `<tool>_alpha.html` / `<tool>_beta.html` — those keep whatever was last built into them. Use `./freshen-channel <tool> <channel>` (worktree-based, no manual `git checkout`) to drag a channel forward to current stable.
The on-page `{{BUILD_LABEL}}` is rendered red+bold for dev/alpha/beta builds (`is_red=1`) and black for stable releases. The label format is: The on-page `{{BUILD_LABEL}}` is rendered red+bold for dev/alpha/beta builds (`is_red=1`) and black for stable releases. The label format is:

View file

@ -18,7 +18,7 @@ This is a **monorepo of independent tools**, not one application:
- `archive/`, `transmittal/`, `classifier/`, `mdedit/`, `landing/` — five self-contained HTML tools, each compiled to a single inlined HTML file in its own `dist/`. Naming: the first four output `dist/tool.html`; **`landing/` outputs `dist/index.html`** (it's the project picker served at the root of `zddc-server`). - `archive/`, `transmittal/`, `classifier/`, `mdedit/`, `landing/` — five self-contained HTML tools, each compiled to a single inlined HTML file in its own `dist/`. Naming: the first four output `dist/tool.html`; **`landing/` outputs `dist/index.html`** (it's the project picker served at the root of `zddc-server`).
- `zddc/` — Go HTTP server (separate sub-project, podman/podman-compose; Go 1.24+). Serves `ZDDC_ROOT/index.html` at `GET /` as the landing page; `Accept: application/json` on `/` returns the ACL-filtered project list. - `zddc/` — Go HTTP server (separate sub-project, podman/podman-compose; Go 1.24+). Serves `ZDDC_ROOT/index.html` at `GET /` as the landing page; `Accept: application/json` on `/` returns the ACL-filtered project list.
- `shared/``base.css` plus shared JS modules (`zddc.js`, `hash.js`, `zddc-filter.js`, `theme.js`, `help.js`) included by every tool's build, and `build-lib.sh` (POSIX sh helpers sourced by every tool's `build.sh`) - `shared/``base.css` plus shared JS modules (`zddc.js`, `hash.js`, `zddc-filter.js`, `theme.js`, `help.js`) included by every tool's build, and `build-lib.sh` (POSIX sh helpers sourced by every tool's `build.sh`)
- `website/` — published artifacts: `index.html` (root URL), `releases/<tool>_v<X.Y.Z>.html` (immutable stable archives), `releases/<tool>_latest.html` (symlink to current stable), `releases/<tool>_{alpha,beta}.html` (mutable channel files), plus bootstrap zips (`install.zip`, `track-{alpha,beta,latest}.zip`). `--release` is the only path to publishing — there is no `website/dev/`. - `website/` — published artifacts: `index.html` (root URL), `releases/<tool>_v<X.Y.Z>.html` (immutable stable archives), `releases/<tool>_stable.html` (symlink to current stable), `releases/<tool>_{alpha,beta}.html` (mutable channel files), plus bootstrap zips (`install.zip`, `track-{alpha,beta,stable}.zip`). `--release` is the only path to publishing — there is no `website/dev/`.
- `tests/` — Playwright specs (Chromium only, requires File System Access API). `tests/schema.spec.js` validates `transmittal.schema.json` against canonical fixtures via `ajv` (only dev dep besides Playwright) - `tests/` — Playwright specs (Chromium only, requires File System Access API). `tests/schema.spec.js` validates `transmittal.schema.json` against canonical fixtures via `ajv` (only dev dep besides Playwright)
## Most-used commands ## Most-used commands
@ -38,7 +38,7 @@ No lint/typecheck/format commands exist — vanilla JS + POSIX sh by design.
## Things that bite if you forget ## Things that bite if you forget
- **`dist/` is gitignored but force-committed** (`git add -f tool/dist/tool.html`). Never hand-edit a `dist/` file. - **`dist/` is gitignored but force-committed** (`git add -f tool/dist/tool.html`). Never hand-edit a `dist/` file.
- **Never write to `website/index.html` or `website/releases/*` directly** — promote via `sh tool/build.sh --release [version|alpha|beta]`. Stable releases write `website/releases/<tool>_v<ver>.html` (immutable) and refresh `<tool>_latest.html`; alpha/beta overwrite `<tool>_<channel>.html` in place. - **Never write to `website/index.html` or `website/releases/*` directly** — promote via `sh tool/build.sh --release [version|alpha|beta]`. Stable releases write `website/releases/<tool>_v<ver>.html` (immutable) and refresh `<tool>_stable.html`; alpha/beta overwrite `<tool>_<channel>.html` in place.
- **Always build before running tests** — Playwright opens `dist/tool.html` via `file://`. - **Always build before running tests** — Playwright opens `dist/tool.html` via `file://`.
- **`</` in JS string/template literals breaks inline `<script>`** embedding. `shared/build-lib.sh` provides `escape_js_close_tags`; every tool's `build.sh` runs JS through it before inlining. - **`</` in JS string/template literals breaks inline `<script>`** embedding. `shared/build-lib.sh` provides `escape_js_close_tags`; every tool's `build.sh` runs JS through it before inlining.
- **All ZDDC parsing/formatting/hashing goes through `window.zddc`** (from `shared/zddc.js` + `shared/hash.js` + `shared/zddc-filter.js`). API: `parseFilename`, `parseFolder`, `parseRevision`, `formatFilename`, `formatFolder`, `compareRevisions`, `isValidStatus`, `splitExtension`, `joinExtension`, `crypto.{sha256Hex, sha256String, sha256File, bytesToHex}`, `filter.{parse, matches}`. File objects across tools use `trackingNumber` (string) and `extension` (string, **no leading dot** — use `zddc.joinExtension(name, ext)` to build a filename). Add edge cases to `tests/zddc.spec.js`, not per-tool tests. - **All ZDDC parsing/formatting/hashing goes through `window.zddc`** (from `shared/zddc.js` + `shared/hash.js` + `shared/zddc-filter.js`). API: `parseFilename`, `parseFolder`, `parseRevision`, `formatFilename`, `formatFolder`, `compareRevisions`, `isValidStatus`, `splitExtension`, `joinExtension`, `crypto.{sha256Hex, sha256String, sha256File, bytesToHex}`, `filter.{parse, matches}`. File objects across tools use `trackingNumber` (string) and `extension` (string, **no leading dot** — use `zddc.joinExtension(name, ext)` to build a filename). Add edge cases to `tests/zddc.spec.js`, not per-tool tests.

View file

@ -12,10 +12,10 @@ The name "Zero Day Document Control" comes from the convention itself — adopt
| Tool | What it does | | Tool | What it does |
|------|--------------| |------|--------------|
| **[Archive Browser](https://zddc.varasys.io/releases/archive_latest.html)** | Browse, search, and filter a project archive folder. Group by transmittal, export selections as ZIP. | | **[Archive Browser](https://zddc.varasys.io/releases/archive_stable.html)** | Browse, search, and filter a project archive folder. Group by transmittal, export selections as ZIP. |
| **[Transmittal Creator](https://zddc.varasys.io/releases/transmittal_latest.html)** | Self-contained HTML transmittal records with SHA-256 checksums and optional digital signatures. | | **[Transmittal Creator](https://zddc.varasys.io/releases/transmittal_stable.html)** | Self-contained HTML transmittal records with SHA-256 checksums and optional digital signatures. |
| **[Document Classifier](https://zddc.varasys.io/releases/classifier_latest.html)** | Spreadsheet-like bulk-renamer that copy/pastes with Excel and writes back to disk. | | **[Document Classifier](https://zddc.varasys.io/releases/classifier_stable.html)** | Spreadsheet-like bulk-renamer that copy/pastes with Excel and writes back to disk. |
| **[Markdown Editor](https://zddc.varasys.io/releases/mdedit_latest.html)** | Browser-based markdown editor with YAML front matter, TOC, and direct local file access. | | **[Markdown Editor](https://zddc.varasys.io/releases/mdedit_stable.html)** | Browser-based markdown editor with YAML front matter, TOC, and direct local file access. |
Each tool is published in three channels (stable, beta, alpha) at `https://zddc.varasys.io/releases/<tool>_<channel>.html`. Append `?v=alpha` (or `?v=0.0.4`, etc.) to any URL to switch versions for one request. See [`bootstrap/README.md`](bootstrap/README.md) for the install / pin / audit story. Each tool is published in three channels (stable, beta, alpha) at `https://zddc.varasys.io/releases/<tool>_<channel>.html`. Append `?v=alpha` (or `?v=0.0.4`, etc.) to any URL to switch versions for one request. See [`bootstrap/README.md`](bootstrap/README.md) for the install / pin / audit story.

View file

@ -65,7 +65,7 @@ choice sticks for everyone using that file.
| URL | Behavior | | URL | Behavior |
|------------------------------------------------------------------|-----------------------------------------| |------------------------------------------------------------------|-----------------------------------------|
| `https://zddc.varasys.io/releases/<tool>_latest.html` | current stable; auto-updates within stable | | `https://zddc.varasys.io/releases/<tool>_stable.html` | current stable; auto-updates within stable |
| `https://zddc.varasys.io/releases/<tool>_beta.html` | latest beta build (mutable) | | `https://zddc.varasys.io/releases/<tool>_beta.html` | latest beta build (mutable) |
| `https://zddc.varasys.io/releases/<tool>_alpha.html` | latest alpha build (mutable) | | `https://zddc.varasys.io/releases/<tool>_alpha.html` | latest alpha build (mutable) |
| `https://zddc.varasys.io/releases/<tool>_v1.2.3.html` | pinned to exact stable version | | `https://zddc.varasys.io/releases/<tool>_v1.2.3.html` | pinned to exact stable version |
@ -112,7 +112,7 @@ upstream must serve `Access-Control-Allow-Origin: *` (or a list including
your deployment origin) on the released HTML files. Verify with: your deployment origin) on the released HTML files. Verify with:
```sh ```sh
curl -I https://zddc.varasys.io/releases/archive_latest.html | grep -i access-control curl -I https://zddc.varasys.io/releases/archive_stable.html | grep -i access-control
``` ```
Level-1 fetches are same-origin so no CORS is involved. Level-1 fetches are same-origin so no CORS is involved.

View file

@ -15,7 +15,7 @@
// //
// URL parameter ?v= selects a specific version or channel: // URL parameter ?v= selects a specific version or channel:
// ?v=0.0.4 (or v0.0.4) tries ../{{TOOL}}_v0.0.4.html locally // ?v=0.0.4 (or v0.0.4) tries ../{{TOOL}}_v0.0.4.html locally
// ?v=alpha|beta|latest tries ../{{TOOL}}_<channel>.html locally // ?v=alpha|beta|stable tries ../{{TOOL}}_<channel>.html locally
// (none) fetches ../{{TOOL}}.html (default) // (none) fetches ../{{TOOL}}.html (default)
// //
// If the requested version is not staged locally, falls back to the // If the requested version is not staged locally, falls back to the
@ -30,7 +30,7 @@
const params = new URLSearchParams(location.search); const params = new URLSearchParams(location.search);
const v = params.get('v'); const v = params.get('v');
const tool = '{{TOOL}}'; const tool = '{{TOOL}}';
const channels = { alpha: '_alpha', beta: '_beta', latest: '_latest', stable: '_latest' }; const channels = { alpha: '_alpha', beta: '_beta', stable: '_stable' };
function suffixFor(value) { function suffixFor(value) {
if (!value) return ''; if (!value) return '';

View file

@ -13,7 +13,7 @@
// document.write()s it in place. The default upstream is the // document.write()s it in place. The default upstream is the
// {{CHANNEL}} channel; the URL parameter ?v= overrides it: // {{CHANNEL}} channel; the URL parameter ?v= overrides it:
// //
// ?v=alpha|beta|latest switches to that channel // ?v=alpha|beta|stable switches to that channel
// ?v=0.0.4 (or v0.0.4) pins to that exact stable version // ?v=0.0.4 (or v0.0.4) pins to that exact stable version
// (none) uses the {{CHANNEL}} default // (none) uses the {{CHANNEL}} default
// //
@ -23,7 +23,7 @@
const v = params.get('v'); const v = params.get('v');
const tool = '{{TOOL}}'; const tool = '{{TOOL}}';
const defaultChannel = '{{CHANNEL}}'; const defaultChannel = '{{CHANNEL}}';
const channels = { alpha: '_alpha', beta: '_beta', latest: '_latest', stable: '_latest' }; const channels = { alpha: '_alpha', beta: '_beta', stable: '_stable' };
function suffixFor(value) { function suffixFor(value) {
if (!value) return '_' + defaultChannel; if (!value) return '_' + defaultChannel;

View file

@ -81,7 +81,7 @@ build_install_zip() {
# Verify a stable release exists for every tool before staging. # Verify a stable release exists for every tool before staging.
_missing="" _missing=""
while IFS='|' read -r _tool _file _title; do while IFS='|' read -r _tool _file _title; do
[ -e "$RELEASES_DIR/${_tool}_latest.html" ] || _missing="$_missing $_tool" [ -e "$RELEASES_DIR/${_tool}_stable.html" ] || _missing="$_missing $_tool"
done <<EOF done <<EOF
$TOOL_TABLE $TOOL_TABLE
EOF EOF
@ -93,7 +93,7 @@ EOF
_staging=$(mktemp -d) _staging=$(mktemp -d)
while IFS='|' read -r _tool _file _title; do while IFS='|' read -r _tool _file _title; do
cp "$RELEASES_DIR/${_tool}_latest.html" "$_staging/$_file" cp "$RELEASES_DIR/${_tool}_stable.html" "$_staging/$_file"
done <<EOF done <<EOF
$TOOL_TABLE $TOOL_TABLE
EOF EOF
@ -139,7 +139,7 @@ echo "=== Building install.zip and track-*.zip ==="
build_install_zip build_install_zip
build_track_zip alpha build_track_zip alpha
build_track_zip beta build_track_zip beta
build_track_zip latest build_track_zip stable
echo "" echo ""
echo "=== All tools built successfully ===" echo "=== All tools built successfully ==="
@ -152,4 +152,4 @@ echo "Bootstrap downloads: website/"
echo " install.zip — self-contained install for deployment root" echo " install.zip — self-contained install for deployment root"
echo " track-alpha.zip — level-2 stubs that track the alpha channel" echo " track-alpha.zip — level-2 stubs that track the alpha channel"
echo " track-beta.zip — level-2 stubs that track the beta channel" echo " track-beta.zip — level-2 stubs that track the beta channel"
echo " track-latest.zip — level-2 stubs that track the latest stable" echo " track-stable.zip — level-2 stubs that track the stable channel"

View file

@ -66,7 +66,7 @@ if [ "$is_release" = "1" ]; then
# NOTE: website/index.html is a hand-edited intro page for # NOTE: website/index.html is a hand-edited intro page for
# zddc.varasys.io, not the landing tool. The landing tool ships # zddc.varasys.io, not the landing tool. The landing tool ships
# only via website/releases/ and install.zip — install.zip puts # only via website/releases/ and install.zip — install.zip puts
# landing_latest.html at the customer deployment root, where the # landing_stable.html at the customer deployment root, where the
# project picker UI is useful (it queries zddc-server for the # project picker UI is useful (it queries zddc-server for the
# project list). See AGENTS.md "Releasing — channels and layout". # project list). See AGENTS.md "Releasing — channels and layout".
fi fi

View file

@ -23,7 +23,7 @@
# See "Channels and release args" below. # See "Channels and release args" below.
# promote_release <tool> — write to website/releases/ in the layout # promote_release <tool> — write to website/releases/ in the layout
# driven by $channel and $build_version. For # driven by $channel and $build_version. For
# stable, also update the _latest.html # stable, also update the _stable.html
# symlink and create the git tag. # symlink and create the git tag.
# #
# Channels and release args: # Channels and release args:
@ -155,7 +155,7 @@ compute_build_label() {
# Reads from caller scope: $channel, $build_version, $output_html, $root_dir. # Reads from caller scope: $channel, $build_version, $output_html, $root_dir.
# #
# Stable releases write website/releases/<tool>_v<version>.html, refresh the # Stable releases write website/releases/<tool>_v<version>.html, refresh the
# website/releases/<tool>_latest.html symlink, and tag <tool>-v<version> in # website/releases/<tool>_stable.html symlink, and tag <tool>-v<version> in
# git. Skips silently when the source has not changed since the latest tag. # git. Skips silently when the source has not changed since the latest tag.
# #
# Alpha and beta channel releases overwrite website/releases/<tool>_<channel>.html # Alpha and beta channel releases overwrite website/releases/<tool>_<channel>.html
@ -190,8 +190,8 @@ promote_release() {
# Symlink target is relative to its own directory so the link survives # Symlink target is relative to its own directory so the link survives
# path moves and works regardless of where the website is mounted. # path moves and works regardless of where the website is mounted.
(cd "$_releases_dir" && ln -sfn "${_tool}_v${build_version}.html" "${_tool}_latest.html") (cd "$_releases_dir" && ln -sfn "${_tool}_v${build_version}.html" "${_tool}_stable.html")
echo "Updated ${_tool}_latest.html -> ${_tool}_v${build_version}.html" echo "Updated ${_tool}_stable.html -> ${_tool}_v${build_version}.html"
git -C "$root_dir" tag "${_tool}-v${build_version}" git -C "$root_dir" tag "${_tool}-v${build_version}"
echo "Tagged ${_tool}-v${build_version} — run: git push --tags" echo "Tagged ${_tool}-v${build_version} — run: git push --tags"

View file

@ -56,7 +56,7 @@ When you open a transmittal, it may display "✓ Signature Valid" - but **this d
**For Document Controllers / Official Verification:** **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" 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 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 4. **Verify file hashes** - Click "Select Directory" and point to the actual files
@ -285,7 +285,7 @@ When viewing a published transmittal, signature status is displayed above the fi
**Verification Actions**: **Verification Actions**:
- **Verify Externally** — Opens a trusted tool instance for independent verification - **Verify Externally** — Opens a trusted tool instance for independent verification
- Copies JSON data to clipboard - 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 - Paste JSON and select directory to verify file hashes independently
- Only trust verification results from the trusted tool, not this document - Only trust verification results from the trusted tool, not this document

View file

@ -353,7 +353,7 @@ conventions at https://codeberg.org/VARASYS/ZDDC#file-naming-convention.
<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>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> <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> </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> <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> <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>

View file

@ -49,19 +49,19 @@
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<div class="dropdown-menu__inner"> <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> <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 Archive Browser
</a> </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> <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 Transmittal Creator
</a> </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> <svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
Document Classifier Document Classifier
</a> </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> <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 Markdown Editor
</a> </a>
@ -101,7 +101,7 @@
<div class="tool-card__title">Archive Browser</div> <div class="tool-card__title">Archive Browser</div>
<div class="tool-card__desc">Browse, search, and filter your project folder. Group by transmittal; filter by tracking number, revision, status, or free text. Export selections as ZIP.</div> <div class="tool-card__desc">Browse, search, and filter your project folder. Group by transmittal; filter by tracking number, revision, status, or free text. Export selections as ZIP.</div>
<div class="channel-row"> <div class="channel-row">
<a href="releases/archive_latest.html" class="channel-stable">stable</a> <a href="releases/archive_stable.html" class="channel-stable">stable</a>
<a href="releases/archive_beta.html" class="channel-beta">beta</a> <a href="releases/archive_beta.html" class="channel-beta">beta</a>
<a href="releases/archive_alpha.html" class="channel-alpha">alpha</a> <a href="releases/archive_alpha.html" class="channel-alpha">alpha</a>
</div> </div>
@ -111,7 +111,7 @@
<div class="tool-card__title">Transmittal Creator</div> <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. Optional digital signatures. The published file <em>is</em> the transmittal record.</div> <div class="tool-card__desc">Fill in metadata, drag in files, publish a self-contained HTML transmittal record with SHA-256 checksums. Optional digital signatures. The published file <em>is</em> the transmittal record.</div>
<div class="channel-row"> <div class="channel-row">
<a href="releases/transmittal_latest.html" class="channel-stable">stable</a> <a href="releases/transmittal_stable.html" class="channel-stable">stable</a>
<a href="releases/transmittal_beta.html" class="channel-beta">beta</a> <a href="releases/transmittal_beta.html" class="channel-beta">beta</a>
<a href="releases/transmittal_alpha.html" class="channel-alpha">alpha</a> <a href="releases/transmittal_alpha.html" class="channel-alpha">alpha</a>
</div> </div>
@ -121,7 +121,7 @@
<div class="tool-card__title">Document Classifier</div> <div class="tool-card__title">Document Classifier</div>
<div class="tool-card__desc">Spreadsheet-like interface for bulk-renaming files into ZDDC format. Copy/paste with Excel. Point it at a folder, fill in the columns, save all at once.</div> <div class="tool-card__desc">Spreadsheet-like interface for bulk-renaming files into ZDDC format. Copy/paste with Excel. Point it at a folder, fill in the columns, save all at once.</div>
<div class="channel-row"> <div class="channel-row">
<a href="releases/classifier_latest.html" class="channel-stable">stable</a> <a href="releases/classifier_stable.html" class="channel-stable">stable</a>
<a href="releases/classifier_beta.html" class="channel-beta">beta</a> <a href="releases/classifier_beta.html" class="channel-beta">beta</a>
<a href="releases/classifier_alpha.html" class="channel-alpha">alpha</a> <a href="releases/classifier_alpha.html" class="channel-alpha">alpha</a>
</div> </div>
@ -131,7 +131,7 @@
<div class="tool-card__title">Markdown Editor</div> <div class="tool-card__title">Markdown Editor</div>
<div class="tool-card__desc">Browser-based markdown editor with live preview, YAML front matter, and table of contents. Direct local file access via the File System Access API.</div> <div class="tool-card__desc">Browser-based markdown editor with live preview, YAML front matter, and table of contents. Direct local file access via the File System Access API.</div>
<div class="channel-row"> <div class="channel-row">
<a href="releases/mdedit_latest.html" class="channel-stable">stable</a> <a href="releases/mdedit_stable.html" class="channel-stable">stable</a>
<a href="releases/mdedit_beta.html" class="channel-beta">beta</a> <a href="releases/mdedit_beta.html" class="channel-beta">beta</a>
<a href="releases/mdedit_alpha.html" class="channel-alpha">alpha</a> <a href="releases/mdedit_alpha.html" class="channel-alpha">alpha</a>
</div> </div>
@ -155,7 +155,7 @@
<div class="install-card"> <div class="install-card">
<h3>Track stable</h3> <h3>Track stable</h3>
<p>Five level-2 bootstrap stubs. Drop over the deployment root to auto-track latest stable.</p> <p>Five level-2 bootstrap stubs. Drop over the deployment root to auto-track latest stable.</p>
<p><a href="track-latest.zip">track-latest.zip →</a></p> <p><a href="track-stable.zip">track-stable.zip →</a></p>
</div> </div>
<div class="install-card"> <div class="install-card">
<h3>Track beta</h3> <h3>Track beta</h3>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
website/track-stable.zip Normal file

Binary file not shown.

View file

@ -47,19 +47,19 @@
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<div class="dropdown-menu__inner"> <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> <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 Archive Browser
</a> </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> <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 Transmittal Creator
</a> </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> <svg class="dropdown-menu-icon" viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
Document Classifier Document Classifier
</a> </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> <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 Markdown Editor
</a> </a>

View file

@ -188,7 +188,7 @@ ZDDC_ROOT/
This is fully self-contained — no external dependencies. To make the This is fully self-contained — no external dependencies. To make the
deployment auto-track a published channel from `zddc.varasys.io`, drop deployment auto-track a published channel from `zddc.varasys.io`, drop
`track-alpha.zip` / `track-beta.zip` / `track-latest.zip` (also at `track-alpha.zip` / `track-beta.zip` / `track-stable.zip` (also at
`https://zddc.varasys.io/`) over `ZDDC_ROOT/`: those replace the root `https://zddc.varasys.io/`) over `ZDDC_ROOT/`: those replace the root
`<tool>.html` files with level-2 bootstrap stubs that fetch the named `<tool>.html` files with level-2 bootstrap stubs that fetch the named
channel from `zddc.varasys.io` on each page load. See channel from `zddc.varasys.io` on each page load. See