79 lines
11 KiB
Markdown
79 lines
11 KiB
Markdown
# Chapter 11 — Kernel extensions and Pear workflows
|
||
|
||
This chapter ties the Hyperdrive-resident kernel ([`kernel/init.js`](../kernel/init.js)), [`ctx`](./02-the-context-object.md), and Pear/Bare distribution patterns together.
|
||
|
||
## Boot composition
|
||
|
||
1. **Stock phases** — `os-release`, `motd`, optional `rc.profile.*`, `rc`, `rc.d`, `rc.local`, `kernel.d`, banner, `onboot` (non-interactive), optional self-test.
|
||
2. **Strict boot** — `BARE_OS_BOOT_STRICT=1` stops on first `execLine` error in trusted snippets.
|
||
3. **Allowlist** — `BARE_OS_BOOT_ALLOWLIST=1` plus [`/etc/bare-os/boot.allow`](../kernel/etc/bare-os/boot.allow.example) restricts the first word of each line in those snippets (builtins like `export` and `cd` stay allowed).
|
||
|
||
## Init, timers, and sockets
|
||
|
||
- **bare-initd** — User drop-ins under `~/.config/bare-os/units/<name>.unit` support `SocketActivationIpc=<fifo>`; the unit’s `start` runs after the first byte is read on that logical FIFO under `/run/bare-os/ipc/…`. Optional `IdleSec=N` (with `stop`) stops the unit after N seconds without further IPC traffic; optional fragments `~/.config/bare-os/units.d/<name>/*.conf` merge before `~/.config/bare-init/units/` overrides. `ReadinessPath=` may be `exec:<execLine>` for a bounded readiness gate. **`ConditionPathExists=`** skips start when a VFS path is missing; **`AssertPathExists=`** fails the unit when missing (systemd-like, bounded absolute paths). **`ConditionPathIsDirectory=`** / **`AssertPathIsDirectory=`** do the same for directories (via **`vfs.lstat`**). Inspect the live DAG at **`/proc/bare_os/initd_graph.json`** (same payload as **`initd_dag.json`**, optional **`dot`** field).
|
||
- **bare-os-www** — Stock initd serves **`GET`/`HEAD**` from `**~/.www`** on **`127.0.0.1:8088`** by default; **`bare-holesail`** starts after it so managed **`bare-www-<port>`** rows reach the listener. **`bare-openssh`** adds **`bare-ssh-<port>`** to the same **`~/.holesail/state.json`** ( **`seed`** / **`key`** persistence); if sshd starts before **`bare-holesail`**, **`startBareUserSessionStack`** re-runs ensure after holesail is up. Handbook [ch.4 § bare-os-www](../handbook/04-the-booter-runtime.md#bare-os-www-static-http-for-www), § **bare-holesail**, § **bare-openssh**.
|
||
- **Timers** — Files in `~/.config/bare-os/timers/*.timer` (max **8**) with a `[Timer]` section: either `OnCalendar=` (five cron fields) + `ExecLine=` on the same minute tick as `~/.crontab`, or `EveryMs=` (**1000**–**86400000**) + `ExecLine=` on a fixed `setInterval`, or **`OnInactiveSec=`** to run after the last timer-triggered finish plus an idle gap (one-shot or repeating; **`Persistent=`** keeps state across sessions where implemented). Optional `JitterSec=` spreads the first (or periodic) `execLine` within **0…N** seconds. Copy from `/etc/bare-os/timers/*.timer.example` on the system image when present.
|
||
- **System cron** — Optional image file `/etc/bare-os/crontab` (see [crontab.example](../kernel/etc/bare-os/crontab.example)) is merged with user crontab entries. Lines may use `@reboot` + command (once per `bare-cron` start) and optional `JitterSec=N` prefix on the command for calendar lines.
|
||
|
||
## P2P lab cookbook
|
||
|
||
Use this flow for deterministic local swarm experiments without touching production lanes:
|
||
|
||
1. Run `npm run test:integration` for a seeder→booter smoke on temporary Corestores.
|
||
2. For explicit testnet bootstrap, set `BARE_OS_INTEGRATION_TESTNET=1` and `BARE_OS_INTEGRATION_TESTNET_BOOTSTRAP=<host:port,...>` before step 1.
|
||
3. For manual two-terminal bring-up, run `npm run os:seeder` and `npm run os:booter` with isolated `BARE_OS_HOST_DATA`, `BARE_OS_SEED_STORE`, and `BARE_OS_BOOT_STORE`.
|
||
4. For network isolation, set `HYPERSWARM_BOOTSTRAP` to dedicated lab nodes only.
|
||
5. Validate runtime state from `/proc/bare_os/replication`, `/proc/bare_os/swarm`, `/proc/bare_os/boot.json`, and `/run/bare-os/boot-perf.json`.
|
||
6. For mirror-drive experiments, generate host env hints with `node scripts/mirror-drive-experiment.mjs --source-key <64hex> --mirror-key <64hex> --aux <n>`.
|
||
|
||
## Observability
|
||
|
||
- **`ctx.bareOsSubscribeBootEvent`** — Same structured events as `BARE_OS_BOOT_TRACE=ndjson` (phase, ms, sessionId); the booter also emits **`booter:*`** phases (**`vfs`**, **`ctx`**, **`repl`**, **`initd`**, **`kernel_invoke`**).
|
||
- **`/proc/bare_os_quotas`** — Pipeline limits, `BARE_OS_EXEC_MAX_DEPTH`, IPC caps, session stats.
|
||
- **`/proc/bare_os_resources`** / **`ctx.bareOsGetResourceStatus()`** — Unified snapshot for operators.
|
||
- **`/proc/bare_os_features`** — Documented kernel-feature words **`bits`**, **`bits2`**, **`bits3`**, **`bits4`**, **`bits5`** (see `bare-os-protocol` exports).
|
||
- **`/proc/bare_os/net_summary.json`** — Coalesced swarm / seed RPC hints for operators (topic, peer count, staging slot, replication queue, snapshot / firewall stats when present).
|
||
- **`ctx.vfs.watch(path)`** — Hyperdrive-backed watch when `BARE_OS_VFS_WATCH` is not `0`; returns `{ watcher, destroy, … }`. With `BARE_OS_VFS_WATCH_PSEUDO=1`, may watch coalesced `/proc/bare_os/metrics_live.json`.
|
||
|
||
### ~1 GiB host RAM (pipeline / swarm / IPC)
|
||
|
||
Set these on the **Pear/Bare host** process before boot (the booter merges them into guest `vfs.env`; Hyperswarm reads swarm caps from the host environment at process start).
|
||
|
||
| Goal | Variables |
|
||
| --- | --- |
|
||
| Large pipeline bursts (`yes \| head …`, big `find`/`ls`) | Stock booter defaults **`BARE_OS_SHELL_STREAMING=1`**, **`BARE_OS_SHELL_STREAMING_MULT=2`**, **`BARE_OS_PIPELINE_MAX_BYTES`** (**512 MiB**), **`BARE_OS_PIPELINE_MAX_LINES`** (**2 M**) when unset on the host. Override with **`BARE_OS_PIPELINE_MAX_STAGES`**, **`BARE_OS_STREAMING_MULTIPLIER`** (alias for **`BARE_OS_SHELL_STREAMING_MULT`**). Absolute ceilings default to **512 MiB** / **2 M** lines (`BARE_OS_PIPELINE_ABS_MAX_BYTES` / `_LINES`). |
|
||
| Swarm | `BARE_OS_SWARM_MAX_PEERS`, `BARE_OS_SWARM_MAX_CLIENT_CONNECTIONS`, `BARE_OS_SWARM_MAX_SERVER_CONNECTIONS`, `BARE_OS_SWARM_MAX_PARALLEL` → Hyperswarm ctor. |
|
||
| FIFOs / POSIX MQ | `BARE_OS_IPC_MAX_CHANNELS`; `BARE_OS_POSIX_MQ_MAX_MSGS`, `BARE_OS_POSIX_MQ_MSG_BYTES` (defaults for `mq_open` when attrs omitted). |
|
||
| FD hint for scripts | `BARE_OS_VFS_MAX_OPEN` → mirrored as `RLIMIT_NOFILE` in **`/proc/bare_os/rlimits.json`**. |
|
||
| Long sessions / cron-style `execLine` wall budget | `BARE_OS_EXEC_LINE_BUDGET_MS` or alias `BARE_OS_TIMER_BUDGET_MS`. |
|
||
| OTL-style JSON lines | `BARE_OS_TELEMETRY_OTEL_JSONL=/abs/path` or shorthand `BARE_OS_TELEMETRY_OTEL=1` → **`/var/log/bare-os/otel.jsonl`**. |
|
||
|
||
**Verify after boot:** **`/proc/bare_os/capabilities.json`** (`ctxApiVersion`, pipeline caps), **`/proc/bare_os_resources`**, **`/proc/bare_os/rlimits.json`**. **`ctxApiVersion`** only changes with a booter/protocol bump, not with env tuning.
|
||
|
||
Storage write limits use existing hooks (**`BARE_OS_VFS_QUOTA_*`**, **`BARE_OS_HOST_STORAGE_JSON`**, **`BARE_OS_BARE_STORAGE_QUOTA_JSON`** on bare-storage paths)—there is no separate `BARE_OS_STORAGE_QUOTA_BYTES` knob.
|
||
|
||
## Pear / Git / HTTP
|
||
|
||
- **Guest Pear apps** — Author, release, install, and launch Pear apps entirely in the shell: see **[Guest Pear and App Store workflow](../docs/guides/guest-pear-and-appstore-workflow.md)** (`/bin/pear`, `/bin/appstore`). Host **`pear run pear://…`** remains for full Pear desktop/runtime on a Pear-capable machine.
|
||
- **Mirror-drive hints** — `ctx.bareOsEmitMirrorDriveHint({ label?, key? })` emits `bare-os:mirror-drive-hint` on Node-style hosts for mirror-drive–style workflows (labels/keys only; trust boundaries unchanged).
|
||
- **Release metadata** — Host can set `BARE_OS_PEAR_CHANNEL`, `BARE_OS_PEAR_RELEASE`, and `BARE_OS_IMAGE_DIGEST`; they appear in `/run/bare-os/boot.json`.
|
||
- **`ctx.bareOsRequestPearReload()`** — Returns hints and env strings; the host `**pear-runtime` / `pear-runtime-updater**` must perform any real reload. A successful host reload can swap the Pear **booter** bundle so a new **`bare-module-manifest.data.mjs`** (from **`npm run sync:bare-manifest`** at staging time) takes effect; **`ctx.bareOsRequestPearReload`** does not rewrite **`ctx.bare`** in-process—expect a new guest boot for an updated host import list. Drive-only edits to **`/lib/bare/bare-module-manifest.json`** still merge bundles from the image without re-staging Pear.
|
||
- **`ctx.bareOsPearUpdaterDelegate()`** (async, `**bareOsCtxApiVersion` 1.32.0+**) — Surfaces non-secret updater state without bundling **`pear-runtime-updater`** in the stock booter. Host options: set **`BARE_OS_PEAR_UPDATER_SNAPSHOT_JSON`** to a JSON string for a fixed operator snapshot, or **`BARE_OS_PEAR_UPDATER_MODULE`** to an ESM URL/path whose default export (or **`getPearUpdaterState`** / **`bareOsPearUpdaterSnapshot`**) is an **`async function`** returning a plain object (for example **`{ version, updating, updated }`** mirroring your **`PearRuntimeUpdater`** instance). See [`bare-os-pear-updater-bridge.js`](../packages/bare-os-booter/lib/bare-os-pear-updater-bridge.js).
|
||
|
||
### System revision and initd (OTA-friendly ordering)
|
||
|
||
Host env **`BARE_OS_SYSTEM_REVISION_ID`**, **`BARE_OS_SYSTEM_REVISION_PENDING`**, and **`BARE_OS_SYSTEM_SLOT`** surface as **`ctx.bareOsSystemRevision`** and in **`/proc/bare_os/provenance`**. For Pear OTA flows, gate user units on pending work: e.g. **`ConditionPathExists=`** on a host-written marker file, or **`After=`** a unit whose **`ReadinessPath=`** checks **`/proc/bare_os/provenance`** JSON (parse in a small **`exec:`** gate). Combine with `**ctx.bareOsRequestPearReload()`** so the host applies the new bundle before initd restarts dependents.
|
||
- **`git-pear`** — `/bin/git-pear help` documents Git-in-Pear (`gip-transport`, `gip-remote`, `git+pear://` remotes).
|
||
- **HTTP** — Delegated **`curl`** / **`wget`** resolve **`fetch`** via **`ctx.httpFetch`** (policy-wrapped when the booter supplies it), then **`ctx.bare.fetch`** from host **`BARE_OS_BARE_MODULES`** and drive **`/lib/bare/bundles`**, then **`globalThis.fetch`**. **`ensureBareFetchGlobals`** may install **`bare-fetch`** or **`bare-https`** when no native fetch exists. **`BARE_OS_HTTP_ALLOWLIST`**, **`BARE_OS_HTTP_DENYLIST`**, **`BARE_OS_DNS_ALLOWLIST`**, and **`BARE_OS_TLS_PIN_SHA256`** (and **`init.bareOsCurlTls`** for **`curl`**) narrow outbound access. Canonical doc: [HTTP: curl and wget](../docs/reference/http-curl-and-wget.md).
|
||
- **SSH (`bare-openssh`)** — The stock booter loads **`bare-ssh2`** from the workspace package **`bare-os-openssh`** (vendored upstream under **`vendor/bare-ssh2`**). Initd starts **`bare-openssh`** automatically unless disabled. **`npm run build -w bare-os-openssh`** stages **`/bin/sshd`**, **`/etc/ssh/sshd_config`**, and merged man pages into **`kernel/`** and the seeder mirror. Implementation: [`packages/bare-os-booter/lib/bare-openssh.js`](../packages/bare-os-booter/lib/bare-openssh.js). Host **`BARE_OS_SSH_LISTEN_PORT`** and **`BARE_OS_SSH_BIND_ALL`** are copied into guest **`vfs.env`** when set on the host.
|
||
|
||
## Building the image
|
||
|
||
- From the repo root, rebuild staged `/bin` utilities: `node packages/bare-os-coreutils/build.mjs`.
|
||
- Keep [`kernel/`](../kernel/) and [`packages/bare-os-seeder/kernel/`](../packages/bare-os-seeder/kernel/) identical (`node scripts/verify-kernel-seeder-parity.mjs`).
|
||
- Pear staging: use **`pear-build`** / app manifests in your Pear project; align `pear.json` channels with `BARE_OS_PEAR_*` env vars on the boot host.
|
||
|
||
## HDMS hooks
|
||
|
||
Use **`ctx.bareOsSubscribeHdmsLifecycle`** to run logic when extra drives mount after unlock (`kind: 'activate'`, `labels`) or before guest teardown (`kind: 'deactivate'`).
|