feat: publish the exact @ekklesia package train to the npm registry (ADR 0053)
CI / verify (pull_request) Successful in 1m1s
CI / infrastructure-smoke (pull_request) Successful in 35s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / package-release (pull_request) Failing after 43s
CI / package-publication (pull_request) Skipped
CI / image-build (pull_request) Successful in 29s
CI / deploy-smoke (split) (pull_request) Canceled after 0s
CI / deploy-smoke (same-origin) (pull_request) Canceled after 38s

Publishes one package release train to the Gitea npm registry under
River_of_Glory_Church, whose packages are publicly readable on purpose:
exactly the .tgz files the package-release gate proved, and nothing else.
Nothing is published by this change.

- scripts/publish-package-train.ts validates the whole local train before
  any request (gate manifest hash, version, revision, unmodified source,
  the nine packages, every artifact's size, SHA-256, integrity,
  SHA256SUMS line, and inner package.json), then publishes in dependency
  order with `npm publish <file.tgz>` under a staging tag. Each package
  is reconciled first (absent: publish; same bytes: accept; other bytes:
  hard stop, version burned), then read back: metadata (name, version,
  integrity, dependency maps, normalized bin, tarball on the registry)
  and the tarball itself, byte for byte, also anonymously. `latest` moves
  only after all nine verify; reruns converge and never delete anything.
  It writes a publication record. The token comes from
  EKKLESIA_PACKAGES_PUBLISH_TOKEN only, through a temporary npm config
  that refers to the variable.
- scripts/test-package-publication.sh proves it against a disposable
  Gitea 1.27.2 with public owners, a publisher team and an outsider:
  anonymous reads, refused unauthorized publishing, byte-identical round
  trips, the registry's own 409, partial-train recovery, the burned
  version hard stop, and dist-tag retry convergence.
- CI: package-release keeps its proven release and hands it on as an
  artifact with its manifest hash; the new package-publication job
  publishes exactly that artifact to the disposable Gitea. Artifact
  actions v3 (node20): v4 refuses any server other than github.com.
- .github/workflows/publish-packages.yml publishes to the real registry
  only by manual dispatch on main, after its own gate run, with the
  secret in the publish step alone.
- docs: the public-read model, the workflow, the record, credentials,
  immutability policy, provider moves, and the first-publication steps.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-10-08 09:49:27 -05:00
co-authored by Claude Opus 5.5
parent 57df2e15f2
commit d3c62e63bf
17 changed files with 2393 additions and 33 deletions
+28 -8
View File
@@ -2,7 +2,7 @@
# The package release gate (ADR 0053): what must pass before a future step may publish a package
# train. It publishes nothing.
#
# bash scripts/test-package-release.sh [--allow-modified]
# bash scripts/test-package-release.sh [--allow-modified] [--keep <directory>]
#
# 1. Builds the public package train from this checkout (`scripts/package-release.ts`): clean build
# output, pack, inspect, release manifest.
@@ -20,13 +20,24 @@
set -euo pipefail
repository_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
allow_modified=()
if [[ "${1:-}" == "--allow-modified" ]]; then
allow_modified=(--allow-modified)
elif (($#)); then
echo "usage: test-package-release.sh [--allow-modified]" >&2
exit 64
fi
allow_modified=() keep=""
while (($#)); do
case "$1" in
--allow-modified)
allow_modified=(--allow-modified)
shift
;;
--keep)
keep="${2:-}"
[[ -n "$keep" ]] || { echo "usage: --keep <directory>" >&2; exit 64; }
shift 2
;;
*)
echo "usage: test-package-release.sh [--allow-modified] [--keep <directory>]" >&2
exit 64
;;
esac
done
# The workspace install's own pnpm store. pnpm chooses a store per file system, so an install in a
# temporary directory would otherwise look in another, empty one; every install here is offline.
@@ -69,4 +80,13 @@ echo "==> Building Core's verifier"
echo "==> Consuming the release from a standalone module"
bash "$repository_root/scripts/test-standalone-module.sh" --release "$release" "${allow_modified[@]}"
# The release this gate proved, for a later job to publish exactly (`--keep`): copied only now, after
# every check passed, into a directory that must not hold an earlier one.
if [[ -n "$keep" ]]; then
mkdir -p "$keep"
[[ ! -e "$keep/$(basename "$release")" ]] || { echo "$keep already holds this release" >&2; exit 1; }
cp -R "$release" "$keep/"
echo " kept in $keep/$(basename "$release")"
fi
echo "Package release gate passed."