Docs+handbook
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# Chapter 1 — Introduction: what “Bare OS” is
|
||||
|
||||
If you have only a minute: **Bare operating system** is a tiny **Unix-flavored environment** whose root filesystem is a **Hyperdrive** replicated from peers. A **seeder** publishes that drive and a **512-byte MBR** over **Hyperswarm**; a **booter** joins the swarm, downloads the image, mounts a **second** Hyperdrive for **per-user mutable state**, and runs JavaScript “kernel” and `/bin` scripts inside a **Bare** or **Node** runtime.
|
||||
|
||||
The rest of this chapter sets vocabulary straight—without it, the architecture diagrams in [Chapter 2](02-blueprints.md) will not stick.
|
||||
|
||||
---
|
||||
|
||||
## The problem this project explores
|
||||
|
||||
Traditional OS images live on block devices or tarball layers. Here, the **image is a Merkle tree** you can **address by key** and **replicate live**. Peers do not hand you a `.iso`; they help you **fill in** the same Hyperdrive from the same discovery key.
|
||||
|
||||
That raises three design questions this repo answers in code:
|
||||
|
||||
1. **Discovery** — How does a fresh node find _someone_ who has block 0 (the MBR) and the drive root?
|
||||
2. **Separation of concerns** — What is **immutable-ish OS** vs **mutable per-device home**?
|
||||
3. **Execution model** — What runs in the host process vs what is “inside” the simulated POSIX surface?
|
||||
|
||||
Bare OS picks: **one swarm topic** for the project, **Protomux** channels for control + replication, **two Hyperdrives** (system + personal), and **AsyncFunction-loaded JS** for kernel and utilities.
|
||||
|
||||
---
|
||||
|
||||
## Key vocabulary
|
||||
|
||||
| Term | Meaning here |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------- |
|
||||
| **System drive** | Hyperdrive containing `/boot/init.js`, `/bin`, `/etc` — replicated from the seeder image |
|
||||
| **Personal drive** | Separate Hyperdrive (Corestore namespace) for `$HOME`, `/.bare`, cron, logs |
|
||||
| **MBR** | 512 bytes: magic `BIOS` + embedded Hyperdrive **public keys** (primary + optional failover) |
|
||||
| **Kernel** | `/boot/init.js` — `async function start(ctx)`; not a microkernel, a **session loop** |
|
||||
| **/bin** | Small JS programs (`async function run(ctx, argv)`) built from **bare-os-coreutils** |
|
||||
| **VFS** | Booter-provided path layer: routes paths under `$HOME` to the **personal** drive, else **system** |
|
||||
| **ctx** | Context object passed to kernel and commands: `vfs`, `console`, `execLine`, identity hooks, etc. |
|
||||
| **Guest** | Default session before `login` — predictable `HOME=/home/guest`, no Ed25519 identity |
|
||||
| **HDMS** | “Hyperdrive management” — optional extra drives mounted under `/mnt` after unlock |
|
||||
|
||||
---
|
||||
|
||||
## Why Hyperdrive and Hyperswarm
|
||||
|
||||
**Hyperdrive** gives you a **single-writer** (per key) log-backed filesystem with **deterministic** reads and **sparse** replication—good for an OS tree that many nodes can share.
|
||||
|
||||
**Hyperswarm** gives you **topic-based** and **discovery-key-based** peer finding. The seeder joins both the **bare-os-v1 topic** (so booters find _some_ peer) and the **drive discovery key** (so Hyperdrive replication completes).
|
||||
|
||||
You do not need to agree with every product choice to read the code: the handbook describes **what the repo does**, not whether it is the only way to build a P2P OS.
|
||||
|
||||
---
|
||||
|
||||
## Relationship to Pear and Bare
|
||||
|
||||
- **Bare** is a minimal JavaScript runtime used by **Pear** apps.
|
||||
- Both **seeder** and **booter** are **Pear applications** (`pear` field in `package.json`) and can run under **`node index.js`** for development.
|
||||
- **brittle-bare** vs **brittle-node** split in tests reflects native addons (e.g. identity crypto) that only load on Bare.
|
||||
|
||||
---
|
||||
|
||||
## Where to go next
|
||||
|
||||
- Big picture: [Chapter 2 — Blueprints](02-blueprints.md)
|
||||
- Wire protocol: [Chapter 3](03-protocol-and-disk.md)
|
||||
- Day-to-day hacking: [Chapter 7](07-operations-and-development.md)
|
||||
|
||||
---
|
||||
|
||||
[← Handbook home](README.md) · [Next: Blueprints →](02-blueprints.md)
|
||||
@@ -0,0 +1,142 @@
|
||||
# Chapter 2 — Blueprints: architecture and trust
|
||||
|
||||
This chapter is the **aerial view**: boxes, arrows, and what is allowed to trust what. Implementation details live in later chapters.
|
||||
|
||||
---
|
||||
|
||||
## 1. Two applications, one protocol
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph publishers [Publish side]
|
||||
Seeder[bare-os-seeder]
|
||||
SysImg[System Hyperdrive]
|
||||
Seeder --> SysImg
|
||||
end
|
||||
subgraph network [Hyperswarm]
|
||||
Topic[bare-os-v1 topic]
|
||||
Disc[Drive discovery keys]
|
||||
end
|
||||
subgraph consumers [Boot side]
|
||||
Booter[bare-os-booter]
|
||||
PeerDisk[SwarmDisk MBR + blocks]
|
||||
Booter --> PeerDisk
|
||||
end
|
||||
Seeder --> Topic
|
||||
Booter --> Topic
|
||||
SysImg --> Disc
|
||||
Booter --> Disc
|
||||
```
|
||||
|
||||
- The **seeder** is the **publisher** of the OS image (plus MBR in a small RAM map).
|
||||
- The **booter** is a **consumer** that refuses to invent a local copy: it **must** see peers.
|
||||
|
||||
---
|
||||
|
||||
## 2. Two drives on the booter
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph booterProcess [Booter process]
|
||||
VFS[VFS layer]
|
||||
Sys[System Hyperdrive]
|
||||
Pers[Personal Hyperdrive]
|
||||
VFS -->|"paths outside HOME"| Sys
|
||||
VFS -->|"HOME and below"| Pers
|
||||
end
|
||||
```
|
||||
|
||||
**Trust model (pragmatic):**
|
||||
|
||||
- **System drive** content is **whatever replicated from the swarm** matching the MBR keys. In dev you treat the seeder as trusted; in the wild this is “who you peer with.”
|
||||
- **Personal drive** is **your** namespace (Corestore `bare-os-personal-v1`). It holds secrets, cron, dotfiles, HDMS registry, vault snapshots.
|
||||
|
||||
---
|
||||
|
||||
## 3. Protocol, MBR, and discovery
|
||||
|
||||
The shared package **bare-os-protocol** pins:
|
||||
|
||||
- `TOPIC_STRING === 'bare-os-v1'`
|
||||
- `topicKey()` = `crypto.hash(b4a.from(TOPIC_STRING))`
|
||||
- MBR layout: **512 bytes**, magic **`BIOS`**, primary key at offset **8**, optional failover keys at **40** and **72**
|
||||
|
||||
MBR layout (512 bytes, see `bare-os-protocol/constants.js`):
|
||||
|
||||
- Bytes **0–3**: `BIOS` magic
|
||||
- Bytes **8–39**: primary system Hyperdrive public key
|
||||
- Bytes **40–71**, **72–103**: optional additional keys
|
||||
|
||||
Protomux channel **`bare-os-v1`** carries:
|
||||
|
||||
- Block read requests (MBR and any indexed RAM the seeder exposes)
|
||||
- Hyperdrive **replication** on the same socket
|
||||
- Stubs for gossip, search, RPC (see `packages/bare-os-protocol/lib/channel.js`)
|
||||
|
||||
---
|
||||
|
||||
## 4. Execution stack inside the booter
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Init[index.js main]
|
||||
Splash[Boot splash TTY]
|
||||
Swarm[Hyperswarm + SwarmDisk]
|
||||
ExecK[executeKernel]
|
||||
Repl[Kernel REPL session]
|
||||
Init --> Splash
|
||||
Init --> Swarm
|
||||
Swarm --> ExecK
|
||||
ExecK --> Repl
|
||||
Repl --> Kernel["runKernelFromSource /boot/init.js"]
|
||||
Kernel --> Shell["execLine → execShellLine"]
|
||||
Shell --> Bin["runBinCommand / paths / PATH"]
|
||||
```
|
||||
|
||||
**Kernel** and **/bin** scripts are **not** separate processes. They are **`AsyncFunction`** closures in the **same** JS realm as the booter, with a **synthetic** `ctx` instead of syscalls.
|
||||
|
||||
---
|
||||
|
||||
## 5. Services after the console exists
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Session[createKernelReplSession]
|
||||
Console[ctx.console = session.console]
|
||||
Initd[startBareInitd]
|
||||
Logger[kernel-logger wraps log/error]
|
||||
Cron[bare-cron setInterval]
|
||||
Session --> Console
|
||||
Console --> Initd
|
||||
Initd --> Logger
|
||||
Initd --> Cron
|
||||
```
|
||||
|
||||
`stopBareInitd()` runs from **REPL session cleanup** so timers do not leak across session restarts.
|
||||
|
||||
---
|
||||
|
||||
## 6. Identity states
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Guest
|
||||
Guest --> Unlocked: login / login --new
|
||||
Unlocked --> Guest: logout
|
||||
Unlocked --> Unlocked: HDMS active after unlock
|
||||
```
|
||||
|
||||
- **Guest**: fixed `HOME=/home/guest`, read-oriented personal tree policy for some operations.
|
||||
- **Unlocked**: `HOME` under `/home/<pubkey-prefix>`, HDMS can attach writable drives, `crontab` install/remove allowed.
|
||||
|
||||
---
|
||||
|
||||
## 7. What is _not_ here (boundary)
|
||||
|
||||
- No hardware kernel, no MMU, no ELF loader for native `/bin`.
|
||||
- No container cgroup isolation—**commands are JS** with full host capability **of the Pear/Bare process**.
|
||||
- No global consensus: **two booters** can diverge if they replicate **different** forks of the same discovery key (Hyperdrive versioning is a separate concern).
|
||||
|
||||
---
|
||||
|
||||
[← Introduction](01-introduction.md) · [Handbook home](README.md) · [Next: Protocol and disk →](03-protocol-and-disk.md)
|
||||
@@ -0,0 +1,86 @@
|
||||
# Chapter 3 — Protocol, MBR, and SwarmDisk
|
||||
|
||||
Here we connect **bare-os-protocol** to what **seeder** and **booter** actually do on the wire and in RAM.
|
||||
|
||||
---
|
||||
|
||||
## Seeder lifecycle
|
||||
|
||||
1. Resolve **kernel root** (`BARE_OS_KERNEL_ROOT` or vendored `kernel/`).
|
||||
2. Optionally **rebuild coreutils** when running under Node (`file:` URL) — skipped under Pear.
|
||||
3. Open **Corestore** + **Hyperdrive**, **`stageKernelTree`**:
|
||||
- `init.js` → `/boot/init.js`
|
||||
- `bin/*` → `/bin/*`
|
||||
- `etc/*` → `/etc/*`
|
||||
4. Build **MBR** with `buildMbr(drive.key)` and store block **0** in a **`Map`** (`localRAM`).
|
||||
5. **Hyperswarm** `join(topicKey())` and `join(drive.discoveryKey)`.
|
||||
6. On each connection: **Protomux** + **`setupSeedChannel`**, which:
|
||||
- Answers **read index** requests from `localRAM` (index `0` → MBR)
|
||||
- Attaches **`drive.replicate(stream)`**
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant S as Seeder
|
||||
participant W as Hyperswarm
|
||||
participant B as Booter
|
||||
S->>W: join topic + discoveryKey
|
||||
B->>W: join topic
|
||||
B->>S: mux connection
|
||||
Note over B,S: Protomux bare-os-v1
|
||||
B->>S: read block 0
|
||||
S-->>B: MBR 512 bytes
|
||||
B->>S: hyperdrive replicate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Booter: from peers to Hyperdrive
|
||||
|
||||
**`SwarmDisk`** (booter) mirrors the seeder’s channel handlers:
|
||||
|
||||
- **`read(index)`** — if not local RAM, broadcast **msg 0** to peers, await **msg 1** (timeout).
|
||||
- **`addPeer`** — open channel, replicate **system** (and later **personal**) drives on the mux stream.
|
||||
|
||||
**Boot path:**
|
||||
|
||||
1. Wait until **`disk.peers.size > 0`** or **boot timeout**.
|
||||
2. **`parseMbr(await disk.read(0))`** → list of 32-byte keys.
|
||||
3. For each key, try `Hyperdrive(store, key)` + replicate until **`/boot/init.js`** exists.
|
||||
4. Initialize **personal drive** namespace and join its discovery key.
|
||||
5. Hand off to **`executeKernel`**.
|
||||
|
||||
There is **intentionally** no “use my checkout’s `kernel/` if the network fails” path—the project forces you to think about **availability** of the swarm.
|
||||
|
||||
---
|
||||
|
||||
## Message IDs (reference)
|
||||
|
||||
Aligned with `packages/bare-os-protocol/lib/channel.js` and `swarm-disk.js`:
|
||||
|
||||
| ID | Direction | Purpose |
|
||||
| ----- | -------------- | -------------------- |
|
||||
| 0 | Client → peers | Read block by index |
|
||||
| 1 | Peer → client | Data payload |
|
||||
| 2 | Gossip stub | Bitfield buffer |
|
||||
| 3 / 4 | Search req/res | Stub (empty matches) |
|
||||
| 5 / 6 | RPC req/res | Stub on seeder |
|
||||
|
||||
The **important** path for boot is **0/1** + **Hyperdrive replication** on the same socket.
|
||||
|
||||
---
|
||||
|
||||
## Personal drive replication
|
||||
|
||||
`SwarmDisk.initPersonalDrive` creates a **separate** Hyperdrive under a stable Corestore namespace and **`swarm.join(personalDrive.discoveryKey)`**. Your `$HOME` tree can therefore sync across **your** devices if peers share that discovery key—orthogonal to the **system** image key from the MBR.
|
||||
|
||||
---
|
||||
|
||||
## Failure modes you will see in the wild
|
||||
|
||||
- **Boot timeout** — no peer answered the topic (seeder not running, firewall, wrong network).
|
||||
- **Invalid MBR** — corrupt block 0 or wrong magic; `parseMbr` throws.
|
||||
- **Drive never completes** — replication stalled; check peer count and discovery key joins.
|
||||
|
||||
---
|
||||
|
||||
[← Blueprints](02-blueprints.md) · [Handbook home](README.md) · [Next: Booter runtime →](04-the-booter-runtime.md)
|
||||
@@ -0,0 +1,117 @@
|
||||
# Chapter 4 — The booter runtime: `ctx`, VFS, shell, kernel, services
|
||||
|
||||
The booter is the **largest** package because it **is** the machine: everything the user experiences as “the OS” (except the raw Hyperdrive bytes) is assembled in **`packages/bare-os-booter/index.js`** and **`lib/*.js`**.
|
||||
|
||||
---
|
||||
|
||||
## Boot splash and stdio
|
||||
|
||||
`resolveStdio()` picks **session stdin/stdout** appropriate for Pear/Bare vs Node. When stdout is a TTY and `BARE_OS_NO_SPLASH` is unset, **`createBootSplash`** shows a **full-screen** progress UI tied to **`BARE_OS_BOOT_TIMEOUT_MS`**, then **`prepareForKernel()`** clears the screen before the line editor attaches.
|
||||
|
||||
Non-TTY mode skips splash noise; automation uses **`BARE_OS_SKIP_REPL=1`**.
|
||||
|
||||
---
|
||||
|
||||
## `executeKernel` in one paragraph
|
||||
|
||||
After the **system** and **personal** drives exist:
|
||||
|
||||
1. Build **`shellEnv`** (guest defaults: `HOME`, `PATH`, `USER`, …).
|
||||
2. **`createVfs(drive, personalDrive, shellEnv)`** — the two-drive router.
|
||||
3. **`applyGuestEnv` + `ensureGuestHome`** — identity stub and `/.bare` skeleton on the personal drive.
|
||||
4. Construct **`ctx`**: disks, `vfs`, `env`, `b4a`, `topic`, identity hooks (`applyUnlock`, `applyLogout`, `saveVault`, …), **`runHdms`** for `/bin/hdms`, **`requestBooterExit`** for `exit`.
|
||||
5. **`createKernelReplSession`** — fish-style **`readLine`** + **`console`** bound to the same stdout as the prompt.
|
||||
6. Set **`ctx.execLine`** to a wrapper that handles **`exit`** then **`execShellLine`**.
|
||||
7. **`await startBareInitd(ctx)`** — see below.
|
||||
8. **`runKernelFromSource(initSource, ctx)`** — runs `/boot/init.js`.
|
||||
|
||||
Cleanup path closes swarm/drives and calls **`session.cleanup()`**, which runs **`stopBareInitd()`**.
|
||||
|
||||
---
|
||||
|
||||
## VFS: two drives, one path space
|
||||
|
||||
`lib/vfs.js` implements **`resolveLogical`** with **`unix-path-resolve(cwd, userPath)`** (two arguments only—important when reading the code).
|
||||
|
||||
- Paths under **`$HOME`** resolve to the **personal** Hyperdrive (mutable `writeFile` / `unlink` where policy allows).
|
||||
- Other absolute paths hit the **system** drive (OS image).
|
||||
- Hyperdrive rejects **`/`** as a filename; the VFS special-cases **logical root** for `stat`, `chdir`, `exists`.
|
||||
|
||||
Virtual listings include **`/home`** (session-specific) and **`/mnt`** when HDMS mounts exist.
|
||||
|
||||
---
|
||||
|
||||
## Shell and kernel runner
|
||||
|
||||
**`execShellLine`** (`lib/shell.js`):
|
||||
|
||||
- Tokenizes words, quotes, escapes, **`$VAR`**, pipelines **`|`**, redirections **`>` / `>>` / `<`**.
|
||||
- Builtins: **`cd`**, **`export`**, **`login`**, **`logout`**, **`exit`** — plus external commands via **`runBinCommand`**.
|
||||
- Pipes capture **`console.log`** into the next stage or a string sink.
|
||||
|
||||
**`runBinCommand`** (`lib/kernel-runner.js`):
|
||||
|
||||
1. If **`argv[0]`** contains **`/`** — resolve via VFS, **`drive.get`**, **`runScriptFromSource`**.
|
||||
2. Else if the name **ends with `.js`** — resolve **`$PWD/name.js`** first (same as explicit `./` for many cases).
|
||||
3. Else walk **`PATH`** on the **system** drive only.
|
||||
|
||||
**`runScriptFromSource`** strips an optional **`#!`** line, requires **`async function run(ctx, argv)`**, and **catches** errors—logs to **`ctx.console.error`** without unwinding the kernel loop.
|
||||
|
||||
**`runKernelFromSource`** requires **`async function start(ctx)`** at the top level of `/boot/init.js`.
|
||||
|
||||
---
|
||||
|
||||
## bare-initd and kernel logger
|
||||
|
||||
**`bare-initd.js`**:
|
||||
|
||||
- **`registerBareService({ name, start })`**
|
||||
- **`startBareInitd(ctx)`** — sequential start, per-service `try/catch`, `[bare-initd] name: err` on failure
|
||||
- **`registerBareInitdDisposer(fn)`** + **`stopBareInitd()`** — for intervals and teardown
|
||||
|
||||
Built-in **`kernel-logger`** wraps **`ctx.console.log` / `error`** to also append UTF-8 lines to **`$HOME/.kernel/kernel.log`** (creates **`~/.kernel/.keep`** best-effort). Failures to write logs are swallowed so logging never kills the session.
|
||||
|
||||
---
|
||||
|
||||
## bare-cron
|
||||
|
||||
**`bare-cron.js`** registers service **`bare-cron`**:
|
||||
|
||||
- Reads **`~/.crontab`** via VFS (silent if missing).
|
||||
- Parses five-field cron lines + command remainder.
|
||||
- Aligns to **minute boundaries**, **`setInterval(60s)`**, runs **`await ctx.execLine(command)`** with per-line **in-flight** guard.
|
||||
- Registers a **disposer** to clear timeout/interval on shutdown.
|
||||
|
||||
Install/list/remove crontab with **`/bin/crontab`** (see [Chapter 6](06-kernel-and-binaries.md)).
|
||||
|
||||
---
|
||||
|
||||
## REPL: fish-style line editor
|
||||
|
||||
When stdin/stdout are a capable TTY and **`BARE_OS_FISH≠0`**, **`fish-readline.js`** provides history, hints, and synchronized **`Console`** output so prompts and **`console.log`** do not fight. History files live on the **personal** drive keyed by user identity.
|
||||
|
||||
---
|
||||
|
||||
## Debug
|
||||
|
||||
**`debug-repl.js`** and env-driven logging can trace readline and write paths—useful when stdin is a pipe vs TTY.
|
||||
|
||||
---
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph ctxCore [ctx surface]
|
||||
vfs[vfs]
|
||||
execLine[execLine]
|
||||
console[console]
|
||||
identity[identity + hooks]
|
||||
hdms[runHdms]
|
||||
end
|
||||
execLine --> shell[execShellLine]
|
||||
shell --> runner[runBinCommand]
|
||||
runner --> script[runScriptFromSource]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[← Protocol and disk](03-protocol-and-disk.md) · [Handbook home](README.md) · [Next: Identity and HDMS →](05-identity-vault-and-hdms.md)
|
||||
@@ -0,0 +1,88 @@
|
||||
# Chapter 5 — Identity, vault, and HDMS
|
||||
|
||||
This chapter covers **who the session is** (guest vs unlocked), **where keys live**, **encrypted vault snapshots**, and **extra Hyperdrives** under `/mnt`.
|
||||
|
||||
---
|
||||
|
||||
## Guest session
|
||||
|
||||
On boot, **`applyGuestEnv`** sets:
|
||||
|
||||
- **`USER` / `LOGNAME`** — `guest`
|
||||
- **`HOME` / `PWD`** — `/home/guest`
|
||||
- **`BARE_OS_IDENTITY`** — `guest`
|
||||
- Empty or absent **`BARE_OS_PUBLIC_KEY`**
|
||||
|
||||
The personal drive still persists: guest data is **not** anonymous to the drive—it is simply the **unauthenticated** profile.
|
||||
|
||||
---
|
||||
|
||||
## Account blob: `/.bare/account`
|
||||
|
||||
**`identity-account.js`** defines **v2** on-disk format:
|
||||
|
||||
- Magic **`BAREOS01`**, version **2**
|
||||
- 32-byte **Ed25519 public key**
|
||||
- **PBKDF2-SHA256** salt + iteration count (default **210000**)
|
||||
- **ChaCha20-Poly1305** seal over the **64-byte** secret key material (`bare-crypto`)
|
||||
|
||||
**`login --new`** creates a new account; **`login`** decrypts an existing one. Legacy v1 blobs are rejected with a message to recreate.
|
||||
|
||||
---
|
||||
|
||||
## Unlocked session
|
||||
|
||||
**`identity-session.js`**:
|
||||
|
||||
- Updates **`ctx.vfs.env`** with real **`USER`**, **`HOME`** under **`/home/<pubkey-prefix>`**, **`BARE_OS_PUBLIC_KEY`**, derived **`UID`/`GID`**-like fields from a hash of the public key.
|
||||
- **`vfs.chdir`** to the new home.
|
||||
- **`onIdentityUnlocked`** (from `index.js`) activates **HDMS** with Corestore, swarm bootstrap, personal drive, mount map.
|
||||
|
||||
**`logout`** zeroes sensitive material and returns to guest; **`logout --save`** (and **`savevault`**) snapshot selected paths into **`/.bare/vault/`** as encrypted records (see `identity-account.js` helpers for AEAD and path hashing).
|
||||
|
||||
---
|
||||
|
||||
## HDMS (Hyperdrive management)
|
||||
|
||||
**`hdms-manager.js`** implements **`/bin/hdms`** via **`ctx.runHdms(argv)`**:
|
||||
|
||||
- Registry JSON on the **personal** drive: **`/.bare/hdms/registry.json`**
|
||||
- **Writable** drives: new Corestore namespace + Hyperdrive, label, replicate to swarm
|
||||
- **Read-only** drives: open by key string
|
||||
- **invite / pair** — uses **Autopass** (static ESM import for Pear tracing)
|
||||
|
||||
**`assertLoggedIn`** requires **`ctx.identity.state === 'unlocked'`** and active controller—guests can list mounts that are already open but cannot **mutate** registry until login.
|
||||
|
||||
**VFS** exposes **`/mnt/<label>/...`** for mounted drives; writable mounts allow **`put`** on those routes.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph personal [Personal drive]
|
||||
Acc["/.bare/account"]
|
||||
Reg["/.bare/hdms/registry.json"]
|
||||
Vault["/.bare/vault/"]
|
||||
end
|
||||
subgraph hdms [HDMS]
|
||||
Extra[Extra Hyperdrives]
|
||||
end
|
||||
Reg --> Extra
|
||||
Extra --> Mnt["/mnt labels"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cron and identity
|
||||
|
||||
**`crontab`** install/remove requires **unlocked** identity so arbitrary guests cannot overwrite **`~/.crontab`** on a shared replica interpretation—**reading** jobs is still “whatever file exists on your personal drive.”
|
||||
|
||||
---
|
||||
|
||||
## Threat sketch (not a formal audit)
|
||||
|
||||
- **Passphrase strength** matters: PBKDF2 iterations slow brute force but do not fix weak secrets.
|
||||
- **Vault** ciphertext is only as safe as the **derived key** and **where copies replicate**.
|
||||
- **JS in-process** commands can exfiltrate keys from memory—this is a **toy OS shell**, not a sandbox.
|
||||
|
||||
---
|
||||
|
||||
[← Booter runtime](04-the-booter-runtime.md) · [Handbook home](README.md) · [Next: Kernel and binaries →](06-kernel-and-binaries.md)
|
||||
@@ -0,0 +1,86 @@
|
||||
# Chapter 6 — Kernel and `/bin` utilities
|
||||
|
||||
The **kernel** is a single script. The **utilities** are many small scripts. Both follow strict **`AsyncFunction`** contracts so the same code runs under **Bare** without a bundler per command.
|
||||
|
||||
---
|
||||
|
||||
## `/boot/init.js`
|
||||
|
||||
Staged from **`kernel/init.js`**. Responsibilities (typical):
|
||||
|
||||
1. Print **`/etc/os-release`** via **`ctx.drive.get`** + **`b4a.toString`**
|
||||
2. Print a **one-line** hint (commands, login, paths)
|
||||
3. Loop forever:
|
||||
- **`line = await readLine('')`**
|
||||
- Break on **`null`** (EOF / session end)
|
||||
- Skip empty lines
|
||||
- **`try/catch`** around **`execLine(t)`** so stray throws do not kill the loop
|
||||
|
||||
The **prompt** (`[user@host:path] > `) is applied by the booter’s readline layer, not by `init.js`.
|
||||
|
||||
---
|
||||
|
||||
## Coreutils build pipeline
|
||||
|
||||
```
|
||||
packages/bare-os-coreutils/lib/runtime.js
|
||||
+
|
||||
packages/bare-os-coreutils/src/<cmd>.js
|
||||
↓ (build.mjs)
|
||||
kernel/bin/<cmd>
|
||||
packages/bare-os-seeder/kernel/bin/<cmd> ← Pear vendored copy
|
||||
```
|
||||
|
||||
**Rule:** no `import` in `src/*.js` — only `async function run(ctx, argv)`.
|
||||
|
||||
---
|
||||
|
||||
## Command reference (summary)
|
||||
|
||||
| Command | Role |
|
||||
| -------------------------------- | -------------------------------------------------------------------------- |
|
||||
| `basename`, `dirname` | Path manipulation |
|
||||
| `cat`, `head`, `tail`, `nl` | Text |
|
||||
| `clear` | ANSI clear screen |
|
||||
| `crontab` | `-l` list, `-r` remove, `<file>` install (`~/.crontab`; writes need login) |
|
||||
| `date` | Date/time |
|
||||
| `echo`, `printf`-like simplicity | Args to stdout |
|
||||
| `env`, `printenv` | Environment |
|
||||
| `exit` | Sets exit code / session end via booter |
|
||||
| `false`, `true` | Status |
|
||||
| `hdms` | Hyperdrive management CLI |
|
||||
| `help` | Lists builtins + `/bin` |
|
||||
| `hostname` | Host string |
|
||||
| `id`, `whoami`, `tty` | Identity / TTY |
|
||||
| `login`, `logout` | Account session |
|
||||
| `ls` | Lists directories; **hides `.*` unless `-a`** |
|
||||
| `pathchk` | Path sanity |
|
||||
| `pwd` | Logical cwd |
|
||||
| `rm` | Unlink files |
|
||||
| `savevault` | Encrypted vault snapshot |
|
||||
| `seq`, `sleep`, `sort` | Misc |
|
||||
| `test`, `[` | Conditionals (as implemented) |
|
||||
| `touch` | Create/empty files |
|
||||
| `uname` | OS string |
|
||||
| `wc`, `which` | Text / PATH lookup |
|
||||
|
||||
Exact flags vary—read each **`src/<cmd>.js`** for truth.
|
||||
|
||||
---
|
||||
|
||||
## Running user scripts
|
||||
|
||||
- **`./foo.js`** — explicit relative path via VFS.
|
||||
- **`foo.js`** — if the basename ends with **`.js`**, the runner tries **`$PWD/foo.js`** **before** scanning **`PATH`** on the system drive.
|
||||
|
||||
Shebang lines **`#!...`** are stripped before compilation.
|
||||
|
||||
---
|
||||
|
||||
## Editing the banner
|
||||
|
||||
Update **`kernel/init.js`** and **`packages/bare-os-seeder/kernel/init.js`** if you want the **staged** Pear copy’s first-run text to match (some workflows copy automatically via build; the seeder’s `kernel/` tree may be vendored separately—check your release process).
|
||||
|
||||
---
|
||||
|
||||
[← Identity and HDMS](05-identity-vault-and-hdms.md) · [Handbook home](README.md) · [Next: Operations →](07-operations-and-development.md)
|
||||
@@ -0,0 +1,120 @@
|
||||
# Chapter 7 — Operations, development, and release
|
||||
|
||||
This chapter is the **operator’s desk**: how to install, test, run Pear apps, and interpret common failures.
|
||||
|
||||
---
|
||||
|
||||
## Repository layout (monorepo)
|
||||
|
||||
| Path | Package / role |
|
||||
| ---------------------------- | ------------------------------------------- |
|
||||
| `package.json` | Workspaces root, `pretest` builds coreutils |
|
||||
| `kernel/` | System image sources |
|
||||
| `packages/bare-os-protocol` | Topic + MBR + Protomux helpers |
|
||||
| `packages/bare-os-coreutils` | Build `/bin` scripts |
|
||||
| `packages/bare-os-seeder` | Publish OS drive |
|
||||
| `packages/bare-os-booter` | Network boot + runtime |
|
||||
| `scripts/` | Pear `node_modules` fixer, etc. |
|
||||
| `data/` | Gitignored Corestore dirs (default for dev) |
|
||||
|
||||
Each workspace has its own **`README.md`** with package-specific commands.
|
||||
|
||||
---
|
||||
|
||||
## Install and test
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm test
|
||||
```
|
||||
|
||||
- **`pretest`** runs **`npm run build -w bare-os-coreutils`**.
|
||||
- **booter** tests use **Node** for Hyperdrive + **Bare** for identity crypto (`test.identity.js`).
|
||||
|
||||
Install **Bare** globally for CI parity: **`npm install -g bare`** (see `.github/workflows/ci.yml`).
|
||||
|
||||
---
|
||||
|
||||
## Running seeder and booter (Node)
|
||||
|
||||
From **`packages/bare-os-seeder`**:
|
||||
|
||||
```bash
|
||||
node index.js
|
||||
```
|
||||
|
||||
From **`packages/bare-os-booter`**:
|
||||
|
||||
```bash
|
||||
node index.js
|
||||
```
|
||||
|
||||
Corestore paths resolve under repo **`data/`** when using `file:` URLs (see each package’s `lib/paths.js`).
|
||||
|
||||
---
|
||||
|
||||
## Running with Pear (recommended for “real” behavior)
|
||||
|
||||
From **repo root**:
|
||||
|
||||
```bash
|
||||
npm run os:seeder
|
||||
npm run os:booter # second terminal
|
||||
```
|
||||
|
||||
These run **`scripts/ensure-pear-node-modules.mjs`** first. **Do not** run `pear run os:seeder` — `os:seeder` is an npm script name, not a Pear link.
|
||||
|
||||
---
|
||||
|
||||
## Environment variables (cheat sheet)
|
||||
|
||||
| Variable | Component | Meaning |
|
||||
| ------------------------- | ------------- | -------------------------------- |
|
||||
| `BARE_OS_KERNEL_ROOT` | Seeder | Override kernel tree path |
|
||||
| `BARE_OS_SEED_STORE` | Seeder | Corestore directory |
|
||||
| `BARE_OS_BOOT_TIMEOUT_MS` | Booter | Boot deadline (default 60000) |
|
||||
| `BARE_OS_NO_SPLASH` | Booter | Disable TTY splash |
|
||||
| `BARE_OS_SKIP_REPL` | Booter | Non-interactive kernel |
|
||||
| `BARE_OS_FISH` | Booter | Set `0` to disable fish readline |
|
||||
| `HYPERSWARM_BOOTSTRAP` | Booter / HDMS | Comma-separated bootstrap nodes |
|
||||
|
||||
---
|
||||
|
||||
## Pear staging and `pear://` links
|
||||
|
||||
After **`pear stage`** / **`pear release`**, Pear prints a **`pear://…`** link per app. Distribution expects consumers to run **those** keys—not arbitrary git checkouts—unless they run in **dev** mode with **`pear run --dev .`**.
|
||||
|
||||
---
|
||||
|
||||
## Formatting
|
||||
|
||||
```bash
|
||||
npm run format
|
||||
npm run lint
|
||||
```
|
||||
|
||||
Prettier config: **no semicolons**, **single quotes** (`.prettierrc`).
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely cause |
|
||||
| ------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| Booter exits at timeout | No seeder peer on `bare-os-v1` topic |
|
||||
| `/bin/foo` missing under Pear | Forgot `npm run build -w bare-os-coreutils` before staging |
|
||||
| `autopass` / module not found in Pear | Hoist/`ensure-pear-node-modules` / static imports in HDMS |
|
||||
| `test is not defined` in user script | Bug in user JS—should **log** and continue (kernel runner catches) |
|
||||
| Double cron or log spam | Session restarted without **`stopBareInitd`** — should run on REPL cleanup |
|
||||
|
||||
---
|
||||
|
||||
## Further reading
|
||||
|
||||
- **[DOCUMENTATION.md](../DOCUMENTATION.md)** — file-by-file reference (large, authoritative for paths)
|
||||
- **[README.md](../README.md)** — short overview
|
||||
- **Handbook [Chapter 1](01-introduction.md)** — vocabulary recap
|
||||
|
||||
---
|
||||
|
||||
[← Kernel and binaries](06-kernel-and-binaries.md) · [Handbook home](README.md)
|
||||
@@ -0,0 +1,48 @@
|
||||
# Bare operating system — handbook
|
||||
|
||||
Welcome. This handbook is the **narrative companion** to the repo: it explains _why_ the pieces exist, _how_ they connect, and _what_ to run when things go wrong. For an **exhaustive file-by-file inventory**, keep [DOCUMENTATION.md](../DOCUMENTATION.md) open alongside—it is the closest thing to a generated map of every source path.
|
||||
|
||||
This project is **experimental research software**: a distributed **system image** living in **Hyperdrive**, discovered over **Hyperswarm**, executed by **Bare**/**Pear** apps. It is not a production OS.
|
||||
|
||||
---
|
||||
|
||||
## Who this is for
|
||||
|
||||
- You want a **mental model** of seeder vs booter vs kernel vs `/bin`.
|
||||
- You need **diagrams** of data flow and trust boundaries.
|
||||
- You are extending **coreutils**, **VFS**, **identity**, **HDMS**, or **initd** services.
|
||||
|
||||
---
|
||||
|
||||
## Reading order
|
||||
|
||||
| Chapter | Topic |
|
||||
| ------------------------------------------------------------------- | --------------------------------------------------- |
|
||||
| [01 — Introduction](01-introduction.md) | Goals, vocabulary, Holepunch stack |
|
||||
| [02 — Blueprints](02-blueprints.md) | Layered architecture, trust, diagrams |
|
||||
| [03 — Protocol and disk](03-protocol-and-disk.md) | MBR, swarm, Protomux, SwarmDisk |
|
||||
| [04 — The booter runtime](04-the-booter-runtime.md) | `ctx`, VFS, shell, kernel runner, initd, cron, REPL |
|
||||
| [05 — Identity, vault, HDMS](05-identity-vault-and-hdms.md) | Guest vs user, `/.bare/account`, extra drives |
|
||||
| [06 — Kernel and binaries](06-kernel-and-binaries.md) | `/boot/init.js`, coreutils catalog |
|
||||
| [07 — Operations and development](07-operations-and-development.md) | Env vars, npm scripts, CI, Pear, troubleshooting |
|
||||
|
||||
---
|
||||
|
||||
## Package READMEs (quick links)
|
||||
|
||||
- [bare-os-protocol](../packages/bare-os-protocol/README.md)
|
||||
- [bare-os-coreutils](../packages/bare-os-coreutils/README.md)
|
||||
- [bare-os-seeder](../packages/bare-os-seeder/README.md)
|
||||
- [bare-os-booter](../packages/bare-os-booter/README.md)
|
||||
- [kernel](../kernel/README.md)
|
||||
- [scripts](../scripts/README.md)
|
||||
|
||||
---
|
||||
|
||||
## Root README
|
||||
|
||||
The top-level [README.md](../README.md) is the short **runbook** (install, test, `pear run`, guest identity). Start there if you only need commands.
|
||||
|
||||
---
|
||||
|
||||
_License: Apache-2.0 — see [LICENSE](../LICENSE)._
|
||||
Reference in New Issue
Block a user