Release v0.1.1:3 with Configure Subspaces, monitor CLI, and spaces v0.0.9x.
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:
2026-07-16 18:53:22 -04:00
co-authored by Cursor
parent ad64a47d42
commit 1fa9674d49
11 changed files with 127 additions and 51 deletions
+17 -5
View File
@@ -60,6 +60,7 @@ image's `docker_entrypoint.sh`; daemons are defined in `startos/main.ts`.
| `/data/subspaces/registry` | `main` | Working directory for the `registry-server` daemon. | | `/data/subspaces/registry` | `main` | Working directory for the `registry-server` daemon. |
| `/data/certrelay/data` | `main` | Certrelay data directory (`CERTRELAY_DATA_DIR`) — anchors, peer state, sqlite. | | `/data/certrelay/data` | `main` | Certrelay data directory (`CERTRELAY_DATA_DIR`) — anchors, peer state, sqlite. |
| `/data/bin/fabric` | `main` | The `fabric` CLI, copied from the certrelay image on each start so the gotty terminal (which has `/data/bin` on PATH) can resolve handles. | | `/data/bin/fabric` | `main` | The `fabric` CLI, copied from the certrelay image on each start so the gotty terminal (which has `/data/bin` on PATH) can resolve handles. |
| `/data/bin/monitor` | `main` | The `monitor` CLI, copied from the certrelay image on each start (file only — not run as a daemon). |
| `/data/support.pdf` | `main` | Workshop PDF served by nacho. Uploaded/replaced via the **Upload Support PDF** action. Missing until an upload has been performed. | | `/data/support.pdf` | `main` | Workshop PDF served by nacho. Uploaded/replaced via the **Upload Support PDF** action. Missing until an upload has been performed. |
| `/data/nacho/ignore_names.txt` | `main` | Comma-separated names hidden from the nacho UI (read at runtime). Created by the `nacho-setup` oneshot with the default (`fold,swifty`) on first start; managed by the **Configure Nacho** action. | | `/data/nacho/ignore_names.txt` | `main` | Comma-separated names hidden from the nacho UI (read at runtime). Created by the `nacho-setup` oneshot with the default (`fold,swifty`) on first start; managed by the **Configure Nacho** action. |
@@ -88,8 +89,9 @@ On the first install, StartOS:
default (`fold,swifty`) on first daemon start if it doesn't exist. default (`fold,swifty`) on first daemon start if it doesn't exist.
6. Launches `spaced` as a managed daemon (no `screen`, no shell auto-start) 6. Launches `spaced` as a managed daemon (no `screen`, no shell auto-start)
and the `gotty` web terminal once the bashrc oneshot completes. and the `gotty` web terminal once the bashrc oneshot completes.
7. Runs `certrelay-setup` (creates `/data/certrelay/data`, copies the `fabric` 7. Runs `certrelay-setup` (creates `/data/certrelay/data`, copies `fabric` and
CLI to `/data/bin/fabric`) and launches the **certrelay** daemon on 7778. `monitor` into `/data/bin/` as CLI files only) and launches the **certrelay**
daemon on 7778.
Certrelay is **always on**; its `CERTRELAY_SPACED_RPC_URL` uses the local Certrelay is **always on**; its `CERTRELAY_SPACED_RPC_URL` uses the local
spaced credentials from `store.spacedAuth`. Configure its self URL etc. via spaced credentials from `store.spacedAuth`. Configure its self URL etc. via
the **Configure Certrelay** action. the **Configure Certrelay** action.
@@ -108,6 +110,7 @@ mainnet-only.
| Bitcoin RPC username / password (registered on bitcoind) | Wallet creation, bidding, and registration -- all driven via `space-cli` inside the terminal | | Bitcoin RPC username / password (registered on bitcoind) | Wallet creation, bidding, and registration -- all driven via `space-cli` inside the terminal |
| Spaced RPC username / password (`SPACED_RPC_USER`/`SPACED_RPC_PASSWORD`) | `space-cli` flags and subcommands | | Spaced RPC username / password (`SPACED_RPC_USER`/`SPACED_RPC_PASSWORD`) | `space-cli` flags and subcommands |
| Subspaces auth toggle + credentials (`SUBS_BASIC_AUTH_USER`/`SUBS_BASIC_AUTH_PASSWORD`, off by default) | | | Subspaces auth toggle + credentials (`SUBS_BASIC_AUTH_USER`/`SUBS_BASIC_AUTH_PASSWORD`, off by default) | |
| `SUBS_PUBLISH_REQUIRE_FINALIZED` (off by default; via **Configure Subspaces**) | |
| Subspaces Prover auth toggle + credentials (`SUBS_PROVER_BASIC_AUTH_USER`/`SUBS_PROVER_BASIC_AUTH_PASSWORD`, off by default) | | | Subspaces Prover auth toggle + credentials (`SUBS_PROVER_BASIC_AUTH_USER`/`SUBS_PROVER_BASIC_AUTH_PASSWORD`, off by default) | |
| Chain selection (locked to `mainnet`) | | | Chain selection (locked to `mainnet`) | |
| Spaced data directory and RPC bind | | | Spaced data directory and RPC bind | |
@@ -142,6 +145,7 @@ mainnet-only.
| `disable-subspaces` | Disable Subspaces | Enabled (hidden when already off) | Any | Sets `store.enableSubspaces = false` and triggers a service restart so the subs and subs-prover daemons stop. On-disk data at `/data/subspaces` is preserved. | | `disable-subspaces` | Disable Subspaces | Enabled (hidden when already off) | Any | Sets `store.enableSubspaces = false` and triggers a service restart so the subs and subs-prover daemons stop. On-disk data at `/data/subspaces` is preserved. |
| `reset-subspaces-state` | Reset Subspaces State | Enabled | Any | Deletes `/data/subspaces` (runtime data only — binaries ship in the image). Use to wipe local handles/proofs. The spaces wallet on spaced is preserved. Warning-gated. | | `reset-subspaces-state` | Reset Subspaces State | Enabled | Any | Deletes `/data/subspaces` (runtime data only — binaries ship in the image). Use to wipe local handles/proofs. The spaces wallet on spaced is preserved. Warning-gated. |
| `set-subs-prover` | Enable / Disable Subspaces Prover | Enabled | Any | Toggle (`store.enableSubsProver`, default **off**) that starts/stops only the `subs-prover` daemon, independent of the overall Subspaces toggle. When off, the daemon doesn't start but its interface (8888) stays registered. Saving restarts the service. | | `set-subs-prover` | Enable / Disable Subspaces Prover | Enabled | Any | Toggle (`store.enableSubsProver`, default **off**) that starts/stops only the `subs-prover` daemon, independent of the overall Subspaces toggle. When off, the daemon doesn't start but its interface (8888) stays registered. Saving restarts the service. |
| `configure-subspaces` | Configure Subspaces | Enabled | Any | Toggle `SUBS_PUBLISH_REQUIRE_FINALIZED` (default **off**). When on, subs requires finalized commitments before certificate publish. Stored in `store.subsPublishRequireFinalized`; injected into the `subs` daemon env. Saving restarts the service. |
| `enable-subs-auth` | Enable Subspaces Auth | Enabled (hidden when already on) | Any | Sets `store.subsAuthEnabled = true`. If no credentials exist yet, generates `{ username: 'spaces', password: random32 }` and stores them in `store.subsAuth`. Restart re-launches `subs` with `SUBS_BASIC_AUTH_USER`/`SUBS_BASIC_AUTH_PASSWORD` env vars set. | | `enable-subs-auth` | Enable Subspaces Auth | Enabled (hidden when already on) | Any | Sets `store.subsAuthEnabled = true`. If no credentials exist yet, generates `{ username: 'spaces', password: random32 }` and stores them in `store.subsAuth`. Restart re-launches `subs` with `SUBS_BASIC_AUTH_USER`/`SUBS_BASIC_AUTH_PASSWORD` env vars set. |
| `disable-subs-auth` | Disable Subspaces Auth | Enabled (hidden when already off) | Any | Sets `store.subsAuthEnabled = false`. Stored credentials are preserved so a later re-enable does not regenerate them. Restart re-launches `subs` without the auth env vars. | | `disable-subs-auth` | Disable Subspaces Auth | Enabled (hidden when already off) | Any | Sets `store.subsAuthEnabled = false`. Stored credentials are preserved so a later re-enable does not regenerate them. Restart re-launches `subs` without the auth env vars. |
| `show-subs-credentials` | Show Subspaces Auth Credentials | Enabled | Any | Surfaces the current `SUBS_BASIC_AUTH_USER`/`SUBS_BASIC_AUTH_PASSWORD` (from `store.subsAuth`) plus a loopback connection URL. Reports whether auth is currently enforced. | | `show-subs-credentials` | Show Subspaces Auth Credentials | Enabled | Any | Surfaces the current `SUBS_BASIC_AUTH_USER`/`SUBS_BASIC_AUTH_PASSWORD` (from `store.subsAuth`) plus a loopback connection URL. Reports whether auth is currently enforced. |
@@ -207,8 +211,9 @@ the same idempotent init logic runs and reuses the existing credentials in
8. **Certrelay is always on.** It ships as the prebuilt 8. **Certrelay is always on.** It ships as the prebuilt
`horologger/certrelay:v0.2.3` image (static musl binaries) and runs on `horologger/certrelay:v0.2.3` image (static musl binaries) and runs on
7778 from service start. It talks to the local spaced over loopback using 7778 from service start. It talks to the local spaced over loopback using
the `store.spacedAuth` credentials. The bundled `fabric` CLI is copied to the `store.spacedAuth` credentials. The `fabric` and `monitor` binaries are copied to
`/data/bin/fabric` so it's runnable from the Space-CLI Web UI. **You must `/data/bin/` for manual use from the Space-CLI Web UI; neither is auto-started
(only the certrelay server runs as a managed daemon). **You must
set `CERTRELAY_SELF_URL`** (via **Configure Certrelay**) to the publicly set `CERTRELAY_SELF_URL`** (via **Configure Certrelay**) to the publicly
visible URL StartOS exposes for the Certrelay interface, or peers/clients visible URL StartOS exposes for the Certrelay interface, or peers/clients
won't be able to reach this relay at the advertised address. won't be able to reach this relay at the advertised address.
@@ -245,7 +250,7 @@ spaces balance
package_id: spaces package_id: spaces
upstream_version: subspacesplus upstream_version: subspacesplus
images: images:
spaces: docker.io/horologger/spaces:v0.0.9s spaces: docker.io/horologger/spaces:v0.0.9s(x)
subspaces: docker.io/horologger/subs:v0.1.2 subspaces: docker.io/horologger/subs:v0.1.2
certrelay: docker.io/horologger/certrelay:v0.2.3 certrelay: docker.io/horologger/certrelay:v0.2.3
nacho: docker.io/horologger/nacho:v1.0.0 nacho: docker.io/horologger/nacho:v1.0.0
@@ -299,6 +304,11 @@ subspaces:
env_vars: # injected only when subsAuthEnabled=true AND subsAuth!=null env_vars: # injected only when subsAuthEnabled=true AND subsAuth!=null
- SUBS_BASIC_AUTH_USER - SUBS_BASIC_AUTH_USER
- SUBS_BASIC_AUTH_PASSWORD - SUBS_BASIC_AUTH_PASSWORD
publish_require_finalized:
default: false
store_field: subsPublishRequireFinalized
env_var: SUBS_PUBLISH_REQUIRE_FINALIZED # always 'true' or 'false' on subs daemon
action: configure-subspaces
actions: actions:
- enable-subs-auth - enable-subs-auth
- disable-subs-auth - disable-subs-auth
@@ -322,6 +332,7 @@ certrelay:
image: horologger/certrelay:v0.2.3 # prebuilt; static musl binaries image: horologger/certrelay:v0.2.3 # prebuilt; static musl binaries
server_bin: /usr/local/bin/certrelay server_bin: /usr/local/bin/certrelay
fabric_bin: /usr/local/bin/fabric # copied to /data/bin/fabric for the CLI fabric_bin: /usr/local/bin/fabric # copied to /data/bin/fabric for the CLI
monitor_bin: /usr/local/bin/monitor # copied to /data/bin/monitor (CLI only; not started)
data_dir: /data/certrelay/data data_dir: /data/certrelay/data
port: 7778 port: 7778
spaced_rpc_creds: from store.spacedAuth (local spaced) spaced_rpc_creds: from store.spacedAuth (local spaced)
@@ -361,6 +372,7 @@ actions:
- enable-subspaces - enable-subspaces
- disable-subspaces - disable-subspaces
- set-subs-prover - set-subs-prover
- configure-subspaces
- enable-subs-auth - enable-subs-auth
- disable-subs-auth - disable-subs-auth
- show-subs-credentials - show-subs-credentials
+65
View File
@@ -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,
}
},
)
+2
View File
@@ -1,6 +1,7 @@
import { sdk } from '../sdk' import { sdk } from '../sdk'
import { configureCertrelay } from './configureCertrelay' import { configureCertrelay } from './configureCertrelay'
import { configureNacho } from './configureNacho' import { configureNacho } from './configureNacho'
import { configureSubspaces } from './configureSubspaces'
import { disableSubsAuth } from './disableSubsAuth' import { disableSubsAuth } from './disableSubsAuth'
import { disableSubsProverAuth } from './disableSubsProverAuth' import { disableSubsProverAuth } from './disableSubsProverAuth'
import { disableSubspaces } from './disableSubspaces' import { disableSubspaces } from './disableSubspaces'
@@ -48,4 +49,5 @@ export const actions = sdk.Actions.of()
.addAction(resetSubspacesState) .addAction(resetSubspacesState)
.addAction(configureCertrelay) .addAction(configureCertrelay)
.addAction(configureNacho) .addAction(configureNacho)
.addAction(configureSubspaces)
.addAction(uploadSupportPdf) .addAction(uploadSupportPdf)
+1
View File
@@ -39,6 +39,7 @@ const shape = z.object({
certrelayBootstrap: z.boolean().nullable().catch(null), certrelayBootstrap: z.boolean().nullable().catch(null),
certrelayHealthcheckHandle: z.string().nullable().catch(null), certrelayHealthcheckHandle: z.string().nullable().catch(null),
nachoWorkshopPdfLinkText: z.string().nullable().catch(null), nachoWorkshopPdfLinkText: z.string().nullable().catch(null),
subsPublishRequireFinalized: z.boolean().nullable().catch(null),
}) })
export const storeJson = FileHelper.json( export const storeJson = FileHelper.json(
+10
View File
@@ -289,6 +289,16 @@ const dict = {
205, 205,
'Subspaces Prover Auth credentials saved. Auth is currently DISABLED — enable it with "Enable Subspaces Prover Auth" to enforce these credentials.': 'Subspaces Prover Auth credentials saved. Auth is currently DISABLED — enable it with "Enable Subspaces Prover Auth" to enforce these credentials.':
206, 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 } as const
/** /**
+11 -3
View File
@@ -16,6 +16,8 @@ import {
CERTRELAY_DIR, CERTRELAY_DIR,
CERTRELAY_FABRIC_BIN, CERTRELAY_FABRIC_BIN,
CERTRELAY_FABRIC_DEST, CERTRELAY_FABRIC_DEST,
CERTRELAY_MONITOR_BIN,
CERTRELAY_MONITOR_DEST,
CERTRELAY_PORT, CERTRELAY_PORT,
CERTRELAY_REMOTE_IP_HEADER, CERTRELAY_REMOTE_IP_HEADER,
dataDir, dataDir,
@@ -147,6 +149,8 @@ export const main = sdk.setupMain(async ({ effects }) => {
SUBS_SPACED_RPC_PASSWORD: spacedAuth.password, SUBS_SPACED_RPC_PASSWORD: spacedAuth.password,
SUBS_PROVER_ENDPOINT: `http://127.0.0.1:${SUBSPACES_PROVER_PORT}`, SUBS_PROVER_ENDPOINT: `http://127.0.0.1:${SUBSPACES_PROVER_PORT}`,
SUBS_REGISTRY_ENDPOINT: `http://127.0.0.1:${SUBSPACES_REGISTRY_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, HOME: SUBSPACES_DATA_DIR,
RUST_LOG: 'subs=info,subs_prover=info,registry_server=info', RUST_LOG: 'subs=info,subs_prover=info,registry_server=info',
...subsAuthEnv, ...subsAuthEnv,
@@ -256,7 +260,7 @@ export const main = sdk.setupMain(async ({ effects }) => {
'spaced is managed by StartOS — do not run it manually.', 'spaced is managed by StartOS — do not run it manually.',
'Use the `spaces` alias to call space-cli, e.g.', 'Use the `spaces` alias to call space-cli, e.g.',
' spaces getserverinfo', ' 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/', '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 // Appends the always-on certrelay chain (setup oneshot + certrelay daemon) to
// any existing chain. certrelay serves cryptographic proofs binding handles 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 // owner keys anchored to Bitcoin. The certrelay-setup oneshot copies `fabric`
// the gotty terminal (which has /data/bin on PATH) can resolve handles. // 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 => const withCertrelay = (chain: any): any =>
chain chain
.addOneshot('certrelay-setup', { .addOneshot('certrelay-setup', {
@@ -280,6 +285,9 @@ export const main = sdk.setupMain(async ({ effects }) => {
echo "certrelay-setup: installing fabric CLI to ${CERTRELAY_FABRIC_DEST}..."; \ echo "certrelay-setup: installing fabric CLI to ${CERTRELAY_FABRIC_DEST}..."; \
cp -f ${CERTRELAY_FABRIC_BIN} ${CERTRELAY_FABRIC_DEST}; \ cp -f ${CERTRELAY_FABRIC_BIN} ${CERTRELAY_FABRIC_DEST}; \
chmod +x ${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."`, echo "certrelay-setup: done."`,
], ],
user: 'root', user: 'root',
+1 -1
View File
@@ -14,7 +14,7 @@ export const manifest = setupManifest({
volumes: ['main'], volumes: ['main'],
images: { images: {
spaces: { spaces: {
source: { dockerTag: 'horologger/spaces:v0.0.9s' }, source: { dockerTag: 'horologger/spaces:v0.0.9x' },
arch: ['x86_64', 'aarch64'], arch: ['x86_64', 'aarch64'],
}, },
subspaces: { subspaces: {
+5 -3
View File
@@ -34,12 +34,14 @@ export const SUBSPACES_PROVER_PORT = 8888
export const SUBSPACES_REGISTRY_PORT = 8081 export const SUBSPACES_REGISTRY_PORT = 8081
export const SUBSPACES_WALLET = 'default' export const SUBSPACES_WALLET = 'default'
// Certrelay ships as the prebuilt horologger/certrelay image; both binaries // Certrelay ships as the prebuilt horologger/certrelay image; CLI binaries
// are static musl, so `fabric` runs anywhere once copied onto the volume. // are static musl, so they run anywhere once copied onto the volume.
export const CERTRELAY_BIN = '/usr/local/bin/certrelay' export const CERTRELAY_BIN = '/usr/local/bin/certrelay'
export const CERTRELAY_FABRIC_BIN = '/usr/local/bin/fabric' 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_FABRIC_DEST = '/data/bin/fabric'
export const CERTRELAY_MONITOR_DEST = '/data/bin/monitor'
export const CERTRELAY_DIR = '/data/certrelay' export const CERTRELAY_DIR = '/data/certrelay'
export const CERTRELAY_DATA_DIR = '/data/certrelay/data' export const CERTRELAY_DATA_DIR = '/data/certrelay/data'
export const CERTRELAY_PORT = 7778 export const CERTRELAY_PORT = 7778
+2 -2
View File
@@ -1,7 +1,7 @@
import { VersionGraph } from '@start9labs/start-sdk' 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({ export const versionGraph = VersionGraph.of({
current: v_0_1_1_2, current: v_0_1_1_3,
other: [], other: [],
}) })
-37
View File
@@ -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,
},
})
+13
View File
@@ -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,
},
})