180 lines
30 KiB
Markdown
180 lines
30 KiB
Markdown
# Package: bare-os-booter
|
||
|
||
Former **DOCUMENTATION.md** §§12.1–12.9 plus **§12.7a** (REPL completion). [Reference index →](README.md)
|
||
|
||
## 12. Package: `bare-os-booter`
|
||
|
||
### 12.1 [packages/bare-os-booter/package.json](../../packages/bare-os-booter/package.json)
|
||
|
||
**Resolved hyperstack (hoisted root lockfile, illustrative):** after **`npm install`** at the repo root, **`node_modules/protomux`** and **`node_modules/hyperswarm`** versions are pinned in **`package-lock.json`** and guarded by **`packages/bare-os-booter/test.runtime.js`** (**`fixtures/protomux-hyperswarm-lock.json`**, `**schema` 2** metadata row). Intentional upgrades require bumping that fixture alongside the lockfile.
|
||
|
||
**Hyperbee guest hints:** **`ctx.bareOsHyperbeeGuestHint()`** (when **`BARE_OS_HYPERBEE_GUEST_INDEX`** is set) returns read-only JSON aligned with optional **[hyperbee2](https://github.com/holepunchto/hyperbee2)**-style guest indexes — see [ADR-hyperbee-guest-index.md](../architecture/ADR-hyperbee-guest-index.md); the stock kernel does not import Hyperbee by default.
|
||
|
||
- `main` — `./index.js`
|
||
- `scripts.start` / `dev` — `bare index.js`
|
||
- `scripts.test` — `brittle-bare test.identity.js` then `node --require ./scripts/bare-node-test-shim.cjs … brittle-node test.js` (shim supplies a chainable **`Bare.on`**, stubs **`bare-thread`** / **`bare-worker`** even when ESM resolves them by absolute path, Bare-style `bare-type` binding + Node `util.inspect` stand-in for `bare-inspect`; `openssl` / `ssh-keygen` delegates lazy-load `bare-crypto` so the main suite does not import native addons at startup)
|
||
- `dependencies` — Same hyperstack as seeder + `bare-os-protocol` + `bare-crypto` (identity account + vault AEAD) + **`@qvac/sdk`** (local QVAC LLM for `/bin/agent`; lean `qvac.config.json` = llamacpp completion only). Set **`BARE_OS_SKIP_QVAC=1`** or pack with **`--skip-qvac`** to stub natives. Bridge: **`ctx.bareOsQvacAvailable` / `Status` / `LoadModel` / `UnloadModel` / `Complete`** ([`lib/bare-os-qvac-host.mjs`](../../packages/bare-os-booter/lib/services/bare-os-qvac-host.mjs)); pack graph via [`bare-os-qvac-pack-anchor.mjs`](../../packages/bare-os-booter/lib/services/bare-os-qvac-pack-anchor.mjs). Models download on first agent use (not seeded in the system image).
|
||
- `devDependencies` — `brittle`
|
||
- `imports` — **`#host-fs`** / **`#host-path`** resolve to **`bare-fs`** / **`bare-path`** under Bare and Node’s built-in **`fs`** / **`path`** under the default condition (package **`imports`** cannot target **`node:`** URLs). First-party sources import **`#host-*`** only (CI forbids bare **`from 'fs'`** / **`from 'path'`**). **`url`** maps to **`bare-url`** / **`node:url`**. `**#bare-os-boot-manifest-sig`** selects Bare vs Node Ed25519 verify helper.
|
||
- `pear.stage.ignore` — Includes `test.js`, `test.identity.js`, `.test-data` so tests are not staged
|
||
|
||
**Pear + npm workspaces:** dependencies are hoisted to the repo root; Pear’s dev bundle often does not follow a single symlinked `node_modules` tree. **[scripts/ensure-pear-node-modules.mjs](../../scripts/ensure-pear-node-modules.mjs)** (run from the repo root) rebuilds `packages/bare-os-booter/node_modules` by symlinking **each top-level** package from the root `node_modules` (matching npm’s flat hoist). **`pear.stage.include`** lists **`node_modules`** so the staged Hyperdrive uses **`node_modules/<pkg>`** paths (Bare **`require('bare-node-net')`** and similar resolve correctly; **`../../node_modules`** alone did not). For **`bare-ssh2`**, **`bare-net`** (Bare TCP) and the **`bare-node-*`** shims it loads are direct **`dependencies`** of the booter so versions match the vendored **`bare-ssh2`** tree and Pear staging always sees them. **`npm run os:booter`** runs the script before `pear run`. After `npm install` at the root, re-run the script if hoisted packages change.
|
||
|
||
### 12.2 [packages/bare-os-booter/lib/host/paths.js](../../packages/bare-os-booter/lib/host/paths.js)
|
||
|
||
- **`packageRootDir(metaUrl)`** — Same as seeder (Pear RTI / `swapDir` / `cwd`).
|
||
- **`defaultBootCorestorePath`** / **`defaultLocalSeedCorestorePath`** — `BARE_OS_BOOT_STORE` / `BARE_OS_LOCAL_SEED`, or under **`hostDataRoot()`** (`BARE_OS_HOST_DATA` or `~/.bare-os`): `corestore/booter` and `corestore/seeder` respectively. Same signature stability as the seeder helper.
|
||
|
||
### 12.2a Boot modularity (loader, capabilities, lifecycle)
|
||
|
||
- **[`lib/bare-os-kernel-loader.js`](../../packages/bare-os-booter/lib/boot/bare-os-kernel-loader.js)** — **`loadOsFromPeers`**, **`loadOsFromOfflineLkg`**: seed capability handshake + optional RPC wave, MBR read, system Hyperdrive open/replicate, `/boot/init.js` fetch, personal drive mount (when not lazy). Invoked from `index.js` inside the boot timeout race.
|
||
- **[`lib/bare-os-capability-registry.js`](../../packages/bare-os-booter/lib/security/bare-os-capability-registry.js)** — **`KERNEL_CAPABILITY_SEED_STRICT_ROWS`**, **`buildStockKernelCapabilityWords`**, **`freezeKernelCapabilityWordsFromCapabilities`**: single place for stock capability word math used by the booter and loader.
|
||
- **[`lib/bare-os-lifecycle-manager.js`](../../packages/bare-os-booter/lib/host/bare-os-lifecycle-manager.js)** — **`exitHostProcess`**, **`teardownBareOsBootResources`**: `Bare.exit` deferral and ordered HDMS → swarm → drives → Corestore teardown (Pear heap safety).
|
||
- **[`lib/bare-os-posix-errno.js`](../../packages/bare-os-booter/lib/posix/bare-os-posix-errno.js)** — POSIX-inspired errno names used by syscall / `/proc` JSON surfaces.
|
||
|
||
See also [Kernel subsystem map](../architecture/kernel-subsystems.md) and [ADR 0001](../adr/0001-kernel-subsystem-boundaries.md).
|
||
|
||
### 12.2b Corestore / swarm suspend–resume bridge
|
||
|
||
- **[`lib/corestore-host-lifecycle.js`](../../packages/bare-os-booter/lib/host/corestore-host-lifecycle.js)** — Registers one-shot hooks so guest **`ctx.bareOsRegisterSuspendHook`** / **`bareOsRegisterResumeHook`** call host **`corestore`** / **`hyperswarm`** `**suspend()**` / `**resume()**` when those methods exist (mobile sleep, Pear lifecycle). **Corestore 7.12+** no longer flushes on **`suspend()`**; the hook **`flush()`**es open sessions first. Host stores are constructed with **[`lib/corestore-opts.js`](../../packages/bare-os-booter/lib/host/corestore-opts.js)** **`treeCache`** (`maxSize: 8192`). **Non-goal (stock booter):** automatic **`corestore-snapshot`** / frozen peer images from the guest — operators replicate Hyperdrives via swarm + personal-drive export of keys when needed; **`bareOsCorestoreSnapshotOperatorHint`** in **`/proc`** is an advisory field only (no guest RPC that invokes **`corestore-snapshot`**).
|
||
|
||
### 12.3 [packages/bare-os-booter/index.js](../../packages/bare-os-booter/index.js)
|
||
|
||
**Imports** — Hyperswarm, Protomux, protocol, `./lib/p2p/swarm-disk.js`, `./lib/boot/kernel-runner.js`, `./lib/boot/bare-os-kernel-loader.js`, `./lib/security/bare-os-capability-registry.js`, `./lib/host/bare-os-lifecycle-manager.js`, `./lib/vfs/vfs.js`, `./lib/shell/shell.js`, `./lib/host/paths.js`, `./lib/tools/bare-os-ipc.js`, `./lib/ctx/bare-os-runtime-caps.js`, stdio/readline/repl/boot-splash helpers, `./lib/identity/identity-session.js`.
|
||
|
||
**`bootStorePath()`** — `defaultBootCorestorePath(_pkg, import.meta.url)`.
|
||
|
||
**`createReadLine()`**
|
||
|
||
- If `BARE_OS_SKIP_REPL === '1'`: returns `async () => null`.
|
||
- Else prefers **fish-style** / **`bare-readline`** raw TTY editing when stdin is a TTY; falls back to a stream line reader (no **`node:readline`** in the stock boot path).
|
||
- On failure: warns and returns `async () => null`.
|
||
|
||
**`executeKernel(disk, store, swarm, initSource)`** (`store`/`swarm` unused but kept for signature symmetry / future use)
|
||
|
||
- Builds `shellEnv` with **guest** defaults: `USER`/`LOGNAME`=`guest`, `HOME`/`PWD`=`/home/guest`, `UID`/`GID`=`65534`, `BARE_OS_IDENTITY=guest`, `BARE_OS_EXIT_STATUS`=`0`, `BARE_OS_CTX_API_VERSION`, `PATH=/bin`, `SHELL`, `HOSTNAME`, `0`. When the host sets any of the keys listed under “host → session passthrough” in [Environment variables and POSIX appendix](environment-and-posix-appendix.md#14-environment-variables-complete-list), those values are copied into `shellEnv`. Sets **`BARE_OS_BOOT_PROFILE_RESOLVED`** from **`BARE_OS_BOOT_PROFILE`** or the first line of **`/etc/bare-os/profile`**, and **`BARE_OS_SESSION_ID`** (random UUID). Seeds **`/run/bare-os/boot.json`** fields **`imageDigest`**, **`pearChannel`**, **`pearRelease`** from **`BARE_OS_IMAGE_DIGEST`**, **`BARE_OS_PEAR_CHANNEL`** / **`PEAR_CHANNEL`**, **`BARE_OS_PEAR_RELEASE`** when present.
|
||
- **`createBareOsIpc({ maxFifoBytes, maxChannels?, perChannelMaxBytes?, ipcRpcToken?, enableFanout?, maxJsonRpcLineBytes?, posixMqDefaultMaxmsg?, posixMqDefaultMaxBytes?, posixMqMaxmsgCeiling? })`** ([`bare-os-ipc.js`](../../packages/bare-os-booter/lib/tools/bare-os-ipc.js)) — FIFOs under **`/run/bare-os/ipc/<name>`**; optional per-name byte caps from **`BARE_OS_IPC_CHANNEL_MAX_BYTES`**; optional global channel cap **`BARE_OS_IPC_MAX_CHANNELS`** (host passthrough); POSIX MQ defaults from **`BARE_OS_POSIX_MQ_MAX_MSGS`** / **`BARE_OS_POSIX_MQ_MSG_BYTES`**; JSON-RPC with optional token and line cap; fan-out `**fanoutPublish`/`fanoutSubscribe**`; **`stats`** includes fan-out counts, quota telemetry, and operator backpressure snapshots when caps expose **`features.ipcFanout`**.
|
||
- **`createVfs(drive, personalDrive, shellEnv, vfsMountRef, vfsOptions)`** → `ctx.vfs` (same `env` object as `ctx.env`). **`vfsOptions`** supply **`procSnapshot`**, dynamic **`/proc/*`** and **`/sys/*`** text (quotas JSON, **`bare_os_features`** with **`bits`**–**`bits5`** when advertised, **`bare_os_net_summary`**, **`bare_os_host_os`**, **`bare_os_sync_window`**, **`bare_os_debug`**, net/disk stubs, session stats), **`bootProfileText`**, **`sessionText`**, **`initdRunText`**, **`bootReadyJsonText`**, mount map for **`/proc/mounts`**, **`bootStartedMs`** for **`/proc/uptime`**, etc. Exposes **`vfs.watch(logicalPath)`** for Hyperdrive-backed paths when **`BARE_OS_VFS_WATCH`** is not **`0`**. Operator blind-relay sketches (**`blind_relay_router`**, **`blind_pairing_sketch`**, **`relay_geo_hint`**) return **schema 1** JSON with **`operatorRedacted: true`** until the host sets **`BARE_OS_PROC_BLIND_PEER_RELAY_HINTS`**. **`kernel-runner`**: when **`BARE_OS_BARE_SUBPROCESS_BRIDGE`** is set, **`BARE_OS_BARE_SUBPROCESS_TIMEOUT_MS`** can default **`runBin`** timeouts.
|
||
- **`applyGuestEnv(ctx)`** then **`ensureGuestHome(ctx)`** — normalizes `ctx.identity` and seeds `/.bare/` (and a guest marker) on the personal drive.
|
||
- **`createReadLine()`** always resolves stdio first and returns `stdout` (may be `null`) alongside `readLine` so the kernel can write to the **same** stream as the REPL (including `bare-stdio` under Pear).
|
||
- Builds `ctx`: **`bareOsCtxApiVersion`** (from [`bare-os-ctx-api.js`](../../packages/bare-os-booter/lib/ctx/bare-os-ctx-api.js)), **`bareOsRuntimeCaps`** (frozen snapshot from [`bare-os-runtime-caps.js`](../../packages/bare-os-booter/lib/ctx/bare-os-runtime-caps.js): pipeline limits, **`quotas`**, pseudo path list, feature flags such as **`vfsWatch`**, **`ipcRpcJson`**, **`initdSocketActivation`**), **`bareOsIpc`**, `disk`, `drive`, `personalDrive`, `vfs`, `env`, `console`, `b4a`, `topic: topicKey()`, `readLine`, **`writeScreen(str)`**, **`bareOsSubscribeBootEvent`** / **`bareOsEmitBootEvent`**, **`bareOsSubscribeHdmsLifecycle`**, **`bareOsAwaitInitdUnits`**, **`bareOsPublishBootReady`**, `execLine` → wraps **`execShellLine`** with optional **audit** (**`BARE_OS_AUDIT`**, **`BARE_OS_AUDIT_JSON`**, redaction), `**execLine` depth cap** (**`BARE_OS_EXEC_MAX_DEPTH`**), then the shell (returns `'ok'` or `'exit'`; updates **`BARE_OS_EXIT_STATUS`** in **`vfs.env`**; bare **`exit`** line sets status then **`requestBooterExit`**), `**runBinCommand(argv)**` → delegates to `**runBinCommand(this, argv)`** from `kernel-runner.js` (for `/bin/time` and similar), plus identity hooks for `/bin` and builtins:
|
||
- **`applyUnlock(passphrase)`** — load `/.bare/account`, decrypt, unlock session.
|
||
- **`applyRegister(passphrase)`** — create account file, unlock.
|
||
- **`applyLogin({ publicKey, secretKey })`** — set session from an already-decoded keypair.
|
||
- **`applyLogout({ save? })`** — optional **`save`** runs encrypted vault snapshot first (see `identity-session.js`).
|
||
- **`saveVault()`** — encrypt personal-drive files into `/.bare/vault/` (skips `/.bare`, `bin`, `boot`, history paths).
|
||
- **`registerKernelShutdownHook(fn)`** — register async/sync teardown before **`stopBareInitd`** when the REPL session cleans up.
|
||
- After **`createKernelReplSession`**: wires **`readLine`**, **`console`**, **`execLine`**, **`suspendReplForSubprocess`** / **`resumeReplAfterSubprocess`**, attaches **`ctx.tui`** / **`ctx.sdk`** (omit with **`BARE_OS_TUI=0`**; image source **`/lib/bare-os/tui.js`**), then **`await startBareInitd(ctx)`** (stock units include **`kernel-logger`**, **`bare-os-www`** — loopback static HTTP for **`~/.www`** — **`bare-holesail`** (managed **`~/.holesail/state.json`**: **`seed`**, **`key`**, stock **`bare-www-*`** / **`bare-ssh-*`** rows), **`bare-cron`**, **`bare-openssh`**, **`bare-os-chat`** when enabled, …).
|
||
- Sets **`disk.os`** **after initd** with **`createBareOsDiskOsBridge`** (**`searchLocal`** with optional path manifest, whitelisted **`execRpc`** / **`bare_os.*`**, **`disk_os_hints`** schema **3**, **`replication_operator_sketch`** schema **7**, cap-gated **`replication_operator_intent`** when **`BARE_OS_DISK_OS_OPERATOR_INTENT_RPC=1`**) — peers use **`SwarmDisk`** messages **3–6**; see [`bare-os-disk-os-bridge.js`](../../packages/bare-os-booter/lib/host/bare-os-disk-os-bridge.js) and §12.4.
|
||
- **`ctx.bareOsHrpcRequest`** (stock) — validates **`service`**, **`method`**, object **`payload`**; optional **`BARE_OS_HRPC_ALLOWLIST_JSON`**; built-in routes **`kernel.ping`**, **`kernel.capabilities`**, **`vfs.readText`**, **`bare_os.echo`**, **`bare_os.disk_os_hints`**, **`bare_os.search_local`**, **`bare_os.replication_operator_sketch`**, **`bare_os.replication_snapshot`**, **`bare_os.pkg_index_get`** (`**BARE_OS_HRPC_ROUTE_TABLE_SCHEMA_VERSION` 3**). **`BARE_OS_HRPC_EMIT_UNLISTED`** forwards unknown routes to **`process.emit('bare-os:hrpc-request', …)`** on Node when enabled.
|
||
- `try { await runKernelFromSource(...) } finally { await session.cleanup() }` — cleanup runs **`bareInitdShutdownActiveUnitsReverse`**, **`runKernelShutdownHooks`**, **`stopBareInitd`**, fish TTY teardown.
|
||
|
||
**`boot-splash.js`** — TTY splash (disabled when `stdout` is not a TTY or `BARE_OS_NO_SPLASH=1`): initial full-screen clear and hidden cursor, then centered redraws from the top-left without erasing the whole screen each tick (reduces flicker); one full clear again if the terminal is resized. Vertically and horizontally centered “card” (Unicode box frame when wide enough; compact rules on very narrow widths). On very wide terminals the framed card (and progress bar) width is capped so the bar does not span the entire display. Layout scales with `stdout.columns` / `stdout.rows` (sensible fallbacks): more log lines on tall terminals (capped), word-wrapped phase text, ANSI-safe centering. **`createBootSplash(stdout, { bootLimitMs?, tagline?, footerLines? })`** — optional **`tagline`** and dim **`footerLines`**; `**main()`** passes booter and protocol package versions. Braille spinner, elapsed boot timer, bar vs `BARE_OS_BOOT_TIMEOUT_MS` (default 60s), shimmer title. `prepareForKernel()` stops the splash ticker, clears again, and shows the cursor before the fish shell; `fail()` centers a wrapped error message.
|
||
|
||
**`loadOsFromPeers(disk, store, swarm, splash)`** (network boot path used by **`main()`**)
|
||
|
||
- Optional pre-MBR **`disk.rpc('bare_os', 'capabilities', …)`** when peers exist and **`BARE_OS_SEED_RPC_HANDSHAKE`** is not **`0`**/**`false`**; result stored on **`disk.seedCapabilityInfo`**; **`BARE_OS_SEED_CAP_STRICT`** / **`BARE_OS_SEED_CAP_FAIL`** tighten failure behavior.
|
||
- **`disk.read(0)`** → **`parseMbr`**.
|
||
- Stores boot provenance as **`disk.mbrKeysHex`** and **`disk.bootMbr512`** (exact 512-byte copy) for later peer-assist eligibility.
|
||
- For each MBR key: `Hyperdrive(store, driveKey)`, `ready()`, replicate on all `disk.peers`’ mux streams, join drive discovery, `findingPeers` + `swarm.flush`, poll up to 30×200ms for `/boot/init.js`.
|
||
- On success: `initPersonalDrive`, `splash.prepareForKernel()`, `executeKernel`.
|
||
|
||
Peer-assist helper path: [`lib/bare-os-peer-system-seed.js`](../../packages/bare-os-booter/lib/p2p/bare-os-peer-system-seed.js) computes **`peerSystemSeedMirror`** eligibility and builds snapshot mirrors with **`buildPeerSeedSnapshots`** (including **`mbr_layout`** from **`seedMbrLayout`**). When eligible, `index.js` writes **`bootMbr512`** into **`localRAM`** and serves mirrored **`bare_os.*`** RPC responses through **`disk.os`** for cold joiners.
|
||
|
||
**`main()`**
|
||
|
||
- `resolveStdio()` → `createBootSplash`, `splash.start()` (initial clear).
|
||
- `Corestore(bootStorePath())`, `Hyperswarm`, `SwarmDisk`, join `topicKey()`.
|
||
- Wait until `disk.peers.size > 0` or **`BARE_OS_BOOT_TIMEOUT_MS`** elapses (default **60000**). There is **no local seed fallback**; without peers, boot fails.
|
||
- `Promise.race` between `loadOsFromPeers` and the remaining time within the same deadline so the whole network boot finishes within the limit.
|
||
- **`finally`**: `swarm.destroy()` first, then close drives and `store` (each in try/catch).
|
||
- **`exitHostProcess`**: `Bare.exit` or `process.exit`.
|
||
|
||
**Entry**: `main().catch(…)`.
|
||
|
||
### 12.4 [packages/bare-os-booter/lib/p2p/swarm-disk.js](../../packages/bare-os-booter/lib/p2p/swarm-disk.js)
|
||
|
||
**`SwarmDisk` class**
|
||
|
||
**State:** `localRAM`, `peers` (Set of `{ chan, mux, socket, id }`), `pendingReads`, `pendingSearches`, `pendingRpc`, counters, `drive`, `personalDrive`, `os`, **`seedCapabilityInfo`** (last **`bare_os.capabilities`** handshake or error object), **`mbrKeysHex`** (MBR-derived key list), **`bootMbr512`** (boot-time 512-byte copy), **`seedMbrLayout`** (optional `bare_os.mbr_layout` snapshot), and **`peerSystemSeedActive`** (helper mirroring active).
|
||
|
||
**`initPersonalDrive(store, swarm, Hyperdrive)`**
|
||
|
||
- `store.namespace('bare-os-personal-v1')`, new `Hyperdrive(localStore)`, ensure writable, structured host log (see **`emitSwarmDiskHostLog`** — stderr JSON when **`BARE_OS_BOOT_TRACE=json|ndjson`**, else stderr / `console.warn`), `swarm.join(personalDrive.discoveryKey)`.
|
||
|
||
**`addPeer(mux, socket)`**
|
||
|
||
- Builds `context` with `onread` / `ondata` / `ongossip` / `onsearchreq` / `onsearchres` / `onrpcreq` / `onrpcres` wired to Protomux messages **0–6** (same order as seeder + hyper-os style): read request, data, gossip buffer, search req/res, RPC req/res.
|
||
- `chan.open()`, track peer, handshake-based `peer.id`, remove peer on `mux.stream` `close`.
|
||
- If `this.drive` / `this.personalDrive` set, `replicate(mux.stream, { live: true, download: true })` for system drive.
|
||
|
||
**`read(index)`**
|
||
|
||
- If `localRAM.has(index)`, return cached.
|
||
- Else broadcast message 0 to all peers, single consumer callback from message 1, **60s** timeout.
|
||
|
||
**`search(query)`**
|
||
|
||
- Fan-out message 3 to all peers with a **single correlation id** per `search()` call. **`pendingSearches`** holds an aggregate state: each peer response appends matches until all peers have answered or a **3s** timeout fires, then the map entry is cleared. Concurrent searches use distinct ids (`searchIdCounter`), so operations do not overwrite each other’s callbacks.
|
||
|
||
**`rpc(module, method, args?, timeoutMs?)`**
|
||
|
||
- Sends message **5** to the **first** peer in **`peers`**; awaits message **6**; parses **`result`** as JSON when possible. Used for the pre-boot **`bare_os.capabilities`** handshake and operator tooling.
|
||
|
||
### 12.5 [packages/bare-os-booter/lib/boot/kernel-runner.js](../../packages/bare-os-booter/lib/boot/kernel-runner.js)
|
||
|
||
- **`AsyncFunction`** = `Object.getPrototypeOf(async function () {}).constructor`.
|
||
|
||
**`runKernelFromSource(source, ctx)`**
|
||
|
||
- `new AsyncFunction('ctx', source + guard + 'return start(ctx)')` where guard checks `typeof start === 'function'`.
|
||
|
||
**`runBinCommand(ctx, argv)`**
|
||
|
||
- **Host delegates first** — [`host-delegate-registry.js`](../../packages/bare-os-booter/lib/host/host-delegate-registry.js) registers **`git`**, **`curl`**, **`wget`**, **`openssl`**, **`ssh-keygen`**, **`tar`**, **`systemctl`** / **`bare-initctl`** / **`journalctl`**, **`warc`**, **`archive`** (ustar front-end), **`hrpc`**, **`bundlebee`**, **`sidecar`**, and **`pear-runtime-matrix`** via [`host-bridge-cli.js`](../../packages/bare-os-booter/lib/host/host-bridge-cli.js), with **static** imports (Pear-safe). Each delegate checks **`BARE_OS_DELEGATE_ALLOW`**; denied kinds exit **126**. **`curl`** and **`wget`** are Fetch-based subsets (not libcurl / full GNU wget); **`/bin/curl`** and **`/bin/wget`** on the image call **`ctx.bareOsRunCurlCli`** / **`ctx.bareOsRunWgetCli`** when present—see [HTTP: curl and wget](http-curl-and-wget.md). **`/bin/systemctl`** and **`/bin/journalctl`** call **`ctx.bareOsRunSystemctlCli`** when present (same backend as the host delegate). **Host bridge CLIs:** **`hrpc probe`** prints **`bareOsHrpcAllowlistProbe()`** (optional **`BARE_OS_HRPC_ALLOWLIST_JSON`**); **`hrpc request`** always calls **`ctx.bareOsHrpcRequest`** (stock handler supports validated built-in routes such as `kernel.ping`, `kernel.capabilities`, `vfs.readText`; host overrides remain supported and `BARE_OS_HRPC_BRIDGE_WIRED=1` still advertises host bridge capability). **`bundlebee hint`** emits **`bare-os:bundlebee-cli`**; **`bundlebee status`** prints **`BARE_OS_BUNDLEBEE_STAGE_JSON`**. **`sidecar cap <class>`** calls **`bareOsSidecarResourceCap`**. **`pear-runtime-matrix`** prints **`bareOsPearRuntimeMatrixProbe()`** (optional **`BARE_OS_PEAR_RUNTIME_MATRIX_JSON`**). **`BARE_OS_SIDECAR_BRIDGE_WIRED`** / **`BARE_OS_BUNDLEBEE_CLI_WIRED`** are advertised via **`bareOsHostCapability`** for operator probes.
|
||
- If **`argv[0]`** is **`git`** (or a POSIX path whose basename is `git`, but not `./git` or `../git`), **delegates** to **`runGitCli`** in [`git-cli.js`](../../packages/bare-os-booter/lib/tools/git-cli.js).
|
||
- If **`argv[0]`** is **`curl`** under the same basename rules, **delegates** to **`runCurlCli`** in [`curl-cli.js`](../../packages/bare-os-booter/lib/tools/curl-cli.js).
|
||
- If **`argv[0]`** is **`wget`** under the same basename rules, **delegates** to **`runWgetCli`** in [`wget-cli.js`](../../packages/bare-os-booter/lib/tools/wget-cli.js).
|
||
- If `argv[0]` contains `/`, resolves with `ctx.vfs.resolveLogical`, `route`, loads script bytes from the routed Hyperdrive (`get` with `follow`).
|
||
- Else walks `$PATH` (`ctx.vfs.env.PATH`, default `/bin`), joining each directory with `unix-path-resolve(dir, cmd)` (not three-argument resolve), loads from **system** `ctx.drive` only.
|
||
- Builds `AsyncFunction('ctx','argv', ...)` with the script source plus `if (typeof run === 'function') await run(ctx, argv)` (top-level statements run first; optional `run` matches `/bin` utilities).
|
||
- Unknown command: `ctx.console.log('unknown command: ...')`.
|
||
|
||
**`resolveBinInPath(ctx, name)`** — returns the first **`PATH`** hit on the system drive (absolute `/bin/...` path string) or **`null`**; used by shell **`command -v`** / **`type`**.
|
||
|
||
### 12.6 [packages/bare-os-booter/lib/vfs/vfs.js](../../packages/bare-os-booter/lib/vfs/vfs.js)
|
||
|
||
**`createVfs(systemDrive, personalDrive, env, mntRef?, vfsOptions?)`**
|
||
|
||
- **Logical paths** under `$HOME` (booter default `/home/guest`; after `login`, `/home/<pubkey-prefix>`) map to the **personal** Hyperdrive under `/.bare-os/home/<basename>/…`; **`/var/log`** and **`/tmp`** map to **`/.bare-os/var/log/…`** and **`/.bare-os/tmp/…`** with the same basename. Read-only synthetic **`/proc`** and **`/sys`** (optional **`vfsOptions`** for version/cmdline, quotas JSON, net/disk stubs, **`/run/bare-os/*`** text providers, mount map, union policy, seed handshake, virtual registry, etc.). Optional union read overlays via env **`BARE_OS_VFS_UNION_PREFIXES`**; optional **`BARE_OS_VFS_UNION_WRITE_DENY`** blocks writes under those prefixes. All other absolute paths use the **system** drive (read-mostly OS image).
|
||
- **`resolveLogical(p)`** — `unix-path-resolve(cwd, p)` so cwd + relative segments work (the `unix-path-resolve` package only accepts two path arguments).
|
||
- **API**: `getcwd`, `chdir` (rejects regular files), `readFile`, `writeFile` / `unlink` (personal only), `exists`, `readdir`, `stat` / `lstat`, `readlink`, `symlink`, `chmod`, `mkdir` (recursive via `.bareos_empty` marker), `rmdir` (empty dirs; marker-aware), `rm` (recursive tree walk), `route`, `resolveLogical`, `env`, **`watch(logicalPath)`** (Hyperdrive-backed paths only; throws on pseudo **`/proc`**/`**/sys**`/`**/run`**/**`/dev`** and on virtual `**$HOME**`, **`/var`**, **`/mnt`** roots).
|
||
- **Hyperdrive quirk**: `entry` / `get` / `exists` use `std(path, false)` and **throw** on path `'/'` (`Invalid filename: /`). The VFS special-cases drive path `'/'` (logical `/` and personal `$HOME` root) for `chdir`, `stat`, `exists`, `isRegularFile`, and blocks `readFile`/`put`/`del` on that key.
|
||
- **Bare / Pear**: do not rely on global `TextEncoder` / `TextDecoder` in booter `lib/*.js`; this tree uses **`b4a`** for UTF-8 where needed (pseudo `/proc` content, symlink size in `vfs-posix-meta.js`, `systemctl` log tailing, etc.).
|
||
|
||
### 12.7 [packages/bare-os-booter/lib/shell/shell.js](../../packages/bare-os-booter/lib/shell/shell.js)
|
||
|
||
- **`defaultShellAliases`** — includes `ll`, `la`, `l`, `..`, `...` as the baseline merged from **`~/.barerc`**.
|
||
- **`tokenize` / `expandWord` / `parsePipeline`** — POSIX-ish words, `'...'`, `"..."`, `\`, `|`, `||`, `&&`, `;`, `>`, `>>`, `<`; `$VAR` and `${VAR}`; pipelines split on `|`; **`;`** splits lists; **`&&`** / **`||`** short-circuit using **`ctx.exitCode`** (left-associative).
|
||
- **`execShellLine(ctx, line)`** — semicolon-separated lists, then per segment AND-OR chains of pipelines; leading `NAME=value` assignments (blocked for `ctx.shellReadonlyVars`), redirections, builtins `alias`, **`barerc`** (`barerc reload` re-parses `~/.barerc` and reapplies theme), `unalias`, `cd`, `export`, `unset`, `readonly`, `umask`, `:`, `command`, `type`, `login`, `logout`, `exit`, **`jobs`**, **`fg`**, **`wait`**, else `runBinCommand`. Optional **`BARE_OS_SHELL_CMDSUBST`** enables bounded **`$(…)`**; optional **`BARE_OS_SHELL_STREAMING`** / **`BARE_OS_SHELL_STREAMING_MULT`** relax pipeline capture caps. Trailing `**&`** at list depth runs prior segments in the **background** (async jobs table). `command -v`/`-V` and `type` use **`resolveBinInPath`**. `login`/`logout` call the same `ctx.applyRegister` / `ctx.applyUnlock` / `ctx.applyLogout` hooks as `/bin/login` and `/bin/logout`. Captures `console.log` for pipes and file redirection; `>` / `>>` target paths via `ctx.vfs.writeFile` (personal tree). Returns `'exit'` when the `exit` builtin runs. After each completed line (except empty input), **`syncBareOsExitStatusEnv`** writes **`ctx.exitCode`** to **`vfs.env.BARE_OS_EXIT_STATUS`**; **`expandWord`** maps `**$?**` / `**${?}`** to that value.
|
||
- **`listBareOsShellBuiltins(env)`** — stable list of builtin names for highlighting and completion parity (includes optional **`read`** when **`BARE_OS_SHELL_READ_BUILTIN`** is set).
|
||
|
||
### 12.7a REPL line editor and completion
|
||
|
||
Narrative reference: **[Shell completion and REPL editor](shell-completion-and-repl-editor.md)**.
|
||
|
||
- **[`lib/repl-session.js`](../../packages/bare-os-booter/lib/cli/repl-session.js)** — **`createKernelReplSession`**: chooses Fish-style **`createFishReadLine`** when `**BARE_OS_FISH` ≠ `0**`, TTY raw mode works, and **`BARE_OS_SKIP_REPL`** is off; wires **`ctx.console`** / **`ctx.readLine`** / **`writeScreen`** to the same stdout as the prompt.
|
||
- **[`lib/fish-readline.js`](../../packages/bare-os-booter/lib/cli/fish-readline.js)** — History file on the personal drive, ghost suggestions, reverse search, **Tab** menu or inline cycling (**`BARE_OS_COMPACT_MENU`** / narrow columns), **Ctrl+Space** man preview, **save/restore cursor** + erase-to-EOS so menu redraws do not stack stale lines.
|
||
- **[`lib/completion-engine.js`](../../packages/bare-os-booter/lib/cli/completion-engine.js)** — **`parseCompletionContext`**, **`gatherCompletionItems`**, **`completeLine`**, **`rankCompletionItems`**, **`suggestGhostFromHistory`**, VFS timeouts, **`/share/man/man.json`** cache, **`ctx.bareOsRegisterCompleter`** registry.
|
||
|
||
### 12.8 [packages/bare-os-booter/lib/identity/identity-account.js](../../packages/bare-os-booter/lib/identity/identity-account.js)
|
||
|
||
- On-disk **`/.bare/account` (v2)**: magic `BAREOS01`, version `2`, 32-byte Ed25519 public key (bare-crypto), 16-byte PBKDF2 salt, 4-byte iteration count (big-endian), ChaCha20-Poly1305 seal of the 64-byte Ed25519 private key material (nonce + ciphertext + tag). Passphrase stretching: **PBKDF2-SHA256** (`210000` iterations by default). **v1** (libsodium) files are rejected with a message to run `login --new`.
|
||
- **`encodeAccount` / `decodeAccount` / `encodeNewAccount**`, `**sealBytes` / `openBytes**`, **`vaultKeyFromSecret`**, **`hashUtf8Path`** — shared by `identity-session.js` (vault snapshots use the same AEAD).
|
||
|
||
### 12.9 [packages/bare-os-booter/lib/identity/identity-session.js](../../packages/bare-os-booter/lib/identity/identity-session.js)
|
||
|
||
- **`applyGuestEnv` / `applyUnlockedEnv`** — set `ctx.vfs.env` (`BARE_OS_PUBLIC_KEY`, `BARE_OS_IDENTITY`, `USER`, `HOME`, derived `UID`/`GID` from pubkey hash for logged-in users) and `vfs.chdir` to the new home. **`applyUnlockedEnv`** calls **`loadBarerc`** after unlock (**`createSkeletonIfMissing: true`** on first login) so **`~/.barerc`** applies without restarting the session. Both paths call **`bareOsResetShellIdentityState`** (clear simulated **`shellBackgroundJobs`**), **`syncVfsIdentitySession`** (**`vfs.bareOsIdentitySession`**, warm-cache invalidation, **`ctx.bareOsInvalidateWarmReadCaches('identity-switch')`** when present), optional **`ctx.bareOsReloadFishHistoryForIdentity`** (fish readline), optional **`scrubGuestWorkspaces`** when `**BARE_OS_GUEST_SCRUB=1`**.
|
||
- **`migrateLegacyPersonalHomeIfNeeded`** — lifts legacy flat **`/`** personal-drive entries into the active **`/.bare-os/home/<segment>/…`** once per segment; records **`/.bare-os/migration/legacy-root-v1.json`**. **Guest** skips when **`/.bare/account`** exists unless **`BARE_OS_PERSONAL_ROOT_MIGRATE=guest`**. **`BARE_OS_PERSONAL_ROOT_MIGRATE=skip`** disables all lifts; **`unlocked-only`** skips guest lifts.
|
||
- **`registerIdentity` / `unlockIdentity` / `logoutIdentity` / `saveVaultToDrive`** — personal Hyperdrive persistence and encrypted vault index under `/.bare/vault/`. **`saveVaultToDrive`** skips other **`bare-os/acct/…`** subtrees when **`BARE_OS_PERSONAL_ACCT_PREFIX`** is on so vault export does not bundle sibling accounts.
|