@toon-protocol/townhouse 0.1.0-rc5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -0
- package/dist/{chunk-IB6TNCUQ.js → chunk-4WCMVIO4.js} +3922 -473
- package/dist/chunk-4WCMVIO4.js.map +1 -0
- package/dist/chunk-GQNBZJ6F.js +39 -0
- package/dist/chunk-GQNBZJ6F.js.map +1 -0
- package/dist/{chunk-UTFWPLTB.js → chunk-I2R4CRUX.js} +2 -22
- package/dist/chunk-I2R4CRUX.js.map +1 -0
- package/dist/chunk-JCOFMUPL.js +65 -0
- package/dist/chunk-JCOFMUPL.js.map +1 -0
- package/dist/cli.d.ts +94 -2
- package/dist/cli.js +3115 -111
- package/dist/cli.js.map +1 -1
- package/dist/compose/townhouse-dev.yml +1 -1
- package/dist/compose/townhouse-hs.yml +126 -19
- package/dist/{demo-MJR47QHZ.js → demo-3DWRDMYY.js} +3 -2
- package/dist/{demo-MJR47QHZ.js.map → demo-3DWRDMYY.js.map} +1 -1
- package/dist/image-manifest.json +12 -12
- package/dist/index.d.ts +1258 -659
- package/dist/index.js +36 -140
- package/dist/index.js.map +1 -1
- package/dist/manager-SsneW_Mj.d.ts +519 -0
- package/dist/rsa-from-seed-VMNLNDZM.js +62 -0
- package/dist/rsa-from-seed-VMNLNDZM.js.map +1 -0
- package/dist/tui-OIFXGBTL.js +625 -0
- package/dist/tui-OIFXGBTL.js.map +1 -0
- package/package.json +18 -2
- package/dist/chunk-IB6TNCUQ.js.map +0 -1
- package/dist/chunk-UTFWPLTB.js.map +0 -1
package/README.md
CHANGED
|
@@ -230,6 +230,119 @@ The package-local `packages/townhouse/compose/townhouse-dev.yml` is the canonica
|
|
|
230
230
|
|
|
231
231
|
For backward compatibility, `docker-compose-townhouse-dev.yml` at the repo root is preserved and continues to be used by `scripts/townhouse-dev-infra.sh`. A follow-up story will route the script through the package-local copy.
|
|
232
232
|
|
|
233
|
+
## DockerOrchestrator Profiles
|
|
234
|
+
|
|
235
|
+
The `DockerOrchestrator` class drives both the contributor dev stack and
|
|
236
|
+
the operator HS-mode apex stack via a single `profile: 'dev' | 'hs'`
|
|
237
|
+
parameter:
|
|
238
|
+
|
|
239
|
+
- **`profile: 'dev'`** (default) — uses `dockerode` for fine-grained
|
|
240
|
+
programmatic control. Matches the lifecycle the existing `townhouse up`
|
|
241
|
+
CLI has shipped since Epic 21. No `composePath` required.
|
|
242
|
+
- **`profile: 'hs'`** — shells out to `docker compose -f <composePath> up -d`
|
|
243
|
+
with `--profile <type>` flags for each enabled peer. Waits on the
|
|
244
|
+
connector's `GET /admin/hs-hostname` endpoint (connector v3.5.0+) until
|
|
245
|
+
the `.anyone` hostname is published. Requires `composePath` (typically
|
|
246
|
+
the path returned by `materializeComposeTemplate('hs')`).
|
|
247
|
+
|
|
248
|
+
Example (HS-mode caller, as Story 45.4's `townhouse hs up` will use):
|
|
249
|
+
```typescript
|
|
250
|
+
import { materializeComposeTemplate, DockerOrchestrator } from '@toon-protocol/townhouse';
|
|
251
|
+
import Docker from 'dockerode';
|
|
252
|
+
|
|
253
|
+
const { composePath } = materializeComposeTemplate('hs');
|
|
254
|
+
const docker = new Docker();
|
|
255
|
+
const orch = new DockerOrchestrator(docker, config, walletManager, {
|
|
256
|
+
profile: 'hs',
|
|
257
|
+
composePath,
|
|
258
|
+
});
|
|
259
|
+
await orch.up([]); // apex-only (connector + townhouse-api)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Connector Anon Requirement (HS Profile)
|
|
263
|
+
|
|
264
|
+
The HS profile's readiness gate calls `GET /admin/hs-hostname`. The
|
|
265
|
+
connector container MUST be configured with `anon.enabled: true` —
|
|
266
|
+
if anon is disabled, the endpoint returns 503 and the orchestrator
|
|
267
|
+
throws `OrchestratorError("connector is anon-disabled — set
|
|
268
|
+
anon.enabled: true in the connector config")`. Story 45.4's
|
|
269
|
+
`townhouse hs up` generates the connector config with `anon.enabled: true`
|
|
270
|
+
by default; manual configurations should mirror that setting.
|
|
271
|
+
|
|
272
|
+
## HS Mode (Apex Install)
|
|
273
|
+
|
|
274
|
+
`townhouse hs up` is the one-command install for homelab operators. It boots the
|
|
275
|
+
apex stack (connector + townhouse-api) and publishes a `.anyone` hidden-service
|
|
276
|
+
address, writing the address to `~/.townhouse/host.json` as the final step.
|
|
277
|
+
|
|
278
|
+
### First-run flow
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
npx @toon-protocol/townhouse init # initialise config + wallet (one-time)
|
|
282
|
+
npx @toon-protocol/townhouse hs up # boot apex — prints "Apex live at <hostname>.anyone"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
On a cold image cache the command takes up to 5 minutes (image pull + anon
|
|
286
|
+
bootstrap). On subsequent runs with a warm cache, the HS bootstrap phase
|
|
287
|
+
(30–90 s) dominates.
|
|
288
|
+
|
|
289
|
+
### Files written by `hs up`
|
|
290
|
+
|
|
291
|
+
| File | Mode | Purpose |
|
|
292
|
+
|------|------|---------|
|
|
293
|
+
| `~/.townhouse/config.yaml` | 0o600 | Townhouse config (written by `init`) |
|
|
294
|
+
| `~/.townhouse/wallet.enc` | 0o600 | Encrypted BIP-39 wallet (written by `init`) |
|
|
295
|
+
| `~/.townhouse/compose/townhouse-hs.yml` | 0o600 | Materialised HS compose template |
|
|
296
|
+
| `~/.townhouse/image-manifest.json` | 0o600 | Digest-pinned image manifest |
|
|
297
|
+
| `~/.townhouse/connector.yaml` | 0o600 | Connector config with `anon.enabled: true` |
|
|
298
|
+
| `~/.townhouse/host.json` | 0o600 | Published hostname + metadata |
|
|
299
|
+
|
|
300
|
+
`host.json` schema:
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"hostname": "<onion>.anyone",
|
|
304
|
+
"publishedAt": "<ISO-8601>",
|
|
305
|
+
"connectorAdminUrl": "http://127.0.0.1:9401",
|
|
306
|
+
"townhouseApiUrl": "http://127.0.0.1:28090",
|
|
307
|
+
"writtenAt": "<ISO-8601>"
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Idempotent re-run
|
|
312
|
+
|
|
313
|
+
Re-running `townhouse hs up` against an already-running apex detects the
|
|
314
|
+
running connector, re-prints the hostname, and exits 0 without pulling images
|
|
315
|
+
or restarting containers. `~/.townhouse/host.json` is refreshed.
|
|
316
|
+
|
|
317
|
+
### `hs down` vs. `hs down --rotate-keys`
|
|
318
|
+
|
|
319
|
+
| Command | Volumes | `host.json` | Next `hs up` |
|
|
320
|
+
|---------|---------|-------------|--------------|
|
|
321
|
+
| `townhouse hs down` | **Preserved** (`townhouse-hs-anon`) | Kept | **Same** `.anyone` address |
|
|
322
|
+
| `townhouse hs down --rotate-keys` | **Deleted** | Deleted | **New** `.anyone` address |
|
|
323
|
+
|
|
324
|
+
`--rotate-keys` prompts for confirmation when stdin is a TTY. When stdin is not
|
|
325
|
+
a TTY (CI, scripted), it proceeds without prompting.
|
|
326
|
+
|
|
327
|
+
### Password sourcing
|
|
328
|
+
|
|
329
|
+
Resolution order:
|
|
330
|
+
1. `--password <pw>` flag
|
|
331
|
+
2. `TOWNHOUSE_WALLET_PASSWORD` environment variable
|
|
332
|
+
3. Interactive prompt (only when `process.stdin.isTTY === true`)
|
|
333
|
+
4. Exit 1 with an error message (non-interactive, no password provided)
|
|
334
|
+
|
|
335
|
+
### Failure-state copy (UX-DR5)
|
|
336
|
+
|
|
337
|
+
| Class | Detection | Next step shown |
|
|
338
|
+
|-------|-----------|-----------------|
|
|
339
|
+
| anon-timeout | `HS hostname publication timeout` in error | `Re-run with DEBUG=townhouse:*` |
|
|
340
|
+
| anon-disabled | `anon-disabled (HTTP 503)` from probe | Edit `connector.yaml`, set `anon.enabled: true` |
|
|
341
|
+
| image-pull-failure | `failed to pull` / `pull access denied` in stderr | Check your network |
|
|
342
|
+
| port-collision | `address already in use` / `port is already allocated` in stderr | Stop the conflicting service |
|
|
343
|
+
| missing-docker-sock | `Cannot connect to the Docker daemon` / `docker CLI not found` | Start Docker |
|
|
344
|
+
| generic | Any other error | `Run with DEBUG=townhouse:*` |
|
|
345
|
+
|
|
233
346
|
## Running the townhouse as a hidden service (laptop)
|
|
234
347
|
|
|
235
348
|
`docker-compose-townhouse-hs.yml` brings up the full operator stack —
|
|
@@ -384,3 +497,7 @@ but the connector at 3.3.x reads a discriminated union keyed on `type`
|
|
|
384
497
|
defaulting to direct — operators toggling ATOR got direct traffic anyway.
|
|
385
498
|
The current generator emits the correct `type: 'socks5'` shape with
|
|
386
499
|
`externalUrl`, `managed`, and `managedOptions` per the connector contract.
|
|
500
|
+
|
|
501
|
+
## Notes
|
|
502
|
+
|
|
503
|
+
`townhouse status --units=sats` exists as an undocumented power-user flag for Bitcoin-native operators. It converts the earnings block to integer sats using a CLI-supplied rate (`--rate <sats-per-usdc>`) or the `TOWNHOUSE_SATS_PER_USDC` environment variable; if neither is set, the command exits 1. There is no built-in price oracle — this is intentionally a manual conversion. USDC remains the canonical denomination across every other Townhouse surface (TUI hero band, drill subcommands like `townhouse peer` and `townhouse channels`); this flag is absent from `townhouse --help` per design decision D44-002.
|