Release v0.1.1:3 with Configure Subspaces, monitor CLI, and spaces v0.0.9x.
Build Service / BuildPackage (push) Has been cancelled
Build Service / BuildPackage (push) Has been cancelled
Adds a user toggle for SUBS_PUBLISH_REQUIRE_FINALIZED, copies the certrelay monitor binary to /data/bin for terminal use, and bumps the spaced image to horologger/spaces:v0.0.9x. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { storeJson } from '../fileModels/storeJson'
|
||||
import { i18n } from '../i18n'
|
||||
import { sdk } from '../sdk'
|
||||
|
||||
const { InputSpec, Value } = sdk
|
||||
|
||||
const inputSpec = InputSpec.of({
|
||||
subsPublishRequireFinalized: Value.toggle({
|
||||
name: i18n('Require Finalized Publish'),
|
||||
description: i18n(
|
||||
'When on, subs blocks certificate publish until commitments are finalized (150 confirmations). Maps to SUBS_PUBLISH_REQUIRE_FINALIZED in the subs daemon environment. Off by default.',
|
||||
),
|
||||
warning: null,
|
||||
footnote: null,
|
||||
default: false,
|
||||
}),
|
||||
})
|
||||
|
||||
export const configureSubspaces = sdk.Action.withInput(
|
||||
// id
|
||||
'configure-subspaces',
|
||||
|
||||
// metadata
|
||||
async ({ effects }) => ({
|
||||
name: i18n('Configure Subspaces'),
|
||||
description: i18n(
|
||||
'Set user-tunable subs options. Saving restarts the service so the subs daemon picks up the new environment.',
|
||||
),
|
||||
warning: null,
|
||||
allowedStatuses: 'any',
|
||||
group: null,
|
||||
visibility: 'enabled',
|
||||
}),
|
||||
|
||||
// input
|
||||
inputSpec,
|
||||
|
||||
// prefill — current value (unset/null => false)
|
||||
async ({ effects }) => {
|
||||
const enabled = await storeJson
|
||||
.read((s) => s.subsPublishRequireFinalized)
|
||||
.once()
|
||||
return { subsPublishRequireFinalized: enabled === true }
|
||||
},
|
||||
|
||||
// run
|
||||
async ({ effects, input }) => {
|
||||
await storeJson.merge(effects, {
|
||||
subsPublishRequireFinalized: input.subsPublishRequireFinalized,
|
||||
})
|
||||
|
||||
return {
|
||||
version: '1',
|
||||
title: i18n('Success'),
|
||||
message: input.subsPublishRequireFinalized
|
||||
? i18n(
|
||||
'Subspaces configuration saved. SUBS_PUBLISH_REQUIRE_FINALIZED is enabled; the service is restarting.',
|
||||
)
|
||||
: i18n(
|
||||
'Subspaces configuration saved. SUBS_PUBLISH_REQUIRE_FINALIZED is disabled; the service is restarting.',
|
||||
),
|
||||
result: null,
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
import { sdk } from '../sdk'
|
||||
import { configureCertrelay } from './configureCertrelay'
|
||||
import { configureNacho } from './configureNacho'
|
||||
import { configureSubspaces } from './configureSubspaces'
|
||||
import { disableSubsAuth } from './disableSubsAuth'
|
||||
import { disableSubsProverAuth } from './disableSubsProverAuth'
|
||||
import { disableSubspaces } from './disableSubspaces'
|
||||
@@ -48,4 +49,5 @@ export const actions = sdk.Actions.of()
|
||||
.addAction(resetSubspacesState)
|
||||
.addAction(configureCertrelay)
|
||||
.addAction(configureNacho)
|
||||
.addAction(configureSubspaces)
|
||||
.addAction(uploadSupportPdf)
|
||||
|
||||
@@ -39,6 +39,7 @@ const shape = z.object({
|
||||
certrelayBootstrap: z.boolean().nullable().catch(null),
|
||||
certrelayHealthcheckHandle: z.string().nullable().catch(null),
|
||||
nachoWorkshopPdfLinkText: z.string().nullable().catch(null),
|
||||
subsPublishRequireFinalized: z.boolean().nullable().catch(null),
|
||||
})
|
||||
|
||||
export const storeJson = FileHelper.json(
|
||||
|
||||
@@ -289,6 +289,16 @@ const dict = {
|
||||
205,
|
||||
'Subspaces Prover Auth credentials saved. Auth is currently DISABLED — enable it with "Enable Subspaces Prover Auth" to enforce these credentials.':
|
||||
206,
|
||||
'Configure Subspaces': 207,
|
||||
'Set user-tunable subs options. Saving restarts the service so the subs daemon picks up the new environment.':
|
||||
208,
|
||||
'Require Finalized Publish': 209,
|
||||
'When on, subs blocks certificate publish until commitments are finalized (150 confirmations). Maps to SUBS_PUBLISH_REQUIRE_FINALIZED in the subs daemon environment. Off by default.':
|
||||
210,
|
||||
'Subspaces configuration saved. SUBS_PUBLISH_REQUIRE_FINALIZED is enabled; the service is restarting.':
|
||||
211,
|
||||
'Subspaces configuration saved. SUBS_PUBLISH_REQUIRE_FINALIZED is disabled; the service is restarting.':
|
||||
212,
|
||||
} as const
|
||||
|
||||
/**
|
||||
|
||||
+11
-3
@@ -16,6 +16,8 @@ import {
|
||||
CERTRELAY_DIR,
|
||||
CERTRELAY_FABRIC_BIN,
|
||||
CERTRELAY_FABRIC_DEST,
|
||||
CERTRELAY_MONITOR_BIN,
|
||||
CERTRELAY_MONITOR_DEST,
|
||||
CERTRELAY_PORT,
|
||||
CERTRELAY_REMOTE_IP_HEADER,
|
||||
dataDir,
|
||||
@@ -147,6 +149,8 @@ export const main = sdk.setupMain(async ({ effects }) => {
|
||||
SUBS_SPACED_RPC_PASSWORD: spacedAuth.password,
|
||||
SUBS_PROVER_ENDPOINT: `http://127.0.0.1:${SUBSPACES_PROVER_PORT}`,
|
||||
SUBS_REGISTRY_ENDPOINT: `http://127.0.0.1:${SUBSPACES_REGISTRY_PORT}`,
|
||||
SUBS_PUBLISH_REQUIRE_FINALIZED:
|
||||
store.subsPublishRequireFinalized === true ? 'true' : 'false',
|
||||
HOME: SUBSPACES_DATA_DIR,
|
||||
RUST_LOG: 'subs=info,subs_prover=info,registry_server=info',
|
||||
...subsAuthEnv,
|
||||
@@ -256,7 +260,7 @@ export const main = sdk.setupMain(async ({ effects }) => {
|
||||
'spaced is managed by StartOS — do not run it manually.',
|
||||
'Use the `spaces` alias to call space-cli, e.g.',
|
||||
' spaces getserverinfo',
|
||||
'`fabric` resolves handles against the local certrelay.',
|
||||
'`fabric` resolves handles; `monitor` is on PATH (copy-only, not auto-started).',
|
||||
'Docs: https://docs.spacesprotocol.org/',
|
||||
]),
|
||||
'',
|
||||
@@ -265,8 +269,9 @@ export const main = sdk.setupMain(async ({ effects }) => {
|
||||
|
||||
// Appends the always-on certrelay chain (setup oneshot + certrelay daemon) to
|
||||
// any existing chain. certrelay serves cryptographic proofs binding handles to
|
||||
// owner keys anchored to Bitcoin. The `fabric` CLI is copied onto /data/bin so
|
||||
// the gotty terminal (which has /data/bin on PATH) can resolve handles.
|
||||
// owner keys anchored to Bitcoin. The certrelay-setup oneshot copies `fabric`
|
||||
// and `monitor` onto /data/bin for the gotty terminal (PATH includes /data/bin).
|
||||
// Only the certrelay server is started as a daemon — monitor is a CLI file only.
|
||||
const withCertrelay = (chain: any): any =>
|
||||
chain
|
||||
.addOneshot('certrelay-setup', {
|
||||
@@ -280,6 +285,9 @@ export const main = sdk.setupMain(async ({ effects }) => {
|
||||
echo "certrelay-setup: installing fabric CLI to ${CERTRELAY_FABRIC_DEST}..."; \
|
||||
cp -f ${CERTRELAY_FABRIC_BIN} ${CERTRELAY_FABRIC_DEST}; \
|
||||
chmod +x ${CERTRELAY_FABRIC_DEST}; \
|
||||
echo "certrelay-setup: installing monitor CLI to ${CERTRELAY_MONITOR_DEST}..."; \
|
||||
cp -f ${CERTRELAY_MONITOR_BIN} ${CERTRELAY_MONITOR_DEST}; \
|
||||
chmod +x ${CERTRELAY_MONITOR_DEST}; \
|
||||
echo "certrelay-setup: done."`,
|
||||
],
|
||||
user: 'root',
|
||||
|
||||
@@ -14,7 +14,7 @@ export const manifest = setupManifest({
|
||||
volumes: ['main'],
|
||||
images: {
|
||||
spaces: {
|
||||
source: { dockerTag: 'horologger/spaces:v0.0.9s' },
|
||||
source: { dockerTag: 'horologger/spaces:v0.0.9x' },
|
||||
arch: ['x86_64', 'aarch64'],
|
||||
},
|
||||
subspaces: {
|
||||
|
||||
+5
-3
@@ -34,12 +34,14 @@ export const SUBSPACES_PROVER_PORT = 8888
|
||||
export const SUBSPACES_REGISTRY_PORT = 8081
|
||||
export const SUBSPACES_WALLET = 'default'
|
||||
|
||||
// Certrelay ships as the prebuilt horologger/certrelay image; both binaries
|
||||
// are static musl, so `fabric` runs anywhere once copied onto the volume.
|
||||
// Certrelay ships as the prebuilt horologger/certrelay image; CLI binaries
|
||||
// are static musl, so they run anywhere once copied onto the volume.
|
||||
export const CERTRELAY_BIN = '/usr/local/bin/certrelay'
|
||||
export const CERTRELAY_FABRIC_BIN = '/usr/local/bin/fabric'
|
||||
// Copied here so the gotty terminal (which has /data/bin on PATH) can run it.
|
||||
export const CERTRELAY_MONITOR_BIN = '/usr/local/bin/monitor'
|
||||
// Copied here so the gotty terminal (which has /data/bin on PATH) can run them.
|
||||
export const CERTRELAY_FABRIC_DEST = '/data/bin/fabric'
|
||||
export const CERTRELAY_MONITOR_DEST = '/data/bin/monitor'
|
||||
export const CERTRELAY_DIR = '/data/certrelay'
|
||||
export const CERTRELAY_DATA_DIR = '/data/certrelay/data'
|
||||
export const CERTRELAY_PORT = 7778
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { VersionGraph } from '@start9labs/start-sdk'
|
||||
import { v_0_1_1_2 } from './v0.1.1.2'
|
||||
import { v_0_1_1_3 } from './v0.1.1.3'
|
||||
|
||||
export const versionGraph = VersionGraph.of({
|
||||
current: v_0_1_1_2,
|
||||
current: v_0_1_1_3,
|
||||
other: [],
|
||||
})
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
||||
|
||||
export const v_0_1_1_2 = VersionInfo.of({
|
||||
version: '0.1.1:2',
|
||||
releaseNotes: {
|
||||
en_US: `- **Optional HTTP basic auth in front of the Subspaces Prover (port 8888).** Same pattern as the subs auth: off by default, gated by \`store.subsProverAuthEnabled\` + \`store.subsProverAuth\`, wired via \`SUBS_PROVER_BASIC_AUTH_USER\` / \`SUBS_PROVER_BASIC_AUTH_PASSWORD\` env vars on the \`subs-prover\` daemon. Four new actions: **Enable Subspaces Prover Auth**, **Disable Subspaces Prover Auth**, **Show Subspaces Prover Auth Credentials**, **Set Subspaces Prover Auth Credentials**. Independent of subs auth — each daemon has its own toggle and credential store.
|
||||
- **Optional HTTP basic auth in front of the Subspaces Web UI and Subs API.** Both share port 7777 on the \`subs\` daemon, so a single toggle gates both. Off by default. Wired via \`SUBS_BASIC_AUTH_USER\` / \`SUBS_BASIC_AUTH_PASSWORD\` env vars injected into subs's environment only when the toggle is on AND credentials are stored. Four new actions manage the lifecycle: **Enable Subspaces Auth** (auto-generates a \`spaces\` / random32 credential pair on first enable; preserves them on subsequent enables), **Disable Subspaces Auth** (preserves credentials across the toggle), **Show Subspaces Auth Credentials** (surfaces user/password + a loopback URL, reports current enforcement state), **Set Subspaces Auth Credentials** (rotate; blank password auto-generates a random one; also enables auth). Stored as \`store.subsAuth\` and \`store.subsAuthEnabled\`. NOTE: the in-package nacho client will break against an authed subs until separately wired — that integration is deferred.
|
||||
- **Nacho ignore list is now file-backed at \`/data/nacho/ignore_names.txt\`** instead of \`EXPO_PUBLIC_IGNORE_NAMES\`. Expo inlines \`EXPO_PUBLIC_*\` into the bundle at build time and connected clients cache that bundle aggressively, so env-var changes only landed after a hard reload. Moving the list to a runtime-read file means nacho picks up changes without a bundle rebuild. The \`nacho-setup\` oneshot creates the file with the default (\`fold,swifty\`) on first start; the **Configure Nacho** action writes the file directly and prefills the form by reading it back (with the default as fallback). The \`nachoIgnoreNames\` field has been removed from \`store.json\`.
|
||||
- **Milestone release: this version ships with Nacho bundled in.** The \`horologger/nacho:v1.0.0\` Expo dev server runs alongside spaced as an always-on UI on port 8082, wired to the Subs API and configurable via the "Configure Nacho" and "Upload Support PDF" actions.
|
||||
- **Removed the embedded explorer feature and its indexer entirely.** Deleted the Explorer Web UI interface (port 3000), the postgres image, the PostgreSQL daemon + chown oneshot, and all stubs for the prebuilt indexer / explorer-UI images. Dropped the actions: enable-explorer, disable-explorer, show-db-credentials, reset-db-state, reset-indexer-state, reset-explorer-state. Removed the \`dbAuth\` and \`enableExplorer\` fields from store.json + their seed tasks (taskSeedDb, taskSeedEnableExplorer). main.ts collapsed to a single always-on chain (no more enableExplorer branching). Drop the related EXPLORER_*, INDEXER_*, POSTGRES_* constants from utils.ts.
|
||||
- Added the nacho service (prebuilt \`horologger/nacho:v1.0.0\`, Expo dev server). Always on; runs the image's entrypoint and exposes a UI interface on port 8082. Env: \`EXPO_PUBLIC_API_BASE_URL\` is derived dynamically from the Subs API StartOS interface (\`sdk.serviceInterface.getOwn('subs-api').const()\`) — preferring the .local URL — so it tracks whatever host:port StartOS exposes for the subs daemon; \`EXPO_PUBLIC_IGNORE_NAMES\` (defaults to "fold,swifty") and \`EXPO_PUBLIC_WORKSHOP_PDF_LINK_TEXT\` (defaults to empty) are user-configurable via the new "Configure Nacho" action; the workshop PDF is uploaded via a separate "Upload Support PDF" action that overwrites /data/support.pdf on the main volume (split from Configure Nacho because the StartOS form serializes an unselected file input as {} rather than null, which Value.file's nullable parser rejects — a required-true dedicated action sidesteps the problem). Service auto-restarts when either the subs-api address info or the ignore-names value changes.
|
||||
- Exposed the spaced JSON-RPC API as a new "Spaces API" StartOS interface (port 7225) and changed SPACED_RPC_BIND from 127.0.0.1 to 0.0.0.0 so external processes can reach it. It remains authenticated with the spaced RPC credentials (store.spacedAuth); internal clients still connect over loopback.
|
||||
- New "Show Spaces API Credentials" action surfaces SPACED_RPC_USER / SPACED_RPC_PASSWORD (and a loopback connection URL) so you can authenticate external clients against the Spaces API.
|
||||
- Added a dedicated "Subs API" interface (type api) on the subs daemon's port (7777), distinct from the Subspaces Prover (8888) and Subspaces Registry (8081) interfaces. The subs daemon is "subsd — an HTTP REST API server"; this surfaces that REST API as its own dashboard entry.
|
||||
- New "Enable / Disable Subspaces Prover" action independently gates just the subs-prover daemon (store.enableSubsProver), **disabled by default**. When off, subs-prover does not start (it runs lengthy boot-time timing tests), but its interface on 8888 stays registered. It is added last and nothing depends on it, so its slow startup never blocks subs, the registry, or certrelay.
|
||||
- Embedded Certrelay (prebuilt \`horologger/certrelay:v0.2.3\` image, static musl binaries). Always on — runs the \`certrelay\` server on port 7778 from service start, as its own StartOS interface. It serves cryptographic proofs binding Bitcoin-anchored handles to owner keys, talking to the local spaced over loopback using the store.spacedAuth credentials. The bundled \`fabric\` CLI is copied to /data/bin/fabric so it's runnable from the Space-CLI Web UI. New "Configure Certrelay" action sets CERTRELAY_SELF_URL, CERTRELAY_BOOTSTRAP, and CERTRELAY_HEALTHCHECK_HANDLE (stored in store.json; saving restarts the service). Set CERTRELAY_SELF_URL to the publicly visible URL StartOS exposes for the Certrelay interface.
|
||||
- Removed the build-from-source chains for the Go indexer and the SvelteKit explorer, and dropped their builder images (\`golang:1.23-alpine\`, \`node:20-alpine\`). This shrinks the .s9pk and removes the multi-minute first-enable compile. The indexer + explorer-UI daemons are now stubbed with TODOs in startos/main.ts pending prebuilt images (indexer image not yet produced; explorer image to be provided). Enabling the embedded explorer currently starts PostgreSQL only. All explorer-indexer actions (show-db-credentials, reset-db-state, reset-indexer-state, reset-explorer-state) are retained.
|
||||
- Embedded Subspaces support (prebuilt \`horologger/subs:\` image). Opt-in via the new "Enable Subspaces" action; "Disable Subspaces" stops it. No compile step — enabling starts three prebuilt daemons, each on its own StartOS interface: **subs** (Web UI, 7777), **subs-prover** (RISC Zero prover, no GPU, 8888), and **registry-server** (handle registry, 8081). subs loads the existing \`default\` spaces wallet at startup (it does not create one). Runtime data persists at /data/subspaces/data across restarts and toggles. New "Reset Subspaces State" action wipes local data. Adds a fifth manifest image (\`horologger/subs:\`, ~84 MB) — switched from building \`spacesops/subs\` from source with \`rust:1-slim\` to shrink the .s9pk and eliminate the multi-minute first-enable compile.
|
||||
- Five distinct interfaces now appear in the dashboard: **Space-CLI Web UI** (gotty terminal, 8080), **Explorer Web UI** (3000, opt-in), **Subspaces Web UI** (7777, opt-in), **Subspaces Prover** (8888, opt-in), **Subspaces Registry** (8081, opt-in). Internal "Web UI" references renamed to **Space-CLI Web UI** for clarity.
|
||||
- Embedded explorer (PostgreSQL + Go indexer + SvelteKit web UI) is now **opt-in**. Fresh installs run in spaces-only mode (spaced + gotty terminal). New "Enable Embedded Explorer" action turns the whole bundle on; "Disable Embedded Explorer" turns it back off. Both auto-restart the service so the new daemon graph takes effect. Indexed data on disk is preserved across toggles.
|
||||
- Embedded SvelteKit explorer web UI (randomlogin/explorer @ c827da175). Fetched into /data/explorer-ui on first enable, \`npm install\` + \`npm run build\` produce a SvelteKit node-adapter bundle, and \`node build\` runs as a managed daemon on port 3000. Exposed as a StartOS interface so it appears alongside the gotty terminal in the dashboard. Reads exclusively from the embedded PostgreSQL; does not talk to spaced or bitcoind directly. New "Reset Explorer UI State" action wipes the cache for a clean rebuild. Adds a fourth manifest image \`node:20-alpine\`.
|
||||
- Embedded spaces-protocol explorer indexer (Go, spacesprotocol/explorer-indexer @ 00ae1e548). When enabled, on first start its source tarball is fetched into /data/explorer-indexer, the \`sync\` binary and \`goose\` migrator are built into /data/explorer-indexer/bin, the goose-managed SQL schema is applied to the embedded PostgreSQL, and the sync binary runs as a managed daemon that polls bitcoind + spaced and writes to the database.
|
||||
- Two patches applied to the indexer source during \`indexer-fetch\` to handle our older spaced binary: \`pkg/node/types.go\` makes \`ptrs_root\` optional in RootAnchor, and \`pkg/store/store.go\` skips the \`getptrblockmeta\` RPC call. Subspaces pointer data won't be indexed; everything else (blocks, transactions, spaces, rollouts, root anchors) does.
|
||||
- Spaced is now configured with static RPC credentials (SPACED_RPC_USER / SPACED_RPC_PASSWORD seeded into store.json.spacedAuth) instead of cookie auth, so the indexer and the gotty terminal share a single auth path. space-cli inside the terminal aliases to \`--rpc-user "$SPACED_RPC_USER" --rpc-password "$SPACED_RPC_PASSWORD"\`.
|
||||
- New "Indexer Sync" standalone health check queries the blocks table for the highest non-orphan block and cross-references against spaced's tip; success when within 5 blocks, otherwise loading with explicit lag.
|
||||
- New "Reset Indexer State" action wipes /data/explorer-indexer so the next start re-fetches the pinned commit and rebuilds the binaries.
|
||||
- Embedded PostgreSQL 16.3 daemon on loopback 127.0.0.1:5432 (data at /data/postgres). "Show Database Credentials" + "Reset Database State" actions. POSTGRES_URI exported into the gotty terminal.
|
||||
- Indexer container is a third manifest image (\`golang:1.23-alpine\`) used both to build the binaries and to run \`sync\`.
|
||||
- "Reset Spaced State" action so a corrupt /data/mainnet/ index can be wiped from the UI.
|
||||
- Web terminal no longer requires spaced to be healthy, so gotty stays reachable when spaced crash-loops.
|
||||
- Initial build bundles spaced + space-cli from horologger/spaces:v0.0.9s, managed spaced daemon (mainnet only), gotty browser terminal with admin basic auth, and the Bitcoin Core 31.x dependency.`,
|
||||
},
|
||||
migrations: {
|
||||
up: async ({ effects }) => {},
|
||||
down: IMPOSSIBLE,
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
||||
|
||||
export const v_0_1_1_3 = VersionInfo.of({
|
||||
version: '0.1.1:3',
|
||||
releaseNotes: {
|
||||
en_US: `- **Configure Subspaces** action toggles \`SUBS_PUBLISH_REQUIRE_FINALIZED\` on the \`subs\` daemon (default off). When enabled, subs blocks certificate publish until commitments are finalized (150 confirmations). Stored as \`store.subsPublishRequireFinalized\`; always injected into subs's environment as \`true\` or \`false\`.
|
||||
- **monitor CLI** from the certrelay image is now copied to \`/data/bin/monitor\` alongside \`fabric\` on each start (file only — not run as a daemon). Both are on PATH in the Space-CLI Web UI terminal.`,
|
||||
},
|
||||
migrations: {
|
||||
up: async ({ effects }) => {},
|
||||
down: IMPOSSIBLE,
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user