diff --git a/.forgejo/workflows/publish-image.yaml b/.forgejo/workflows/publish-image.yaml
index 9b572cf..4011105 100644
--- a/.forgejo/workflows/publish-image.yaml
+++ b/.forgejo/workflows/publish-image.yaml
@@ -1,5 +1,5 @@
-# Uses the estate's tier-2 container-build runner and organization-scoped
-# REGISTRY_USER / REGISTRY_TOKEN secrets.
+# Uses the estate's tier-2 container-build runner, a dedicated repository-read
+# FORGEJO_SOURCE_TOKEN, and package-write REGISTRY_USER / REGISTRY_TOKEN.
name: Build and publish policy-nexus image
on:
@@ -25,8 +25,12 @@ concurrency:
group: policy-nexus-publication
cancel-in-progress: false
+permissions:
+ contents: read
+
env:
REGISTRY: forgejo.coulomb.social
+ FORGEJO_ORIGIN: https://forgejo.coulomb.social
IMAGE_NAME: coulomb/policy-nexus
DOCKER_HOST: tcp://127.0.0.1:2375
@@ -36,12 +40,17 @@ jobs:
steps:
- name: Build, verify, and publish immutable policy artifact
env:
+ FORGEJO_SOURCE_TOKEN: ${{ secrets.FORGEJO_SOURCE_TOKEN }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
set -eu
REF="${GITHUB_SHA:-}"
test "${#REF}" -eq 40
+ if [ -z "${FORGEJO_SOURCE_TOKEN:-}" ]; then
+ echo "FORGEJO_SOURCE_TOKEN is required for private source repositories" >&2
+ exit 2
+ fi
SHORT="${REF:0:7}"
BUILD_ROOT="$(mktemp -d)"
PYTHON_CONTAINER=""
@@ -56,7 +65,8 @@ jobs:
mkdir -p "${BUILD_CONTEXT}" "${HOME}/bin"
wget -qO "${BUILD_ROOT}/policy-nexus.tar.gz" \
- "https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${SHORT}.tar.gz"
+ --header="Authorization: token ${FORGEJO_SOURCE_TOKEN}" \
+ "${FORGEJO_ORIGIN}/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz"
tar xzf "${BUILD_ROOT}/policy-nexus.tar.gz" \
-C "${BUILD_CONTEXT}" --strip-components=1
@@ -69,11 +79,14 @@ jobs:
docker create --name "${PYTHON_CONTAINER}" "${PYTHON_IMAGE}" sleep 300
docker cp "${BUILD_CONTEXT}/." "${PYTHON_CONTAINER}:/workspace"
docker start "${PYTHON_CONTAINER}"
- docker exec --workdir /workspace "${PYTHON_CONTAINER}" \
+ docker exec --workdir /workspace \
+ --env FORGEJO_SOURCE_TOKEN "${PYTHON_CONTAINER}" \
python3 tools/fetch_sources.py \
--config source-inventory.config.json \
--destination _sources \
- --policy-revision "${REF}"
+ --policy-revision "${REF}" \
+ --token-env FORGEJO_SOURCE_TOKEN \
+ --token-origin "${FORGEJO_ORIGIN}"
NETKINGDOM_REVISION="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["repositories"]["net-kingdom"]["revision"])')"
SOURCE_SET_DIGEST="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["source_set_digest"])')"
docker cp "${PYTHON_CONTAINER}:/workspace/_sources" "${BUILD_CONTEXT}/"
diff --git a/build/adr/addressing-and-permanence/v1/index.html b/build/adr/addressing-and-permanence/v1/index.html
index 25607cc..ac3df5e 100644
--- a/build/adr/addressing-and-permanence/v1/index.html
+++ b/build/adr/addressing-and-permanence/v1/index.html
@@ -1,6 +1,6 @@
-
+
Policy addressing and permanence
-policy-nexus-adr-0001 accepted · accepted-1 the-custodian reviewed 2026-08-18generated from canonical source — do not edit
Policy addressing and permanence
Source: policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 6515ed9ef8499cb3de3397f0ae3993cc71440599
Review due: 2027-02-18
- Status: accepted
- Date: 2026-08-18
- Owner: the-custodian
+policy-nexus-adr-0001 accepted · accepted-1 the-custodian reviewed 2026-08-18generated from canonical source — do not edit
Policy addressing and permanence
Source: policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373
Review due: 2027-02-18
- Status: accepted
- Date: 2026-08-18
- Owner: the-custodian
Decision
A document has one stable current address and immutable revision addresses:
/<kind>/<document>/<version>/
@@ -211,4 +211,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
Consequences
- Builds fail if a source disappears, an id differs, a path collides, or an immutable revision would change; stale output is not silently called fresh.
- Pages show status, revision, owner, last review and exact source revision.
- Availability remains restart recovery on the single-node rail. This contract promises stable addressing, not a high-availability SLA.
-
+