Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6db66db87f |
@@ -16,13 +16,28 @@ use ed25519_dalek::VerifyingKey;
|
|||||||
|
|
||||||
/// Hex of the pinned Ed25519 release-root public key (32 bytes / 64 hex chars).
|
/// Hex of the pinned Ed25519 release-root public key (32 bytes / 64 hex chars).
|
||||||
///
|
///
|
||||||
/// Pinned 2026-07-02 from the release-root signing ceremony
|
/// ROTATED 2026-08-04 to did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT.
|
||||||
/// (signer did:key:z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur). The
|
///
|
||||||
|
/// The previous root (z6Mkkid…q7ur, pinned 2026-07-02) was exposed in a chat
|
||||||
|
/// transcript and is treated as compromised.
|
||||||
|
///
|
||||||
|
/// Rotation is ORDERING-CRITICAL. Nodes pin the OLD key, so the release that
|
||||||
|
/// carries this change must itself be signed with the OLD key — that is the
|
||||||
|
/// only signature a node running the previous binary will accept. Only the
|
||||||
|
/// release AFTER it may be signed with the new key. Signing the rotation
|
||||||
|
/// release with the new key makes every node reject it and ends OTA
|
||||||
|
/// fleet-wide, recoverable only by touching each node by hand.
|
||||||
|
///
|
||||||
|
/// Verified before pinning: this hex and the did:key above are the same
|
||||||
|
/// keypair (the did:key encodes exactly these 32 bytes), checked with a
|
||||||
|
/// decoder round-tripped against the previous known-good pair. An earlier
|
||||||
|
/// candidate hex was rejected because it did not match the stated DID.
|
||||||
|
/// The
|
||||||
/// corresponding mnemonic is held offline by the publisher — see
|
/// corresponding mnemonic is held offline by the publisher — see
|
||||||
/// `docs/workstream-b-signing-runbook.md`. Regenerate/verify with:
|
/// `docs/workstream-b-signing-runbook.md`. Regenerate/verify with:
|
||||||
/// `RELEASE_MASTER_MNEMONIC=… archipelago ceremony pubkey`.
|
/// `RELEASE_MASTER_MNEMONIC=… archipelago ceremony pubkey`.
|
||||||
pub const RELEASE_ROOT_PUBKEY_HEX: Option<&str> =
|
pub const RELEASE_ROOT_PUBKEY_HEX: Option<&str> =
|
||||||
Some("5d15cbee8a108f7dd288c02d29a1d9d71f198acc99186aad8008b4f28d469951");
|
Some("1578adccf137024159dd936f44a56e8869ac7775785962f7e92e2faf2c034418");
|
||||||
|
|
||||||
const ENV_OVERRIDE: &str = "ARCHY_RELEASE_ROOT_PUBKEY";
|
const ENV_OVERRIDE: &str = "ARCHY_RELEASE_ROOT_PUBKEY";
|
||||||
|
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ install -m 0644 "$FRONTEND_ARCHIVE" "$VERSION_DIR/archipelago-frontend-${VERSION
|
|||||||
# warning and falls through — and the commit then happened anyway. A release
|
# warning and falls through — and the commit then happened anyway. A release
|
||||||
# commit carrying a manifest no node will accept has no valid use, so refuse
|
# commit carrying a manifest no node will accept has no valid use, so refuse
|
||||||
# to create one rather than leave a tag that has to be re-cut.
|
# to create one rather than leave a tag that has to be re-cut.
|
||||||
EXPECTED_DID="did:key:z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur"
|
EXPECTED_DID="did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT"
|
||||||
if ! grep -q '"signature":' "$PROJECT_ROOT/releases/manifest.json" \
|
if ! grep -q '"signature":' "$PROJECT_ROOT/releases/manifest.json" \
|
||||||
|| ! grep -q "\"signed_by\": \"$EXPECTED_DID\"" "$PROJECT_ROOT/releases/manifest.json"; then
|
|| ! grep -q "\"signed_by\": \"$EXPECTED_DID\"" "$PROJECT_ROOT/releases/manifest.json"; then
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ fail() { echo "Error: $*" >&2; exit 1; }
|
|||||||
# with the pinned release-root anchor refuse to auto-apply unsigned manifests,
|
# with the pinned release-root anchor refuse to auto-apply unsigned manifests,
|
||||||
# and enforcement will tighten to hard-reject — an unsigned publish would
|
# and enforcement will tighten to hard-reject — an unsigned publish would
|
||||||
# strand them. Grep proves presence; ceremony verify proves the crypto.
|
# strand them. Grep proves presence; ceremony verify proves the crypto.
|
||||||
EXPECTED_DID="did:key:z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur"
|
EXPECTED_DID="did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT"
|
||||||
grep -q '"signature":' "$PROJECT_ROOT/releases/manifest.json" \
|
grep -q '"signature":' "$PROJECT_ROOT/releases/manifest.json" \
|
||||||
&& grep -q "\"signed_by\": \"$EXPECTED_DID\"" "$PROJECT_ROOT/releases/manifest.json" \
|
&& grep -q "\"signed_by\": \"$EXPECTED_DID\"" "$PROJECT_ROOT/releases/manifest.json" \
|
||||||
|| fail "releases/manifest.json is not signed by the release root — run: bash scripts/sign-manifest.sh"
|
|| fail "releases/manifest.json is not signed by the release root — run: bash scripts/sign-manifest.sh"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
REPO="/home/archipelago/Projects/archy"
|
REPO="/home/archipelago/Projects/archy"
|
||||||
CATALOG="$REPO/releases/app-catalog.json"
|
CATALOG="$REPO/releases/app-catalog.json"
|
||||||
EXPECTED_DID="did:key:z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur"
|
EXPECTED_DID="did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT"
|
||||||
|
|
||||||
# Use ONLY the prebuilt signer. If it isn't ready, stop cleanly — never compile
|
# Use ONLY the prebuilt signer. If it isn't ready, stop cleanly — never compile
|
||||||
# here (compiling caused the earlier hangs). Claude builds it in the background.
|
# here (compiling caused the earlier hangs). Claude builds it in the background.
|
||||||
|
|||||||
Reference in New Issue
Block a user