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>
341 lines
24 KiB
Markdown
341 lines
24 KiB
Markdown
# AGENTS.md — ZDDC
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Build all tools (writes to dist/ only; also regenerates website/releases/index.html)
|
|
sh build.sh
|
|
|
|
# Build single tool
|
|
sh tool/build.sh # archive | transmittal | classifier | mdedit | landing
|
|
|
|
# Cut a stable release (auto-increments patch version, writes website/releases/<tool>_v<X.Y.Z>.html, refreshes 5 symlinks, tags <tool>-v<X.Y.Z>)
|
|
sh tool/build.sh --release
|
|
sh tool/build.sh --release 1.2.0 # explicit version
|
|
|
|
# Cut an alpha/beta channel build (overwrites website/releases/<tool>_<channel>.html in place; on a beta cut, alpha cascades to a symlink → beta. No git tag.)
|
|
sh tool/build.sh --release alpha
|
|
sh tool/build.sh --release beta
|
|
|
|
# Release all tools at once
|
|
sh build.sh --release [version|alpha|beta]
|
|
|
|
# Test all tools
|
|
npm test
|
|
|
|
# Test single tool
|
|
npx playwright test tool # archive | transmittal | classifier | mdedit
|
|
|
|
# Dev server (cache-busting HTTP, on port 8000)
|
|
./dev-server start
|
|
./dev-server stop
|
|
```
|
|
|
|
No lint, typecheck, or format commands exist — the project is plain sh + vanilla JS.
|
|
|
|
## Architecture
|
|
|
|
Five independent single-file HTML tools (`archive`, `transmittal`, `classifier`, `mdedit`, `landing`). Each compiles to one self-contained `.html` in `dist/` with all CSS and JS inlined — the first four name their output `dist/tool.html`; `landing` writes `dist/index.html` (it's served at `/` by `zddc-server`). Tools share a small set of canonical helpers in `shared/` (filename parsing, ZDDC filter UI, theme, help) — see "Shared modules" below.
|
|
|
|
```
|
|
tool/
|
|
css/ source stylesheets (concatenated in order)
|
|
js/ vanilla JS IIFEs (concatenated in order)
|
|
template.html placeholder markers: {{CSS_PLACEHOLDER}}, {{JS_PLACEHOLDER}}, {{BUILD_LABEL}}
|
|
build.sh assembles dist/tool.html
|
|
dist/tool.html generated output — committed with `git add -f`
|
|
|
|
shared/
|
|
base.css CSS tokens and primitives included first by every tool's CSS build
|
|
zddc.js canonical filename/folder/revision parsers, formatters, status validation
|
|
zddc-filter.js shared ZDDC project/status filter UI module
|
|
theme.js light/dark theme switcher
|
|
help.js shared help dialog module
|
|
build-lib.sh POSIX sh helpers (ensure_exists, concat_files, build_timestamp)
|
|
sourced by every tool's build.sh via: . "$root_dir/../shared/build-lib.sh"
|
|
|
|
website/
|
|
index.html hand-edited intro page + install snippets (root URL)
|
|
releases/
|
|
index.html versions index, regenerated by build.sh from filesystem scan
|
|
<tool>_v<X.Y.Z>.html real per-version files (committed, immutable)
|
|
<tool>_v<X.Y>.html -> ... symlink: latest patch within X.Y.*
|
|
<tool>_v<X>.html -> ... symlink: latest within X.*.*
|
|
<tool>_stable.html -> ... symlink: current stable
|
|
<tool>_beta.html -> ... symlink to stable (or real bytes if active beta)
|
|
<tool>_alpha.html -> ... symlink to beta/stable (or real bytes if active alpha)
|
|
|
|
helm/
|
|
zddc-server-prod/ production-shaped Helm chart (compiles from source via init container)
|
|
zddc-server-dev/ dev-shaped variant (tracks main HEAD; debug-level logging; faster probes)
|
|
README.md chart design rationale + quick-start
|
|
```
|
|
|
|
**Critical:** `dist/` files are gitignored. They're the canonical built artifact for testing and the source for `--release` writes into `website/releases/`, but they aren't checked in. Never edit them directly.
|
|
|
|
`website/releases/` IS committed — per-version files as real bytes, partial-version pins (`_v<X.Y>`, `_v<X>`) and channel mirrors (`_stable`, `_beta`, `_alpha`) as symlinks. The build script (`shared/build-lib.sh promote_release`) maintains the symlink chain on each release. zddc-server binaries are NOT in this repo — they're attached as Codeberg release assets to clean `zddc-server-vX.Y.Z` tags by `zddc/release.sh`.
|
|
|
|
## Shared CSS (`shared/base.css`)
|
|
|
|
Included as the **first** positional arg to every tool's `concat_files` CSS call. Provides:
|
|
- `:root` CSS custom properties — `--primary`, `--bg`, `--text`, `--border`, `--font`, etc.
|
|
- Brand color: `--primary: #2a5a8a` (matches zddc.varasys.io)
|
|
- Button primitive: `.btn`, `.btn-primary`, `.btn-secondary`, `.btn-sm`, `.btn-lg`, `.btn-link`
|
|
- `.app-header` + `.app-header__title` chrome rules
|
|
- `.build-timestamp`, `.hidden`, `.truncate`, webkit scrollbars
|
|
|
|
**Do not** define these in any tool's own CSS — they come from shared.
|
|
|
|
**Toast CSS** lives in `classifier/css/base.css` only (classifier is the only tool that uses toasts).
|
|
|
|
## Transmittal CSS quirks
|
|
|
|
- `transmittal/css/base.css` overrides `html { font-size: 16px }` inside `@media screen` — this must stay. `shared/base.css` sets `14px`; transmittal's floating labels are rem-based and were designed for 16px.
|
|
- The floating label position is defined in `transmittal/css/forms.css`, not Tailwind classes. If adding new Tailwind classes to `template.html`, add them to `transmittal/css/utilities.css` too — there is no Tailwind build step.
|
|
|
|
## Build system rules
|
|
|
|
- Every `build.sh` sources `shared/build-lib.sh` first (provides `ensure_exists`, `concat_files`, `build_timestamp`). Set `root_dir` before sourcing.
|
|
- Build scripts use **POSIX sh** (`#!/bin/sh` with `set -eu`), not bash.
|
|
- `concat_files` accepts **positional args only** (not array names).
|
|
- `awk` processes `template.html`, replacing `{{PLACEHOLDER}}` markers and stripping CDN `<script>`/`<link>` tags (pattern: `https?://`)
|
|
- `{{BUILD_LABEL}}` is substituted in all five tools via `gsub` in awk (use `gsub`, not `print` — the placeholder is inline in an HTML line). Value is `Built: <timestamp> BETA` for dev builds, `v<version>` for stable releases, and `<channel> · <date> · <sha>` for alpha/beta channel builds; computed before the awk step. The shared `is_red` flag controls whether the label is wrapped in a red+bold `<span>` (true for dev/alpha/beta, false for stable).
|
|
- Cleans up temp files via `trap cleanup EXIT`
|
|
|
|
**`</` escaping is mandatory.** Any JS containing `</tag>` inside string or template literals will break inline `<script>` embedding. Run:
|
|
```bash
|
|
sed 's#</#<\\/#g' "$input_js" > "$safe_js"
|
|
```
|
|
Required for any new tool with vendor JS or JS containing HTML template literals.
|
|
|
|
## JS module pattern
|
|
|
|
All JS is vanilla, no bundlers. Files are IIFEs, registered on `window.app.modules`. Load order = declaration order in `build.sh`. `window.app` is the only global.
|
|
|
|
```javascript
|
|
(function() {
|
|
window.app.modules.mymodule = { ... };
|
|
})();
|
|
```
|
|
|
|
**Exception:** archive uses plain globals (`APP_STATE`, top-level functions) — not the IIFE/modules pattern.
|
|
|
|
## ZDDC filename parsers
|
|
|
|
All parsing/formatting goes through `shared/zddc.js`, exposed as `window.zddc`. Tools call it directly — no per-tool wrappers.
|
|
|
|
`window.zddc` exports:
|
|
- `parseFilename(name)` → `{ trackingNumber, revision, status, title, extension, valid } | null` (extension WITHOUT leading dot)
|
|
- `parseFolder(name)` → `{ date, trackingNumber, status, title, valid } | null`
|
|
- `parseRevision(rev)` → `{ base, modifier, modifierType, modifierNumber, isDraft, modifierIsDraft, full }`
|
|
- `compareRevisions(a, b)` → number (canonical sort order)
|
|
- `formatFilename(parts)` / `formatFolder(parts)` — round-trips parsed output
|
|
- `isValidStatus(code)` — accepts known status codes plus `---`
|
|
|
|
All file objects across tools use `file.trackingNumber` (string) and `file.extension` (string, **no leading dot**, e.g. `'pdf'` not `'.pdf'`). When concatenating into a filename, write `name + '.' + ext`.
|
|
|
|
Coverage lives in `tests/zddc.spec.js` (47 cases). Add new edge cases there, not in tool tests.
|
|
|
|
## Testing quirks
|
|
|
|
- Playwright + Chromium only (File System Access API requirement)
|
|
- Tests open `dist/tool.html` via `file://` protocol — **always build before testing**
|
|
- File System Access API is mocked via `page.addInitScript()` using `tests/fixtures/mock-fs-api.js`
|
|
- Use `waitUntil: 'load'` or `'domcontentloaded'` not `'networkidle'` — bundled scripts keep the network "active"
|
|
- Archive's `#noDirectoryMessage` empty-state overlay is `position: absolute; top: 50px` — it must clear the header or it will block button clicks in tests
|
|
|
|
## ZDDC filename convention
|
|
|
|
Format: `trackingNumber_revision (status) - title.extension`
|
|
|
|
- `trackingNumber`: no spaces or underscores (e.g. `123456-EL-SPC-2623`)
|
|
- `revision`: `A`, `B`, `0`; draft prefix `~`; modifiers `+C1`, `+B1`, `+N1`, `+Q1`
|
|
- `status`: `IFA IFB IFC IFD IFI IFP IFR IFU REC RSA RSB RSC RSD RSI` or `---`
|
|
- Folder names prefix with date: `2025-10-31_trackingNumber (status) - title`
|
|
|
|
## Git workflow
|
|
|
|
- Feature-branch workflow; squash-merge feature branches to `main`
|
|
- Conventional commits: `feat(archive): ...`, `fix(transmittal): ...`
|
|
- Release tags: `archive-v1.0.0` (per-tool semver)
|
|
- Commit dist files: `git add -f tool/dist/tool.html`
|
|
|
|
### Releasing — channels and layout
|
|
|
|
Three channels. Versioning is **per-tool semver**: stable owns clean `vX.Y.Z`; alpha and beta are mutable channel mirrors that get overwritten in place (no counter tags — channel URLs are stable URLs by design). The next-stable target X.Y.Z used in alpha/beta on-page labels is patch-bumped from the latest clean `<tool>-vX.Y.Z` tag.
|
|
|
|
**Storage model.** All HTML tool artifacts live in this repo under `website/releases/`. Per-version files (`<tool>_v<X.Y.Z>.html`) are real, immutable, committed bytes; partial-version pins (`<tool>_v<X.Y>.html`, `<tool>_v<X>.html`) and channel mirrors (`<tool>_<channel>.html`) are checked-in symlinks pointing at the appropriate concrete file. No `manifest.json`, no Codeberg indirection, no Caddy proxy magic. Caddy serves these as plain static files.
|
|
|
|
zddc-server binaries are a separate concern — they ship as Codeberg release assets attached to clean `zddc-server-vX.Y.Z` tags by `zddc/release.sh`. zddc-server has no alpha/beta channel for binaries; the helm charts under `helm/` build from source.
|
|
|
|
`shared/build-lib.sh promote_release` is the single point of truth for HTML-tool releases:
|
|
|
|
- **Stable** (`sh tool/build.sh --release [version]`, or just `--release` to auto-bump patch): Writes `website/releases/<tool>_v<X.Y.Z>.html` (immutable real bytes), then refreshes 5 symlinks — `<tool>_v<X.Y>.html`, `<tool>_v<X>.html`, `<tool>_stable.html`, `<tool>_beta.html`, `<tool>_alpha.html` — all → the new versioned file. Tags `<tool>-v<X.Y.Z>`. Cascade rule: stable cut means beta and alpha both reset to stable (no active dev on either downstream channel). Skips silently if source has not changed since the latest stable tag.
|
|
- **Beta** (`sh tool/build.sh --release beta`): Overwrites `<tool>_beta.html` with the dist HTML bytes (replacing the symlink with a real file if one was there). Cascade: `<tool>_alpha.html` → `<tool>_beta.html` (symlink). No tag.
|
|
- **Alpha** (`sh tool/build.sh --release alpha`): Overwrites `<tool>_alpha.html` with the dist HTML bytes. No tag, no other side-effects.
|
|
- **Plain dev builds** (no `--release`): produce `tool/dist/<tool>.html` only. No `website/releases/` side-effect, no commit. To publish, re-run with `--release alpha`.
|
|
|
|
On-page `{{BUILD_LABEL}}` format:
|
|
|
|
- Plain dev: `vX.Y.Z-alpha · <full-ts> · <sha>[-dirty]` (red), where X.Y.Z is the next-stable target.
|
|
- `--release alpha`: `vX.Y.Z-alpha · <date> · <sha>` (red).
|
|
- `--release beta`: `vX.Y.Z-beta · <date> · <sha>` (red).
|
|
- `--release [version]`: `v<X.Y.Z>` (black).
|
|
|
|
After cutting a stable release, `git push origin <tag>` to publish the tag. `git push origin main` publishes the new versioned file + updated symlinks.
|
|
|
|
No `$CODEBERG_TOKEN` is needed for HTML-tool releases — they never touch Codeberg. (`zddc/release.sh` for zddc-server stable cuts still requires it for binary uploads.)
|
|
|
|
`website/index.html` (the root URL of zddc.varasys.io) is **hand-edited static content**, not built by `landing/build.sh`. Its "Install on your server" section points operators at two paths: local download (per-tool links to `/releases/`) and `zddc-server` install (the binary has the current-stable build of every tool baked in via `//go:embed`). The landing tool's release file is `website/releases/landing_v<X.Y.Z>.html`; on a `zddc-server` deployment, the embedded copy is served at the root URL by default, with operators able to override via `.zddc apps:` entries or by dropping a real `index.html`.
|
|
|
|
### Channel discipline (MUST rules)
|
|
|
|
The build system does not enforce these. Treating channels carelessly defeats the point of having three. Be disciplined.
|
|
|
|
1. **Stable doesn't regress.** No known-broken features that worked in the previous stable. If you ship `v0.0.5` with a bug, the path forward is `v0.0.6` with a fix — never edit a previously-published `<tool>_v0.0.5.html` in place. Stable per-version files are immutable.
|
|
2. **Coordinated minor/major bumps.** When any tool needs a minor or major bump, all five tools cut at the same time even if patches differ. Per-tool patches stay independent. This is a release-time process rule, not enforced by tooling.
|
|
3. **No backports.** Don't try to patch an older stable version. Always cut a new stable at a higher version. Users pinned to the old version stay pinned by choice; they can move forward when they want.
|
|
4. **Alpha and beta are mutable.** Document this anywhere you invite users to test them. Pinning a deployment to a channel mirror means it gets rebuilt without notice. For something stable, pin to a per-version URL (the `<tool>_v0.0.5.html` file).
|
|
5. **Cascade is automatic.** A stable cut resets beta and alpha symlinks → stable. A beta cut resets alpha → beta. So "no active beta" silently shows current stable and "no active alpha" silently shows current beta. Operators don't need to run a freshen step after a stable release; the cascade handles it.
|
|
6. **Hotfix path.** For critical bugs: fix on `main`, cut a new stable. Tag the commit message `fix:` or include "hotfix" so intent is visible in `git log`.
|
|
7. **Beta soak before promoting (recommended).** Give a beta a few days of exposure before cutting the same code as stable. Not enforced; use judgment for trivial changes.
|
|
|
|
### Freshen helper
|
|
|
|
`./freshen-channel <tool> <channel>` rebuilds the alpha or beta channel of a tool from its current stable tag — useful when you want a channel to advance to current stable code without doing active dev on it (e.g. after upstream dependency changes). Most of the time you don't need it: the cascade rule (rule 5 above) means a stable cut already resets the downstream channel symlinks. Use this when you specifically want a fresh build with a new on-page label timestamp instead of a symlink.
|
|
|
|
```sh
|
|
./freshen-channel archive alpha
|
|
./freshen-channel transmittal beta
|
|
```
|
|
|
|
What it does:
|
|
|
|
1. Finds the latest `<tool>-v*` clean stable tag.
|
|
2. Creates a temporary git worktree at that tag — does **not** touch the main worktree's HEAD or working tree.
|
|
3. Runs `<tool>/build.sh --release <channel>` inside the worktree, which overwrites `<tool>_<channel>.html` with the freshly-built bytes. (Note: this is in the worktree, not on main — you'll need to commit the resulting changes back to main afterward.)
|
|
4. Removes the worktree.
|
|
|
|
The build pipeline used is the one **at the tag**, not on `main`. That is intentional (pure reproducibility). If you have made build-system improvements since stable was cut and want the freshen to use them, cut a new stable first.
|
|
|
|
### Install model
|
|
|
|
No install script. Two paths:
|
|
|
|
- **Local** — download a tool `.html` from `https://zddc.varasys.io/releases/` and open it. Done.
|
|
- **Server** (`zddc-server`) — every tool is `//go:embed`'d into the binary at compile time (the current-stable build). The server virtually serves them at folder-name-driven paths:
|
|
- `archive.html` at every directory (multi-project, project, archive, vendor levels)
|
|
- `classifier.html` in any `Incoming`/`Working`/`Staging` directory and its subtree
|
|
- `mdedit.html` in any `Working` directory and its subtree
|
|
- `transmittal.html` in any `Staging` directory and its subtree
|
|
- `index.html` (landing) only at the deployment root
|
|
|
|
See `internal/apps/availability.go`. Outside these locations, requesting `<app>.html` returns 404 (just like any other missing file).
|
|
|
|
To override at any level, either:
|
|
1. Drop a real `<app>.html` file at the path → static handler serves it (highest priority).
|
|
2. Write an `apps:` entry in any `.zddc` along the path. Spec is one of `stable`/`beta`/`alpha`/`v0.0.4`/`v0.0`/`v0`/full URL/local path. Closer-to-leaf entries win.
|
|
|
|
URL sources fetch once and cache forever in `<ZDDC_ROOT>/_app/<host>/<path>`. To force a re-fetch, delete the cache file. No background refresh, no SHA-256 verification, no admin UI. If a configured URL fetch fails, the server falls back to the embedded copy and emits a one-time WARN log.
|
|
|
|
Operators audit by reading the `X-ZDDC-Source` response header: `fetch:URL` / `cache:URL` / `path:/abs` / `embedded:<app>@<build>`. Direct URL access to `/_app/...` is blocked at the dispatch layer.
|
|
|
|
**Runtime mode detection** in archive is independent of install: it auto-detects multi-project / project-root / in-archive from `?projects=` plus folder shape. The other tools don't care where they live.
|
|
|
|
### Worktrees
|
|
|
|
Use `git worktree` to run multiple agents on separate branches simultaneously without filesystem collisions.
|
|
|
|
- Worktrees live at `~/src/zddc-<branch-name>` (sibling of the main clone)
|
|
- Before starting work on a feature branch, check `git worktree list`; if no worktree exists, create one: `git worktree add ~/src/zddc-<branch-name> -b <branch-name>`
|
|
- All edits, builds (`sh build.sh`), and tests (`npm test`) run from within the worktree directory — build scripts use relative paths so this works correctly
|
|
- The `dist/` force-commit rule (`git add -f`) applies per-worktree
|
|
- After the branch is merged, clean up: `git worktree remove ~/src/zddc-<branch-name>` then delete the branch
|
|
- Never run `git checkout` or `git switch` inside a worktree that another agent may be using
|
|
|
|
## Transmittal-specific
|
|
|
|
- Two-phase hydration: `populateStatic()` before publish, `hydrate()` on load of published file
|
|
- Reactive state via Proxy — `app.state.mode = 'view'` auto-notifies subscribers
|
|
- Runtime CDN loads (jszip, docx-preview, xlsx) are allowed only for the optional DOCX/XLSX preview; core features work offline
|
|
- Published payload stored in `<script id="transmittal-data" type="application/json">`
|
|
|
|
## mdedit-specific
|
|
|
|
- `css/tailwind-utils.css` is a pre-generated static subset (~80 classes). Add new Tailwind classes here; do not re-run Tailwind.
|
|
- Toast UI Editor v3.2.2 is bundled in `vendor/`; `template.html` loads it from CDN for dev convenience
|
|
- `</` escaping is essential: `sed 's#</#<\\/#g'` runs on both app JS and vendor JS at build time
|
|
|
|
## zddc-server
|
|
|
|
Go HTTP server sub-project living at `zddc/`. Replaces `caddy file-server --browse` for ZDDC archives.
|
|
|
|
### Build
|
|
|
|
zddc-server ships as a cross-compiled binary, not a container image. There's no Containerfile or compose file in this repo (the chart Dockerfiles in `tnd-zddc-chart` compile from source at deploy time, fetching the right tag from Codeberg).
|
|
|
|
```sh
|
|
# Compile a local binary for the host platform (requires Go 1.24+)
|
|
(cd zddc && go build -o zddc-server ./cmd/zddc-server)
|
|
|
|
# Or run directly without producing a binary
|
|
(cd zddc && go run ./cmd/zddc-server)
|
|
```
|
|
|
|
The repo's top-level `sh build.sh` cross-compiles the four release binaries (linux/amd64, darwin/amd64, darwin/arm64, windows/amd64) into `zddc/dist/` when Go is on PATH. It's silently skipped otherwise — the HTML tools build regardless.
|
|
|
|
### Run (development)
|
|
|
|
```sh
|
|
ZDDC_ROOT=/path/to/your/archive ZDDC_TLS_CERT=none ZDDC_ADDR=:8080 \
|
|
go run ./cmd/zddc-server
|
|
```
|
|
|
|
For a release binary (downloaded from Codeberg or built via `sh build.sh`):
|
|
|
|
```sh
|
|
ZDDC_ROOT=/path/to/your/archive ZDDC_TLS_CERT=none ZDDC_ADDR=:8080 \
|
|
./zddc/dist/zddc-server-linux-amd64
|
|
```
|
|
|
|
### Key environment variables
|
|
|
|
| Variable | Default | Purpose |
|
|
|---|---|---|
|
|
| `ZDDC_ROOT` | *(required)* | Path to served file tree |
|
|
| `ZDDC_ADDR` | `:8443` | Bind address |
|
|
| `ZDDC_EMAIL_HEADER` | `X-Auth-Request-Email` | Header set by upstream proxy with user email (oauth2-proxy / nginx auth-request convention) |
|
|
| `ZDDC_INDEX_PATH` | `.archive` | Virtual archive index URL segment |
|
|
| `ZDDC_LOG_LEVEL` | `info` | Logging verbosity |
|
|
| `ZDDC_CORS_ORIGIN` | `https://zddc.varasys.io` | Comma-separated CORS allowlist; empty value disables CORS. Default lets tools served from zddc.varasys.io call back into a customer-deployed server. |
|
|
|
|
### Release tagging
|
|
|
|
`zddc/release.sh` is the canonical path. It tags the commit, cross-compiles binaries (native Go), and uploads them as Codeberg release assets. **Stable cuts only** — zddc-server has no alpha/beta channel for binary distribution. Active dev/soak happens via the `helm/zddc-server-dev/` chart, which builds from source on every pod restart against any commit you point it at.
|
|
|
|
```sh
|
|
sh zddc/release.sh # patch-bump from latest clean stable tag
|
|
sh zddc/release.sh 0.1.0 # explicit version
|
|
```
|
|
|
|
The script tags the commit but does NOT push — finish with `git push origin main` and `git push origin <tag>`.
|
|
|
|
**Versioning** — clean semver. Stable cuts get `<tool>-vX.Y.Z` tags; no `-alpha.N` / `-beta.N` counters. The historical `zddc-server-v0.0.8-alpha.1` and `-alpha.2` tags from the previous scheme stay as artifacts but no new alpha/beta tags get added.
|
|
|
|
**Binary publishing** — release.sh uploads the four cross-compiled binaries (`zddc-server-{linux,darwin,windows}-{amd64,arm64}`) as release assets attached to the new git tag on Codeberg. Operators download from `https://codeberg.org/VARASYS/ZDDC/releases/download/zddc-server-vX.Y.Z/zddc-server-<platform>` directly.
|
|
|
|
Prerequisites:
|
|
- Go 1.24+ on PATH (or run from a Go container).
|
|
- `$CODEBERG_TOKEN` exported, scoped to write the VARASYS/ZDDC repo.
|
|
|
|
There is no CI for this — solo workflow benefits from one canonical
|
|
local path that fails loudly and visibly on the developer's terminal.
|
|
|
|
### Notes
|
|
|
|
- No external test framework yet — Go unit tests run with `go test ./...` inside `zddc/` (requires Go 1.24+)
|
|
- Portfolio files (`*.portfolio`) in the served tree appear as virtual group directories
|
|
- Every folder exposes a `.archive` virtual directory backed by the same global index — the depth in the URL only matters so HTML produced for offline use can reach `.archive/` via `../.archive/` relative links and have the browser resolve them before the request hits the server. The flat listing emits two redirect entries per tracking number: `<tracking>.html` (highest base rev) and `<tracking>_<rev>.html` (each specific base rev). Both redirect to the first chronologically received copy of the named revision. Modifier files (`<tracking>_<rev>+C1.html` etc.) remain reachable via the resolver but are not surfaced in the listing — they're return traffic, not primary documents. ACL is the only filter: the listing endpoint is gated by the contextPath's `.zddc` chain, and each entry is then filtered against the ACL of its resolved file's directory; per-target denials return 404 rather than 403 to avoid leaking that the tracking number exists in another subtree
|
|
- ACL is enforced via cascading `.zddc` YAML files; authentication is delegated to the upstream proxy via the `X-Auth-Request-Email` header (configurable with `ZDDC_EMAIL_HEADER`)
|
|
- `.zddc` schema also supports a top-level `admins:` glob list, peer to `acl.allow`/`acl.deny`. Honored **only** at the root `.zddc` (subdir `admins` entries are ignored to prevent privilege escalation via subtree write access). Drives the built-in debug dashboard at `/.admin/` (sub-routes: `/whoami`, `/config`, `/logs`); non-admin requests get 404 so the page is invisible. See `zddc/README.md` § "Admin Debug Page".
|
|
- **Reserved entry prefixes** under `ZDDC_ROOT`: `.`-prefixed entries are excluded from listings AND 404 on direct fetch (only `.archive` and `.admin` are exempt) — for invisible side-state like dev-shell home dirs. `_`-prefixed entries are excluded from listings only — for operator scaffolding like the `_template/` directory created by the self-contained install snippet, still reachable by direct URL. Drop side-state under `_` if it should be linkable; under `.` if it should be unreachable.
|