Merge pull request 'LithosAnanke v4.0.0-alpha.1: the first alpha release' (#127) from StarForth-v4.0.0 into master
Runner image / Build and publish the runner image (push) Successful in 51s

This commit was merged in pull request #127.
This commit is contained in:
2026-11-07 17:46:01 +00:00
66 changed files with 2416 additions and 26 deletions
+14 -1
View File
@@ -18,7 +18,8 @@ on:
workflow_dispatch:
concurrency:
group: qemu # one QEMU at a time on the runner: shared with nightly.yml and release.yml
group: qemu # every workflow shares this one group: one run at a time,
# a runner-image rebuild included (Captain Bob, 2026-11-07)
cancel-in-progress: false
jobs:
@@ -37,6 +38,18 @@ jobs:
fetch-depth: 0 # the SBOM's version is git describe
lfs: false # only the logs and DoE CSVs are in LFS; the build needs neither
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
fi
- name: Acceptance amd64
run: scripts/nightly.sh accept amd64
- name: Acceptance aarch64
+30
View File
@@ -9,8 +9,14 @@ name: Build
on:
push:
branches: [StarForth-v4.0.0] # not master: what reaches it has just passed acceptance (#119)
paths-ignore: ['site/**'] # the websites (site/) build nothing here; each run is ~17 min on
# the server the wikis share (Captain Bob, 2026-11-07)
workflow_dispatch:
concurrency:
group: qemu # every workflow shares this one group (Captain Bob, 2026-11-07: a
cancel-in-progress: false # runner-image rebuild blocks other jobs, always): one run at a time
jobs:
image:
name: Image ${{ matrix.board }}
@@ -34,6 +40,18 @@ jobs:
fetch-depth: 0 # the SBOM's version is git describe
lfs: false # only the logs and DoE CSVs are in LFS; the build needs neither
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
fi
- name: Boot image
run: make boot_image TARGET=${{ matrix.board }}
@@ -62,5 +80,17 @@ jobs:
with:
lfs: false
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
fi
- name: make -C v4 test
run: make -C v4 test
+4
View File
@@ -14,6 +14,10 @@ on:
- cron: '0 4 * * *' # 04:00 UTC, after the images (nightly.yml, 03:00)
workflow_dispatch:
concurrency:
group: qemu # every workflow shares this one group (Captain Bob, 2026-11-07: a
cancel-in-progress: false # runner-image rebuild blocks other jobs, always): one run at a time
jobs:
docs:
name: Book, volumes, API reference
+14 -1
View File
@@ -20,7 +20,8 @@ on:
workflow_dispatch:
concurrency:
group: qemu # one QEMU at a time on the runner: shared with acceptance.yml
group: qemu # every workflow shares this one group: one run at a time,
# a runner-image rebuild included (Captain Bob, 2026-11-07)
cancel-in-progress: false
jobs:
@@ -39,6 +40,18 @@ jobs:
fetch-depth: 0 # the SBOM's version is git describe
lfs: false # only the logs and DoE CSVs are in LFS; the build needs neither
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
fi
- name: Acceptance amd64
run: scripts/nightly.sh accept amd64
- name: Acceptance aarch64
+14 -1
View File
@@ -14,7 +14,8 @@ on:
tags: ['v*']
concurrency:
group: qemu # one QEMU at a time on the runner: shared with acceptance.yml
group: qemu # every workflow shares this one group: one run at a time,
# a runner-image rebuild included (Captain Bob, 2026-11-07)
cancel-in-progress: false
jobs:
@@ -33,6 +34,18 @@ jobs:
fetch-depth: 0
lfs: false
- name: The capsule-signing key
env:
KEY: ${{ secrets.CAPSULE_SIGN_KEY }}
run: | # ci/pki/make-ca.sh; kernel/Makefile signs with SIGN_KEY
if [ -n "$KEY" ]; then
f="${RUNNER_TEMP:-/tmp}/capsule-signing.key"
(umask 077; printf '%s\n' "$KEY" > "$f")
echo "SIGN_KEY=$f" >> "$GITHUB_ENV"; echo "The capsules will be signed."
else
echo "::warning::No CAPSULE_SIGN_KEY secret: the capsules are built unsigned."
fi
- name: The tag names the tree's version
run: |
tree="v$(sed -n 's/^LITHOS_VERSION *?= *//p' kernel/Makefile)"
+7 -1
View File
@@ -17,6 +17,10 @@ on:
paths: ['ci/runner-image/**', 'Makefile']
workflow_dispatch:
concurrency:
group: qemu # every workflow shares this one group (Captain Bob, 2026-11-07: a
cancel-in-progress: false # runner-image rebuild blocks other jobs, always): one run at a time
jobs:
image:
name: Build and publish the runner image
@@ -44,7 +48,9 @@ jobs:
tag=$(git rev-parse --short=12 HEAD)
ctx=$(mktemp -d) # not the repository: 7 GB of context
cp -r Makefile boards ci/runner-image/Dockerfile "$ctx/"
docker build -t "$img:$tag" "$ctx"
tok=$(mktemp); printf '%s' "$TOKEN" > "$tok" # the HOL-Library heap's download (Dockerfile)
docker build --secret id=pkgtoken,src="$tok" -t "$img:$tag" "$ctx"
rm -f "$tok"
echo "$TOKEN" | docker login gitea.starshipos-f18.org -u rajames --password-stdin
docker push "$img:$tag"
echo "Published $img:$tag"
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## 2026-11-07 — LithosAnanke v4.0.0-alpha.1: the first alpha release
The first alpha of the kernel, `v4.0.0-alpha.1`: v4, StarForth's F18 engine, is the system every
board boots by default, with v3 a boot argument away. The kernel's version goes from 2.1.0 to the
4.x working line (Captain Bob, 2026-11-07); the engine stays 3.2.0. Accepted in full before the tag:
amd64, aarch64 and riscv64 to `[zuse@Hera] ok>` with POST 538/538 and one `dict_hash`
(`0xfec8c47cfc6f437f`), the PC stick loaded high, `test-32` (39 programs, 0 failures), and the
Isabelle/HOL proofs. An alpha: the v4.0.0 milestone's own definition -- parity with v3's vocabulary,
K=1.0 measured on v4, the hosted mesh, Verilator -- is still open, and the capsules are unsigned until
the StarshipOS CA is made (FABRIC-3.md XLVI). Also today: CI in a prebuilt runner image, the
nightly's proofs no longer able to hold back its images, and the .com and .org websites. Full record:
`docs/fabric/FABRIC-3.md` XLVII.
## 2026-11-07 — CI jobs start ready: the runner image
The CI jobs now run in `lithosananke-runner` (`ci/runner-image`, #120), an image with everything
Binary file not shown.
Binary file not shown.
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# make-ca.sh -- the StarshipOS capsule-signing PKI, made once, on the CI box (Captain Bob,
# 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil intermediate").
#
# StarshipOS Root CA Ed25519, 20 years, self-signed. Its key never leaves this box:
# not in the repository, not in Gitea, not in any image.
# StarshipOS Capsule Signing Ed25519, 10 years, signed by the root; CA:TRUE, pathlen:0.
# Its certificate is built into every image (capsules/pki/
# starshipos-intermediate.der) and checks each capsule at boot;
# its key signs the capsules (mkcapsule --sign-key), in CI from
# the repository secret CAPSULE_SIGN_KEY.
#
# Replaces the offline LithosAnanke Root CA and its snakeoil intermediate (FABRIC-2.md,
# Milestone 6) for every build. Run as root:
#
# sudo ci/pki/make-ca.sh [dir] # dir defaults to /var/lib/starshipos-ca
#
# It refuses to overwrite an existing CA. When it is done it prints the two certificates (public:
# paste them where they are wanted) and says how to put the signing key into Gitea. With
# GITEA_TOKEN set (a token that may administer the repository), it stores the secret itself.
set -euo pipefail
umask 077
dir=${1:-/var/lib/starshipos-ca}
repo=${GITEA_REPO:-rajames/LithosAnanke}
api=${GITEA_API:-https://gitea.starshipos-f18.org/api/v1}
command -v openssl >/dev/null || { echo "make-ca: needs openssl" >&2; exit 1; }
[ -e "$dir/root/root.key" ] && { echo "make-ca: $dir already holds a CA; not overwriting it" >&2; exit 1; }
mkdir -p "$dir/root" "$dir/signing"
cd "$dir"
cat > ca.cnf <<'CNF'
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
[ root_ext ]
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
[ signing_ext ]
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
CNF
# the root
openssl genpkey -algorithm ed25519 -out root/root.key
openssl req -new -x509 -key root/root.key -days 7305 -config ca.cnf -extensions root_ext \
-subj "/O=StarshipOS/CN=StarshipOS Root CA" -out root/root.pem
# the capsule-signing intermediate, signed by the root
openssl genpkey -algorithm ed25519 -out signing/signing.key
openssl req -new -key signing/signing.key -config ca.cnf \
-subj "/O=StarshipOS/CN=StarshipOS Capsule Signing" -out signing/signing.csr
openssl x509 -req -in signing/signing.csr -CA root/root.pem -CAkey root/root.key \
-CAcreateserial -days 3652 -extfile ca.cnf -extensions signing_ext -out signing/signing.pem
openssl x509 -in signing/signing.pem -outform DER -out signing/starshipos-intermediate.der
openssl verify -CAfile root/root.pem signing/signing.pem
chmod 700 root signing; chmod 600 root/* signing/*
if [ -n "${GITEA_TOKEN:-}" ]; then
python3 -c 'import json,sys; print(json.dumps({"data": open(sys.argv[1]).read()}))' signing/signing.key |
curl -fsS -o /dev/null -X PUT -H "Authorization: token $GITEA_TOKEN" -H 'Content-Type: application/json' \
"$api/repos/$repo/actions/secrets/CAPSULE_SIGN_KEY" -d @- &&
echo "make-ca: stored the signing key as $repo's secret CAPSULE_SIGN_KEY"
else
echo "make-ca: put $dir/signing/signing.key, whole, into $repo's Actions secret CAPSULE_SIGN_KEY"
echo " (Settings -> Actions -> Secrets), or run again with GITEA_TOKEN set -- after"
echo " removing $dir, since it refuses to overwrite a CA."
fi
echo
echo "=== The root certificate (public) -- $dir/root/root.pem"
cat root/root.pem
echo "=== The capsule-signing certificate (public) -- $dir/signing/signing.pem"
cat signing/signing.pem
echo "=== Fingerprints"
openssl x509 -in root/root.pem -noout -fingerprint -sha256 -subject -enddate
openssl x509 -in signing/signing.pem -noout -fingerprint -sha256 -subject -issuer -enddate
+17 -1
View File
@@ -1,7 +1,8 @@
# The CI runner image (#120): gitea/runner-images' Ubuntu 24.04 with Node -- which
# actions/checkout and upload-artifact run on -- plus everything the jobs install at their start:
# what `make ARCH=amd64,aarch64,riscv64 init INIT_DOCS=0` installs (taken from the Makefile
# itself, not copied, so the two cannot drift), and Maven and a JRE for the publish steps.
# itself, not copied, so the two cannot drift), Maven and a JRE for the publish steps, and
# Isabelle's HOL-Library already built, for the proofs.
#
# Built by .gitea/workflows/runner-image.yml, from a context of the Makefile, boards/ and this file.
FROM gitea/runner-images:ubuntu-24.04-v26.11.03
@@ -11,4 +12,19 @@ WORKDIR /opt/starship-init
RUN make --no-print-directory ARCH=amd64,aarch64,riscv64 init INIT_DOCS=0 \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y -qq maven default-jre-headless \
&& rm -rf /var/lib/apt/lists/* /opt/starship-init/build/cache/downloads
# HOL-Library, prebuilt, into Isabelle's own heaps, so the proofs build only the StarForth session
# (~2.2 GiB, under a minute). Built from scratch it takes ~5.3 GiB (nightly 174 was killed doing it),
# and capped it still needs ~2.6-3.3 GiB: more than the server has. So it is built once, elsewhere,
# by the same Isabelle2025-2, and fetched from this repository's package registry, its checksum
# pinned here (FABRIC-3.md XLVII). Isabelle ships its own HOL heap the same way. The token is a
# build secret (runner-image.yml): it is in neither the image nor its history.
ARG HOL_LIBRARY_URL=https://gitea.starshipos-f18.org/api/packages/rajames/generic/isabelle-hol-library/Isabelle2025-2/hol-library-Isabelle2025-2.tar.xz
ARG HOL_LIBRARY_SHA256=bb24784664def9379e5db27f88802e3679b8e1c628177f6fbe7084e999cb339e
RUN --mount=type=secret,id=pkgtoken \
curl -fsSL -H "Authorization: token $(cat /run/secrets/pkgtoken)" -o /tmp/hol-library.tar.xz "$HOL_LIBRARY_URL" \
&& echo "$HOL_LIBRARY_SHA256 /tmp/hol-library.tar.xz" | sha256sum -c - \
&& heaps=$(isabelle getenv -b ISABELLE_HEAPS_SYSTEM) && mkdir -p "$heaps" \
&& xz -dc /tmp/hol-library.tar.xz | tar -C "$heaps" -xf - \
&& rm /tmp/hol-library.tar.xz \
&& test -s "$heaps/polyml-5.9.2_x86_64_32-linux/HOL-Library"
WORKDIR /
+104
View File
@@ -6061,3 +6061,107 @@ four conflicts resolved to the branch's files (`92ca805e`).
- The first scheduled nightly's publish to Nexus (#17).
- The Pi 5 and Mars images booted on their boards (#27, #28); a Pi 4 port (#26).
- Revoke the access token `claude-session-20261106` (Settings, Applications).
## XLVI. The StarshipOS CA: capsules signed in CI, by a root on the CI box (2026-11-07)
### 1. Found
Every image built anywhere but Captain Bob's machine carried unsigned capsules: CI, the
acceptance runs, the nightly bound for Nexus, a release, the demo. The capsule-signing key -- the
snakeoil intermediate of the offline LithosAnanke Root CA (FABRIC-2.md, Milestone 6) -- lived only
there, `kernel/Makefile`'s `SIGN_KEY` named its path, and a missing signature is a warning by
design (2026-08-26), so they booted: `V4: capsule v4:sys:core.f18 signature: missing (unsigned)`
in every accepted log (`logs/20261106-004933`). And `mkcapsule` signed with whatever key it was
given: a key that is not the embedded certificate's makes every signature INVALID, which refuses
Mama.
### 2. Ruled
Captain Bob, 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil
intermediate."
### 3. Built
- `ci/pki/make-ca.sh`, run once on the CI box: **StarshipOS Root CA** (Ed25519, 20 years,
self-signed; its key stays on that box, in `/var/lib/starshipos-ca`) and **StarshipOS Capsule
Signing** (Ed25519, 10 years, issued by the root, `CA:TRUE, pathlen:0`). It refuses to
overwrite a CA, prints both certificates, and stores the signing key as the repository secret
`CAPSULE_SIGN_KEY` (or says how).
- The image carries `capsules/pki/starshipos-intermediate.der` in place of the snakeoil
intermediate; the kernel finds it by one name, `CAPSULE_SIGNING_CERT_NAME` (`capsule_sig.h`).
- `mkcapsule` checks the signing key against that certificate before it writes anything, and
refuses a key that is not its, or a key with no certificate to check.
- `SIGN_KEY` has no default (`kernel/Makefile`, `v4/Makefile`): CI sets it from the secret (a step
in `acceptance.yml`, `build.yml`, `nightly.yml`, `release.yml`); unset, the capsules are built
unsigned, as before.
What it is not: the kernel still does not check the intermediate against a root at boot
(`x509_ed25519.h`; `ACL.4th`'s `ACL-CA-KEY` is still 0). A signature proves a capsule matches the
certificate in the same image. That is unchanged by this, and a ruling of its own.
### 4. Verified
With a CA made by `make-ca.sh` in a scratch directory (not the real one): `openssl verify` of the
chain OK; `make-ca.sh` refuses a second run; `mkcapsule` with the signing key -- "signing key
matches"; with the root's key -- refused; with a key and no certificate -- refused; with no key --
unsigned, as before. The acceptance with the real certificate is the PR's.
## XLVII. LithosAnanke v4.0.0-alpha.1: the first alpha release (2026-11-07)
### 1. Ruled
Captain Bob, 2026-11-07: "next on the list is do a tag/release of v4.0.0" -- then, on what the number
names: "StarForth version stays the same ... Kernel is 4.0.0. This is our first alpha release." The
tag names the kernel (`release.yml`: `v<LITHOS_VERSION>`), so:
- `LITHOS_VERSION` 2.1.0 -> **4.0.0-alpha.1**; the tag is `v4.0.0-alpha.1`; Nexus takes
`org.starship:kernelImage:4.0.0-alpha.1` and `org.starship:documentation:4.0.0-alpha.1`.
- The engine's `VERSION` stays **3.2.0**.
- The versioning policy (`kernel/Makefile`, FABRIC-3.5.md XXX): 4.x is a working line (even major).
v3.0.0, the first LTS, is no longer the next number; an LTS line takes the next odd major when
XXX.5's criteria are met. Alphas are numbered: a release repository takes each version once.
- The v4.0.0 milestone is unchanged: its definition (v4 equivalent to v3, K=1.0 on all three host
ISAs, a hosted mesh, Verilator co-simulation) is what 4.0.0 itself will be; nine of its issues
are open. This is an alpha of it.
- The release is built and proved here first (this session, 15 GiB), its logs committed; the
server's release run follows once it can pass -- the proofs need HOL-Library in the runner image.
The capsules are unsigned for this release.
### 2. Verified (this session, `b7534107`, before the tag)
- amd64 (`logs/20261107-150809`), aarch64 (`-151023`), riscv64 (`-151359`): `LithosAnanke
v4.0.0-alpha.1 <arch>`, `[zuse@Hera] ok>`, `PARITY:V4_POST tests=538 pass=538 fail=0`,
`POST: PASSED`, Zuse identity confirmed, `PARITY:V4_SYSTEM word_count=317
dict_hash=0xfec8c47cfc6f437f` on all three.
- The PC stick loaded high (`logs/20261107-151539`): the same, from the stick, no fault.
- `make -C v4 test-32`: 39 programs, 0 failures.
- The Isabelle/HOL proofs (`logs/20261107-152312/isabelle`).
- Each v4 capsule logs `signature: no root key (cert not found/parseable)`: the kernel looks for the
StarshipOS Capsule Signing certificate (XLVI), which is not in the tree until `ci/pki/make-ca.sh`
has run. A warning, as "missing (unsigned)" was before; nothing is refused.
### 3. The StarshipOS CA, and acceptance again (`4ca935d8`)
`ci/pki/make-ca.sh` ran on the CI box (2026-11-07 16:50 UTC): the StarshipOS Root CA there, the
signing key in the secret `CAPSULE_SIGN_KEY`, and the certificate -- O=StarshipOS, CN=StarshipOS
Capsule Signing, issued by the root, 2026-11-07 to 2036-11-06, `CA:TRUE, pathlen:0`, SHA-256 of the
DER `13a28dda...029b9a6c` -- in the tree as `capsules/pki/starshipos-intermediate.der`, the snakeoil
intermediate out of it. The tree changed, so the protocol ran again here: amd64
(`logs/20261107-165611`), aarch64 (`-165817`), riscv64 (`-170149`) -- POST 538/538,
`dict_hash=0xfec8c47cfc6f437f` on all three; the stick loaded high (`-170326`); `test-32`, 39
programs, 0 failures; the proofs (`-171020`). Each capsule now logs `signature: missing (unsigned)`:
the kernel found and read the StarshipOS certificate (it said "no root key" without it), and this
session has no key to sign with. CI signs with the secret: the PR's acceptance and the release are
where every capsule first verifies.
### 4. HOL-Library, prebuilt
The runner image was to build HOL-Library itself (XLVI's companion change, `4ae1f759`); the server
cannot: from scratch it peaks at ~5.3 GiB, and with Poly/ML capped at 1.6 GiB the build still needs
Isabelle's Java side at ~1 GiB (at 384 MiB it ran out and hung) -- 2.6-3.3 GiB against the server's
3.8 GiB in all, ~2.3 GiB free with both wikis stopped. So the heap built here by the same
Isabelle2025-2 (HOL-Library and its build database) is a package in this repository's registry,
`generic/isabelle-hol-library/Isabelle2025-2/hol-library-Isabelle2025-2.tar.xz` (45 MB, SHA-256
`bb247846...e999cb339e`), and the image fetches it into Isabelle's system heaps, checksum pinned,
its token a Docker build secret. Shown portable first: a fresh Isabelle home holding only that heap
checks the StarForth session without rebuilding HOL-Library (24 s).
+14 -8
View File
@@ -89,6 +89,12 @@ endif
# v2.2.0 — amd64 bare-metal bring-up (Beelink SER5)
# v2.x — further working releases; riscv64 / aarch64 board bring-up
# v3.0.0 — FIRST LTS, when and only when FABRIC-3.5.md §XXX.5's 5 criteria are met
# v4.0.0-alpha.1 — the first alpha release (Captain Bob, 2026-11-07: "Kernel is 4.0.0. This is
# our first alpha release"): v4, the F18 engine, the default system. The kernel goes
# from v2.1.0 straight to the 4.x working line (even: breaking changes land here);
# v3.0.0, the first LTS, is no longer the next number -- an LTS line takes the next
# odd major when §XXX.5's criteria are met. The engine stays 3.2.0. Alphas are
# numbered (-alpha.N); a release repository takes each version once.
# LITHOS_VERSION (kernel) and VERSION (embedded StarForth engine) are independent
# and do not auto-sync (§XXX.4) — do not infer a relationship if they ever coincide.
# Engine VERSION bumps at tag time by what actually changed (§XXX.6): major = any
@@ -97,7 +103,7 @@ endif
# the messaging layer was replaced by kernel-Hermes, PLOT/FB-* relocated to Hestia —
# all dictionary-visible, no FORTH-79 word semantics changed.
VERSION ?= 3.2.0
LITHOS_VERSION ?= 2.1.0
LITHOS_VERSION ?= 4.0.0-alpha.1
# ==============================================================================
# BUILD PATHS
@@ -207,7 +213,8 @@ MKCAPSULE_SRC = tools/mkcapsule.c tools/pkcs8_ed25519.c \
kernel/src/crypto/ed25519.c \
kernel/src/crypto/fe25519.c \
kernel/src/crypto/scalar25519.c \
kernel/src/crypto/sha512.c
kernel/src/crypto/sha512.c \
kernel/src/crypto/x509_ed25519.c
MKCAPSULE_BIN = $(BUILD_DIR)/tools/mkcapsule
# mkartemis: formats and signs an Artemis partition at build with the kernel's own
# block-subsystem and artemis_sig code (tools/mkartemis.c), built as v4/Makefile builds them.
@@ -215,12 +222,11 @@ MKARTEMIS_SRC = tools/mkartemis.c kernel/src/artemis_sig.c \
$(addprefix v3/src/,block_subsystem.c blkio_ram.c blkio_file.c log.c \
platform/platform_init.c platform/linux/time.c)
MKARTEMIS_BIN = $(BUILD_DIR)/tools/mkartemis
# Milestone 6 (Phase 8): the snakeoil intermediate's private key, generated
# offline outside this repo entirely (see FABRIC-2.md's Phase 8 §Milestone 6
# writeup) -- not present in CI or a fresh checkout, so signing is skipped
# gracefully ($(wildcard ...) below) rather than failing the build. Override
# with `make SIGN_KEY=/path/to/key.pem ...` on a machine that holds it.
SIGN_KEY ?= /home/rajames/CLionProjects/lithosananke-ca/intermediate/snakeoil-intermediate.key
# The capsule-signing key: "StarshipOS Capsule Signing"'s private key (ci/pki/make-ca.sh,
# FABRIC-3.md XLVI). CI sets SIGN_KEY from the secret CAPSULE_SIGN_KEY; elsewhere set it by hand
# (`make SIGN_KEY=/path/to/signing.key ...`). Unset or absent, the capsules are built unsigned,
# which boots with a warning per capsule. mkcapsule refuses a key that is not the certificate's.
SIGN_KEY ?=
SIGN_KEY_ARGS = $(if $(wildcard $(SIGN_KEY)),--sign-key $(SIGN_KEY),)
CAPSULE_GENERATED = $(BUILD_DIR)/capsule_generated.c
CAPSULE_GENERATED_OBJ = $(BUILD_DIR)/capsule_generated.o
+2 -1
View File
@@ -171,7 +171,8 @@ typedef struct {
*
* Milestone 6 (Phase 8): each capsule's payload bytes (the same bytes
* content_hash already covers), signed by mkcapsule at build time with
* the snakeoil intermediate's private key. has_sig=0 for a capsule built
* the capsule-signing key (StarshipOS Capsule Signing, capsule_sig.h;
* the snakeoil intermediate's until 2026-11-07). has_sig=0 for a capsule built
* before this feature existed or otherwise unsigned -- a real, distinct
* state, not "signature is all-zero bytes" (which sig[64] full of 0x00
* would otherwise look ambiguous with). Indexed 1:1 with
+9 -3
View File
@@ -22,6 +22,12 @@
#include "starkernel/capsule.h"
/* The certificate whose key the capsules are signed with: "StarshipOS
* Capsule Signing", issued by the StarshipOS Root CA (ci/pki/make-ca.sh;
* FABRIC-3.md XLVI), replacing the snakeoil intermediate of Milestone 6.
* mkcapsule refuses to sign with a key that is not this certificate's. */
#define CAPSULE_SIGNING_CERT_NAME "pki:starshipos-intermediate.der"
typedef enum {
CAPSULE_SIG_OK = 0, /* has_sig=1, and it verifies */
CAPSULE_SIG_MISSING, /* has_sig=0 -- not signed at all */
@@ -31,9 +37,9 @@ typedef enum {
/*
* Verify capsule descs[index]'s Ed25519 signature against the embedded
* snakeoil intermediate cert's public key (capsule name
* "pki:snakeoil-intermediate.der", found and parsed once, cached for
* every later call this boot -- the cert doesn't change mid-boot).
* capsule-signing certificate's public key (CAPSULE_SIGNING_CERT_NAME,
* found and parsed once, cached for every later call this boot -- the
* cert doesn't change mid-boot).
*
* descs/names/sigs must be the same three parallel arrays
* (capsule_get_descriptors()/capsule_get_names()/capsule_get_signatures()),
+4 -3
View File
@@ -6,9 +6,10 @@
*
* x509_extract_ed25519_pubkey() only ever reads SubjectPublicKeyInfo --
* no signature verification, no chain validation, no extension parsing.
* That's the capsule-PKI use case (Milestone 6): the embedded snakeoil
* intermediate cert is trusted because it's baked into the trusted build,
* never re-verified against the offline root CA at boot.
* That's the capsule-PKI use case (Milestone 6): the embedded capsule-
* signing cert (StarshipOS Capsule Signing since 2026-11-07, the snakeoil
* intermediate before it) is trusted because it's baked into the trusted
* build, never re-verified against its root CA at boot.
*
* x509_verify_signature()/x509_extract_serial() (added 2026-08-28,
* FABRIC-2.md §F.7/§F.17) are for CERTVERIFY -- a regular user's cert,
+1 -3
View File
@@ -4,8 +4,6 @@
#include "starkernel/ed25519.h"
#include <string.h>
#define SNAKEOIL_CERT_NAME "pki:snakeoil-intermediate.der"
/* Cached once per boot: the cert doesn't change mid-boot, and every
* capsule birth (Mama, then every child VM) would otherwise re-find and
* re-parse the same cert. -1 = not yet attempted, 0 = failed, 1 = ready. */
@@ -20,7 +18,7 @@ static int find_and_cache_pubkey(const CapsuleDesc *descs,
pubkey_state = 0; /* assume failure unless every step below succeeds */
for (uint32_t i = 0; i < desc_count; i++) {
if (strcmp(names[i].name, SNAKEOIL_CERT_NAME) == 0) {
if (strcmp(names[i].name, CAPSULE_SIGNING_CERT_NAME) == 0) {
const CapsuleDesc *cert_desc = &descs[i];
if (x509_extract_ed25519_pubkey(arena_base + cert_desc->offset,
(size_t)cert_desc->length,
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More