Files
bare-operating-system/developer-guide/11-kernel-pear-cookbook.md
T
2026-05-27 00:00:13 +00:00

79 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 units `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`.
### ~1GiB 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`** (**512MiB**), **`BARE_OS_PIPELINE_MAX_LINES`** (**2M**) 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 **512MiB** / **2M** 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-drivestyle 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'`).