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
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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)"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.
Executable
+81
@@ -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
|
||||
@@ -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 /
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
-1
@@ -17,7 +17,8 @@
|
||||
# make -C v4 test-32: v4 with 32-bit cells, every test (the acceptance's last part).
|
||||
# scripts/nightly.sh proofs
|
||||
# isabelle build -c -D proof/: the StarForth session checked afresh every run, whatever is
|
||||
# cached (HOL-Library is reused); its log is logs/<TS>/isabelle/, as a boot's is.
|
||||
# cached (HOL-Library is reused: the CI image has it built, ci/runner-image); its log is
|
||||
# logs/<TS>/isabelle/, as a boot's is.
|
||||
# scripts/nightly.sh images
|
||||
# The board images, into build/nightly/:
|
||||
# raspi5.img.xz Raspberry Pi 5 (make boot_image TARGET=RASPI), for Raspberry Pi Imager
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
__pycache__/
|
||||
@@ -0,0 +1,14 @@
|
||||
# site/brand -- the wikis' banner
|
||||
|
||||
The top bar of both XWikis shows the starshipOS wordmark, not XWiki's logo, and the browser tab's
|
||||
title ends "- StarshipOS" (Captain Bob, 2026-11-07). `starshipos-com.png` and `starshipos-org.png`
|
||||
are the wordmark (Exo 2, white with an orange "OS", transparent), rendered at 2x.
|
||||
|
||||
```
|
||||
XWIKI_USER=rajames XWIKI_PASSWORD=... site/brand/install.sh https://starshipos-f18.com starshipos-com.png
|
||||
XWIKI_USER=rajames XWIKI_PASSWORD=... site/brand/install.sh https://starshipos-f18.org starshipos-org.png
|
||||
```
|
||||
|
||||
The logo belongs to the colour theme, so this makes one of our own, `FlamingoThemes.StarshipOS` (a
|
||||
copy of the stock Iceberg with the wordmark), and makes it the wiki's. To undo: set the wiki's
|
||||
colour theme back to Iceberg (Administration, Look & Feel, Themes).
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# install.sh -- the wiki's banner says StarshipOS, not XWiki (Captain Bob, 2026-11-07: "The banner
|
||||
# XWiki should not say that").
|
||||
#
|
||||
# site/brand/install.sh https://starshipos-f18.com starshipos-com.png
|
||||
# site/brand/install.sh https://starshipos-f18.org starshipos-org.png
|
||||
#
|
||||
# In XWiki 17 the top bar's logo is the colour theme's. This makes a colour theme of our own,
|
||||
# FlamingoThemes.StarshipOS -- a copy of the stock Iceberg with our wordmark as its logo -- and
|
||||
# makes it the wiki's; the stock theme is not touched (set colorTheme back to
|
||||
# FlamingoThemes.Iceberg to undo). It also makes the browser tab's title "<page> - StarshipOS".
|
||||
# Run again after changing the wordmark: the logo is replaced. XWIKI_USER and XWIKI_PASSWORD as for
|
||||
# site/*/install.sh. Everything goes as XML: XWiki refuses form and plain-text writes without its
|
||||
# form token.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
base=${1:?usage: install.sh <wiki URL> <logo.png>}
|
||||
logo=${2:?usage: install.sh <wiki URL> <logo.png>}
|
||||
rest="$base/rest/wikis/xwiki/spaces"
|
||||
auth=(-u "${XWIKI_USER:?set XWIKI_USER}:${XWIKI_PASSWORD:?set XWIKI_PASSWORD}")
|
||||
theme="$rest/FlamingoThemes/pages/StarshipOS"
|
||||
x() { curl -fsS -m 60 "${auth[@]}" "$@"; }
|
||||
prop() { # prop <object URL> <name> <value>: set one property
|
||||
x -o /dev/null -w " $2: %{http_code}\n" -X PUT -H 'Content-Type: application/xml' \
|
||||
--data-binary "$(python3 -c '
|
||||
import sys
|
||||
from xml.sax.saxutils import escape
|
||||
print("<property xmlns=\"http://www.xwiki.org\" name=\"%s\"><value>%s</value></property>" % (escape(sys.argv[1]), escape(sys.argv[2])))' "$2" "$3")" \
|
||||
"$1/properties/$2"
|
||||
}
|
||||
|
||||
echo "=== $base: the colour theme FlamingoThemes.StarshipOS"
|
||||
x -o /dev/null -w " page: %{http_code}\n" -X PUT -H 'Content-Type: application/xml' --data-binary \
|
||||
'<page xmlns="http://www.xwiki.org"><title>StarshipOS</title><syntax>xwiki/2.1</syntax><content>{{include reference="FlamingoThemesCode.ThemeSheet"/}}</content></page>' \
|
||||
"$theme"
|
||||
x -o /dev/null -w " logo $logo: %{http_code}\n" -X PUT -H 'Content-Type: image/png' --data-binary "@$logo" \
|
||||
"$theme/attachments/$logo"
|
||||
have=$(x -H 'Accept: application/json' "$theme/objects/FlamingoThemesCode.ThemeClass" |
|
||||
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))')
|
||||
if [ "$have" = 0 ]; then
|
||||
# Iceberg's theme object, every property as it is, posted to our page
|
||||
x -H 'Accept: application/xml' "$rest/FlamingoThemes/pages/Iceberg/objects/FlamingoThemesCode.ThemeClass/0" |
|
||||
x -o /dev/null -w " theme object, from Iceberg: %{http_code}\n" -X POST -H 'Content-Type: application/xml' \
|
||||
--data-binary @- "$theme/objects"
|
||||
fi
|
||||
prop "$theme/objects/FlamingoThemesCode.ThemeClass/0" logo "$logo"
|
||||
prop "$theme/objects/FlamingoThemesCode.ThemeClass/0" logo-description "StarshipOS"
|
||||
|
||||
echo "=== the wiki's preferences"
|
||||
prefs="$rest/XWiki/pages/XWikiPreferences/objects/XWiki.XWikiPreferences/0"
|
||||
prop "$prefs" colorTheme "FlamingoThemes.StarshipOS"
|
||||
prop "$prefs" title "\$tdoc.getRenderedTitle('plain/1.0') - StarshipOS"
|
||||
|
||||
echo "=== check, as a guest"
|
||||
page=$(curl -sS -m 60 "$base/bin/login/XWiki/XWikiLogin") # a page that shows the chrome to a guest
|
||||
case "$page" in *"FlamingoThemes/StarshipOS/$logo"*) echo " the banner's logo: ours";; *) echo " the banner's logo: NOT ours" >&2; exit 1;; esac
|
||||
case "$page" in *"- StarshipOS</title>"*) echo " the tab's title: ends - StarshipOS";; *) echo " the tab's title: NOT ours" >&2; exit 1;; esac
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,64 @@
|
||||
"""colorlock.py -- keep a page's own colours inside a wiki whose theme forces its own.
|
||||
|
||||
Both XWikis carry a high-contrast theme (skins/flamingo/cssVariablesInit.css on the server) that sets
|
||||
every element black on white with !important. On our pages the design's colours win instead
|
||||
(Captain Bob, 2026-11-07), and on those pages only; the rest of the wiki keeps the theme:
|
||||
|
||||
- every colour an element states in its style="" is made !important -- an inline !important beats
|
||||
any stylesheet's;
|
||||
- a stylesheet scoped to the page's root (class "ssos") covers the elements that state no colour:
|
||||
".ssos *" outranks the theme's "*" (both !important, the more specific wins).
|
||||
"""
|
||||
import re
|
||||
|
||||
ROOT_CLASS = "ssos"
|
||||
STYLE = """<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>"""
|
||||
COLOUR_PROPS = re.compile(r"^\s*(color|background|background-color|border|border-(top|right|bottom|left)|"
|
||||
r"border-color|border-(top|right|bottom|left)-color|accent-color|fill)\s*:", re.I)
|
||||
|
||||
|
||||
def _lock_style(m):
|
||||
decls = []
|
||||
for d in m.group(1).split(";"):
|
||||
if d.strip() and COLOUR_PROPS.match(d) and "!important" not in d:
|
||||
d = d.rstrip() + " !important"
|
||||
decls.append(d)
|
||||
return 'style="%s"' % ";".join(decls)
|
||||
|
||||
|
||||
def lock(html, root_marker):
|
||||
"""root_marker: the opening text of the page's root element, e.g. '<div style="background: #0A1222'."""
|
||||
assert html.count(root_marker) >= 1, root_marker
|
||||
html = html.replace(root_marker, root_marker.replace("<div ", '<div class="%s" ' % ROOT_CLASS, 1), 1)
|
||||
html = re.sub(r'style="([^"]*)"', _lock_style, html)
|
||||
return STYLE + "\n" + html
|
||||
|
||||
|
||||
# For visitors (guests) only, the page is the design alone: XWiki's own chrome -- the top bar with
|
||||
# Register and Log-in, the breadcrumb, the title and "Last modified", the page menu, the side panels,
|
||||
# the footer and the welcome tour -- is hidden, and the design runs the full width. Logged in, the
|
||||
# wiki is all there, to edit with. (Captain Bob, 2026-11-07: "Menu bar".)
|
||||
GUEST_CHROME = """{{velocity}}
|
||||
#if ($isGuest)
|
||||
#[[{{html clean="false"}}<style>
|
||||
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
|
||||
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
|
||||
#xwikimaincontainerinner > a.btn { display: none !important; }
|
||||
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
|
||||
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
|
||||
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
|
||||
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
|
||||
#xwikicontent > .ssos { border: 0 !important; }
|
||||
#xwikimaincontainer { padding: 0 !important; }
|
||||
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
|
||||
</style>{{/html}}]]#
|
||||
#end
|
||||
{{/velocity}}
|
||||
"""
|
||||
@@ -0,0 +1,120 @@
|
||||
{{velocity}}
|
||||
#if ($isGuest)
|
||||
#[[{{html clean="false"}}<style>
|
||||
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
|
||||
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
|
||||
#xwikimaincontainerinner > a.btn { display: none !important; }
|
||||
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
|
||||
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
|
||||
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
|
||||
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
|
||||
#xwikicontent > .ssos { border: 0 !important; }
|
||||
#xwikimaincontainer { padding: 0 !important; }
|
||||
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
|
||||
</style>{{/html}}]]#
|
||||
#end
|
||||
{{/velocity}}
|
||||
{{html clean="false"}}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>
|
||||
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 0">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D !important">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a>
|
||||
<a href="/bin/view/Inquiries/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Inquiries</a>
|
||||
<a href="https://starshipos-f18.org/" style="color: #F5891F !important; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Inquiries</p>
|
||||
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">Talk to the bridge.</h1>
|
||||
<p style="margin: 0; max-width: 640px; font-size: 18px; color: #C8D1DE !important">Licensing, research collaboration, press or plain curiosity — every message is read by a human. Want to contribute code? Head to <a href="https://starshipos-f18.org/">starshipos-f18.org</a>.</p>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 96px; display: flex; flex-wrap: wrap; gap: 48px; align-items: flex-start">
|
||||
|
||||
<form action="https://starshipos-f18.org/bin/view/PublicInquiry/" method="post" aria-label="Inquiry form" style="flex: 999 1 520px; min-width: 0; background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 32px; display: flex; flex-direction: column; gap: 20px">
|
||||
<div aria-hidden="true" style="position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden"><label for="q-website">Leave this empty</label><input id="q-website" name="website" type="text" tabindex="-1" autocomplete="off"></div>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-name" style="font-size: 14px; color: #C8D1DE !important">Name</label>
|
||||
<input id="q-name" name="name" type="text" autocomplete="name" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-email" style="font-size: 14px; color: #C8D1DE !important">Email</label>
|
||||
<input id="q-email" name="email" type="email" autocomplete="email" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-org" style="font-size: 14px; color: #C8D1DE !important">Organization <span style="color: #A3AEC2 !important">(optional)</span></label>
|
||||
<input id="q-org" name="organization" type="text" autocomplete="organization" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-topic" style="font-size: 14px; color: #C8D1DE !important">Topic</label>
|
||||
<select id="q-topic" name="topic" style="min-height: 48px; padding: 0 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
|
||||
<option>General question</option>
|
||||
<option>Licensing</option>
|
||||
<option>Research collaboration</option>
|
||||
<option>Hardware / FPGA</option>
|
||||
<option>Press & media</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-msg" style="font-size: 14px; color: #C8D1DE !important">Message</label>
|
||||
<textarea id="q-msg" name="message" rows="7" style="padding: 12px 14px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px; resize: vertical"></textarea>
|
||||
</div>
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px">
|
||||
<input id="q-list" name="announcements" type="checkbox" style="width: 20px; height: 20px; margin: 3px 0 0; accent-color: #F5891F !important">
|
||||
<label for="q-list" style="font-size: 14px; color: #C8D1DE !important">Also add me to launch announcements (low volume, unsubscribe anytime).</label>
|
||||
</div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 16px">
|
||||
<button type="submit" style="min-height: 48px; padding: 0 28px; background: #F5891F !important; color: #0A1222 !important; border: 0 !important; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Send inquiry</button>
|
||||
<span style="font-size: 13px; color: #A3AEC2 !important">Replies usually within a few days.</span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<aside aria-label="Direct addresses" style="flex: 1 1 300px; display: flex; flex-direction: column; gap: 24px">
|
||||
<h2 style="margin: 0; font-family: 'Exo 2', sans-serif; font-size: 24px">Or write directly</h2>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">General</div>
|
||||
<a href="mailto:info@starshipos.com" style="font-size: 16px">info@starshipos.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">Licensing & partnerships</div>
|
||||
<a href="mailto:licensing@starshipos.com" style="font-size: 16px">licensing@starshipos.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">Press & media</div>
|
||||
<a href="mailto:press@starshipos.com" style="font-size: 16px">press@starshipos.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">Security reports</div>
|
||||
<a href="mailto:security@starshipos.org" style="font-size: 16px">security@starshipos.org</a>
|
||||
</div>
|
||||
<p style="margin: 0; padding-top: 16px; border-top: 1px solid #22324D !important; font-size: 13px; color: #A3AEC2 !important">StarshipOS is developed in Ashland, Ohio.</p>
|
||||
</aside>
|
||||
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Main/" style="color: #C8D1DE !important">Home</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
{{/html}}
|
||||
@@ -0,0 +1,152 @@
|
||||
{{velocity}}
|
||||
#if ($isGuest)
|
||||
#[[{{html clean="false"}}<style>
|
||||
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
|
||||
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
|
||||
#xwikimaincontainerinner > a.btn { display: none !important; }
|
||||
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
|
||||
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
|
||||
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
|
||||
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
|
||||
#xwikicontent > .ssos { border: 0 !important; }
|
||||
#xwikimaincontainer { padding: 0 !important; }
|
||||
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
|
||||
</style>{{/html}}]]#
|
||||
#end
|
||||
{{/velocity}}
|
||||
{{html clean="false"}}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>
|
||||
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 0">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D !important">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="#system" style="color: #C8D1DE !important; text-decoration: none">System</a>
|
||||
<a href="#research" style="color: #C8D1DE !important; text-decoration: none">Research</a>
|
||||
<a href="#silicon" style="color: #C8D1DE !important; text-decoration: none">Silicon</a>
|
||||
<a href="/bin/view/Inquiries/" style="color: #C8D1DE !important; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos-f18.org/" style="color: #F5891F !important; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 72px; display: flex; flex-wrap: wrap; align-items: center; gap: 56px">
|
||||
<div style="flex: 999 1 520px; min-width: 0">
|
||||
<p style="margin: 0 0 20px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">ok> bare metal · FORTH · C99</p>
|
||||
<h1 style="margin: 0 0 24px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(40px, 6vw, 68px); line-height: 1.05; letter-spacing: -0.01em">An operating system that obeys a conservation law.</h1>
|
||||
<p style="margin: 0 0 36px; max-width: 620px; font-size: 18px; color: #C8D1DE !important">StarshipOS is a bare-metal operating system built from the ground up in StarForth and C99. One compudynamic engine governs every word, message, block and virtual machine — and holds K≡1.0 on every architecture it runs on.</p>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 16px">
|
||||
<a href="#system" style="display: inline-block; padding: 14px 24px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px">See how it works</a>
|
||||
<a href="/bin/view/Inquiries/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px">Make an inquiry</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: 1 1 400px; display: flex; justify-content: center">
|
||||
<img src="/bin/download/Main/WebHome/badge.jpg" alt="StarshipOS badge: Santino the mascot inside a ring on a starfield" style="width: 100%; max-width: 540px; height: auto; display: block; border-radius: 8px; border: 1px solid #22324D !important">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-label="At a glance" style="border-top: 1px solid #22324D !important; border-bottom: 1px solid #22324D !important; background: #0E182B !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">38,400+</div><div style="font-size: 14px; color: #A3AEC2 !important">experimental runs validating K≡1.0</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">3 ISAs</div><div style="font-size: 14px; color: #A3AEC2 !important">amd64 · aarch64 · riscv64</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">FORTH-79</div><div style="font-size: 14px; color: #A3AEC2 !important">compliant core, live at the ok> prompt</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">Patent pending</div><div style="font-size: 14px; color: #A3AEC2 !important">LithosAnanke kernel architecture</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="system" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">The system</p>
|
||||
<h2 style="margin: 0 0 48px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">One engine. One fabric. Everything in it obeys the same physics.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">StarForth</h3>
|
||||
<p style="margin: 0 0 16px; font-size: 13px; color: #F5891F !important">the language and the VM</p>
|
||||
<p style="margin: 0; color: #C8D1DE !important">A FORTH-79 compliant adaptive virtual machine written in C99. Words execute by heat: what the system uses, it keeps close. Everything a user touches is StarForth — there is no compiler inside the box.</p>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">LithosAnanke</h3>
|
||||
<p style="margin: 0 0 16px; font-size: 13px; color: #F5891F !important">the microkernel</p>
|
||||
<p style="margin: 0; color: #C8D1DE !important">A bare-metal microkernel built around the Stadium — a single fabric where words, messages, blocks and VMs live side by side, all governed by one compudynamic engine.</p>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">The fleet</h3>
|
||||
<p style="margin: 0 0 16px; font-size: 13px; color: #F5891F !important">VMs that are born, not spawned</p>
|
||||
<p style="margin: 0; color: #C8D1DE !important">Hera births and governs the fleet. Artemis keeps the blocks. Console draws a vector framebuffer. Hermes, in the kernel, carries every message — and every message is checked against its ACL.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D !important; padding-top: 48px">
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Phenomenon first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Observe the behaviour, then write the mathematics. Document before code.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Parity first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">The same machine on every ISA, proven by reproducible dictionary hashes.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Identity on a key</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Your certificate lives on a thumb drive. No key, no session.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Minimal by design</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">A small core of primitives; everything else composed in FORTH.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="research" style="max-width: 1120px; margin: 0 auto; padding: 72px 24px">
|
||||
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
|
||||
<div style="flex: 999 1 480px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Research</p>
|
||||
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">James Law: K≡1.0</h2>
|
||||
<p style="margin: 0; color: #C8D1DE !important">A conservation invariant that holds regardless of instruction set. Validated across 38,400+ runs in 128 configurations under QEMU on amd64, aarch64 and riscv64, and published on SSRN.</p>
|
||||
</div>
|
||||
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
|
||||
<a href="https://starshipos-f18.org/" style="display: inline-block; padding: 14px 20px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">Read the paper</a>
|
||||
<a href="https://starshipos-f18.org/" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px; text-align: center">Design docs on the .org</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="silicon" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Next: silicon</p>
|
||||
<h2 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">From virtual machine to fabric.</h2>
|
||||
<p style="margin: 0; max-width: 720px; color: #C8D1DE !important">StarForth V4 is being brought up as a mesh of tiny stack-machine cores on FPGA — words as instructions, messaging in hardware, and the compudynamic engine steering what runs and when. Same machine, same parity, now in logic.</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="bridge-h" style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 48px; align-items: center; background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 8px; padding: 32px">
|
||||
<img src="/bin/download/Main/WebHome/captain-bob.jpg" alt="Painted portrait of Captain Bob at a keyboard with a mug of coffee, wearing a StarshipOS jacket" style="flex: 1 1 260px; width: 100%; max-width: 340px; aspect-ratio: 2 / 3; height: auto; object-fit: cover; border-radius: 6px; display: block">
|
||||
<div style="flex: 999 1 420px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">From the bridge</p>
|
||||
<h2 id="bridge-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 36px; line-height: 1.15">Built by one engineer, in the open.</h2>
|
||||
<p style="margin: 0 0 24px; color: #C8D1DE !important">StarshipOS is designed and built by Captain Bob — Robert Allan James — drawing on roughly fifty years of embedded-systems work. Development happens in Ashland, Ohio, and in public on starshipos-f18.org.</p>
|
||||
<a href="/bin/view/Inquiries/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px">Get in touch</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="signup-h" style="border-top: 1px solid #22324D !important; background: #0E182B !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 64px 24px; display: flex; flex-wrap: wrap; gap: 32px; align-items: center; justify-content: space-between">
|
||||
<div style="flex: 1 1 360px; min-width: 0">
|
||||
<h2 id="signup-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 28px">Launch announcements</h2>
|
||||
<p style="margin: 0; color: #A3AEC2 !important; font-size: 14px">Milestones, releases and papers. Low volume. Unsubscribe anytime.</p>
|
||||
</div>
|
||||
<form action="mailto:info@starshipos.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">
|
||||
<label for="sub-email" style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Email address</label>
|
||||
<input id="sub-email" name="email" type="email" required placeholder="you@example.com" style="flex: 1 1 240px; min-height: 48px; padding: 0 16px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
|
||||
<button type="submit" style="min-height: 48px; padding: 0 24px; background: #F5891F !important; color: #0A1222 !important; border: 0 !important; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Subscribe</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Inquiries/" style="color: #C8D1DE !important">Inquiries</a><a href="mailto:info@starshipos.com" style="color: #C8D1DE !important">info@starshipos.com</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
{{/html}}
|
||||
@@ -0,0 +1,18 @@
|
||||
# site/com -- the starshipos-f18.com XWiki's pages
|
||||
|
||||
The public face of StarshipOS, made from the "StarshipOS.com" design canvas (claude.ai), whose
|
||||
artboards are copied into `canvas/` as they are: Home (`Main.WebHome`), `Inquiries.WebHome`,
|
||||
`TryIt.WebHome`. `build.py` turns each into one `{{html}}` block (a page author with script rights)
|
||||
and says what changes on the way: the wiki's links and domains, the images as attachments
|
||||
(`badge.jpg`, `captain-bob.jpg`, web-size copies of the canvas's), the real console in Try it, the
|
||||
forms by e-mail. `install.sh` puts them on the wiki and checks a guest can read them:
|
||||
|
||||
```
|
||||
site/com/build.py
|
||||
XWIKI_USER=rajames XWIKI_PASSWORD=... site/com/install.sh
|
||||
```
|
||||
|
||||
Change the design on the canvas, copy the artboard into `canvas/`, and run both again.
|
||||
|
||||
Installed 2026-11-07. Try it is on the wiki but not in the navigation (#117): its console,
|
||||
`try.starshipos-f18.com`, is not served yet (#115).
|
||||
@@ -0,0 +1,128 @@
|
||||
{{velocity}}
|
||||
#if ($isGuest)
|
||||
#[[{{html clean="false"}}<style>
|
||||
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
|
||||
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
|
||||
#xwikimaincontainerinner > a.btn { display: none !important; }
|
||||
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
|
||||
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
|
||||
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
|
||||
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
|
||||
#xwikicontent > .ssos { border: 0 !important; }
|
||||
#xwikimaincontainer { padding: 0 !important; }
|
||||
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
|
||||
</style>{{/html}}]]#
|
||||
#end
|
||||
{{/velocity}}
|
||||
{{html clean="false"}}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>
|
||||
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 0">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D !important">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a>
|
||||
<a href="/bin/view/TryIt/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Try it</a>
|
||||
<a href="/bin/view/Inquiries/" style="color: #C8D1DE !important; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos-f18.org/" style="color: #F5891F !important; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">ok> try it</p>
|
||||
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">A StarshipOS machine of your own.</h1>
|
||||
<p style="margin: 0; max-width: 680px; font-size: 18px; color: #C8D1DE !important">Not a recording, not a simulation of StarshipOS: the console below is a real machine, started just for you and already at its prompt. You are Zuse, the superuser — of a machine that exists only for your session. There is nothing to break, and nothing you do is kept.</p>
|
||||
</section>
|
||||
|
||||
<section aria-label="The console" style="max-width: 1120px; margin: 0 auto; padding: 24px 24px 48px">
|
||||
<div style="background: #050A14 !important; border: 1px solid #34486A !important; border-radius: 8px; overflow: hidden">
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-bottom: 1px solid #22324D !important; background: #0E182B !important; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span style="display: flex; align-items: center; gap: 10px"><span aria-hidden="true" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #4FD1B0 !important"></span>StarshipOS · amd64 · your session</span>
|
||||
<span>try.starshipos-f18.com</span>
|
||||
</div>
|
||||
<iframe src="https://try.starshipos-f18.com/" title="StarshipOS console" style="display: block; width: 100%; height: 30em; border: 0 !important; background: #050A14 !important"></iframe>
|
||||
</div>
|
||||
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2 !important">If the console does not connect, every machine is in use: try again in a few minutes.</p>
|
||||
</section>
|
||||
|
||||
<section aria-label="Your machine" style="border-top: 1px solid #22324D !important; border-bottom: 1px solid #22324D !important; background: #0E182B !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">Zuse</div><div style="font-size: 14px; color: #A3AEC2 !important">the superuser, of this machine only</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">amd64</div><div style="font-size: 14px; color: #A3AEC2 !important">LithosAnanke v2.1.0 · StarForth v4</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">30 min</div><div style="font-size: 14px; color: #A3AEC2 !important">then it is gone; reload for a new one</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">Offline</div><div style="font-size: 14px; color: #A3AEC2 !important">no network inside the machine</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="try-h" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Things to try</p>
|
||||
<h2 id="try-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">StarshipOS speaks FORTH.</h2>
|
||||
<p style="margin: 0 0 40px; max-width: 680px; color: #C8D1DE !important">Type a line and press Enter. When the machine has done it, it answers ok.</p>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">You type</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7 !important">3 4 + .</p>
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">It answers</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #F5891F !important">7 ok</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #C8D1DE !important">Numbers go on a stack; + adds the top two; . prints the result.</p>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">You type</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7 !important">: SQUARE DUP * ;</p>
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">It answers</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #F5891F !important">ok</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #C8D1DE !important">You have just taught the machine a new word, SQUARE.</p>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">You type</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7 !important">7 SQUARE .</p>
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2 !important">It answers</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #F5891F !important">49 ok</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #C8D1DE !important">…and used it, as if it had always been there.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D !important; padding-top: 48px">
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">A machine of your own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Resumed at its prompt from one that booted, passed its 538 power-on self-tests and logged Zuse in — so you never wait for a boot.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">The latest green build</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Always the most recent build that booted on amd64, aarch64 and riscv64 and passed every acceptance check.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">A Zuse of its own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Zuse is whoever holds the identity drive. Here it is a demo Zuse minted for this page alone — not anyone's real identity.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7 !important">Gone when you go</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2 !important">Close the page, or let 30 minutes pass, and the machine is stopped and discarded. The next visitor starts clean.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
|
||||
<div style="flex: 999 1 480px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">A small server</p>
|
||||
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">Emulated, so a little slower.</h2>
|
||||
<p style="margin: 0; color: #C8D1DE !important">The demo runs in an emulator on a modest server: slower than StarshipOS on real hardware, and only a few machines at once. The real thing boots straight from firmware, with nothing beneath it.</p>
|
||||
</div>
|
||||
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
|
||||
<a href="/bin/view/Main/" style="display: inline-block; padding: 14px 20px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">How it works</a>
|
||||
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px; text-align: center">Read the source</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Main/" style="color: #C8D1DE !important">Home</a><a href="/bin/view/Inquiries/" style="color: #C8D1DE !important">Inquiries</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
{{/html}}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
Executable
+103
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""build.py -- the starshipos-f18.com XWiki pages, made from the "StarshipOS.com" design canvas.
|
||||
|
||||
site/com/build.py canvas/{Main,Inquiries,TryIt}.dc.html -> {Main,Inquiries,TryIt}.WebHome.xwiki
|
||||
|
||||
The canvas is the source: its artboards are copied into canvas/ as they are, and this turns each into
|
||||
one {{html}} block (which needs a page author with script rights). What changes on the way:
|
||||
|
||||
- the accent hole becomes its default colour, and the canvas's links become the wiki's pages
|
||||
(Main.dc.html -> /bin/view/Main/, ...) and the real domains (starshipos.org -> starshipos-f18.org);
|
||||
- the two images become attachments of Main.WebHome (badge.jpg, captain-bob.jpg -- web-size copies
|
||||
of the canvas's uploads);
|
||||
- Try it: the drawn console becomes the real one, an iframe of try.starshipos-f18.com;
|
||||
- the inquiry form posts to the .org's PublicInquiry, which files it under Inquiries there
|
||||
(admin-only, site/org/inquiries); the announcements form, which has no server, sends by e-mail;
|
||||
- a link the canvas left as a placeholder ([SSRN PAPER URL]) points at the .org until it is given.
|
||||
|
||||
install.sh puts the pages and the images on the wiki.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
|
||||
import colorlock # noqa: E402 the design's colours over the wiki's high-contrast theme
|
||||
|
||||
ACCENT = "#F5891F"
|
||||
FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">\n'
|
||||
'<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700'
|
||||
'&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">')
|
||||
ORG = "https://starshipos-f18.org/"
|
||||
PAGES = ["Main", "Inquiries", "TryIt"]
|
||||
IMAGES = {"/_blob/5b564d54d98e02ad600c913a9a1888f2": "badge.jpg",
|
||||
"/_blob/5483451f292782a8b366e437181c4bcf": "captain-bob.jpg"}
|
||||
|
||||
CONSOLE = '''<div style="background: #050A14; border: 1px solid #34486A; border-radius: 8px; overflow: hidden">
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-bottom: 1px solid #22324D; background: #0E182B; font-size: 13px; color: #A3AEC2">
|
||||
<span style="display: flex; align-items: center; gap: 10px"><span aria-hidden="true" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #4FD1B0"></span>StarshipOS · amd64 · your session</span>
|
||||
<span>try.starshipos-f18.com</span>
|
||||
</div>
|
||||
<iframe src="https://try.starshipos-f18.com/" title="StarshipOS console" style="display: block; width: 100%; height: 30em; border: 0; background: #050A14"></iframe>
|
||||
</div>
|
||||
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2">If the console does not connect, every machine is in use: try again in a few minutes.</p>'''
|
||||
|
||||
|
||||
def body(src):
|
||||
m = re.search(r"<x-dc>(.*)</x-dc>", src, re.S)
|
||||
html = re.sub(r"<helmet>.*?</helmet>", "", m.group(1), flags=re.S).strip()
|
||||
html = html.replace("{{accent}}", ACCENT)
|
||||
for p in PAGES:
|
||||
html = html.replace('href="%s.dc.html"' % p, 'href="/bin/view/%s/"' % p)
|
||||
html = html.replace('href="https://starshipos.org"', 'href="%s"' % ORG)
|
||||
html = html.replace(">starshipos.org</a>", ">starshipos-f18.org</a>")
|
||||
html = html.replace("on starshipos.org.", "on starshipos-f18.org.")
|
||||
html = html.replace('href="[SSRN PAPER URL]"', 'href="%s"' % ORG)
|
||||
for blob, name in IMAGES.items():
|
||||
html = html.replace('src="%s"' % blob, 'src="/bin/download/Main/WebHome/%s"' % name)
|
||||
html = html.replace("min-height: 100vh", "min-height: 0") # inside the wiki's page, not a screen
|
||||
return html
|
||||
|
||||
|
||||
def try_it(html):
|
||||
start = html.index('<div style="background: #050A14')
|
||||
end = html.index("</p>", html.index("[LIVE CONSOLE]")) + len("</p>")
|
||||
return html[:start] + CONSOLE + html[end:]
|
||||
|
||||
|
||||
def forms(html, page):
|
||||
if page == "Main":
|
||||
html = html.replace('<form style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">',
|
||||
'<form action="mailto:info@starshipos.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">')
|
||||
html = html.replace('<input id="sub-email" type="email"', '<input id="sub-email" name="email" type="email" required')
|
||||
html = html.replace('<button type="button" style="min-height: 48px; padding: 0 24px',
|
||||
'<button type="submit" style="min-height: 48px; padding: 0 24px')
|
||||
if page == "Inquiries":
|
||||
html = html.replace('<form aria-label="Inquiry form"',
|
||||
'<form action="https://starshipos-f18.org/bin/view/PublicInquiry/" method="post" aria-label="Inquiry form"')
|
||||
# a field people cannot see; a robot fills it, and PublicInquiry keeps nothing it sends
|
||||
html = html.replace('<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">',
|
||||
'<div aria-hidden="true" style="position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden">'
|
||||
'<label for="q-website">Leave this empty</label><input id="q-website" name="website" type="text" tabindex="-1" autocomplete="off"></div>\n'
|
||||
'<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">', 1)
|
||||
for i, n in (("q-name", "name"), ("q-email", "email"), ("q-org", "organization"), ("q-topic", "topic"),
|
||||
("q-msg", "message"), ("q-list", "announcements")):
|
||||
html = html.replace('id="%s"' % i, 'id="%s" name="%s"' % (i, n), 1)
|
||||
html = html.replace('<button type="button" style="min-height: 48px; padding: 0 28px',
|
||||
'<button type="submit" style="min-height: 48px; padding: 0 28px')
|
||||
html = html.replace("Replies usually within a few days.",
|
||||
"Replies usually within a few days.")
|
||||
return html
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
for p in PAGES:
|
||||
html = forms(body(open("canvas/%s.dc.html" % p).read()), p)
|
||||
if p == "TryIt":
|
||||
html = try_it(html)
|
||||
html = colorlock.lock(html, '<div style="background: #0A1222')
|
||||
assert "{{" not in html.replace(colorlock.STYLE, "") and "[SSRN" not in html and ".dc.html" not in html and "_blob" not in html, p
|
||||
with open("%s.WebHome.xwiki" % p, "w") as f:
|
||||
f.write(colorlock.GUEST_CHROME + '{{html clean="false"}}\n%s\n%s\n{{/html}}\n' % (FONTS, html))
|
||||
print("wrote", ", ".join("%s.WebHome.xwiki" % p for p in PAGES))
|
||||
@@ -0,0 +1,118 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>StarshipOS — Inquiries</title>
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body{margin:0;background:#0A1222}
|
||||
a{color:#F5891F}a:hover{color:#FFB061}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
|
||||
<a href="Inquiries.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Inquiries</p>
|
||||
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">Talk to the bridge.</h1>
|
||||
<p style="margin: 0; max-width: 640px; font-size: 18px; color: #C8D1DE">Licensing, research collaboration, press or plain curiosity — every message is read by a human. Want to contribute code? Head to <a href="https://starshipos.org">starshipos.org</a>.</p>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 96px; display: flex; flex-wrap: wrap; gap: 48px; align-items: flex-start">
|
||||
|
||||
<form aria-label="Inquiry form" style="flex: 999 1 520px; min-width: 0; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 32px; display: flex; flex-direction: column; gap: 20px">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px">
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-name" style="font-size: 14px; color: #C8D1DE">Name</label>
|
||||
<input id="q-name" type="text" autocomplete="name" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-email" style="font-size: 14px; color: #C8D1DE">Email</label>
|
||||
<input id="q-email" type="email" autocomplete="email" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-org" style="font-size: 14px; color: #C8D1DE">Organization <span style="color: #A3AEC2">(optional)</span></label>
|
||||
<input id="q-org" type="text" autocomplete="organization" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-topic" style="font-size: 14px; color: #C8D1DE">Topic</label>
|
||||
<select id="q-topic" style="min-height: 48px; padding: 0 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
|
||||
<option>General question</option>
|
||||
<option>Licensing</option>
|
||||
<option>Research collaboration</option>
|
||||
<option>Hardware / FPGA</option>
|
||||
<option>Press & media</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px">
|
||||
<label for="q-msg" style="font-size: 14px; color: #C8D1DE">Message</label>
|
||||
<textarea id="q-msg" rows="7" style="padding: 12px 14px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px; resize: vertical"></textarea>
|
||||
</div>
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px">
|
||||
<input id="q-list" type="checkbox" style="width: 20px; height: 20px; margin: 3px 0 0; accent-color: {{accent}}">
|
||||
<label for="q-list" style="font-size: 14px; color: #C8D1DE">Also add me to launch announcements (low volume, unsubscribe anytime).</label>
|
||||
</div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 16px">
|
||||
<button type="button" style="min-height: 48px; padding: 0 28px; background: {{accent}}; color: #0A1222; border: 0; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Send inquiry</button>
|
||||
<span style="font-size: 13px; color: #A3AEC2">Replies usually within a few days.</span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<aside aria-label="Direct addresses" style="flex: 1 1 300px; display: flex; flex-direction: column; gap: 24px">
|
||||
<h2 style="margin: 0; font-family: 'Exo 2', sans-serif; font-size: 24px">Or write directly</h2>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">General</div>
|
||||
<a href="mailto:info@starshipos.com" style="font-size: 16px">info@starshipos.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">Licensing & partnerships</div>
|
||||
<a href="mailto:licensing@starshipos.com" style="font-size: 16px">licensing@starshipos.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">Press & media</div>
|
||||
<a href="mailto:press@starshipos.com" style="font-size: 16px">press@starshipos.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">Security reports</div>
|
||||
<a href="mailto:security@starshipos.org" style="font-size: 16px">security@starshipos.org</a>
|
||||
</div>
|
||||
<p style="margin: 0; padding-top: 16px; border-top: 1px solid #22324D; font-size: 13px; color: #A3AEC2">StarshipOS is developed in Ashland, Ohio.</p>
|
||||
</aside>
|
||||
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Main.dc.html" style="color: #C8D1DE">Home</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":1700}}'>
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
return { accent: this.props.accent ?? '#F5891F' };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,151 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>StarshipOS — Home</title>
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body{margin:0;background:#0A1222}
|
||||
a{color:#F5891F}a:hover{color:#FFB061}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="#system" style="color: #C8D1DE; text-decoration: none">System</a>
|
||||
<a href="#research" style="color: #C8D1DE; text-decoration: none">Research</a>
|
||||
<a href="#silicon" style="color: #C8D1DE; text-decoration: none">Silicon</a>
|
||||
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 72px; display: flex; flex-wrap: wrap; align-items: center; gap: 56px">
|
||||
<div style="flex: 999 1 520px; min-width: 0">
|
||||
<p style="margin: 0 0 20px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">ok> bare metal · FORTH · C99</p>
|
||||
<h1 style="margin: 0 0 24px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(40px, 6vw, 68px); line-height: 1.05; letter-spacing: -0.01em">An operating system that obeys a conservation law.</h1>
|
||||
<p style="margin: 0 0 36px; max-width: 620px; font-size: 18px; color: #C8D1DE">StarshipOS is a bare-metal operating system built from the ground up in StarForth and C99. One compudynamic engine governs every word, message, block and virtual machine — and holds K≡1.0 on every architecture it runs on.</p>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 16px">
|
||||
<a href="#system" style="display: inline-block; padding: 14px 24px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px">See how it works</a>
|
||||
<a href="Inquiries.dc.html" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">Make an inquiry</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: 1 1 400px; display: flex; justify-content: center">
|
||||
<img src="/_blob/5b564d54d98e02ad600c913a9a1888f2" alt="StarshipOS badge: Santino the mascot inside a ring on a starfield" style="width: 100%; max-width: 540px; height: auto; display: block; border-radius: 8px; border: 1px solid #22324D">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-label="At a glance" style="border-top: 1px solid #22324D; border-bottom: 1px solid #22324D; background: #0E182B">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">38,400+</div><div style="font-size: 14px; color: #A3AEC2">experimental runs validating K≡1.0</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">3 ISAs</div><div style="font-size: 14px; color: #A3AEC2">amd64 · aarch64 · riscv64</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">FORTH-79</div><div style="font-size: 14px; color: #A3AEC2">compliant core, live at the ok> prompt</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">Patent pending</div><div style="font-size: 14px; color: #A3AEC2">LithosAnanke kernel architecture</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="system" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">The system</p>
|
||||
<h2 style="margin: 0 0 48px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">One engine. One fabric. Everything in it obeys the same physics.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">StarForth</h3>
|
||||
<p style="margin: 0 0 16px; font-size: 13px; color: {{accent}}">the language and the VM</p>
|
||||
<p style="margin: 0; color: #C8D1DE">A FORTH-79 compliant adaptive virtual machine written in C99. Words execute by heat: what the system uses, it keeps close. Everything a user touches is StarForth — there is no compiler inside the box.</p>
|
||||
</article>
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">LithosAnanke</h3>
|
||||
<p style="margin: 0 0 16px; font-size: 13px; color: {{accent}}">the microkernel</p>
|
||||
<p style="margin: 0; color: #C8D1DE">A bare-metal microkernel built around the Stadium — a single fabric where words, messages, blocks and VMs live side by side, all governed by one compudynamic engine.</p>
|
||||
</article>
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">The fleet</h3>
|
||||
<p style="margin: 0 0 16px; font-size: 13px; color: {{accent}}">VMs that are born, not spawned</p>
|
||||
<p style="margin: 0; color: #C8D1DE">Hera births and governs the fleet. Artemis keeps the blocks. Console draws a vector framebuffer. Hermes, in the kernel, carries every message — and every message is checked against its ACL.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D; padding-top: 48px">
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Phenomenon first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Observe the behaviour, then write the mathematics. Document before code.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Parity first</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">The same machine on every ISA, proven by reproducible dictionary hashes.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Identity on a key</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Your certificate lives on a thumb drive. No key, no session.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Minimal by design</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">A small core of primitives; everything else composed in FORTH.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="research" style="max-width: 1120px; margin: 0 auto; padding: 72px 24px">
|
||||
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
|
||||
<div style="flex: 999 1 480px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Research</p>
|
||||
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">James Law: K≡1.0</h2>
|
||||
<p style="margin: 0; color: #C8D1DE">A conservation invariant that holds regardless of instruction set. Validated across 38,400+ runs in 128 configurations under QEMU on amd64, aarch64 and riscv64, and published on SSRN.</p>
|
||||
</div>
|
||||
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
|
||||
<a href="[SSRN PAPER URL]" style="display: inline-block; padding: 14px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">Read the paper</a>
|
||||
<a href="https://starshipos.org" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px; text-align: center">Design docs on the .org</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="silicon" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Next: silicon</p>
|
||||
<h2 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">From virtual machine to fabric.</h2>
|
||||
<p style="margin: 0; max-width: 720px; color: #C8D1DE">StarForth V4 is being brought up as a mesh of tiny stack-machine cores on FPGA — words as instructions, messaging in hardware, and the compudynamic engine steering what runs and when. Same machine, same parity, now in logic.</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="bridge-h" style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 48px; align-items: center; background: #111C30; border: 1px solid #22324D; border-radius: 8px; padding: 32px">
|
||||
<img src="/_blob/5483451f292782a8b366e437181c4bcf" alt="Painted portrait of Captain Bob at a keyboard with a mug of coffee, wearing a StarshipOS jacket" style="flex: 1 1 260px; width: 100%; max-width: 340px; aspect-ratio: 2 / 3; height: auto; object-fit: cover; border-radius: 6px; display: block">
|
||||
<div style="flex: 999 1 420px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">From the bridge</p>
|
||||
<h2 id="bridge-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 36px; line-height: 1.15">Built by one engineer, in the open.</h2>
|
||||
<p style="margin: 0 0 24px; color: #C8D1DE">StarshipOS is designed and built by Captain Bob — Robert Allan James — drawing on roughly fifty years of embedded-systems work. Development happens in Ashland, Ohio, and in public on starshipos.org.</p>
|
||||
<a href="Inquiries.dc.html" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">Get in touch</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="signup-h" style="border-top: 1px solid #22324D; background: #0E182B">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 64px 24px; display: flex; flex-wrap: wrap; gap: 32px; align-items: center; justify-content: space-between">
|
||||
<div style="flex: 1 1 360px; min-width: 0">
|
||||
<h2 id="signup-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 28px">Launch announcements</h2>
|
||||
<p style="margin: 0; color: #A3AEC2; font-size: 14px">Milestones, releases and papers. Low volume. Unsubscribe anytime.</p>
|
||||
</div>
|
||||
<form style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">
|
||||
<label for="sub-email" style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Email address</label>
|
||||
<input id="sub-email" type="email" placeholder="you@example.com" style="flex: 1 1 240px; min-height: 48px; padding: 0 16px; background: #0A1222; border: 1px solid #34486A; border-radius: 4px; color: #EEF2F7; font-family: inherit; font-size: 15px">
|
||||
<button type="button" style="min-height: 48px; padding: 0 24px; background: {{accent}}; color: #0A1222; border: 0; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Subscribe</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="mailto:info@starshipos.com" style="color: #C8D1DE">info@starshipos.com</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":3700}}'>
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
return { accent: this.props.accent ?? '#F5891F' };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,136 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>StarshipOS — Try it</title>
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body{margin:0;background:#0A1222}
|
||||
a{color:#F5891F}a:hover{color:#FFB061}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
|
||||
<a href="TryIt.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Try it</a>
|
||||
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">ok> try it</p>
|
||||
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">A StarshipOS machine of your own.</h1>
|
||||
<p style="margin: 0; max-width: 680px; font-size: 18px; color: #C8D1DE">Not a recording, not a simulation of StarshipOS: the console below is a real machine, started just for you and already at its prompt. You are Zuse, the superuser — of a machine that exists only for your session. There is nothing to break, and nothing you do is kept.</p>
|
||||
</section>
|
||||
|
||||
<section aria-label="The console" style="max-width: 1120px; margin: 0 auto; padding: 24px 24px 48px">
|
||||
<div style="background: #050A14; border: 1px solid #34486A; border-radius: 8px; overflow: hidden">
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-bottom: 1px solid #22324D; background: #0E182B; font-size: 13px; color: #A3AEC2">
|
||||
<span style="display: flex; align-items: center; gap: 10px"><span aria-hidden="true" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #4FD1B0"></span>StarshipOS · amd64 · your session</span>
|
||||
<span>try.starshipos-f18.com</span>
|
||||
</div>
|
||||
<div style="padding: 24px; min-height: 360px; font-size: 15px; line-height: 1.7; color: #EEF2F7; overflow-x: auto">
|
||||
<div style="color: #A3AEC2">StarshipOS -- starting a throwaway machine, yours for up to 30 minutes. Nothing you do is kept.</div>
|
||||
<div style="color: #A3AEC2">Try: 3 4 + . : SQUARE DUP * ; 7 SQUARE .</div>
|
||||
<div style="color: #A3AEC2; margin-bottom: 12px">Ready -- type a line and press Enter.</div>
|
||||
<div><span style="color: #FFA500">[zuse@Hera]</span> <span style="color: #55FFFF">ok></span> 3 4 + .</div>
|
||||
<div><span style="color: #FFA500">[zuse@Hera]</span> 7 ok</div>
|
||||
<div><span style="color: #FFA500">[zuse@Hera]</span> <span style="color: #55FFFF">ok></span> : SQUARE DUP * ; 7 SQUARE .</div>
|
||||
<div><span style="color: #FFA500">[zuse@Hera]</span> 49 ok</div>
|
||||
<div><span style="color: #FFA500">[zuse@Hera]</span> <span style="color: #55FFFF">ok></span> <span aria-hidden="true" style="display: inline-block; width: 9px; height: 18px; vertical-align: text-bottom; background: #EEF2F7"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2">[LIVE CONSOLE] On the site this panel is the machine itself — the console of try.starshipos-f18.com, embedded. If it does not connect, every machine is in use; try again in a few minutes.</p>
|
||||
</section>
|
||||
|
||||
<section aria-label="Your machine" style="border-top: 1px solid #22324D; border-bottom: 1px solid #22324D; background: #0E182B">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">Zuse</div><div style="font-size: 14px; color: #A3AEC2">the superuser, of this machine only</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">amd64</div><div style="font-size: 14px; color: #A3AEC2">LithosAnanke v2.1.0 · StarForth v4</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">30 min</div><div style="font-size: 14px; color: #A3AEC2">then it is gone; reload for a new one</div></div>
|
||||
<div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: {{accent}}">Offline</div><div style="font-size: 14px; color: #A3AEC2">no network inside the machine</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="try-h" style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Things to try</p>
|
||||
<h2 id="try-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 40px; line-height: 1.15; max-width: 760px">StarshipOS speaks FORTH.</h2>
|
||||
<p style="margin: 0 0 40px; max-width: 680px; color: #C8D1DE">Type a line and press Enter. When the machine has done it, it answers ok.</p>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">You type</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7">3 4 + .</p>
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">It answers</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: {{accent}}">7 ok</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #C8D1DE">Numbers go on a stack; + adds the top two; . prints the result.</p>
|
||||
</article>
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">You type</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7">: SQUARE DUP * ;</p>
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">It answers</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: {{accent}}">ok</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #C8D1DE">You have just taught the machine a new word, SQUARE.</p>
|
||||
</article>
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px">
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">You type</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: #EEF2F7">7 SQUARE .</p>
|
||||
<p style="margin: 0 0 4px; font-size: 13px; color: #A3AEC2">It answers</p>
|
||||
<p style="margin: 0 0 16px; font-size: 20px; color: {{accent}}">49 ok</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #C8D1DE">…and used it, as if it had always been there.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px; border-top: 1px solid #22324D; padding-top: 48px">
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">A machine of your own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Resumed at its prompt from one that booted, passed its 538 power-on self-tests and logged Zuse in — so you never wait for a boot.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">The latest green build</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Always the most recent build that booted on amd64, aarch64 and riscv64 and passed every acceptance check.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">A Zuse of its own</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Zuse is whoever holds the identity drive. Here it is a demo Zuse minted for this page alone — not anyone's real identity.</p></div>
|
||||
<div><h3 style="margin: 0 0 8px; font-size: 16px; color: #EEF2F7">Gone when you go</h3><p style="margin: 0; font-size: 14px; color: #A3AEC2">Close the page, or let 30 minutes pass, and the machine is stopped and discarded. The next visitor starts clean.</p></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px; align-items: center">
|
||||
<div style="flex: 999 1 480px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">A small server</p>
|
||||
<h2 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 32px; line-height: 1.2">Emulated, so a little slower.</h2>
|
||||
<p style="margin: 0; color: #C8D1DE">The demo runs in an emulator on a modest server: slower than StarshipOS on real hardware, and only a few machines at once. The real thing boots straight from firmware, with nothing beneath it.</p>
|
||||
</div>
|
||||
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
|
||||
<a href="Main.dc.html" style="display: inline-block; padding: 14px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">How it works</a>
|
||||
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="display: inline-block; padding: 14px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px; text-align: center">Read the source</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Main.dc.html" style="color: #C8D1DE">Home</a><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":2900}}'>
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
return { accent: this.props.accent ?? '#F5891F' };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# install.sh -- the starshipos-f18.com XWiki's pages, from the "StarshipOS.com" design canvas
|
||||
# (build.py makes them): Main.WebHome (Home), Inquiries.WebHome, TryIt.WebHome, and the two
|
||||
# images, attachments of Main.WebHome. All readable by everyone; the wiki's own rights decide the
|
||||
# rest. Through XWiki's REST API:
|
||||
#
|
||||
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/com/install.sh [https://starshipos-f18.com]
|
||||
#
|
||||
# Run it again after build.py: pages and images are replaced. It ends by checking, without
|
||||
# logging in, that every page and image is there.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
base=${1:-https://starshipos-f18.com}
|
||||
rest="$base/rest/wikis/xwiki"
|
||||
user=${XWIKI_USER:?set XWIKI_USER}
|
||||
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
|
||||
auth=(-u "$user:$pass")
|
||||
|
||||
page() { # page <space> <title> <file>: create or replace <space>.WebHome
|
||||
local body
|
||||
body=$(python3 -c '
|
||||
import sys
|
||||
from xml.sax.saxutils import escape
|
||||
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
|
||||
"<content>%s</content></page>" % (escape(sys.argv[1]), escape(open(sys.argv[2]).read())))' "$2" "$3")
|
||||
curl -fsS -o /dev/null -w " page $1.WebHome: %{http_code}\n" "${auth[@]}" -X PUT \
|
||||
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$1/pages/WebHome"
|
||||
}
|
||||
attach() { # attach <space> <file>: create or replace an attachment of <space>.WebHome
|
||||
curl -fsS -o /dev/null -w " attachment $1.WebHome/$2: %{http_code}\n" "${auth[@]}" -X PUT \
|
||||
-H 'Content-Type: image/jpeg' --data-binary "@$2" "$rest/spaces/$1/pages/WebHome/attachments/$2"
|
||||
}
|
||||
|
||||
echo "=== $base, as $user"
|
||||
page Main "StarshipOS" Main.WebHome.xwiki
|
||||
attach Main badge.jpg
|
||||
attach Main captain-bob.jpg
|
||||
page Inquiries "Inquiries" Inquiries.WebHome.xwiki
|
||||
page TryIt "Try StarshipOS" TryIt.WebHome.xwiki
|
||||
|
||||
echo "=== as a guest"
|
||||
bad=
|
||||
for u in /bin/view/Main/ /bin/view/Inquiries/ /bin/view/TryIt/ \
|
||||
/bin/download/Main/WebHome/badge.jpg /bin/download/Main/WebHome/captain-bob.jpg; do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' "$base$u")
|
||||
if [ "$code" = 200 ]; then echo " $u: 200"; else echo " $u: $code -- NOT readable"; bad=1; fi
|
||||
done
|
||||
[ -z "$bad" ] || { echo "install: a guest cannot read everything; see above" >&2; exit 1; }
|
||||
echo "=== done: $base/bin/view/Main/"
|
||||
@@ -0,0 +1,62 @@
|
||||
{{html clean="false"}}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>
|
||||
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6">
|
||||
<header style="border-bottom: 1px solid #22324D !important">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span><span style="font-size: 14px; color: #A3AEC2 !important; margin-left: 6px">.org</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px"><a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a><a href="/bin/view/Contributors/" style="color: #C8D1DE !important; text-decoration: none">Contributors</a><a href="/bin/view/Admin/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Admin</a><a href="https://starshipos-f18.com/" style="color: #F5891F !important; text-decoration: none">starshipos-f18.com →</a></div>
|
||||
</nav>
|
||||
</header>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">Administrator only</p>
|
||||
<h1 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(36px, 5vw, 56px); line-height: 1.08">Admin dashboard.</h1>
|
||||
<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE !important">Seen by <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">XWiki.rajames</code> alone: the Admin space allows view and edit to that account and nobody else.</p>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">CI</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Every workflow, live.</h2>
|
||||
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Acceptance -- the gate on every PR into master</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/acceptance.yml/badge.svg" alt="acceptance.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=acceptance.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Build -- the quick check on StarForth-v4.0.0</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/build.yml/badge.svg?branch=StarForth-v4.0.0" alt="build.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=build.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly.yml/badge.svg?branch=master" alt="nightly.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=nightly.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly documents (04:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly-docs.yml/badge.svg?branch=master" alt="nightly-docs.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=nightly-docs.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Runner image</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/runner-image.yml/badge.svg?branch=master" alt="runner-image.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=runner-image.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Release -- a v<version> tag</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/release.yml/badge.svg" alt="release.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=release.yml" style="font-size: 13px">runs</a></span></div></div>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Run the project</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Work, artifacts, sites.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Work</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">Gitea</p>
|
||||
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/pulls?state=open">Open pull requests</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open">Open issues</a> — <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=23">in progress</a>, <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=20">blocked</a>, <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=21">needs acceptance</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/milestones">Milestones</a> and <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/projects">the project board</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/settings/branches">Branch protection</a> — master: no pushes, merges only after Acceptance</li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/settings/actions/secrets">Actions secrets</a> — <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">NEXUS_CI_PASSWORD</code>, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">PACKAGES_TOKEN</code>, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">CAPSULE_SIGN_KEY</code></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/settings/actions/runners">Runners</a></li><li><a href="https://gitea.starshipos-f18.org/user/settings/applications">Access tokens</a> — revoke what a session no longer needs</li></ul>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Artifacts</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">Nexus and packages</p>
|
||||
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://nexus.starshipos-f18.org/#browse/browse:starshipos-snapshots:org%2Fstarship">Snapshots</a> — <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">kernelImage</code> (pc, raspi5, milkv, logs), <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">documentation</code> (book, vol1–vol3, api)</li><li><a href="https://nexus.starshipos-f18.org/#browse/browse:starshipos-releases:org%2Fstarship">Releases</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/-/packages">Container images</a> — <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">lithosananke-runner</code></li></ul>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Sites</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">and the wiki itself</p>
|
||||
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://starshipos-f18.com/">starshipos-f18.com</a> and <a href="https://starshipos-f18.com/bin/view/TryIt/">Try it</a></li><li><a href="/bin/view/Contributors/">Contributors' dashboard</a></li><li><a href="/bin/admin/XWiki/XWikiPreferences">Wiki administration</a> — users, the group <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">XWiki.StarshipContributors</code>, rights</li></ul>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="color: #C8D1DE !important">Source</a><a href="https://starshipos-f18.com/" style="color: #C8D1DE !important">starshipos-f18.com</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
{{/html}}
|
||||
@@ -0,0 +1,72 @@
|
||||
{{html clean="false"}}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>
|
||||
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6">
|
||||
<header style="border-bottom: 1px solid #22324D !important">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span><span style="font-size: 14px; color: #A3AEC2 !important; margin-left: 6px">.org</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px"><a href="/bin/view/Main/" style="color: #C8D1DE !important; text-decoration: none">Home</a><a href="/bin/view/Contributors/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Contributors</a><a href="https://starshipos-f18.com/" style="color: #F5891F !important; text-decoration: none">starshipos-f18.com →</a></div>
|
||||
</nav>
|
||||
</header>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">Contributors</p>
|
||||
<h1 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(36px, 5vw, 56px); line-height: 1.08">Contributors' dashboard.</h1>
|
||||
<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE !important">For the members of <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">XWiki.StarshipContributors</code> and the administrator. Ask Captain Bob to be added.</p>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">How we work</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">The Captain Bob method.</h2>
|
||||
<p style="margin: 0 0 32px; max-width: 720px; color: #C8D1DE !important">Neither agile nor waterfall: one process from the developer's desk to master.</p>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">1</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Found</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">An issue says what is wrong or missing, with the evidence: a log, a line of code.</p></article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">2</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Ruled</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">Captain Bob decides what is to be done. Nothing is built without a ruling, and no fix nobody asked for.</p></article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">3</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Built</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">On the working branch, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">StarForth-v4.0.0</code>. C99, no GNU extensions; compose in FORTH before adding a C word.</p></article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">4</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Verified</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">The acceptance protocol, below; its logs are committed under <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">logs/</code>.</p></article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="font-family: 'Exo 2', sans-serif; font-size: 28px; font-weight: 700; color: #F5891F !important">5</div><h3 style="margin: 4px 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">Merged</h3><p style="margin: 0; color: #C8D1DE !important; font-size: 14px">A pull request into <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">master</code>, which runs acceptance by itself. master takes nothing else.</p></article>
|
||||
</div>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">The acceptance protocol</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">In this order, one QEMU at a time, in the foreground.</h2>
|
||||
<pre style="margin: 0 0 24px; background: #0E182B !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 24px; overflow-x: auto; font-size: 14px; color: #EEF2F7 !important">make -f kernel/Makefile ARCH=amd64 clean qemu
|
||||
make -f kernel/Makefile ARCH=aarch64 clean qemu
|
||||
make -f kernel/Makefile ARCH=riscv64 clean qemu
|
||||
make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high
|
||||
make -C v4 test-32</pre>
|
||||
<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE !important">Each boot reaches <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">[zuse@Hera] ok></code> with <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">POST: PASSED</code> and every POST check passing, and the three architectures report the same <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">dict_hash</code>. <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">make ARCH=amd64,aarch64,riscv64 init</code> installs everything this needs.</p>
|
||||
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Acceptance -- the gate on every PR into master</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/acceptance.yml/badge.svg" alt="acceptance.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=acceptance.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Build -- the quick check on StarForth-v4.0.0</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/build.yml/badge.svg?branch=StarForth-v4.0.0" alt="build.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=build.yml" style="font-size: 13px">runs</a></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly.yml/badge.svg?branch=master" alt="nightly.yml status" style="display: block; height: 20px"> <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions?workflow=nightly.yml" style="font-size: 13px">runs</a></span></div></div>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 0 24px 96px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Reference</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Where things are, and what not to do.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Where things are</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">start here</p>
|
||||
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke">The repository</a> — <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">README.md</code>, <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">docs/README.md</code>; the design record is <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">docs/fabric/FABRIC-3.md</code></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues/new/choose">New issue</a> — the forms: bug, work, ruling, board</li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=2">Open features</a> and <a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&labels=1">bugs</a></li><li><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues?state=open&milestone=2">Board bring-up</a> — <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">boards/BRINGUP.md</code></li><li>Before touching a capsule: read <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">experiments/bare_metal/README.md</code> — the block ranges are shared by every capsule</li></ul>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Rules that bite</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">learned the hard way</p>
|
||||
<ul style="margin: 0; padding-left: 20px; color: #C8D1DE !important; font-size: 15px; display: flex; flex-direction: column; gap: 8px"><li>No new branch, no <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">git stash</code>, without Captain Bob's say-so.</li><li>Never modify a registered, tested FORTH word to fix it: the problem is in the caller.</li><li>ACL policy lives in <code style="color: #EEF2F7 !important; background: #0A1222 !important; padding: 1px 6px; border-radius: 3px">ACL.4th</code>, not in C.</li><li>Tags are sacred: each has the logs proving its state.</li></ul>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="color: #C8D1DE !important">Source</a><a href="https://starshipos-f18.com/" style="color: #C8D1DE !important">starshipos-f18.com</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
{{/html}}
|
||||
@@ -0,0 +1,93 @@
|
||||
{{velocity}}
|
||||
#if ($isGuest)
|
||||
#[[{{html clean="false"}}<style>
|
||||
#menuview, #hierarchy_breadcrumb, .document-header, #xdocFooter, #footerglobal, #leftPanels, #rightPanels,
|
||||
#leftPanelsToggle, #rightPanelsToggle, .tour, .tour-backdrop, #bootstrap_tour_restart, .xtour-restart,
|
||||
#xwikimaincontainerinner > a.btn { display: none !important; }
|
||||
html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #contentcolumn, .main,
|
||||
#mainContentArea, #xwikicontent, #mainContentArea .row { background-color: #0A1222 !important; }
|
||||
#contentcontainer, #contentcolumn, .main, #mainContentArea, #xwikicontent, #mainContentArea .row {
|
||||
width: 100% !important; max-width: none !important; margin: 0 !important; padding: 0 !important; border: 0 !important; float: none !important; }
|
||||
#xwikicontent > .ssos { border: 0 !important; }
|
||||
#xwikimaincontainer { padding: 0 !important; }
|
||||
.main hr:not(.ssos hr), #xwikicontent > :not(.ssos) { display: none !important; }
|
||||
</style>{{/html}}]]#
|
||||
#end
|
||||
{{/velocity}}
|
||||
{{html clean="false"}}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
.ssos, .ssos *, .ssos *::before, .ssos *::after { background-color: transparent !important; color: inherit !important; border-color: #22324D !important; }
|
||||
.ssos a, .ssos a * { color: #F5891F !important; }
|
||||
.ssos a:hover { color: #FFB061 !important; }
|
||||
.ssos input, .ssos textarea, .ssos select { background-color: #0A1222 !important; color: #EEF2F7 !important; border-color: #34486A !important; }
|
||||
.ssos ::placeholder { color: #A3AEC2 !important; opacity: 1 !important; }
|
||||
.ssos img { background-color: transparent !important; }
|
||||
</style>
|
||||
<div class="ssos" style="background: #0A1222 !important; color: #EEF2F7 !important; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6">
|
||||
<header style="border-bottom: 1px solid #22324D !important">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="/bin/view/Main/" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7 !important; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: #F5891F !important">OS</span><span style="font-size: 14px; color: #A3AEC2 !important; margin-left: 6px">.org</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px"><a href="/bin/view/Main/" aria-current="page" style="color: #EEF2F7 !important; text-decoration: none; border-bottom: 2px solid #F5891F !important">Home</a><a href="/bin/view/Contributors/" style="color: #C8D1DE !important; text-decoration: none">Contributors</a><a href="https://starshipos-f18.com/" style="color: #F5891F !important; text-decoration: none">starshipos-f18.com →</a></div>
|
||||
</nav>
|
||||
</header>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0 !important">ok> the working home</p>
|
||||
<h1 style="margin: 0 0 20px; font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: clamp(36px, 5vw, 56px); line-height: 1.08">Where StarshipOS is built.</h1>
|
||||
<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE !important">StarshipOS is an operating system with no other operating system underneath it. LithosAnanke, a UEFI microkernel, boots straight from the firmware and runs StarForth, a FORTH virtual machine, as its only runtime. This wiki holds its design, its record and its dashboards; the public face is <a href="https://starshipos-f18.com/">starshipos-f18.com</a>.</p>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 16px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="display: inline-block; padding: 14px 24px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px">Browse the source</a><a href="https://starshipos-f18.com/bin/view/TryIt/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px">Try it in a browser</a></div>
|
||||
</section>
|
||||
<section aria-label="At a glance" style="border-top: 1px solid #22324D !important; border-bottom: 1px solid #22324D !important; background: #0E182B !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px"><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">v2.1.0</div><div style="font-size: 14px; color: #A3AEC2 !important">LithosAnanke, the UEFI microkernel</div></div><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">v4</div><div style="font-size: 14px; color: #A3AEC2 !important">StarForth, the F18 engine</div></div><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">3 ISAs</div><div style="font-size: 14px; color: #A3AEC2 !important">amd64 · aarch64 · riscv64</div></div><div><div style="font-family: 'Exo 2', sans-serif; font-size: 32px; font-weight: 700; color: #F5891F !important">538</div><div style="font-size: 14px; color: #A3AEC2 !important">POST checks on every boot</div></div></div>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 96px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">The project</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">One repository, one process, one line to master.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px">
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">The source</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">kernel, StarForth, proofs, documents</p>
|
||||
<p style="margin: 0 0 16px; color: #C8D1DE !important">Everything in one repository: LithosAnanke, StarForth v3 and v4, the Isabelle/HOL proofs and the books.</p><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke">Browse it →</a>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Issues</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">found, ruled, built, verified</p>
|
||||
<p style="margin: 0 0 16px; color: #C8D1DE !important">Every piece of work starts as an issue with its evidence, and is ruled before it is built.</p><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/issues">Open issues →</a>
|
||||
</article>
|
||||
<article style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px">
|
||||
<h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 22px">Pull requests</h3>
|
||||
<p style="margin: 0 0 14px; font-size: 13px; color: #F5891F !important">the only way into master</p>
|
||||
<p style="margin: 0 0 16px; color: #C8D1DE !important">master takes nothing but a pull request that passed the acceptance protocol.</p><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/pulls">Pull requests →</a>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">How a change is accepted</p>
|
||||
<h2 style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 34px; line-height: 1.15; max-width: 760px">Booted on three architectures, every time.</h2>
|
||||
<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE !important">The kernel boots in QEMU on amd64, aarch64 and riscv64 to its prompt, its power-on self-test passing every check; the PC stick boots loaded the way a PC loads it; the 32-bit build passes its tests. A developer runs it by hand, a pull request runs it by itself, and the nightly runs it again before it publishes.</p>
|
||||
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px"><div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Acceptance -- the gate on every PR into master</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/acceptance.yml/badge.svg" alt="acceptance.yml status" style="display: block; height: 20px"></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly.yml/badge.svg?branch=master" alt="nightly.yml status" style="display: block; height: 20px"></span></div>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-top: 1px solid #22324D !important"><span style="color: #C8D1DE !important; font-size: 14px">Nightly documents (04:00 UTC)</span><span style="display: flex; align-items: center; gap: 16px"><img src="https://gitea.starshipos-f18.org/rajames/LithosAnanke/actions/workflows/nightly-docs.yml/badge.svg?branch=master" alt="nightly-docs.yml status" style="display: block; height: 20px"></span></div></div>
|
||||
</section>
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<div style="background: #111C30 !important; border: 1px solid #22324D !important; border-radius: 6px; padding: 28px; padding: 40px; display: flex; flex-wrap: wrap; gap: 32px; align-items: center">
|
||||
<div style="flex: 999 1 480px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #F5891F !important">Contributors</p>
|
||||
<h2 style="margin: 0 0 12px; font-family: 'Exo 2', sans-serif; font-size: 30px">Working on StarshipOS?</h2>
|
||||
<p style="margin: 0; color: #C8D1DE !important">Contributors have a dashboard of their own: the method, the acceptance commands, the open work. Log in to see it.</p>
|
||||
</div>
|
||||
<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">
|
||||
<a href="/bin/login/XWiki/XWikiLogin?xredirect=/bin/view/Contributors/" style="display: inline-block; padding: 14px 24px; background: #F5891F !important; color: #0A1222 !important; font-weight: 700; text-decoration: none; border-radius: 4px; text-align: center">Log in</a>
|
||||
<a href="/bin/view/Contributors/" style="display: inline-block; padding: 14px 24px; border: 1px solid #34486A !important; color: #EEF2F7 !important; text-decoration: none; border-radius: 4px; text-align: center">Contributors' dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="color: #C8D1DE !important">Source</a><a href="https://starshipos-f18.com/" style="color: #C8D1DE !important">starshipos-f18.com</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
{{/html}}
|
||||
@@ -0,0 +1,27 @@
|
||||
# site/org -- the .org XWiki's pages
|
||||
|
||||
The project's working wiki at `starshipos-f18.org` (the public face is the `.com`; `demo/` has its
|
||||
"Try it" page). Three pages, ruled by Captain Bob on 2026-11-07:
|
||||
|
||||
| Page | File | Who sees it |
|
||||
|---|---|---|
|
||||
| `Main.WebHome` -- the landing page | `Main.WebHome.xwiki` | everyone, guests included |
|
||||
| `Admin.WebHome` -- the admin dashboard | `Admin.WebHome.xwiki` | the administrator (`XWiki.rajames`) alone |
|
||||
| `Contributors.WebHome` -- the contributors' dashboard | `Contributors.WebHome.xwiki` | the group `XWiki.StarshipContributors`, and the administrator |
|
||||
|
||||
They are in the starshipos-f18.com look -- the "StarshipOS.com" design canvas (navy `#0A1222`, accent
|
||||
`#F5891F`, JetBrains Mono with Exo 2 headings), where they are also drawn as the `.org` artboards.
|
||||
`build.py` writes the three `.xwiki` files (and, with `--canvas <dir>`, the artboards) from one
|
||||
source: edit it, not the `.xwiki` files. Each page is one `{{html}}` block, which needs a page author
|
||||
with script rights (the administrator has them). CI is shown as Gitea's live workflow badges, which
|
||||
need no login.
|
||||
|
||||
`install.sh` puts them on the wiki through its REST API, makes the group and the rights, and checks
|
||||
as a guest that the landing page is readable and the dashboards are not:
|
||||
|
||||
```
|
||||
XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/install.sh
|
||||
```
|
||||
|
||||
Contributors are added to `XWiki.StarshipContributors` in the wiki's administration (Users and
|
||||
Groups). The wiki-wide rights -- what guests may do anywhere else -- are the wiki's own, not this.
|
||||
Executable
+337
@@ -0,0 +1,337 @@
|
||||
#!/usr/bin/env python3
|
||||
"""build.py -- the .org XWiki's three pages in the starshipos-f18.com look (the "StarshipOS.com"
|
||||
design canvas: navy #0A1222, accent #F5891F, JetBrains Mono, Exo 2 headings), from one source.
|
||||
|
||||
site/org/build.py writes Main.WebHome.xwiki, Admin.WebHome.xwiki,
|
||||
Contributors.WebHome.xwiki (each one {{html}} block)
|
||||
site/org/build.py --canvas <dir>
|
||||
also writes <dir>/project/Org*.dc.html, the same pages as
|
||||
design-canvas artboards (status badges drawn as placeholders:
|
||||
a canvas loads nothing from Gitea)
|
||||
|
||||
The {{html}} macro needs a page author with script rights. install.sh puts the pages on the wiki.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
|
||||
import colorlock # noqa: E402 the design's colours over the wiki's high-contrast theme
|
||||
|
||||
GITEA = "https://gitea.starshipos-f18.org/rajames/LithosAnanke"
|
||||
COM = "https://starshipos-f18.com/"
|
||||
ISSUES = GITEA + "/issues?state=open"
|
||||
ACCENT = "#F5891F"
|
||||
TEAL = "#4FD1B0"
|
||||
|
||||
FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">\n'
|
||||
'<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700'
|
||||
'&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">')
|
||||
|
||||
H = "font-family: 'Exo 2', sans-serif"
|
||||
CARD = "background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px"
|
||||
EYEBROW = ("margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; "
|
||||
"color: {accent}")
|
||||
BTN = ("display: inline-block; padding: 14px 24px; background: {accent}; color: #0A1222; "
|
||||
"font-weight: 700; text-decoration: none; border-radius: 4px")
|
||||
BTN2 = ("display: inline-block; padding: 14px 24px; border: 1px solid #34486A; color: #EEF2F7; "
|
||||
"text-decoration: none; border-radius: 4px")
|
||||
WRAP = "max-width: 1120px; margin: 0 auto"
|
||||
|
||||
WORKFLOWS = { # file -> (branch for the badge, what it is)
|
||||
"acceptance.yml": (None, "Acceptance -- the gate on every PR into master"),
|
||||
"build.yml": ("StarForth-v4.0.0", "Build -- the quick check on StarForth-v4.0.0"),
|
||||
"nightly.yml": ("master", "Nightly -- acceptance, images to Nexus, proofs (03:00 UTC)"),
|
||||
"nightly-docs.yml": ("master", "Nightly documents (04:00 UTC)"),
|
||||
"runner-image.yml": ("master", "Runner image"),
|
||||
"release.yml": (None, "Release -- a v<version> tag"),
|
||||
}
|
||||
|
||||
|
||||
def badge(wf, canvas):
|
||||
branch = WORKFLOWS[wf][0]
|
||||
if canvas:
|
||||
return ('<span style="display: inline-block; padding: 2px 10px; border: 1px dashed #34486A; '
|
||||
'border-radius: 4px; font-size: 12px; color: #A3AEC2">[LIVE STATUS]</span>')
|
||||
q = "?branch=" + branch if branch else ""
|
||||
return ('<img src="%s/actions/workflows/%s/badge.svg%s" alt="%s status" '
|
||||
'style="display: block; height: 20px">' % (GITEA, wf, q, wf))
|
||||
|
||||
|
||||
def status_rows(wfs, canvas, runs=True):
|
||||
rows = []
|
||||
for wf in wfs:
|
||||
link = (' <a href="%s/actions?workflow=%s" style="font-size: 13px">runs</a>' % (GITEA, wf)
|
||||
if runs else "")
|
||||
rows.append('<div style="display: flex; flex-wrap: wrap; align-items: center; '
|
||||
'justify-content: space-between; gap: 12px; padding: 14px 0; '
|
||||
'border-top: 1px solid #22324D">'
|
||||
'<span style="color: #C8D1DE; font-size: 14px">%s</span>'
|
||||
'<span style="display: flex; align-items: center; gap: 16px">%s%s</span></div>'
|
||||
% (WORKFLOWS[wf][1], badge(wf, canvas), link))
|
||||
return "\n".join(rows)
|
||||
|
||||
|
||||
def nav(here, links):
|
||||
items = []
|
||||
for label, href, key in links:
|
||||
cur = ' aria-current="page"' if key == here else ""
|
||||
style = ("color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {accent}"
|
||||
if key == here else "color: #C8D1DE; text-decoration: none")
|
||||
items.append('<a href="%s"%s style="%s">%s</a>' % (href, cur, style, label))
|
||||
items.append('<a href="%s" style="color: {accent}; text-decoration: none">starshipos-f18.com →</a>'
|
||||
% COM)
|
||||
return ('<header style="border-bottom: 1px solid #22324D">\n'
|
||||
'<nav aria-label="Main" style="%s; padding: 20px 24px; display: flex; flex-wrap: wrap; '
|
||||
'align-items: center; justify-content: space-between; gap: 16px">\n'
|
||||
'<a href="%s" style="%s; font-weight: 700; font-size: 22px; color: #EEF2F7; '
|
||||
'text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {accent}">OS</span>'
|
||||
'<span style="font-size: 14px; color: #A3AEC2; margin-left: 6px">.org</span></a>\n'
|
||||
'<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">%s</div>\n'
|
||||
'</nav>\n</header>' % (WRAP, links[0][1], H, "".join(items)))
|
||||
|
||||
|
||||
FOOTER = ('<footer style="border-top: 1px solid #22324D">\n'
|
||||
'<div style="%s; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; '
|
||||
'justify-content: space-between; font-size: 13px; color: #A3AEC2">\n'
|
||||
'<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>\n'
|
||||
'<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="%s" style="color: #C8D1DE">Source</a>'
|
||||
'<a href="%s" style="color: #C8D1DE">starshipos-f18.com</a></span>\n</div>\n</footer>' % (WRAP, GITEA, COM))
|
||||
|
||||
|
||||
def hero(eyebrow, title, text, buttons=""):
|
||||
return ('<section style="%s; padding: 80px 24px 48px">\n'
|
||||
'<p style="%s">%s</p>\n'
|
||||
'<h1 style="margin: 0 0 20px; %s; font-weight: 700; font-size: clamp(36px, 5vw, 56px); '
|
||||
'line-height: 1.08">%s</h1>\n'
|
||||
'<p style="margin: 0 0 32px; max-width: 680px; font-size: 18px; color: #C8D1DE">%s</p>\n%s'
|
||||
'</section>' % (WRAP, EYEBROW.replace("{accent}", TEAL), eyebrow, H, title, text,
|
||||
('<div style="display: flex; flex-wrap: wrap; gap: 16px">%s</div>\n' % buttons)
|
||||
if buttons else ""))
|
||||
|
||||
|
||||
def section(eyebrow, title, body, pad="48px 24px"):
|
||||
return ('<section style="%s; padding: %s">\n<p style="%s">%s</p>\n'
|
||||
'<h2 style="margin: 0 0 32px; %s; font-size: 34px; line-height: 1.15; max-width: 760px">%s</h2>\n'
|
||||
'%s\n</section>' % (WRAP, pad, EYEBROW, eyebrow, H, title, body))
|
||||
|
||||
|
||||
def card(title, sub, body):
|
||||
return ('<article style="%s">\n<h3 style="margin: 0 0 4px; %s; font-size: 22px">%s</h3>\n'
|
||||
'<p style="margin: 0 0 14px; font-size: 13px; color: {accent}">%s</p>\n%s\n</article>'
|
||||
% (CARD, H, title, sub, body))
|
||||
|
||||
|
||||
def grid(items, min_w=280):
|
||||
return ('<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(%dpx, 1fr)); '
|
||||
'gap: 24px">\n%s\n</div>' % (min_w, "\n".join(items)))
|
||||
|
||||
|
||||
def links(items):
|
||||
return ('<ul style="margin: 0; padding-left: 20px; color: #C8D1DE; font-size: 15px; '
|
||||
'display: flex; flex-direction: column; gap: 8px">%s</ul>'
|
||||
% "".join("<li>%s</li>" % i for i in items))
|
||||
|
||||
|
||||
def a(href, text):
|
||||
return '<a href="%s">%s</a>' % (href, text)
|
||||
|
||||
|
||||
def code(s):
|
||||
return '<code style="color: #EEF2F7; background: #0A1222; padding: 1px 6px; border-radius: 3px">%s</code>' % s
|
||||
|
||||
|
||||
def page_main(canvas, url):
|
||||
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors")]
|
||||
glance = [("v2.1.0", "LithosAnanke, the UEFI microkernel"), ("v4", "StarForth, the F18 engine"),
|
||||
("3 ISAs", "amd64 · aarch64 · riscv64"), ("538", "POST checks on every boot")]
|
||||
strip = ('<section aria-label="At a glance" style="border-top: 1px solid #22324D; border-bottom: 1px solid '
|
||||
'#22324D; background: #0E182B">\n<div style="%s; padding: 32px 24px; display: grid; '
|
||||
'grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px">%s</div>\n</section>'
|
||||
% (WRAP, "".join('<div><div style="%s; font-size: 32px; font-weight: 700; color: {accent}">%s</div>'
|
||||
'<div style="font-size: 14px; color: #A3AEC2">%s</div></div>' % (H, n, t)
|
||||
for n, t in glance)))
|
||||
project = section("The project", "One repository, one process, one line to master.", grid([
|
||||
card("The source", "kernel, StarForth, proofs, documents",
|
||||
'<p style="margin: 0 0 16px; color: #C8D1DE">Everything in one repository: LithosAnanke, '
|
||||
'StarForth v3 and v4, the Isabelle/HOL proofs and the books.</p>' + a(GITEA, "Browse it →")),
|
||||
card("Issues", "found, ruled, built, verified",
|
||||
'<p style="margin: 0 0 16px; color: #C8D1DE">Every piece of work starts as an issue with its '
|
||||
'evidence, and is ruled before it is built.</p>' + a(GITEA + "/issues", "Open issues →")),
|
||||
card("Pull requests", "the only way into master",
|
||||
'<p style="margin: 0 0 16px; color: #C8D1DE">master takes nothing but a pull request that '
|
||||
'passed the acceptance protocol.</p>' + a(GITEA + "/pulls", "Pull requests →")),
|
||||
]), pad="96px 24px 48px")
|
||||
accept = section("How a change is accepted", "Booted on three architectures, every time.",
|
||||
'<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE">The kernel boots in QEMU '
|
||||
'on amd64, aarch64 and riscv64 to its prompt, its power-on self-test passing every check; '
|
||||
'the PC stick boots loaded the way a PC loads it; the 32-bit build passes its tests. A '
|
||||
'developer runs it by hand, a pull request runs it by itself, and the nightly runs it '
|
||||
'again before it publishes.</p>\n<div style="%s">%s</div>'
|
||||
% (CARD, status_rows(["acceptance.yml", "nightly.yml", "nightly-docs.yml"], canvas, False)))
|
||||
contrib = ('<section style="%s; padding: 48px 24px 96px">\n<div style="%s; padding: 40px; display: flex; '
|
||||
'flex-wrap: wrap; gap: 32px; align-items: center">\n<div style="flex: 999 1 480px; min-width: 0">\n'
|
||||
'<p style="%s">Contributors</p>\n<h2 style="margin: 0 0 12px; %s; font-size: 30px">'
|
||||
'Working on StarshipOS?</h2>\n<p style="margin: 0; color: #C8D1DE">Contributors have a dashboard '
|
||||
'of their own: the method, the acceptance commands, the open work. Log in to see it.</p>\n</div>\n'
|
||||
'<div style="flex: 1 1 220px; display: flex; flex-direction: column; gap: 12px">\n'
|
||||
'<a href="%s" style="%s; text-align: center">Log in</a>\n'
|
||||
'<a href="%s" style="%s; text-align: center">Contributors\' dashboard</a>\n</div>\n</div>\n</section>'
|
||||
% (WRAP, CARD, EYEBROW, H, url("login"), BTN, url("Contributors"), BTN2))
|
||||
return "\n".join([
|
||||
nav("Main", links_),
|
||||
hero("ok> the working home", "Where StarshipOS is built.",
|
||||
"StarshipOS is an operating system with no other operating system underneath it. LithosAnanke, a "
|
||||
"UEFI microkernel, boots straight from the firmware and runs StarForth, a FORTH virtual machine, "
|
||||
"as its only runtime. This wiki holds its design, its record and its dashboards; the public face "
|
||||
"is " + a(COM, "starshipos-f18.com") + ".",
|
||||
'<a href="%s" style="%s">Browse the source</a><a href="%s" style="%s">Try it in a browser</a>'
|
||||
% (GITEA, BTN, COM + "bin/view/TryIt/", BTN2)),
|
||||
strip, project, accept, contrib, FOOTER])
|
||||
|
||||
|
||||
def page_admin(canvas, url):
|
||||
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors"),
|
||||
("Admin", url("Admin"), "Admin")]
|
||||
ci = section("CI", "Every workflow, live.", '<div style="%s">%s</div>' % (CARD, status_rows(list(WORKFLOWS), canvas)),
|
||||
pad="0 24px 48px")
|
||||
work = card("Work", "Gitea", links([
|
||||
a(GITEA + "/pulls?state=open", "Open pull requests"),
|
||||
a(ISSUES, "Open issues") + " — " + a(ISSUES + "&labels=23", "in progress") + ", "
|
||||
+ a(ISSUES + "&labels=20", "blocked") + ", " + a(ISSUES + "&labels=21", "needs acceptance"),
|
||||
a(GITEA + "/milestones", "Milestones") + " and " + a(GITEA + "/projects", "the project board"),
|
||||
a(GITEA + "/settings/branches", "Branch protection") + " — master: no pushes, merges only after Acceptance",
|
||||
a(GITEA + "/settings/actions/secrets", "Actions secrets") + " — " + code("NEXUS_CI_PASSWORD") + ", "
|
||||
+ code("PACKAGES_TOKEN") + ", " + code("CAPSULE_SIGN_KEY"),
|
||||
a(GITEA + "/settings/actions/runners", "Runners"),
|
||||
a("https://gitea.starshipos-f18.org/user/settings/applications", "Access tokens")
|
||||
+ " — revoke what a session no longer needs"]))
|
||||
arts = card("Artifacts", "Nexus and packages", links([
|
||||
a("https://nexus.starshipos-f18.org/#browse/browse:starshipos-snapshots:org%2Fstarship", "Snapshots")
|
||||
+ " — " + code("kernelImage") + " (pc, raspi5, milkv, logs), " + code("documentation")
|
||||
+ " (book, vol1–vol3, api)",
|
||||
a("https://nexus.starshipos-f18.org/#browse/browse:starshipos-releases:org%2Fstarship", "Releases"),
|
||||
a("https://gitea.starshipos-f18.org/rajames/-/packages", "Container images") + " — "
|
||||
+ code("lithosananke-runner"), ]))
|
||||
sites = card("Sites", "and the wiki itself", links([
|
||||
a(COM, "starshipos-f18.com") + " and " + a(COM + "bin/view/TryIt/", "Try it"),
|
||||
a(url("Contributors"), "Contributors' dashboard"),
|
||||
a(url("admin"), "Wiki administration") + " — users, the group " + code("XWiki.StarshipContributors")
|
||||
+ ", rights"]))
|
||||
return "\n".join([
|
||||
nav("Admin", links_),
|
||||
hero("Administrator only", "Admin dashboard.",
|
||||
"Seen by " + code("XWiki.rajames") + " alone: the Admin space allows view and edit to that "
|
||||
"account and nobody else."),
|
||||
ci, section("Run the project", "Work, artifacts, sites.", grid([work, arts, sites], 300), pad="0 24px 96px"),
|
||||
FOOTER])
|
||||
|
||||
|
||||
def page_contrib(canvas, url):
|
||||
links_ = [("Home", url("Main"), "Main"), ("Contributors", url("Contributors"), "Contributors")]
|
||||
steps = [("Found", "An issue says what is wrong or missing, with the evidence: a log, a line of code."),
|
||||
("Ruled", "Captain Bob decides what is to be done. Nothing is built without a ruling, and no fix "
|
||||
"nobody asked for."),
|
||||
("Built", "On the working branch, " + code("StarForth-v4.0.0") + ". C99, no GNU extensions; compose "
|
||||
"in FORTH before adding a C word."),
|
||||
("Verified", "The acceptance protocol, below; its logs are committed under " + code("logs/") + "."),
|
||||
("Merged", "A pull request into " + code("master") + ", which runs acceptance by itself. master takes "
|
||||
"nothing else.")]
|
||||
method = section("How we work", "The Captain Bob method.",
|
||||
'<p style="margin: 0 0 32px; max-width: 720px; color: #C8D1DE">Neither agile nor waterfall: '
|
||||
'one process from the developer\'s desk to master.</p>\n' + grid(
|
||||
['<article style="%s"><div style="%s; font-size: 28px; font-weight: 700; color: {accent}">'
|
||||
'%d</div><h3 style="margin: 4px 0 8px; %s; font-size: 22px">%s</h3>'
|
||||
'<p style="margin: 0; color: #C8D1DE; font-size: 14px">%s</p></article>'
|
||||
% (CARD, H, i + 1, H, t, d) for i, (t, d) in enumerate(steps)], 190), pad="0 24px 48px")
|
||||
cmds = ("make -f kernel/Makefile ARCH=amd64 clean qemu\n"
|
||||
"make -f kernel/Makefile ARCH=aarch64 clean qemu\n"
|
||||
"make -f kernel/Makefile ARCH=riscv64 clean qemu\n"
|
||||
"make -f kernel/Makefile ARCH=amd64 clean qemu-stick-high\n"
|
||||
"make -C v4 test-32")
|
||||
accept = section("The acceptance protocol", "In this order, one QEMU at a time, in the foreground.",
|
||||
'<pre style="margin: 0 0 24px; background: #0E182B; border: 1px solid #22324D; '
|
||||
'border-radius: 6px; padding: 24px; overflow-x: auto; font-size: 14px; color: #EEF2F7">'
|
||||
'%s</pre>\n<p style="margin: 0 0 24px; max-width: 760px; color: #C8D1DE">Each boot reaches '
|
||||
'%s with %s and every POST check passing, and the three architectures report the same '
|
||||
'%s. %s installs everything this needs.</p>\n<div style="%s">%s</div>'
|
||||
% (cmds, code("[zuse@Hera] ok>"), code("POST: PASSED"), code("dict_hash"),
|
||||
code("make ARCH=amd64,aarch64,riscv64 init"), CARD,
|
||||
status_rows(["acceptance.yml", "build.yml", "nightly.yml"], canvas)))
|
||||
where = card("Where things are", "start here", links([
|
||||
a(GITEA, "The repository") + " — " + code("README.md") + ", " + code("docs/README.md")
|
||||
+ "; the design record is " + code("docs/fabric/FABRIC-3.md"),
|
||||
a(GITEA + "/issues/new/choose", "New issue") + " — the forms: bug, work, ruling, board",
|
||||
a(ISSUES + "&labels=2", "Open features") + " and " + a(ISSUES + "&labels=1", "bugs"),
|
||||
a(ISSUES + "&milestone=2", "Board bring-up") + " — " + code("boards/BRINGUP.md"),
|
||||
"Before touching a capsule: read " + code("experiments/bare_metal/README.md")
|
||||
+ " — the block ranges are shared by every capsule"]))
|
||||
rules = card("Rules that bite", "learned the hard way", links([
|
||||
"No new branch, no " + code("git stash") + ", without Captain Bob's say-so.",
|
||||
"Never modify a registered, tested FORTH word to fix it: the problem is in the caller.",
|
||||
"ACL policy lives in " + code("ACL.4th") + ", not in C.",
|
||||
"Tags are sacred: each has the logs proving its state."]))
|
||||
return "\n".join([
|
||||
nav("Contributors", links_),
|
||||
hero("Contributors", "Contributors' dashboard.",
|
||||
"For the members of " + code("XWiki.StarshipContributors") + " and the administrator. "
|
||||
"Ask Captain Bob to be added."),
|
||||
method, accept, section("Reference", "Where things are, and what not to do.",
|
||||
grid([where, rules], 360), pad="0 24px 96px"),
|
||||
FOOTER])
|
||||
|
||||
|
||||
PAGES = { # name -> (builder, title, canvas file, canvas height)
|
||||
"Main": (page_main, "StarshipOS", "OrgHome.dc.html", 2300),
|
||||
"Admin": (page_admin, "Admin Dashboard", "OrgAdmin.dc.html", 1900),
|
||||
"Contributors": (page_contrib, "Contributors' Dashboard", "OrgContributors.dc.html", 2500),
|
||||
}
|
||||
|
||||
|
||||
def wiki_url(key):
|
||||
return {"login": "/bin/login/XWiki/XWikiLogin?xredirect=/bin/view/Contributors/",
|
||||
"admin": "/bin/admin/XWiki/XWikiPreferences"}.get(key, "/bin/view/%s/" % key)
|
||||
|
||||
|
||||
def canvas_url(key):
|
||||
files = {k: v[2] for k, v in PAGES.items()}
|
||||
return files.get(key, "https://starshipos-f18.org" + wiki_url(key))
|
||||
|
||||
|
||||
def body(name, canvas):
|
||||
html = PAGES[name][0](canvas, canvas_url if canvas else wiki_url)
|
||||
return ('<div style="background: #0A1222; color: #EEF2F7; font-family: \'JetBrains Mono\', ui-monospace, '
|
||||
'monospace; font-size: 16px; line-height: 1.6">\n%s\n</div>' % html)
|
||||
|
||||
|
||||
def write_wiki(name):
|
||||
html = colorlock.lock(body(name, False).replace("{accent}", ACCENT), "<div style=\"background: #0A1222")
|
||||
with open("%s.WebHome.xwiki" % name, "w") as f:
|
||||
# the landing page is the public one: the design alone for visitors, as on the .com
|
||||
chrome = colorlock.GUEST_CHROME if name == "Main" else ""
|
||||
f.write(chrome + '{{html clean="false"}}\n%s\n%s\n{{/html}}\n' % (FONTS, html))
|
||||
|
||||
|
||||
def write_canvas(name, root):
|
||||
title, file, h = PAGES[name][1], PAGES[name][2], PAGES[name][3]
|
||||
html = body(name, True).replace("{accent}", "{{accent}}")
|
||||
doc = ('<!doctype html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<title>StarshipOS.org — %s'
|
||||
'</title>\n<script src="./support.js"></script>\n</head>\n<body>\n<x-dc>\n<helmet>\n%s\n<style>\n'
|
||||
'body{margin:0;background:#0A1222}\na{color:#F5891F}a:hover{color:#FFB061}\n</style>\n</helmet>\n%s\n'
|
||||
'</x-dc>\n<script type="text/x-dc" data-dc-script data-props=\'{"accent":{"editor":"color","default":'
|
||||
'"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":%d}}\'>\n'
|
||||
'class Component extends DCLogic {\n renderVals() {\n return { accent: this.props.accent ?? '
|
||||
'\'#F5891F\' };\n }\n}\n</script>\n</body>\n</html>\n' % (title, FONTS, html, h))
|
||||
os.makedirs(os.path.join(root, "project"), exist_ok=True)
|
||||
with open(os.path.join(root, "project", file), "w") as f:
|
||||
f.write(doc)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
canvas_root = sys.argv[2] if len(sys.argv) > 2 and sys.argv[1] == "--canvas" else None
|
||||
for n in PAGES:
|
||||
write_wiki(n)
|
||||
if canvas_root:
|
||||
write_canvas(n, canvas_root)
|
||||
print("wrote", ", ".join("%s.WebHome.xwiki" % n for n in PAGES),
|
||||
"and the canvas artboards" if canvas_root else "")
|
||||
@@ -0,0 +1,26 @@
|
||||
{{velocity}}
|
||||
## Makes the inquiry class's fields, once. Run it by viewing this page as an administrator
|
||||
## (programming right); install.sh does. Viewing it again changes nothing.
|
||||
#if (!$hasProgramming)
|
||||
Needs the programming right.
|
||||
#else
|
||||
#set ($xdoc = $xwiki.getDocument('Inquiries.Code.InquiryClass').getDocument().clone())
|
||||
#set ($c = $xdoc.getXClass())
|
||||
#set ($changed = false)
|
||||
#if (!$c.get('name'))#set ($d = $c.addTextField('name', 'Name', 60))#set ($changed = true)#end
|
||||
#if (!$c.get('email'))#set ($d = $c.addTextField('email', 'Email', 60))#set ($changed = true)#end
|
||||
#if (!$c.get('organization'))#set ($d = $c.addTextField('organization', 'Organization', 60))#set ($changed = true)#end
|
||||
#if (!$c.get('topic'))#set ($d = $c.addTextField('topic', 'Topic', 60))#set ($changed = true)#end
|
||||
#if (!$c.get('message'))#set ($d = $c.addTextAreaField('message', 'Message', 80, 12))#set ($d = $c.get('message').setStringValue('contenttype', 'PureText'))#set ($changed = true)#end
|
||||
#if (!$c.get('announcements'))#set ($d = $c.addBooleanField('announcements', 'Wants announcements', 'yesno'))#set ($changed = true)#end
|
||||
#if (!$c.get('source'))#set ($d = $c.addTextField('source', 'Source', 60))#set ($changed = true)#end
|
||||
#if (!$c.get('status'))#set ($d = $c.addStaticListField('status', 'Status', 1, false, 'new|read|answered|closed'))#set ($changed = true)#end
|
||||
#if ($changed)
|
||||
#set ($d = $xdoc.setTitle('Inquiry class'))
|
||||
#set ($d = $xwiki.getXWiki().saveDocument($xdoc, 'The inquiry fields', $xcontext.getContext()))
|
||||
CLASS-SAVED
|
||||
#else
|
||||
CLASS-UNCHANGED
|
||||
#end
|
||||
#end
|
||||
{{/velocity}}
|
||||
@@ -0,0 +1,3 @@
|
||||
Every inquiry sent from the form on [[starshipos-f18.com>>https://starshipos-f18.com/bin/view/Inquiries/]], newest first. Open one for the whole message and to set its status. Only the administrator can see this space.
|
||||
|
||||
{{liveData id="inquiries" source="liveTable" sourceParameters="className=Inquiries.Code.InquiryClass&translationPrefix=" properties="doc.title,doc.creationDate,name,email,topic,status" sort="doc.creationDate:desc" limit="25"}}{{/liveData}}
|
||||
@@ -0,0 +1,26 @@
|
||||
{{velocity}}
|
||||
#set ($o = $doc.getObject('Inquiries.Code.InquiryClass'))
|
||||
#if (!$o)
|
||||
This page holds no inquiry.
|
||||
#else
|
||||
[[← All inquiries>>Inquiries.WebHome]]
|
||||
|
||||
|=Received|$escapetool.xml($xwiki.formatDate($doc.creationDate))
|
||||
|=Status|$doc.display('status', $o)
|
||||
|=Name|$doc.display('name', $o)
|
||||
|=Email|$doc.display('email', $o)
|
||||
|=Organization|$doc.display('organization', $o)
|
||||
|=Topic|$doc.display('topic', $o)
|
||||
|=Announcements|$doc.display('announcements', $o)
|
||||
|=Source|$doc.display('source', $o)
|
||||
|
||||
== Message ==
|
||||
|
||||
$doc.display('message', $o)
|
||||
|
||||
#if ($xcontext.action == 'view')
|
||||
## the e-mail is checked as plain characters when it arrives (PublicInquiry), and escaped here too
|
||||
{{html}}<p><a href="$escapetool.xml($doc.getURL('edit', 'editor=inline'))">Set its status</a>#if ("$!o.getProperty('email').value" != '') · <a href="mailto:$escapetool.xml($escapetool.url($o.getProperty('email').value).replace('%40','@'))">Reply by e-mail</a>#end</p>{{/html}}
|
||||
#end
|
||||
#end
|
||||
{{/velocity}}
|
||||
@@ -0,0 +1,41 @@
|
||||
{{velocity}}
|
||||
## Receives the inquiry form on starshipos-f18.com (POST) and files it as a page under
|
||||
## Inquiries.Entries, which only the administrator can read. It runs with this page's author's
|
||||
## rights (getDocumentAsAuthor, saveAsAuthor): a guest can reach nothing but this. Nothing a visitor
|
||||
## sends is ever written into this page's output or an entry's title: with this author's rights,
|
||||
## text that reached the wiki markup could run a macro.
|
||||
#macro (field $n $max)#set ($v = "$!request.getParameter($n)")#set ($v = $v.trim())#if ($v.length() > $max)#set ($v = $v.substring(0, $max))#end#end
|
||||
#if ($request.method != 'POST')
|
||||
This page receives the inquiry form on [[starshipos-f18.com>>https://starshipos-f18.com/bin/view/Inquiries/]].
|
||||
#else
|
||||
#field('website' 200)#set ($trap = $v)
|
||||
#field('name' 200)#set ($name = $v)
|
||||
#field('email' 200)#set ($email = $v)
|
||||
#field('organization' 200)#set ($org = $v)
|
||||
#field('topic' 100)#set ($topic = $v)
|
||||
#field('message' 10000)#set ($message = $v)
|
||||
#set ($wants = "$!request.getParameter('announcements')" != '')
|
||||
#if ($trap != '')
|
||||
## a robot filled the field people cannot see: say thanks, keep nothing
|
||||
{{html}}<p>Thank you. Your inquiry has been received.</p>{{/html}}
|
||||
#elseif ($name == '' || $message == '' || !$email.matches('^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'))
|
||||
{{html}}<p>Your inquiry was not sent: a name, a valid e-mail address and a message are needed. <a href="https://starshipos-f18.com/bin/view/Inquiries/">Back to the form</a>.</p>{{/html}}
|
||||
#else
|
||||
#set ($stamp = $datetool.format('yyyyMMdd-HHmmss', $datetool.date))
|
||||
#set ($ref = "Inquiries.Entries.I${stamp}-$mathtool.random(1000, 9999)")
|
||||
#set ($entry = $xwiki.getDocumentAsAuthor($ref))
|
||||
#set ($d = $entry.setTitle("Inquiry $stamp"))
|
||||
#set ($o = $entry.newObject('Inquiries.Code.InquiryClass'))
|
||||
#set ($d = $o.set('name', $name))
|
||||
#set ($d = $o.set('email', $email))
|
||||
#set ($d = $o.set('organization', $org))
|
||||
#set ($d = $o.set('topic', $topic))
|
||||
#set ($d = $o.set('message', $message))
|
||||
#if ($wants)#set ($d = $o.set('announcements', 1))#else#set ($d = $o.set('announcements', 0))#end
|
||||
#set ($d = $o.set('source', 'starshipos-f18.com'))
|
||||
#set ($d = $o.set('status', 'new'))
|
||||
#set ($d = $entry.saveAsAuthor('An inquiry from the .com form'))
|
||||
{{html}}<p>Thank you. Your inquiry has been received; every message is read by a human, and replies usually come within a few days.</p><p><a href="https://starshipos-f18.com/">Back to starshipos-f18.com</a></p>{{/html}}
|
||||
#end
|
||||
#end
|
||||
{{/velocity}}
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/bin/bash
|
||||
# install.sh -- inquiries on the .org XWiki (Captain Bob, 2026-11-07: the .com's inquiries go to an
|
||||
# admin-only page on the .org, master/detail):
|
||||
#
|
||||
# Inquiries.WebPreferences view, edit, comment, delete: $ADMIN_USER alone -- made first
|
||||
# Inquiries.Code.InquiryClass the fields (made by Inquiries.Code.ClassSetup, viewed once as the
|
||||
# administrator: the class has no REST API), bound to the sheet
|
||||
# Inquiries.Code.InquirySheet the detail: one inquiry, its status set by editing the page
|
||||
# Inquiries.WebHome the master: every inquiry, newest first (a Live Data table)
|
||||
# Inquiries.Entries.I<time> one page per inquiry, made by PublicInquiry
|
||||
# PublicInquiry.WebHome public: the .com's form posts here; it files the inquiry with its
|
||||
# author's rights and thanks the visitor, echoing nothing they sent
|
||||
#
|
||||
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/inquiries/install.sh [https://starshipos-f18.org]
|
||||
#
|
||||
# It ends by checking a guest's view, then sends one test inquiry as a guest, finds it as the
|
||||
# administrator, and deletes it.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
base=${1:-https://starshipos-f18.org}
|
||||
rest="$base/rest/wikis/xwiki"
|
||||
user=${XWIKI_USER:?set XWIKI_USER}
|
||||
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
|
||||
admin=${ADMIN_USER:-XWiki.$user}
|
||||
auth=(-u "$user:$pass")
|
||||
|
||||
xml_page() { # xml_page <title> <file>
|
||||
python3 -c '
|
||||
import sys
|
||||
from xml.sax.saxutils import escape
|
||||
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
|
||||
"<content>%s</content></page>" % (escape(sys.argv[1]), escape(open(sys.argv[2]).read())))' "$1" "$2"
|
||||
}
|
||||
page() { # page <space path, a/b> <name> <title> <file>
|
||||
local spaces=${1//\//\/spaces\/}
|
||||
curl -fsS -o /dev/null -w " page ${1//\//.}.$2: %{http_code}\n" "${auth[@]}" -X PUT \
|
||||
-H 'Content-Type: application/xml' --data-binary "$(xml_page "$3" "$4")" "$rest/spaces/$spaces/pages/$2"
|
||||
}
|
||||
objects() { # objects <space path> <page> <class>: how many
|
||||
local spaces=${1//\//\/spaces\/}
|
||||
curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/$spaces/pages/$2/objects/$3" |
|
||||
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))'
|
||||
}
|
||||
object() { # object <space path> <page> <class> <property=value>...: add one, as XML
|
||||
local spaces=${1//\//\/spaces\/} s=$1 p=$2 c=$3; shift 3
|
||||
local body
|
||||
body=$(python3 -c '
|
||||
import sys
|
||||
from xml.sax.saxutils import escape
|
||||
props = "".join("<property name=\"%s\"><value>%s</value></property>" % (escape(k), escape(v))
|
||||
for k, v in (a.split("=", 1) for a in sys.argv[2:]))
|
||||
print("<object xmlns=\"http://www.xwiki.org\"><className>%s</className>%s</object>" % (escape(sys.argv[1]), props))' "$c" "$@")
|
||||
curl -fsS -o /dev/null -w " ${s//\//.}.$p: $c added (%{http_code})\n" "${auth[@]}" -X POST \
|
||||
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$spaces/pages/$p/objects"
|
||||
}
|
||||
|
||||
echo "=== $base, as $user"
|
||||
echo "=== rights first: Inquiries is the administrator's alone"
|
||||
page Inquiries WebPreferences "Inquiries rights" /dev/null
|
||||
if [ "$(objects Inquiries WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
|
||||
object Inquiries WebPreferences XWiki.XWikiGlobalRights \
|
||||
"levels=view,edit,comment,delete" "users=$admin" "groups=" "allow=1"
|
||||
else
|
||||
echo " rights there already, left as they are"
|
||||
fi
|
||||
|
||||
echo "=== the class, its sheet"
|
||||
page Inquiries/Code InquiryClass "Inquiry class" /dev/null
|
||||
page Inquiries/Code ClassSetup "Inquiry class setup" ClassSetup.xwiki
|
||||
out=$(curl -fsS "${auth[@]}" "$base/bin/view/Inquiries/Code/ClassSetup?basicauth=1")
|
||||
case "$out" in
|
||||
*CLASS-SAVED*) echo " the class's fields: made";;
|
||||
*CLASS-UNCHANGED*) echo " the class's fields: there already";;
|
||||
*) echo "install: the class setup did not run (programming right?)" >&2; exit 1;;
|
||||
esac
|
||||
page Inquiries/Code InquirySheet "Inquiry sheet" InquirySheet.xwiki
|
||||
if [ "$(objects Inquiries/Code InquiryClass XWiki.ClassSheetBinding)" = 0 ]; then
|
||||
object Inquiries/Code InquiryClass XWiki.ClassSheetBinding "sheet=Inquiries.Code.InquirySheet"
|
||||
else
|
||||
echo " sheet bound already"
|
||||
fi
|
||||
|
||||
echo "=== the master, and the public intake"
|
||||
page Inquiries WebHome "Inquiries" Inquiries.WebHome.xwiki
|
||||
page PublicInquiry WebHome "Inquiry" PublicInquiry.WebHome.xwiki
|
||||
|
||||
echo "=== as a guest"
|
||||
bad=
|
||||
for p in Inquiries:401 PublicInquiry:200; do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/json' "$rest/spaces/${p%%:*}/pages/WebHome")
|
||||
if [ "$code" = "${p##*:}" ]; then echo " ${p%%:*}.WebHome: $code -- as it should be"
|
||||
else echo " ${p%%:*}.WebHome: $code -- NOT as it should be"; bad=1; fi
|
||||
done
|
||||
[ -z "$bad" ] || { echo "install: a guest's view is wrong; see above" >&2; exit 1; }
|
||||
|
||||
echo "=== a test inquiry, sent as a guest"
|
||||
reply=$(curl -fsS -X POST "$base/bin/view/PublicInquiry/" \
|
||||
--data-urlencode "name=install.sh test" --data-urlencode "email=test@example.org" \
|
||||
--data-urlencode "topic=General question" --data-urlencode "message=A test from site/org/inquiries/install.sh; it deletes this.")
|
||||
case "$reply" in *"has been received"*) echo " thanked";; *) echo "install: no thanks for the test" >&2; exit 1;; esac
|
||||
found=$(curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/Inquiries/spaces/Entries/pages" |
|
||||
python3 -c '
|
||||
import json,sys
|
||||
print(" ".join(p["name"] for p in json.load(sys.stdin)["pageSummaries"]))')
|
||||
test_page=
|
||||
for n in $found; do
|
||||
if curl -fsS "${auth[@]}" -H 'Accept: application/json' \
|
||||
"$rest/spaces/Inquiries/spaces/Entries/pages/$n/objects/Inquiries.Code.InquiryClass/0/properties/name" |
|
||||
grep -q 'install.sh test'; then test_page=$n; fi
|
||||
done
|
||||
[ -n "$test_page" ] || { echo "install: the test inquiry was not filed" >&2; exit 1; }
|
||||
echo " filed as Inquiries.Entries.$test_page"
|
||||
curl -fsS -o /dev/null -w " deleted: %{http_code}\n" "${auth[@]}" -X DELETE \
|
||||
"$rest/spaces/Inquiries/spaces/Entries/pages/$test_page"
|
||||
echo "=== done: $base/bin/view/Inquiries/"
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#!/bin/bash
|
||||
# install.sh -- the .org XWiki's three pages (Captain Bob, 2026-11-07): a landing page anyone can
|
||||
# read, an admin dashboard for the administrator alone, and a contributors' dashboard for the
|
||||
# group XWiki.StarshipContributors (and the administrator). Through XWiki's REST API:
|
||||
#
|
||||
# Main.WebHome Main.WebHome.xwiki rights untouched: the wiki's own (guests view)
|
||||
# Admin.WebHome Admin.WebHome.xwiki Admin.WebPreferences: view, edit, comment,
|
||||
# delete -- $ADMIN_USER alone
|
||||
# Contributors.WebHome Contributors.WebHome.xwiki Contributors.WebPreferences: view, comment --
|
||||
# XWiki.StarshipContributors and $ADMIN_USER;
|
||||
# edit, delete -- $ADMIN_USER
|
||||
# XWiki.StarshipContributors the group, created empty; members are added in the wiki's
|
||||
# administration (Users and Groups)
|
||||
#
|
||||
# An allow on a space denies that right there to everyone not named -- guests included.
|
||||
#
|
||||
# XWIKI_USER=rajames XWIKI_PASSWORD=... site/org/install.sh [https://starshipos-f18.org]
|
||||
#
|
||||
# Run it again after editing a page: pages are replaced, rights and the group are added once.
|
||||
# It ends by checking, without logging in, that the landing page is readable and the dashboards
|
||||
# are not.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
base=${1:-https://starshipos-f18.org}
|
||||
rest="$base/rest/wikis/xwiki"
|
||||
user=${XWIKI_USER:?set XWIKI_USER}
|
||||
pass=${XWIKI_PASSWORD:?set XWIKI_PASSWORD}
|
||||
admin=${ADMIN_USER:-XWiki.$user}
|
||||
group=XWiki.StarshipContributors
|
||||
auth=(-u "$user:$pass")
|
||||
|
||||
page() { # page <space> <name> <title> [file]: create or replace
|
||||
local body
|
||||
body=$(python3 -c '
|
||||
import sys
|
||||
from xml.sax.saxutils import escape
|
||||
title, path = sys.argv[1], sys.argv[2]
|
||||
content = open(path).read() if path else ""
|
||||
print("<page xmlns=\"http://www.xwiki.org\"><title>%s</title><syntax>xwiki/2.1</syntax>"
|
||||
"<content>%s</content></page>" % (escape(title), escape(content)))' "$3" "${4:-}")
|
||||
curl -fsS -o /dev/null -w " page $1.$2: %{http_code}\n" "${auth[@]}" -X PUT \
|
||||
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$1/pages/$2"
|
||||
}
|
||||
objects() { # objects <space> <page> <class>: how many the page has
|
||||
curl -fsS "${auth[@]}" -H 'Accept: application/json' "$rest/spaces/$1/pages/$2/objects/$3" |
|
||||
python3 -c 'import json,sys; print(len(json.load(sys.stdin).get("objectSummaries") or []))'
|
||||
}
|
||||
object() { # object <space> <page> <class> <property=value>...: add one
|
||||
# as XML: XWiki refuses a form-encoded POST without its form token (CSRF), not an XML one
|
||||
local s=$1 p=$2 c=$3; shift 3
|
||||
local body
|
||||
body=$(python3 -c '
|
||||
import sys
|
||||
from xml.sax.saxutils import escape
|
||||
props = "".join("<property name=\"%s\"><value>%s</value></property>" % (escape(k), escape(v))
|
||||
for k, v in (a.split("=", 1) for a in sys.argv[2:]))
|
||||
print("<object xmlns=\"http://www.xwiki.org\"><className>%s</className>%s</object>" % (escape(sys.argv[1]), props))' "$c" "$@")
|
||||
curl -fsS -o /dev/null -w " $s.$p: $c added (%{http_code})\n" "${auth[@]}" -X POST \
|
||||
-H 'Content-Type: application/xml' --data-binary "$body" "$rest/spaces/$s/pages/$p/objects"
|
||||
}
|
||||
|
||||
echo "=== $base, as $user"
|
||||
echo "=== the group $group"
|
||||
page XWiki StarshipContributors "Starship Contributors"
|
||||
if [ "$(objects XWiki StarshipContributors XWiki.XWikiGroups)" = 0 ]; then
|
||||
object XWiki StarshipContributors XWiki.XWikiGroups "member="
|
||||
else
|
||||
echo " already a group"
|
||||
fi
|
||||
|
||||
echo "=== rights"
|
||||
page Admin WebPreferences "Admin rights"
|
||||
if [ "$(objects Admin WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
|
||||
object Admin WebPreferences XWiki.XWikiGlobalRights \
|
||||
"levels=view,edit,comment,delete" "users=$admin" "groups=" "allow=1"
|
||||
else
|
||||
echo " Admin: rights there already, left as they are"
|
||||
fi
|
||||
page Contributors WebPreferences "Contributors rights"
|
||||
if [ "$(objects Contributors WebPreferences XWiki.XWikiGlobalRights)" = 0 ]; then
|
||||
object Contributors WebPreferences XWiki.XWikiGlobalRights \
|
||||
"levels=view,comment" "users=$admin" "groups=$group" "allow=1"
|
||||
object Contributors WebPreferences XWiki.XWikiGlobalRights \
|
||||
"levels=edit,delete" "users=$admin" "groups=" "allow=1"
|
||||
else
|
||||
echo " Contributors: rights there already, left as they are"
|
||||
fi
|
||||
|
||||
echo "=== the pages -- after their spaces' rights, so a dashboard is never readable without them"
|
||||
page Main WebHome "StarshipOS" Main.WebHome.xwiki
|
||||
page Admin WebHome "Admin Dashboard" Admin.WebHome.xwiki
|
||||
page Contributors WebHome "Contributors' Dashboard" Contributors.WebHome.xwiki
|
||||
|
||||
echo "=== as a guest"
|
||||
bad=
|
||||
for p in Main Admin Contributors; do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/json' "$rest/spaces/$p/pages/WebHome")
|
||||
case "$p:$code" in
|
||||
Main:200|Admin:401|Admin:403|Contributors:401|Contributors:403)
|
||||
echo " $p.WebHome: $code -- as it should be";;
|
||||
*) echo " $p.WebHome: $code -- NOT as it should be"; bad=1;;
|
||||
esac
|
||||
done
|
||||
[ -z "$bad" ] || { echo "install: a guest's view is wrong; see above" >&2; exit 1; }
|
||||
echo "=== done: $base/bin/view/Main/"
|
||||
@@ -56,6 +56,8 @@
|
||||
|
||||
#include "pkcs8_ed25519.h"
|
||||
#include "starkernel/ed25519.h"
|
||||
#include "starkernel/x509_ed25519.h"
|
||||
#include "starkernel/capsule_sig.h"
|
||||
|
||||
/*===========================================================================
|
||||
* xxHash64 (embedded for build tool — no external dependency)
|
||||
@@ -1575,6 +1577,34 @@ static int load_sign_key(const char *key_path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The signing key must be the one whose certificate the image carries
|
||||
* (CAPSULE_SIGNING_CERT_NAME): the kernel checks every signature against
|
||||
* that certificate, and refuses a signature that does not verify -- Mama's
|
||||
* own included. A key that is not the certificate's would build an image
|
||||
* that cannot boot, so refuse to build it. Returns 0 if they match. */
|
||||
static int check_sign_key_matches_cert(void) {
|
||||
uint8_t key_pub[32], cert_pub[32];
|
||||
ed25519_keygen(sign_seed, key_pub);
|
||||
for (int i = 0; i < capsule_count; i++) {
|
||||
if (strcmp(capsules[i].name, CAPSULE_SIGNING_CERT_NAME) != 0) continue;
|
||||
if (x509_extract_ed25519_pubkey(capsules[i].data, capsules[i].length, cert_pub) != 0) {
|
||||
fprintf(stderr, "mkcapsule: ERROR: %s is not an Ed25519 certificate\n",
|
||||
CAPSULE_SIGNING_CERT_NAME);
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(key_pub, cert_pub, 32) != 0) {
|
||||
fprintf(stderr, "mkcapsule: ERROR: the signing key is not %s's -- every "
|
||||
"capsule would fail its check at boot\n", CAPSULE_SIGNING_CERT_NAME);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "mkcapsule: signing key matches %s\n", CAPSULE_SIGNING_CERT_NAME);
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, "mkcapsule: ERROR: --sign-key given, but no %s to check it against\n",
|
||||
CAPSULE_SIGNING_CERT_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* --manifest mode: generate block ownership markdown. Optional
|
||||
* --sign-key <keyfile> prefix: mkcapsule --manifest [--sign-key
|
||||
@@ -1717,6 +1747,10 @@ int main(int argc, char **argv) {
|
||||
|
||||
fprintf(stderr, "mkcapsule: %d capsule(s) collected\n", capsule_count);
|
||||
|
||||
if (have_sign_seed && check_sign_key_matches_cert() != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE *out = fopen(output_path, "w");
|
||||
if (!out) {
|
||||
fprintf(stderr, "mkcapsule: ERROR: cannot create '%s'\n", output_path);
|
||||
|
||||
+4
-2
@@ -173,10 +173,12 @@ RUN_amd64 ?=
|
||||
RUN_aarch64 ?= qemu-aarch64
|
||||
RUN_riscv64 ?= qemu-riscv64
|
||||
|
||||
SIGN_KEY ?= /home/rajames/CLionProjects/lithosananke-ca/intermediate/snakeoil-intermediate.key
|
||||
# as kernel/Makefile: CI sets SIGN_KEY; unset, the capsules are built unsigned
|
||||
SIGN_KEY ?=
|
||||
SIGN_KEY_ARGS = $(if $(wildcard $(SIGN_KEY)),--sign-key $(SIGN_KEY),)
|
||||
CRYPTO_SRCS := $(addprefix $(ROOT)/kernel/src/crypto/,ed25519.c fe25519.c scalar25519.c sha512.c)
|
||||
MKCAPSULE_SRCS := $(ROOT)/tools/mkcapsule.c $(ROOT)/tools/pkcs8_ed25519.c $(CRYPTO_SRCS)
|
||||
MKCAPSULE_SRCS := $(ROOT)/tools/mkcapsule.c $(ROOT)/tools/pkcs8_ed25519.c $(CRYPTO_SRCS) \
|
||||
$(ROOT)/kernel/src/crypto/x509_ed25519.c
|
||||
CAPSULE_FILES := $(shell find $(ROOT)/capsules -type f ! -name '.*' 2>/dev/null)
|
||||
CAPSULE_DIR_C := $(BINDIR)/capsule_generated.c
|
||||
MACHINE_64 := $(BINDIR)/rom-64.c $(BINDIR)/v4_map_64.c
|
||||
|
||||
Reference in New Issue
Block a user