feat(booter): hrpc allowlist parser, snapshot hints parity, shell pipefix, safer mv staging
- Add bare-os-hrpc-allowlist.js; wire stock bareOsHrpcRequest + bareOsHrpcAllowlistProbe; passthrough BARE_OS_HRPC_ALLOWLIST_JSON and operator env for snapshot/blind-relay/mirror/pear-doctor - Merge BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON into bareOsReadSnapshotHintsJson (match proc) - Shell: pipefail runs all pipeline stages; aggregate first non-zero exit after assign prefixes - mv: stage renames via vfs.resolveLogical so temp files stay in writable destination dir - coreutils: POSIX-style split suffixes past zz; xargs doc for -P vs host subprocess - identity-session: stable Error.code for no-account / passphrase failures - Docs: KERNEL_CONTRACT, POSIX profile, handbook 5/7/9, kernel-extensions strict-boot table, env appendix, developer-guide + scripts README, protocol/booter CHANGELOGs; hrpc allowlist schema - Tests: hrpc allowlist, pear_doctor schema 2, split suffix, pipefail pipeline; fix PLACEHOLDER_BASELINE link Pretest: refreshed kernel bins, man.json, posix dashboard, bundle health, seeder parity
This commit is contained in:
@@ -10,6 +10,8 @@ This chapter ties together **Holepunch `bare-*` packages**, the **Pear** host ru
|
|||||||
|
|
||||||
2. **`ctx.bare` (host fallback)** — Unless **`BARE_OS_BARE_HOST_IMPORTS=0`**, the booter then **`import()`**s any manifest packages **still missing** after drive merge—typically native or Bare-only packages that could not be bundled, or when the image is older than the manifest. Set **`BARE_OS_BARE_HOST_IMPORTS=0`** for a **fully image-local** `ctx.bare` (no Pear host `node_modules` participation). Disable all `ctx.bare` with **`BARE_OS_BARE_MODULES=0`**. Manifest rows may include optional **`tier`** (**`core`** vs extended) and **`risk`** (**`low`**, **`medium`**, **`high`**) for distributor policy; the build honors **`tier`** via **`BARE_OS_BUNDLE_TIER`**.
|
2. **`ctx.bare` (host fallback)** — Unless **`BARE_OS_BARE_HOST_IMPORTS=0`**, the booter then **`import()`**s any manifest packages **still missing** after drive merge—typically native or Bare-only packages that could not be bundled, or when the image is older than the manifest. Set **`BARE_OS_BARE_HOST_IMPORTS=0`** for a **fully image-local** `ctx.bare` (no Pear host `node_modules` participation). Disable all `ctx.bare` with **`BARE_OS_BARE_MODULES=0`**. Manifest rows may include optional **`tier`** (**`core`** vs extended) and **`risk`** (**`low`**, **`medium`**, **`high`**) for distributor policy; the build honors **`tier`** via **`BARE_OS_BUNDLE_TIER`**.
|
||||||
|
|
||||||
|
**Boot cold path / stdlib budget:** the stock booter measures drive merge + host **`import()`** resolution for **`ctx.bare`** and sets **`BARE_OS_BOOT_BARE_STDLIB_RESOLUTION_MS`** before the guest starts. Operators may set **`BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB`** to log **`boot-perf.json`** / stderr warnings when resolution exceeds the budget; combine with **`BARE_OS_BUNDLE_TIER=core`** (or a smaller manifest) to shrink cold I/O. Use **`node scripts/kernel-microbench.mjs`** for regression-shaped timings (not a literal Pear cold boot).
|
||||||
|
|
||||||
3. **The full mirror (discoverability)** — A local checkout of Holepunch repos (for example **`holepunchto_repos`** under your Pear tooling tree) lists on the order of **150+** repositories whose names start with **`bare-`**. Many are **native addons**, **platform-specific** (mobile, GUI, FFmpeg, …), or **developer tools**. The **manifest** can list them for `ctx.bare`, but only rows that bundle cleanly become real drive IIFEs; the rest rely on host import or stubs until you trim the manifest.
|
3. **The full mirror (discoverability)** — A local checkout of Holepunch repos (for example **`holepunchto_repos`** under your Pear tooling tree) lists on the order of **150+** repositories whose names start with **`bare-`**. Many are **native addons**, **platform-specific** (mobile, GUI, FFmpeg, …), or **developer tools**. The **manifest** can list them for `ctx.bare`, but only rows that bundle cleanly become real drive IIFEs; the rest rely on host import or stubs until you trim the manifest.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This project is **experimental research software**. APIs described here follow t
|
|||||||
|
|
||||||
**Kernel source set:** [`docs/reference/kernel-extensions.md`](../docs/reference/kernel-extensions.md) — first-party paths (`kernel/init.js`, `kernel/lib/boot`, built `/bin`) vs vendored **`kernel/lib/bare/bundles`** (Holepunch IIFEs), CI allowlists, and seeder parity. Hand-authored code must stay free of incomplete markers; bundles are gated by **`verify-bundle-markers.mjs`**, **`verify-bundle-throws.mjs`** ( **`new Error` messages** with *not implemented* / abstract-base-class semantics — see [`docs/audit/bundle-throw-allowlist.json`](../docs/audit/bundle-throw-allowlist.json)), and **`sanitize-bare-bundles.mjs`**. Prefer shrinking the throw allowlist via upstream bundle refreshes over silent drift.
|
**Kernel source set:** [`docs/reference/kernel-extensions.md`](../docs/reference/kernel-extensions.md) — first-party paths (`kernel/init.js`, `kernel/lib/boot`, built `/bin`) vs vendored **`kernel/lib/bare/bundles`** (Holepunch IIFEs), CI allowlists, and seeder parity. Hand-authored code must stay free of incomplete markers; bundles are gated by **`verify-bundle-markers.mjs`**, **`verify-bundle-throws.mjs`** ( **`new Error` messages** with *not implemented* / abstract-base-class semantics — see [`docs/audit/bundle-throw-allowlist.json`](../docs/audit/bundle-throw-allowlist.json)), and **`sanitize-bare-bundles.mjs`**. Prefer shrinking the throw allowlist via upstream bundle refreshes over silent drift.
|
||||||
|
|
||||||
**Local Holepunch clones:** run **`node scripts/sync-holepunch-clones.mjs`** to emit **`docs/audit/holepunch-clone-sync-report.json`** comparing **`bare-module-manifest.json`** names to optional checkouts under **`BARE_OS_HOLEPUNCH_CLONES_ROOT`** (default **`~/dev/pearcli/holepunch-repos/holepunchto_repos`**).
|
**Local Holepunch mirror:** run **`node scripts/sync-holepunch-clones.mjs`** to emit **`docs/audit/holepunch-clone-sync-report.json`** comparing manifest package names to optional checkouts under **`BARE_OS_HOLEPUNCH_CLONES_ROOT`** (default **`~/dev/pearcli/holepunch-repos/holepunchto_repos`**). Root **`pretest`** runs **`node scripts/verify-holepunch-clone-drift.mjs`** against basenames listed in **`docs/audit/holepunch-drift-repos.json`** (empty **`repos[]`** = no-op). Regenerate the maximal npm catalog with **`node scripts/gen-bare-holepunch-catalog.mjs`** (or **`npm run gen:bare-catalog`**), then **`npm run sync:bare-manifest`** — see [scripts/README.md](../scripts/README.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Shared error classes (stable `code` field): [`packages/bare-os-booter/lib/bare-o
|
|||||||
## Seed RPC and hrpc bridges
|
## Seed RPC and hrpc bridges
|
||||||
|
|
||||||
- **Seed RPC** (`bare_os.*` methods on the seeder wire): [`packages/bare-os-protocol/lib/channel.js`](../../packages/bare-os-protocol/lib/channel.js) answers only methods listed in [`seed-rpc-methods.js`](../../packages/bare-os-protocol/lib/seed-rpc-methods.js); unknown names return **`bare_os.rpc_unknown_method`** (default deny). Boot policy may add **`denySeedRpcMethods`** / env **`BARE_OS_BOOT_POLICY_DENY_SEED_RPC_METHODS`** so the stock booter skips selected calls.
|
- **Seed RPC** (`bare_os.*` methods on the seeder wire): [`packages/bare-os-protocol/lib/channel.js`](../../packages/bare-os-protocol/lib/channel.js) answers only methods listed in [`seed-rpc-methods.js`](../../packages/bare-os-protocol/lib/seed-rpc-methods.js); unknown names return **`bare_os.rpc_unknown_method`** (default deny). Boot policy may add **`denySeedRpcMethods`** / env **`BARE_OS_BOOT_POLICY_DENY_SEED_RPC_METHODS`** so the stock booter skips selected calls.
|
||||||
- **hrpc** (`ctx.bareOsHrpcRequest`): the stock booter implementation validates inputs, enforces optional **`BARE_OS_HRPC_ALLOWLIST_JSON`**, and serves a built-in route table (**`kernel.ping`**, **`kernel.capabilities`**, **`vfs.readText`**, **`bare_os.echo`**, **`bare_os.disk_os_hints`** — the last mirrors the disk.os RPC hint JSON). **`process.emit('bare-os:hrpc-request', …)`** runs for unsupported routes only when **`BARE_OS_HRPC_EMIT_UNLISTED`** is **`1`** / **`true`**. Set **`BARE_OS_HRPC_AUDIT`** to append tamper-evident audit rows for attempts (via **`bareOsAuditChainLinkAppend`**). Treat new routes as security-sensitive: extend only with explicit allowlist semantics and tests.
|
- **hrpc** (`ctx.bareOsHrpcRequest`): the stock booter implementation validates inputs, enforces optional **`BARE_OS_HRPC_ALLOWLIST_JSON`** (JSON **array** of **`"service.method"`** strings, or **object** whose **keys** are route names and values are truthy — see [`docs/schemas/bare-os-hrpc-allowlist.schema.json`](../schemas/bare-os-hrpc-allowlist.schema.json); wildcards **`"*"`**, **`"kernel.*"`**, etc.), and serves a built-in route table (**`kernel.ping`**, **`kernel.capabilities`**, **`vfs.readText`**, **`bare_os.echo`**, **`bare_os.disk_os_hints`** — the last mirrors the disk.os RPC hint JSON). **Deny-by-default:** any **`service.method`** not in the stock table throws **`bareOsHrpcRequest: unsupported route …`** unless the host replaces **`ctx.bareOsHrpcRequest`** or **`BARE_OS_HRPC_EMIT_UNLISTED`** is **`1`** / **`true`** (then **`process.emit('bare-os:hrpc-request', …)`** fires for unlisted routes). Set **`BARE_OS_HRPC_AUDIT`** to append tamper-evident audit rows for attempts (via **`bareOsAuditChainLinkAppend`**). Treat new routes as security-sensitive: extend only with explicit allowlist semantics and tests.
|
||||||
|
|
||||||
## Related docs
|
## Related docs
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This document is the **normative contract** for how closely the stock Bare OS ke
|
|||||||
|
|
||||||
Bare OS does **not** expose a C ABI. The following **observability contracts** stand in for “system calls”:
|
Bare OS does **not** expose a C ABI. The following **observability contracts** stand in for “system calls”:
|
||||||
|
|
||||||
- **`/proc/bare_os/syscalls.json`** — Declares **fd model**, **signal model**, **errno hints**, **operation detail**, **`posixXsh`**, **`socketMsgSurface`**, and related adjuncts (schema **8** in stock builds; see [`docs/reference/posix-compliance-matrix.json`](../reference/posix-compliance-matrix.json)). **`ops`** lists invocable **`ctx.bareOsSyscall`** names; **`opsDetail`** also carries **POSIX.1 XSH** logical names (**`open`**, **`close`**, **`read`**, **`write`**, **`readv`**, **`writev`**, **`getsockopt`**, **`setsockopt`**, **`lseek`**, **`pipe`**, **`dup`**, **`dup2`**, **`fcntl`**, **`poll`**, **`select`**, **`umask`**, and **socket family** probes) with **`posixAlignment`** (**`simulated`**, **`partial`**, **`ENOTSUP`**) and **`mapsTo`** for traceability. The **`posixXsh`** object summarizes those XSH names (via **`bareOsPosixXshOpsCsv()`**). **`socketMsgSurface`** (schema **2**) documents **`sendmsg`** / **`recvmsg`**: with **`BARE_OS_POSIX_SOCKET_FD_BRIDGE`** and **`SOCK_DGRAM`**, **`sendmsg`** flattens bounded **iovec** lists into one datagram and **`recvmsg`** returns **`buf`** plus **`msgHdr.name`** from **`rinfo`**; ancillary control messages and scatter **`recvmsg`** remain **`ENOTSUP`**. **`fcntl`** supports **`F_GETFL`** / **`F_SETFL`** (Linux-shaped **`O_APPEND`** **`0x400`**, **`O_NONBLOCK`** **`0x800`**) and **cooperative advisory locks** via **`F_GETLK`** / **`F_SETLK`** / **`F_SETLKW`** using **`args.path`** (absolute) or **`args.fd`** whose logical target is an absolute path; contended **`F_SETLK`** returns **`EAGAIN`**. **`F_SETLKW`** also returns **`EAGAIN`** by default; with **`BARE_OS_POSIX_FCNTL_BLOCKING_WAIT`**, it **awaits** the lock up to **`BARE_OS_FCNTL_LOCK_WAIT_MS_MAX`** (default **30000**, max **300000**) then **`ETIMEDOUT`**. Unknown FDs yield **`EBADF`**. **`readv`** / **`writev`** perform bounded scatter/gather on **`BARE_OS_POSIX_FD_SIM`** pipe read/write ends. **`poll`** / **`select`** share the same logical FD readiness probe when **`BARE_OS_POSIX_FD_SIM`** is enabled; with **`BARE_OS_POSIX_SOCKET_FD_BRIDGE=1`**, bridged **datagram** fds participate (**`SOCK_DGRAM`** via **`bareDgram`** when merged) with bounded **`recv`** / **`recvfrom`** queues (**`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**, **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**). **Socket-shaped** syscalls default to **`ENOSYS`** / **`ENOTSUP`**; with **`BARE_OS_POSIX_SOCKET_FD_BRIDGE=1`**, **`socket`** + **`connect`** may use **`ctx.bare.bareTcp.Socket`** (**`SOCK_STREAM`**) or **`bareDgram`** (**`SOCK_DGRAM`**) when merged. The stock booter **caches** this JSON until warm read-cache invalidation.
|
- **`/proc/bare_os/syscalls.json`** — Declares **fd model**, **signal model**, **errno hints**, **operation detail**, **`posixXsh`**, **`socketMsgSurface`**, and related adjuncts (schema **8** in stock builds; see [`docs/reference/posix-compliance-matrix.json`](../reference/posix-compliance-matrix.json)). **`ops`** lists invocable **`ctx.bareOsSyscall`** names; **`opsDetail`** also carries **POSIX.1 XSH** logical names (**`open`**, **`close`**, **`read`**, **`write`**, **`readv`**, **`writev`**, **`getsockopt`**, **`setsockopt`**, **`lseek`**, **`pipe`**, **`dup`**, **`dup2`**, **`fcntl`**, **`poll`**, **`select`**, **`umask`**, and **socket family** probes) with **`posixAlignment`** (**`simulated`**, **`partial`**, **`ENOTSUP`**) and **`mapsTo`** for traceability. The **`posixXsh`** object summarizes those XSH names (via **`bareOsPosixXshOpsCsv()`**). **`socketMsgSurface`** (schema **3**) documents **`sendmsg`** / **`recvmsg`** on the bridge: bounded **iovec** flattening for datagram and stream paths; non-empty ancillary **`cmsgs`/`control`/`controllen`/`msgHdr.*` on `sendmsg`** → **`ENOTSUP`** + structured **`ancillaryReject`**; **`recvmsg`** **`controllen`** **0**. **`fcntl`** supports **`F_GETFL`** / **`F_SETFL`** (Linux-shaped **`O_APPEND`** **`0x400`**, **`O_NONBLOCK`** **`0x800`**) and **cooperative advisory locks** via **`F_GETLK`** / **`F_SETLK`** / **`F_SETLKW`** using **`args.path`** (absolute) or **`args.fd`** whose logical target is an absolute path; contended **`F_SETLK`** returns **`EAGAIN`**. **`F_SETLKW`** also returns **`EAGAIN`** by default; with **`BARE_OS_POSIX_FCNTL_BLOCKING_WAIT`**, waiters are queued **FIFO per lock path** until the lock is free or **`BARE_OS_FCNTL_LOCK_WAIT_MS_MAX`** elapses (**`ETIMEDOUT`**; default **30000** ms, max **300000**). There is **no** cross-path global fairness and **no** host deadlock detection. Unknown FDs yield **`EBADF`**. **`readv`** / **`writev`** perform bounded scatter/gather on **`BARE_OS_POSIX_FD_SIM`** pipe read/write ends. **`poll`** / **`select`** share the same logical FD readiness probe when **`BARE_OS_POSIX_FD_SIM`** is enabled; with **`BARE_OS_POSIX_SOCKET_FD_BRIDGE=1`**, bridged **datagram** fds participate (**`SOCK_DGRAM`** via **`bareDgram`** when merged) with bounded **`recv`** / **`recvfrom`** queues (**`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**, **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**); passive **`SOCK_STREAM`** uses **`bind`/`listen`/`accept`** when **`bareTcp.Server`** is available. **Socket-shaped** syscalls default to **`ENOSYS`** / **`ENOTSUP`**; with **`BARE_OS_POSIX_SOCKET_FD_BRIDGE=1`**, **`socket`** + **`connect`** may use **`ctx.bare.bareTcp.Socket`** (**`SOCK_STREAM`**) or **`bareDgram`** (**`SOCK_DGRAM`**) when merged. The stock booter **caches** this JSON until warm read-cache invalidation.
|
||||||
- **`/proc/bare_os/process_table.json`** — **PGID** / **SID**-style fields, **`parentName`** (from **`ppid`**), **signal routing**, and initd binding for the **logical** process table (not host PIDs).
|
- **`/proc/bare_os/process_table.json`** — **PGID** / **SID**-style fields, **`parentName`** (from **`ppid`**), **signal routing**, and initd binding for the **logical** process table (not host PIDs).
|
||||||
|
|
||||||
**Explicit non-goals**
|
**Explicit non-goals**
|
||||||
@@ -53,7 +53,7 @@ Utilities are **Issue 7–inspired** JavaScript implementations. High-traffic to
|
|||||||
|
|
||||||
Two logical drives (**system** + **personal**) form one namespace; **`.bareos_empty`** marks empty directories. Synthetic trees: **`/proc`**, **`/sys`**, **`/run`**, **`/dev`**, session **`/tmp`**. **`/dev/shm/<name>`** holds **in-memory** named byte segments (not host **`shm_open`**); names match **`^[a-zA-Z0-9._-]{1,128}$`**. Optional **`/mirror/aux*`** for auxiliary read-only drives.
|
Two logical drives (**system** + **personal**) form one namespace; **`.bareos_empty`** marks empty directories. Synthetic trees: **`/proc`**, **`/sys`**, **`/run`**, **`/dev`**, session **`/tmp`**. **`/dev/shm/<name>`** holds **in-memory** named byte segments (not host **`shm_open`**); names match **`^[a-zA-Z0-9._-]{1,128}$`**. Optional **`/mirror/aux*`** for auxiliary read-only drives.
|
||||||
|
|
||||||
**Rename:** No atomic cross-drive **`rename`**; **`mv`** implements copy + remove where needed (handbook ch.9).
|
**Rename:** No atomic cross-drive **`rename`**; **`mv`** implements copy + remove where needed (handbook ch.9). For a **single regular file** to a non-directory destination, **`/bin/mv`** stages bytes under a unique **`.bare-os-mv-tmp.*`** name in the **resolved destination directory** (same folder as the target after **`vfs.resolveLogical`**), writes the final name, removes the staging entry, then unlinks the source so a failed final write leaves the source path intact (best-effort staging cleanup).
|
||||||
|
|
||||||
**`pathconf` / `getconf`:** Live **`getconf _PC_* /path`** delegates to **`ctx.bareOsPathconf`**. Union read prefixes (**`BARE_OS_VFS_UNION_PREFIXES`**) and read-only **mirror** paths (**`/mirror/…`**) adjust documented **`_PC_NO_TRUNC`** and **`_PC_CHOWN_RESTRICTED`** hints (not a certifiable pathconf implementation).
|
**`pathconf` / `getconf`:** Live **`getconf _PC_* /path`** delegates to **`ctx.bareOsPathconf`**. Union read prefixes (**`BARE_OS_VFS_UNION_PREFIXES`**) and read-only **mirror** paths (**`/mirror/…`**) adjust documented **`_PC_NO_TRUNC`** and **`_PC_CHOWN_RESTRICTED`** hints (not a certifiable pathconf implementation).
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ This document classifies incomplete surfaces as of the kernel hardening pass. It
|
|||||||
| Item | Location | Notes |
|
| Item | Location | Notes |
|
||||||
| ---------------------------- | --------------------------- | ----- |
|
| ---------------------------- | --------------------------- | ----- |
|
||||||
| ~~`gen-ctx-client-stub.mjs`~~ → **`gen-ctx-client-helper.mjs`** | `scripts/` | Renamed; generates TS client version constant aligned with **`BARE_OS_CTX_API_VERSION`**. |
|
| ~~`gen-ctx-client-stub.mjs`~~ → **`gen-ctx-client-helper.mjs`** | `scripts/` | Renamed; generates TS client version constant aligned with **`BARE_OS_CTX_API_VERSION`**. |
|
||||||
| Man / reference “placeholder” prose | `docs/`, `kernel/share/man/` | Tracked for alignment with implemented behavior. |
|
| Man / reference “placeholder” prose | `docs/`, `kernel/share/man/` | **Closed for stock tree:** `node scripts/verify-man-coverage.mjs` gates **146** Tier-1 commands; regenerate merged man DB with **`npm run build -w bare-os-coreutils`** when pages change. Narrative alignment: [handbook ch.9 §5](../../handbook/09-posix-utilities-shell-and-vfs.md#5-bin-utilities-catalog). |
|
||||||
|
|
||||||
## Extension multisig gate (stock kernel)
|
## Extension multisig gate (stock kernel)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"generatedAt": "2026-04-05T05:06:01.522Z",
|
"generatedAt": "2026-04-05T05:30:46.141Z",
|
||||||
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
||||||
"buildTool": "packages/bare-os-bare-libs/build.mjs",
|
"buildTool": "packages/bare-os-bare-libs/build.mjs",
|
||||||
"bundles": [
|
"bundles": [
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Single place to compare **protocol**, **booter `ctx` API**, **feature-bit docume
|
|||||||
|
|
||||||
## Version artifacts
|
## Version artifacts
|
||||||
|
|
||||||
**`bareOsCtxApiVersion`** (current stock: **`1.44.0`**) — Defined in [`packages/bare-os-booter/lib/bare-os-ctx-api.js`](../../packages/bare-os-booter/lib/bare-os-ctx-api.js). This is the semver string for the documented **`ctx`** contract; bump it when stable guest-visible behavior changes.
|
**`bareOsCtxApiVersion`** (current stock: **`1.45.0`**) — Defined in [`packages/bare-os-booter/lib/bare-os-ctx-api.js`](../../packages/bare-os-booter/lib/bare-os-ctx-api.js). This is the semver string for the documented **`ctx`** contract; bump it when stable guest-visible behavior changes.
|
||||||
|
|
||||||
**`BARE_OS_KERNEL_FEATURE_BITS_DOC`** (current stock: **`15`**) — Exported from [`packages/bare-os-protocol/lib/kernel-feature-bits.js`](../../packages/bare-os-protocol/lib/kernel-feature-bits.js). It versions the feature-bit documentation and related governance; keep it aligned with [`developer-guide/adr/001-kernel-feature-bits-governance.md`](../../developer-guide/adr/001-kernel-feature-bits-governance.md).
|
**`BARE_OS_KERNEL_FEATURE_BITS_DOC`** (current stock: **`15`**) — Exported from [`packages/bare-os-protocol/lib/kernel-feature-bits.js`](../../packages/bare-os-protocol/lib/kernel-feature-bits.js). It versions the feature-bit documentation and related governance; keep it aligned with [`developer-guide/adr/001-kernel-feature-bits-governance.md`](../../developer-guide/adr/001-kernel-feature-bits-governance.md).
|
||||||
|
|
||||||
@@ -26,7 +26,9 @@ Single place to compare **protocol**, **booter `ctx` API**, **feature-bit docume
|
|||||||
|
|
||||||
**POSIX-like profile** — **`BARE_OS_POSIX_PROFILE_VERSION`** (**`1.0.9`**) and **`BARE_OS_POSIX_PROFILE_ID`** (**`bare-os-posix-like`**) in [`bare-os-protocol/lib/bare-os-posix-profile.js`](../../packages/bare-os-protocol/lib/bare-os-posix-profile.js). Surfaced under **`/proc/bare_os_features`** as **`capabilitySurface.posixProfile`** and in **`/proc/bare_os/syscalls.json`**.
|
**POSIX-like profile** — **`BARE_OS_POSIX_PROFILE_VERSION`** (**`1.0.9`**) and **`BARE_OS_POSIX_PROFILE_ID`** (**`bare-os-posix-like`**) in [`bare-os-protocol/lib/bare-os-posix-profile.js`](../../packages/bare-os-protocol/lib/bare-os-posix-profile.js). Surfaced under **`/proc/bare_os_features`** as **`capabilitySurface.posixProfile`** and in **`/proc/bare_os/syscalls.json`**.
|
||||||
|
|
||||||
**`/proc/bare_os/syscalls.json`** — Schema **8** documents cooperative **`fcntl`** advisory locks (optional **`BARE_OS_POSIX_FCNTL_BLOCKING_WAIT`** for **`F_SETLKW`**-shaped waits), optional **`BARE_OS_POSIX_SOCKET_FD_BRIDGE`** **`socket`/`connect`** (**`SOCK_STREAM`** via **`bareTcp`**, **`SOCK_DGRAM`** via **`bareDgram`** when merged) with bounded **`send`/`sendmsg`/`recv`/`recvfrom`/`recvmsg`** on bridged datagram fds (**`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**, **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**), **`socketMsgSurface`** schema **2** (**`sendmsg`/`recvmsg`** partial on bridge; ancillary CMSGS **`ENOTSUP`**), and retains socket-family **probes** plus **`posixXsh`**. Earlier schemas added **`fdModel`**, **`signalModel`**, **`opsDetail`**, **`errnoHints`**, and **`posixProfile`**. The stock booter **caches** the JSON text until **`vfs.bareOsClearWarmReadCaches()`** / **`ctx.bareOsInvalidateWarmReadCaches()`** (same invalidation path as **`/bin`** warm cache; **`boot/init.js`** and **`lib/init/**` batch puts also invalidate). Example payload: [`kernel/etc/bare-os/syscalls.example.json`](../../kernel/etc/bare-os/syscalls.example.json); JSON Schema: [`docs/schemas/bare-os-syscalls.schema.json`](../schemas/bare-os-syscalls.schema.json).
|
**`/proc/bare_os/syscalls.json`** — Schema **8** (see also [handbook ch.9 §2.3](../../handbook/09-posix-utilities-shell-and-vfs.md#23-pseudo-proc-sys-run-dev-and-session-tmp)) documents cooperative **`fcntl`** advisory locks (optional **`BARE_OS_POSIX_FCNTL_BLOCKING_WAIT`** for **`F_SETLKW`**-shaped waits), optional **`BARE_OS_POSIX_SOCKET_FD_BRIDGE`** **`socket`/`connect`** (**`SOCK_STREAM`** via **`bareTcp`**, **`SOCK_DGRAM`** via **`bareDgram`** when merged) with bounded **`send`/`sendmsg`/`recv`/`recvfrom`/`recvmsg`** on bridged datagram fds (**`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**, **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**), **`socketMsgSurface`** schema **3** (**`sendmsg`/`recvmsg`** partial on bridge; non-empty ancillary on **`sendmsg`** → **`ENOTSUP`** + **`ancillaryReject`**; **`recvmsg`** **`controllen` 0**), and retains socket-family **probes** plus **`posixXsh`**. Earlier schemas added **`fdModel`**, **`signalModel`**, **`opsDetail`**, **`errnoHints`**, and **`posixProfile`**. The stock booter **caches** the JSON text until **`vfs.bareOsClearWarmReadCaches()`** / **`ctx.bareOsInvalidateWarmReadCaches()`** (same invalidation path as **`/bin`** warm cache; **`boot/init.js`** and **`lib/init/**` batch puts also invalidate). Example payload: [`kernel/etc/bare-os/syscalls.example.json`](../../kernel/etc/bare-os/syscalls.example.json); JSON Schema: [`docs/schemas/bare-os-syscalls.schema.json`](../schemas/bare-os-syscalls.schema.json).
|
||||||
|
|
||||||
|
**`/proc/bare_os/process_table.json`** — Schema **7** (see **`fdModel.processTableSchema`** inside **`syscalls.json`** and [handbook ch.9 §2.3](../../handbook/09-posix-utilities-shell-and-vfs.md#23-pseudo-proc-sys-run-dev-and-session-tmp)); documents logical jobs, PGID/SID-style fields, initd binding, and signal routing.
|
||||||
|
|
||||||
**Boot policy pins** — [`kernel/etc/bare-os/boot.policy.example.json`](../../kernel/etc/bare-os/boot.policy.example.json) shows **`extensionSignerPinsV3`**, **`extensionSignerPinsV4`**, and **`kernelExtensionHashPins`** for **`kernel.ext.d`** governance, plus semver gates (**`requireCtxApiMin`**, **`requireBooterSemver`**, **`requireProtocolPackageMin`**, …). Keep this file aligned with [`docs/schemas/boot.policy.schema.json`](../schemas/boot.policy.schema.json) when adding fields.
|
**Boot policy pins** — [`kernel/etc/bare-os/boot.policy.example.json`](../../kernel/etc/bare-os/boot.policy.example.json) shows **`extensionSignerPinsV3`**, **`extensionSignerPinsV4`**, and **`kernelExtensionHashPins`** for **`kernel.ext.d`** governance, plus semver gates (**`requireCtxApiMin`**, **`requireBooterSemver`**, **`requireProtocolPackageMin`**, …). Keep this file aligned with [`docs/schemas/boot.policy.schema.json`](../schemas/boot.policy.schema.json) when adding fields.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Auto-generated by scripts/gen-ctx-client-helper.mjs — do not edit by hand.
|
// Auto-generated by scripts/gen-ctx-client-helper.mjs — do not edit by hand.
|
||||||
|
|
||||||
/** Canonical `ctx` API semver from `packages/bare-os-booter/lib/bare-os-ctx-api.js`. */
|
/** Canonical `ctx` API semver from `packages/bare-os-booter/lib/bare-os-ctx-api.js`. */
|
||||||
export const BARE_OS_CTX_API_CLIENT_VERSION = '1.44.0' as const
|
export const BARE_OS_CTX_API_CLIENT_VERSION = '1.45.0' as const
|
||||||
|
|
||||||
/** Relative path to the hand-maintained TypeScript contract (schema source of truth). */
|
/** Relative path to the hand-maintained TypeScript contract (schema source of truth). */
|
||||||
export const BARE_OS_CTX_DTS_SOURCE = 'packages/bare-os-booter/lib/bare-os-ctx.d.ts' as const
|
export const BARE_OS_CTX_DTS_SOURCE = 'packages/bare-os-booter/lib/bare-os-ctx.d.ts' as const
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ The list below is one **bullet per variable** in the form **name — component
|
|||||||
- `BARE_OS_KERNEL_ROOT` — Seeder — Absolute path to kernel tree (default: `repo/kernel`)
|
- `BARE_OS_KERNEL_ROOT` — Seeder — Absolute path to kernel tree (default: `repo/kernel`)
|
||||||
- `BARE_OS_SEED_CORESTORE_SNAPSHOT_TAG` — Seeder — Optional tag string; when set (and **`BARE_OS_SEED_SNAPSHOT_HINTS_JSON`** is unset), the seeder builds **`snapshotHintsJson`** for **`bare_os.snapshot_hints`** so the booter can surface it under **`/proc/bare_os/snapshot_hints.json`** after RPC.
|
- `BARE_OS_SEED_CORESTORE_SNAPSHOT_TAG` — Seeder — Optional tag string; when set (and **`BARE_OS_SEED_SNAPSHOT_HINTS_JSON`** is unset), the seeder builds **`snapshotHintsJson`** for **`bare_os.snapshot_hints`** so the booter can surface it under **`/proc/bare_os/snapshot_hints.json`** after RPC.
|
||||||
- `BARE_OS_SEED_SNAPSHOT_HINTS_JSON` — Seeder — Optional JSON string; when set, passed verbatim as **`snapshotHintsJson`** (wins over **`BARE_OS_SEED_CORESTORE_SNAPSHOT_TAG`**).
|
- `BARE_OS_SEED_SNAPSHOT_HINTS_JSON` — Seeder — Optional JSON string; when set, passed verbatim as **`snapshotHintsJson`** (wins over **`BARE_OS_SEED_CORESTORE_SNAPSHOT_TAG`**).
|
||||||
|
- `BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON` — Booter — Optional JSON merged into **`/proc/bare_os/snapshot_hints.json`** and **`ctx.bareOsReadSnapshotHintsJson()`** as **`corestoreSnapshotWorkflow`** (keep shape aligned with seeder **`snapshot_hints`** / corestore-snapshot tooling; parse errors set **`corestoreSnapshotWorkflowParseError`**).
|
||||||
|
- `BARE_OS_HRPC_ALLOWLIST_JSON` — Booter — Optional allowlist for stock **`ctx.bareOsHrpcRequest`**: JSON **array** of **`service.method`** strings or **object** with route keys and truthy values; wildcards **`"*"`** / **`kernel.*`** supported. Invalid JSON fails the first hrpc call. Schema: [`docs/schemas/bare-os-hrpc-allowlist.schema.json`](../schemas/bare-os-hrpc-allowlist.schema.json).
|
||||||
|
- `BARE_OS_BLIND_RELAY_TOPOLOGY_JSON` — Booter — Optional JSON summarized under **`/proc/bare_os/swarm.json`** → **`blindRelayTopology`** (PII-free operator sketch).
|
||||||
|
- `BARE_OS_MIRROR_DRIVE_COMPOSITION_HINT_JSON` — Booter — Optional JSON summarized under **`/proc/bare_os/replication`** → **`mirrorDriveCompositionHint`** (mirror-drive–style aux composition hints).
|
||||||
|
- `BARE_OS_REPLICATION_PLAN_JSON` — Booter — Optional JSON merged into **`/proc/bare_os/replication`** as **`guestReplicationPlan`** (operator warm-replication hints).
|
||||||
|
- `BARE_OS_PEAR_DOCTOR_STATE_JSON` / `BARE_OS_PEAR_INSPECT_PROBE` / `BARE_OS_PEAR_DOCTOR_MODULE` — Booter — Feed **`/proc/bare_os_pear_doctor_state.json`** (**schema 2**) for pear-runtime / pear-inspect parity (**`pearDoctorModuleHint`**, **`pearInspectProbe`**, **`runtimeVersion`** via **`BARE_OS_PEAR_RUNTIME_VERSION`**).
|
||||||
- `BARE_OS_HOST_DATA` — paths — Base directory for host state (default `~/.bare-os`; Corestore dirs live under `corestore/`)
|
- `BARE_OS_HOST_DATA` — paths — Base directory for host state (default `~/.bare-os`; Corestore dirs live under `corestore/`)
|
||||||
- `BARE_OS_SEED_STORE` — Seeder — Corestore directory (default: `~/.bare-os/corestore/seeder`)
|
- `BARE_OS_SEED_STORE` — Seeder — Corestore directory (default: `~/.bare-os/corestore/seeder`)
|
||||||
- `BARE_OS_BOOT_STORE` — Booter — Corestore for boot side (default: `~/.bare-os/corestore/booter`)
|
- `BARE_OS_BOOT_STORE` — Booter — Corestore for boot side (default: `~/.bare-os/corestore/booter`)
|
||||||
@@ -147,9 +153,10 @@ The list below is one **bullet per variable** in the form **name — component
|
|||||||
- `BARE_OS_POSIX_FD_SIM_MAX_BYTES` — Booter — Max buffered bytes per simulated pipe pair (default **`1048576`**, hard cap **16 MiB**).
|
- `BARE_OS_POSIX_FD_SIM_MAX_BYTES` — Booter — Max buffered bytes per simulated pipe pair (default **`1048576`**, hard cap **16 MiB**).
|
||||||
- `BARE_OS_POSIX_FCNTL_BLOCKING_WAIT` — Booter — When **`1`** / **`true`** / **`yes`**, **`F_SETLKW`** on cooperative advisory locks **waits** (FIFO queue) until the lock is free or **`BARE_OS_FCNTL_LOCK_WAIT_MS_MAX`** elapses (**`ETIMEDOUT`**).
|
- `BARE_OS_POSIX_FCNTL_BLOCKING_WAIT` — Booter — When **`1`** / **`true`** / **`yes`**, **`F_SETLKW`** on cooperative advisory locks **waits** (FIFO queue) until the lock is free or **`BARE_OS_FCNTL_LOCK_WAIT_MS_MAX`** elapses (**`ETIMEDOUT`**).
|
||||||
- `BARE_OS_FCNTL_LOCK_WAIT_MS_MAX` — Booter — Upper bound in milliseconds for **`F_SETLKW`** blocking wait (default **`30000`**, hard cap **`300000`**).
|
- `BARE_OS_FCNTL_LOCK_WAIT_MS_MAX` — Booter — Upper bound in milliseconds for **`F_SETLKW`** blocking wait (default **`30000`**, hard cap **`300000`**).
|
||||||
- `BARE_OS_POSIX_SOCKET_FD_BRIDGE` — Booter — When **`1`** / **`true`**, **`ctx.bareOsSyscall('socket')`** allocates a logical bridge fd; **`SOCK_STREAM`** **`connect`** may use **`ctx.bare.bareTcp.Socket`** when **`bare-tcp`** is merged; **`SOCK_DGRAM`** uses **`ctx.bare.bareDgram`** when merged, with **`send`**, **`recv`**, **`recvfrom`**, bounded **`sendmsg`/`recvmsg`** (flattened iovs on the bridge path), and **`poll`/`select`** readiness on the logical fd. See **`socketMsgSurface`** in **`/proc/bare_os/syscalls.json`** for the advertised surface.
|
- `BARE_OS_POSIX_SOCKET_FD_BRIDGE` — Booter — When **`1`** / **`true`**, **`ctx.bareOsSyscall('socket')`** allocates a logical bridge fd; **`SOCK_STREAM`** **`connect`** may use **`ctx.bare.bareTcp.Socket`** when **`bare-tcp`** is merged; **`SOCK_DGRAM`** uses **`ctx.bare.bareDgram`** when merged, with **`send`**, **`recv`**, **`recvfrom`**, bounded **`sendmsg`/`recvmsg`** (flattened iovs on the bridge path; non-empty ancillary **`cmsgs`/`control`/`controllen`/`msgHdr.*` on **`sendmsg`** → **`ENOTSUP`** + **`ancillaryReject`** per **`socketMsgSurface` schema 3**), and **`poll`/`select`** readiness on the logical fd. See **`socketMsgSurface`** in **`/proc/bare_os/syscalls.json`** for the advertised surface.
|
||||||
- `BARE_OS_POSIX_DGRAM_RECVQ_MAX` — Booter — Max queued datagrams per bridged UDP fd (bounded **`recv`** path); default and caps are enforced in the booter.
|
- `BARE_OS_POSIX_DGRAM_RECVQ_MAX` — Booter — Max queued datagrams per bridged UDP fd (bounded **`recv`** path); default and caps are enforced in the booter. Also bounds per-chunk queue depth for **accepted** SOCK_STREAM bridge fds (**`tcpRecvQueue`**).
|
||||||
- `BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX` — Booter — Optional blocking **`recv`** wait cap (ms) for bridged UDP fds before **`EAGAIN`**-shaped timeout notes.
|
- `BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX` — Booter — Optional blocking **`recv`** / **`accept`** wait cap (ms) for bridged UDP fds and for **`accept`** on listening TCP bridge fds before **`EAGAIN`**-shaped timeout notes.
|
||||||
|
- `BARE_OS_POSIX_ACCEPT_QUEUE_MAX` — Booter — Max pending **`bareTcp.Server`** connections held before **`accept`** (default **64**, cap **1024**).
|
||||||
- `BARE_OS_PROTOMUX_APP_CHANNEL` — Booter / seeder — When **`1`** / **`true`**, opens a second Protomux channel **`bare-os-app-v1`** alongside **`bare-os-v1`** for namespaced app RPC (see **`bare-os-protocol`** **`PROTOCOL_APP_CHANNEL_NAME`**).
|
- `BARE_OS_PROTOMUX_APP_CHANNEL` — Booter / seeder — When **`1`** / **`true`**, opens a second Protomux channel **`bare-os-app-v1`** alongside **`bare-os-v1`** for namespaced app RPC (see **`bare-os-protocol`** **`PROTOCOL_APP_CHANNEL_NAME`**).
|
||||||
- `BARE_OS_PHYS_PAGES_HINT` — Booter — Optional integer string for **`getconf _SC_PHYS_PAGES`** via **`ctx.bareOsGetconfSysconf`** (default **`524288`** when unset).
|
- `BARE_OS_PHYS_PAGES_HINT` — Booter — Optional integer string for **`getconf _SC_PHYS_PAGES`** via **`ctx.bareOsGetconfSysconf`** (default **`524288`** when unset).
|
||||||
- `BARE_OS_SHELL_HEREDOC_MAX_BYTES` — Booter — When **`BARE_OS_SHELL_POSIX_MODE`** is on, caps here-document body size (default **`262144`**, max **2 MiB**).
|
- `BARE_OS_SHELL_HEREDOC_MAX_BYTES` — Booter — When **`BARE_OS_SHELL_POSIX_MODE`** is on, caps here-document body size (default **`262144`**, max **2 MiB**).
|
||||||
|
|||||||
@@ -17,6 +17,19 @@ Bare OS splits **hand-authored kernel code** from **vendored Holepunch runtime b
|
|||||||
|
|
||||||
**`kernel.ext.d` ordering:** The Kahn topological sort in [`kernel/lib/init/init-main.js`](../../kernel/lib/init/init-main.js) must stay aligned with [`packages/bare-os-booter/lib/kernel-extension-resolver.js`](../../packages/bare-os-booter/lib/kernel-extension-resolver.js) (**`topologicalOrderKernelExtensions`**); CI covers this via the Brittle test **`kernel extension topological order matches guest Kahn tie-break`** in **`packages/bare-os-booter/test.js`**. Additional harness tests cover **`minCtxApiVersion`** skip paths, **`conflictsWith`** / dependency **cycles** under strict boot policy (no extension scripts run on hard failures).
|
**`kernel.ext.d` ordering:** The Kahn topological sort in [`kernel/lib/init/init-main.js`](../../kernel/lib/init/init-main.js) must stay aligned with [`packages/bare-os-booter/lib/kernel-extension-resolver.js`](../../packages/bare-os-booter/lib/kernel-extension-resolver.js) (**`topologicalOrderKernelExtensions`**); CI covers this via the Brittle test **`kernel extension topological order matches guest Kahn tie-break`** in **`packages/bare-os-booter/test.js`**. Additional harness tests cover **`minCtxApiVersion`** skip paths, **`conflictsWith`** / dependency **cycles** under strict boot policy (no extension scripts run on hard failures).
|
||||||
|
|
||||||
|
### Strict boot / `kernel.ext.d` failure catalog (operator)
|
||||||
|
|
||||||
|
When **`BARE_OS_BOOT_POLICY_STRICT=1`** (or equivalent strict policy paths), the stock kernel may abort before running extension scripts. Common structured outcomes:
|
||||||
|
|
||||||
|
| Kind | Guest signal | Notes |
|
||||||
|
|------|----------------|-------|
|
||||||
|
| Dependency cycle | **`kernelExt.cycle`**, **`/run/bare-os/kernel-ext-resolution.json`** **`failure.kind: dependency_cycle`** | Topological sort fails; extension IDs listed in proc/trace JSON. |
|
||||||
|
| **`conflictsWith`** | **`kernelExt.conflict`** | Two loaded ids mutually exclude each other. |
|
||||||
|
| **`minCtxApiVersion`** | **`kernelExt.minCtxApiVersion`** | Drop-in skipped or strict boot fails when **`ctx.bareOsCtxApiVersion`** is below the declared floor. |
|
||||||
|
| **`denyKernelExtensionIds` / deny id** | **`kernelExt.denyId`** | Policy denies an extension **`id`** before script execution. |
|
||||||
|
| **Pear multisig gate** | **`kernelExt.multisigMissing`**, **`kernelExt.multisigInvalid`**, **`kernelExt.multisigRead`** | When multisig verification is required, **`/etc/bare-os/pear.multisig.json`** must be well-formed (**`signers`**, **`quorum`**). |
|
||||||
|
| **Extension signer pins (v2–v5)** | Env **`BARE_OS_BOOT_POLICY_EXTENSION_SIGNER_PINS_V*_JSON`** | Merged from **`boot.policy.json`** when present — capability alignment for downstream verifiers; CI **`scripts/verify-boot-policy-extension-signer-pins.mjs`** guards the env mapping. |
|
||||||
|
|
||||||
## Governance (feature bits doc v14)
|
## Governance (feature bits doc v14)
|
||||||
|
|
||||||
New capability bits are governed by [ADR 001 — Kernel feature bit governance](../../developer-guide/adr/001-kernel-feature-bits-governance.md). **`BARE_OS_KERNEL_FEATURE_BITS_DOC`** must bump when semantics change. Bits **28–30** on word 1 are assigned (see ADR). **Word 2 (`bits2`)** carries the extended seeding platform surface; always mask with **`>>> 0`**. Avoid `1 << 31` on word 1 in JS without `>>> 0` discipline.
|
New capability bits are governed by [ADR 001 — Kernel feature bit governance](../../developer-guide/adr/001-kernel-feature-bits-governance.md). **`BARE_OS_KERNEL_FEATURE_BITS_DOC`** must bump when semantics change. Bits **28–30** on word 1 are assigned (see ADR). **Word 2 (`bits2`)** carries the extended seeding platform surface; always mask with **`>>> 0`**. Avoid `1 << 31` on word 1 in JS without `>>> 0` discipline.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"profileId": "bare-os-posix-like",
|
"profileId": "bare-os-posix-like",
|
||||||
"note": "Machine-readable summary; normative detail remains in handbook ch.9 and environment POSIX appendix. Profile 1.0.9 / syscalls schema 8: cooperative fcntl locks (optional F_SETLKW blocking wait; waiters wake on unlock; not full POSIX deadlock detection), SOCK_DGRAM send/sendmsg/recv/recvfrom/recvmsg + poll/select readiness on socket FD bridge, sendmsg/recvmsg partial iovec/msgHdr on bridge (ancillary CMSGS ENOTSUP), dynamic sysconf via ctx.bareOsGetconfSysconf, guestReplicationPlan via BARE_OS_REPLICATION_PLAN_JSON in /proc/bare_os/replication JSON; liveHyperdrive replication sketch schema 2 (auxiliaryDriveCount).",
|
"note": "Machine-readable summary; normative detail remains in handbook ch.9 and environment POSIX appendix. Profile 1.0.9 / syscalls schema 8: cooperative fcntl locks (optional BARE_OS_POSIX_FCNTL_BLOCKING_WAIT: F_SETLKW FIFO waiters per path, BARE_OS_FCNTL_LOCK_WAIT_MS_MAX ETIMEDOUT; not full POSIX deadlock detection), SOCK_DGRAM send/sendmsg/recv/recvfrom/recvmsg + poll/select readiness on socket FD bridge, sendmsg/recvmsg partial iovec/msgHdr on bridge; socketMsgSurface schema 3 documents explicit ancillary rejection (ENOTSUP + ancillaryReject) on sendmsg when cmsgs/control/controllen/msgHdr.* present, recvmsg controllen 0. /bin/split uses POSIX-style multi-length suffixes (aa–zz then aaa…). Dynamic sysconf via ctx.bareOsGetconfSysconf, guestReplicationPlan via BARE_OS_REPLICATION_PLAN_JSON in /proc/bare_os/replication JSON; liveHyperdrive replication sketch schema 2 (auxiliaryDriveCount).",
|
||||||
"utilities": {
|
"utilities": {
|
||||||
"tier1_bin": "high",
|
"tier1_bin": "high",
|
||||||
"sed_awk_grep": "issue7_inspired_js_engines",
|
"sed_awk_grep": "issue7_inspired_js_engines",
|
||||||
@@ -25,6 +25,6 @@
|
|||||||
"syscalls_json_schema": 8,
|
"syscalls_json_schema": 8,
|
||||||
"process_table_schema": 7,
|
"process_table_schema": 7,
|
||||||
"paths": ["/proc/bare_os/syscalls.json", "/proc/bare_os/process_table.json"],
|
"paths": ["/proc/bare_os/syscalls.json", "/proc/bare_os/process_table.json"],
|
||||||
"posix_xsh_surface": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl cooperative F_GETLK/F_SETLK/F_SETLKW + F_GETFL/F_SETFL,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown in syscalls.json posixXsh.namesCsv; default socket ENOSYS-shaped; BARE_OS_POSIX_SOCKET_FD_BRIDGE SOCK_STREAM connect via bareTcp, SOCK_DGRAM connect+send+sendmsg+recv+recvfrom+recvmsg via bareDgram with BARE_OS_POSIX_DGRAM_RECVQ_MAX / BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX; poll/select mark UDP bridge fds readable when queue non-empty; ctx.bareOsSyscall readv/writev on POSIX_FD_SIM pipes; ctx.bareOsPosixPoll; socketMsgSurface schema 2 documents partial sendmsg/recvmsg on bridge (ancillary ENOTSUP)"
|
"posix_xsh_surface": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl cooperative F_GETLK/F_SETLK/F_SETLKW + F_GETFL/F_SETFL,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown in syscalls.json posixXsh.namesCsv; default socket ENOSYS-shaped; BARE_OS_POSIX_SOCKET_FD_BRIDGE SOCK_STREAM connect via bareTcp; passive SOCK_STREAM bind+listen+accept via bareTcp.Server; accepted stream fds use send/recv with bounded tcpRecvQueue; SOCK_DGRAM connect+send+sendmsg+recv+recvfrom+recvmsg via bareDgram with BARE_OS_POSIX_DGRAM_RECVQ_MAX / BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX; BARE_OS_POSIX_ACCEPT_QUEUE_MAX; poll/select mark UDP bridge fds readable when queue non-empty, TCP accepted fds when tcpRecvQueue non-empty, listening fds when accept queue non-empty; ctx.bareOsSyscall readv/writev on POSIX_FD_SIM pipes; ctx.bareOsPosixPoll; socketMsgSurface schema 3 documents partial sendmsg/recvmsg on bridge + ancillaryControl rejection contract"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Normative narrative: [`docs/architecture/POSIX_DECLARED_PROFILE.md`](../architec
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Profile | profileId | bare-os-posix-like |
|
| Profile | profileId | bare-os-posix-like |
|
||||||
| Profile | schema | 1 |
|
| Profile | schema | 1 |
|
||||||
| Profile | note | Machine-readable summary; normative detail remains in handbook ch.9 and environment POSIX appendix. Profile 1.0.9 / syscalls schema 8: cooperative fcntl locks (optional F_SETLKW blocking wait; waiters wake on unlock; not full POSIX deadlock detection), SOCK_DGRAM send/sendmsg/recv/recvfrom/recvmsg + poll/select readiness on socket FD bridge, sendmsg/recvmsg partial iovec/msgHdr on bridge (ancillary CMSGS ENOTSUP), dynamic sysconf via ctx.bareOsGetconfSysconf, guestReplicationPlan via BARE_OS_REPLICATION_PLAN_JSON in /proc/bare_os/replication JSON; liveHyperdrive replication sketch schema 2 (auxiliaryDriveCount). |
|
| Profile | note | Machine-readable summary; normative detail remains in handbook ch.9 and environment POSIX appendix. Profile 1.0.9 / syscalls schema 8: cooperative fcntl locks (optional BARE_OS_POSIX_FCNTL_BLOCKING_WAIT: F_SETLKW FIFO waiters per path, BARE_OS_FCNTL_LOCK_WAIT_MS_MAX ETIMEDOUT; not full POSIX deadlock detection), SOCK_DGRAM send/sendmsg/recv/recvfrom/recvmsg + poll/select readiness on socket FD bridge, sendmsg/recvmsg partial iovec/msgHdr on bridge; socketMsgSurface schema 3 documents explicit ancillary rejection (ENOTSUP + ancillaryReject) on sendmsg when cmsgs/control/controllen/msgHdr.* present, recvmsg controllen 0. /bin/split uses POSIX-style multi-length suffixes (aa–zz then aaa…). Dynamic sysconf via ctx.bareOsGetconfSysconf, guestReplicationPlan via BARE_OS_REPLICATION_PLAN_JSON in /proc/bare_os/replication JSON; liveHyperdrive replication sketch schema 2 (auxiliaryDriveCount). |
|
||||||
| Utilities | tier1_bin | high |
|
| Utilities | tier1_bin | high |
|
||||||
| Utilities | sed_awk_grep | issue7_inspired_js_engines |
|
| Utilities | sed_awk_grep | issue7_inspired_js_engines |
|
||||||
| Utilities | coreutils | see packages/bare-os-coreutils/src |
|
| Utilities | coreutils | see packages/bare-os-coreutils/src |
|
||||||
@@ -27,4 +27,4 @@ Normative narrative: [`docs/architecture/POSIX_DECLARED_PROFILE.md`](../architec
|
|||||||
| synthetic /proc | syscalls_json_schema | 8 |
|
| synthetic /proc | syscalls_json_schema | 8 |
|
||||||
| synthetic /proc | process_table_schema | 7 |
|
| synthetic /proc | process_table_schema | 7 |
|
||||||
| synthetic /proc | paths | /proc/bare_os/syscalls.json, /proc/bare_os/process_table.json |
|
| synthetic /proc | paths | /proc/bare_os/syscalls.json, /proc/bare_os/process_table.json |
|
||||||
| synthetic /proc | posix_xsh_surface | open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl cooperative F_GETLK/F_SETLK/F_SETLKW + F_GETFL/F_SETFL,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown in syscalls.json posixXsh.namesCsv; default socket ENOSYS-shaped; BARE_OS_POSIX_SOCKET_FD_BRIDGE SOCK_STREAM connect via bareTcp, SOCK_DGRAM connect+send+sendmsg+recv+recvfrom+recvmsg via bareDgram with BARE_OS_POSIX_DGRAM_RECVQ_MAX / BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX; poll/select mark UDP bridge fds readable when queue non-empty; ctx.bareOsSyscall readv/writev on POSIX_FD_SIM pipes; ctx.bareOsPosixPoll; socketMsgSurface schema 2 documents partial sendmsg/recvmsg on bridge (ancillary ENOTSUP) |
|
| synthetic /proc | posix_xsh_surface | open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl cooperative F_GETLK/F_SETLK/F_SETLKW + F_GETFL/F_SETFL,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown in syscalls.json posixXsh.namesCsv; default socket ENOSYS-shaped; BARE_OS_POSIX_SOCKET_FD_BRIDGE SOCK_STREAM connect via bareTcp; passive SOCK_STREAM bind+listen+accept via bareTcp.Server; accepted stream fds use send/recv with bounded tcpRecvQueue; SOCK_DGRAM connect+send+sendmsg+recv+recvfrom+recvmsg via bareDgram with BARE_OS_POSIX_DGRAM_RECVQ_MAX / BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX; BARE_OS_POSIX_ACCEPT_QUEUE_MAX; poll/select mark UDP bridge fds readable when queue non-empty, TCP accepted fds when tcpRecvQueue non-empty, listening fds when accept queue non-empty; ctx.bareOsSyscall readv/writev on POSIX_FD_SIM pipes; ctx.bareOsPosixPoll; socketMsgSurface schema 3 documents partial sendmsg/recvmsg on bridge + ancillaryControl rejection contract |
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://bare-os.local/schemas/bare-os-hrpc-allowlist.schema.json",
|
||||||
|
"title": "BARE_OS_HRPC_ALLOWLIST_JSON",
|
||||||
|
"description": "Optional allowlist for stock ctx.bareOsHrpcRequest. Parsed by packages/bare-os-booter/lib/bare-os-hrpc-allowlist.js. An empty allow set (empty array or all-falsy object) does not restrict routes.",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-zA-Z0-9._-]{1,64}\\.[a-zA-Z0-9._-]{1,96}$|^[a-zA-Z0-9._*.-]{1,64}$",
|
||||||
|
"description": "service.method or wildcard token such as * or kernel.*"
|
||||||
|
},
|
||||||
|
"maxItems": 512
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": { "type": "boolean" },
|
||||||
|
"propertyNames": {
|
||||||
|
"pattern": "^[a-zA-Z0-9._*.-]{1,160}$"
|
||||||
|
},
|
||||||
|
"maxProperties": 512
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -57,9 +57,21 @@
|
|||||||
},
|
},
|
||||||
"socketMsgSurface": {
|
"socketMsgSurface": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "sendmsg/recvmsg metadata (defaults ENOTSUP; bridge uses recv/recvfrom buffers only)",
|
"description": "sendmsg/recvmsg metadata (defaults ENOTSUP; bridge uses recv/recvfrom buffers only); schema 3 adds ancillaryControl rejection contract",
|
||||||
"properties": {
|
"properties": {
|
||||||
"schema": { "type": "integer" },
|
"schema": { "type": "integer" },
|
||||||
|
"ancillaryControl": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"supported": { "type": "boolean" },
|
||||||
|
"errno": { "type": "string" },
|
||||||
|
"rejectKeys": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"note": { "type": "string" }
|
||||||
|
}
|
||||||
|
},
|
||||||
"sendmsg": { "type": "object" },
|
"sendmsg": { "type": "object" },
|
||||||
"recvmsg": { "type": "object" }
|
"recvmsg": { "type": "object" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ This chapter covers **who the session is** (guest vs unlocked), **where keys liv
|
|||||||
|
|
||||||
**Pairing hints (operators):** when the host sets **`BARE_OS_AUTOPASS_INVITE_URL`**, the guest exposes a JSON hint at **`/proc/bare_os/hdms_hints.json`**. The guest does **not** open network URLs automatically; hosts or operators consume the hint out-of-band. **`/proc/bare_os/hdms_health.json`** (and flat alias) summarizes **non-secret** mount/registry metadata (counts, labels) for dashboards—no key material.
|
**Pairing hints (operators):** when the host sets **`BARE_OS_AUTOPASS_INVITE_URL`**, the guest exposes a JSON hint at **`/proc/bare_os/hdms_hints.json`**. The guest does **not** open network URLs automatically; hosts or operators consume the hint out-of-band. **`/proc/bare_os/hdms_health.json`** (and flat alias) summarizes **non-secret** mount/registry metadata (counts, labels) for dashboards—no key material.
|
||||||
|
|
||||||
|
**Unlock errors (automation):** when **`unlockIdentity`** in [`identity-session.js`](../packages/bare-os-booter/lib/identity-session.js) throws, stable **`Error.code`** values include **`BARE_OS_IDENTITY_NO_ACCOUNT`** (no **`/.bare/account`** blob) and **`BARE_OS_IDENTITY_PASSPHRASE_REJECTED`** (decrypt/parse failure; **`error.cause`** carries the underlying error when present). Human-readable messages remain for interactive **`login`**.
|
||||||
|
|
||||||
Cron note: **`crontab`** install/remove requires **unlocked** identity so arbitrary guests cannot overwrite **`~/.crontab`**.
|
Cron note: **`crontab`** install/remove requires **unlocked** identity so arbitrary guests cannot overwrite **`~/.crontab`**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ This chapter is the **operator’s desk**: how to install, test, run Pear apps,
|
|||||||
- [Continuous integration](#continuous-integration-github-actions)
|
- [Continuous integration](#continuous-integration-github-actions)
|
||||||
- [`pretest`](#pretest-what-runs-before-npm-test)
|
- [`pretest`](#pretest-what-runs-before-npm-test)
|
||||||
- [Holepunch catalog and Bare manifest](#holepunch-catalog-and-bare-manifest-maintainers)
|
- [Holepunch catalog and Bare manifest](#holepunch-catalog-and-bare-manifest-maintainers)
|
||||||
|
- [Warm read cache (operators)](#warm-read-cache-operators)
|
||||||
- [Release checklist](#release-checklist)
|
- [Release checklist](#release-checklist)
|
||||||
- [Install and test](#install-and-test)
|
- [Install and test](#install-and-test)
|
||||||
- [Running seeder and booter (Node)](#running-seeder-and-booter-node)
|
- [Running seeder and booter (Node)](#running-seeder-and-booter-node)
|
||||||
@@ -89,6 +90,17 @@ Each **`npm run build -w bare-os-bare-libs`** run writes **`kernel/lib/bare/mani
|
|||||||
|
|
||||||
Use provenance to audit which commit produced an image’s Holepunch IIFEs and to compare bundle tiers across environments.
|
Use provenance to audit which commit produced an image’s Holepunch IIFEs and to compare bundle tiers across environments.
|
||||||
|
|
||||||
|
### Warm read cache (operators)
|
||||||
|
|
||||||
|
When **`BARE_OS_VFS_BIN_CACHE`** and/or **`BARE_OS_VFS_LIB_BARE_CACHE`** are on, the booter serves hot **`/bin`** and **`/lib/bare`** reads from an LRU. After **live replication**, **OTA-style `/bin` or `/lib/bare` writes**, or **`kernel.ext.d` hot reload** that changes bundles, stale bytes are a real risk.
|
||||||
|
|
||||||
|
1. Prefer **`ctx.bareOsVfsBatchWrite`** for batch **`put`** operations — it clears warm entries when paths touch **`bin/`**, **`lib/bare/`**, **`boot/init.js`**, or **`lib/init/`**, and uses **selective** **`vfs.bareOsEvictLibBareBundlesFromManifest`** when only **`lib/bare/bare-module-manifest.json`** changes.
|
||||||
|
2. Call **`ctx.bareOsInvalidateWarmReadCaches('reason')`** (or **`vfs.bareOsClearWarmReadCaches()`**) after host-driven replication or policy changes that bypass the batch writer.
|
||||||
|
3. For manifest-only updates, use **`ctx.bareOsInvalidateWarmReadCachesFromBareManifestJson(buf)`** to evict **`bundles/<ctxKey>.js`** rows without flushing unrelated cache entries.
|
||||||
|
4. Optional **`BARE_OS_VFS_WARM_CACHE_INVALIDATE_ON_APPEND`** registers Hypercore **append** listeners so replication can clear caches automatically (higher churn on busy drives).
|
||||||
|
|
||||||
|
Tests in **`packages/bare-os-booter/test.js`** cover hit/miss, full clear, manifest-selective eviction, and hrpc allowlist helpers adjacent to the VFS suite.
|
||||||
|
|
||||||
### Pear bundle and pack pipeline (OS images)
|
### Pear bundle and pack pipeline (OS images)
|
||||||
|
|
||||||
For Pear-shaped releases, align **`pear-bundle`** / **`pear-pack`** with the same **`kernel/`** tree the seeder stages: run **`npm run build -w bare-os-coreutils`** and **`npm run build -w bare-os-bare-libs`**, verify **`scripts/verify-kernel-seeder-parity.mjs`**, then point Pear tooling at **`packages/bare-os-seeder`** or the published Hyperdrive key. Keep **`pear-runtime`** and **`bare-os-protocol`** versions coupled per [compatibility-matrix.md](../docs/reference/compatibility-matrix.md).
|
For Pear-shaped releases, align **`pear-bundle`** / **`pear-pack`** with the same **`kernel/`** tree the seeder stages: run **`npm run build -w bare-os-coreutils`** and **`npm run build -w bare-os-bare-libs`**, verify **`scripts/verify-kernel-seeder-parity.mjs`**, then point Pear tooling at **`packages/bare-os-seeder`** or the published Hyperdrive key. Keep **`pear-runtime`** and **`bare-os-protocol`** versions coupled per [compatibility-matrix.md](../docs/reference/compatibility-matrix.md).
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ If you come from Linux or macOS, Bare OS **feels** like a small Unix: **`ls`**,
|
|||||||
|
|
||||||
**Declared profile (single spec):** [POSIX_DECLARED_PROFILE.md](../docs/architecture/POSIX_DECLARED_PROFILE.md) — contract for XCU/XSH-like behavior, proc stand-ins for “syscalls,” and explicit non-goals.
|
**Declared profile (single spec):** [POSIX_DECLARED_PROFILE.md](../docs/architecture/POSIX_DECLARED_PROFILE.md) — contract for XCU/XSH-like behavior, proc stand-ins for “syscalls,” and explicit non-goals.
|
||||||
|
|
||||||
**Declared profile (constants):** the protocol package publishes **`BARE_OS_POSIX_PROFILE_VERSION`** / **`BARE_OS_POSIX_PROFILE_ID`** (`bare-os-posix-like`), surfaced on **`/proc/bare_os_features`** and in **`/proc/bare_os/syscalls.json`** (schema **8** for that file — **`fdModel`** / **`signalModel`** plus **`opsDetail`** / **`posixXsh`** (schema **2**) / **`socketMsgSurface`** (schema **2**) / **`errnoHints`**, including cooperative **`fcntl`** advisory locks with optional **`F_SETLKW`** blocking wait (**`BARE_OS_POSIX_FCNTL_BLOCKING_WAIT`**) and optional socket-bridge datagram **`send`/`sendmsg`/`recv`/`recvfrom`/`recvmsg`** with bounded queues (**ancillary CMSGS remain ENOTSUP**); **`/proc/bare_os/index.json`** uses schema **8**). **`getconf BARE_OS_POSIX_XSH_OPS`** lists the XSH names; **`getconf BARE_OS_SYSCALL_OPS`** lists ctx op names only. Cold-boot wall time vs **`BARE_OS_BOOT_BUDGET_MS_COLD`** is also written to **`/run/bare-os/boot-perf.json`** when the VFS supports it. **`metrics_live`** includes **`initdReadiness`** (schema **2**) and paths such as **`utilitiesIndexPath`** → **`/etc/bare-os/posix_utilities.json`** when present.
|
**Declared profile (constants):** the protocol package publishes **`BARE_OS_POSIX_PROFILE_VERSION`** / **`BARE_OS_POSIX_PROFILE_ID`** (`bare-os-posix-like`), surfaced on **`/proc/bare_os_features`** and in **`/proc/bare_os/syscalls.json`** (schema **8** for that file — **`fdModel`** / **`signalModel`** plus **`opsDetail`** / **`posixXsh`** (schema **2**) / **`socketMsgSurface`** (schema **3**: non-empty ancillary on **`sendmsg`** → **`ENOTSUP`** + **`ancillaryReject`**; **`recvmsg`** **`controllen: 0`**) / **`errnoHints`**, including cooperative **`fcntl`** advisory locks with optional **`F_SETLKW`** blocking wait (**`BARE_OS_POSIX_FCNTL_BLOCKING_WAIT`**) and optional socket-bridge datagram **`send`/`sendmsg`/`recv`/`recvfrom`/`recvmsg`** with bounded queues; **`/proc/bare_os/index.json`** uses schema **8**). **`getconf BARE_OS_POSIX_XSH_OPS`** lists the XSH names; **`getconf BARE_OS_SYSCALL_OPS`** lists ctx op names only. Cold-boot wall time vs **`BARE_OS_BOOT_BUDGET_MS_COLD`** is also written to **`/run/bare-os/boot-perf.json`** when the VFS supports it. **`metrics_live`** includes **`initdReadiness`** (schema **2**) and paths such as **`utilitiesIndexPath`** → **`/etc/bare-os/posix_utilities.json`** when present.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ We borrow **names and muscle memory** from POSIX because that makes scripts port
|
|||||||
## 1. Executive summary: what is _not_ POSIX here
|
## 1. Executive summary: what is _not_ POSIX here
|
||||||
|
|
||||||
- **Full POSIX `sh` grammar** — Bare uses a **line-at-a-time** shell: builtins plus **`/bin`**; lists with **`;`** (outside compound statements), **`&&`**, and **`|`** pipelines; bounded **`if`** … **`fi`**; bounded **`while`** / **`for`** (iteration cap **`BARE_OS_SHELL_LOOP_MAX`**, default **10000**); optional **`break`** / **`continue`** when **`BARE_OS_SHELL_LOOP_CONTROL=1`**; bounded **`case`** … **`esac`** (**`BARE_OS_SHELL_CASE_MAX_BRANCHES`**, default **32**). Optional bounded **`$(…)`** when **`BARE_OS_SHELL_CMDSUBST=1`** (see §3). With **`BARE_OS_SHELL_POSIX_MODE=1`**, **subshell-free grouped lists** **`( compound-list )`** run as a single statement (same session context). There are **no forked subshells** and no full **`sh`** grammar.
|
- **Full POSIX `sh` grammar** — Bare uses a **line-at-a-time** shell: builtins plus **`/bin`**; lists with **`;`** (outside compound statements), **`&&`**, and **`|`** pipelines; bounded **`if`** … **`fi`**; bounded **`while`** / **`for`** (iteration cap **`BARE_OS_SHELL_LOOP_MAX`**, default **10000**); optional **`break`** / **`continue`** when **`BARE_OS_SHELL_LOOP_CONTROL=1`**; bounded **`case`** … **`esac`** (**`BARE_OS_SHELL_CASE_MAX_BRANCHES`**, default **32**). Optional bounded **`$(…)`** when **`BARE_OS_SHELL_CMDSUBST=1`** (see §3). With **`BARE_OS_SHELL_POSIX_MODE=1`**, **subshell-free grouped lists** **`( compound-list )`** run as a single statement (same session context). There are **no forked subshells** and no full **`sh`** grammar.
|
||||||
- **Processes, `fork`, pipes as OS primitives** — Pipelines are **simulated** by capturing **`console.log`** (and merged **`console.error`** when **`2>&1`** is used) into the next command. With **`BARE_OS_POSIX_FD_SIM=1`**, extensions may also use **`ctx.bareOsPosixFdSimPipe`** / **`bareOsPosixFdSimRead`** / **`bareOsPosixFdSimWrite`** for bounded in-memory pipe pairs surfaced as logical FDs in **`/proc/self/fd`** (not full kernel pipes). Logical FDs support **`ctx.bareOsSyscall('fcntl', { fd, cmd: 'F_GETFL' | 'F_SETFL', arg })`** (Linux-shaped **`O_APPEND`** **`0x400`**, **`O_NONBLOCK`** **`0x800`**), cooperative **`F_GETLK` / `F_SETLK` / `F_SETLKW`** on absolute paths (or fd→path), and readiness via **`ctx.bareOsPosixPoll`** / **`ctx.bareOsSyscall('posixPoll', { fds, timeoutMs })`** (see **`/proc/bare_os/syscalls.json`**). Cooperative locks are **not** kernel wait queues: **`F_SETLKW`** may surface an **`EINTR`-shaped note** when the blocking wait budget elapses or a stale-owner grace window passes — there is no host deadlock detector. With **`BARE_OS_POSIX_SOCKET_FD_BRIDGE=1`**, **`socket`** + **`connect`** may use **`ctx.bare.bareTcp`** for **`SOCK_STREAM`** and **`ctx.bare.bareDgram`** for **`SOCK_DGRAM`** when merged; bridged UDP supports **`send`**, **`recv`**, and **`recvfrom`** with **`BARE_OS_POSIX_DGRAM_RECVQ_MAX`** / **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**, and **`poll`/`select`** treat the fd readable when the queue is non-empty.
|
- **Processes, `fork`, pipes as OS primitives** — Pipelines are **simulated** by capturing **`console.log`** (and merged **`console.error`** when **`2>&1`** is used) into the next command. With **`BARE_OS_POSIX_FD_SIM=1`**, extensions may also use **`ctx.bareOsPosixFdSimPipe`** / **`bareOsPosixFdSimRead`** / **`bareOsPosixFdSimWrite`** for bounded in-memory pipe pairs surfaced as logical FDs in **`/proc/self/fd`** (not full kernel pipes). Logical FDs support **`ctx.bareOsSyscall('fcntl', { fd, cmd: 'F_GETFL' | 'F_SETFL', arg })`** (Linux-shaped **`O_APPEND`** **`0x400`**, **`O_NONBLOCK`** **`0x800`**), cooperative **`F_GETLK` / `F_SETLK` / `F_SETLKW`** on absolute paths (or fd→path), and readiness via **`ctx.bareOsPosixPoll`** / **`ctx.bareOsSyscall('posixPoll', { fds, timeoutMs })`** (see **`/proc/bare_os/syscalls.json`**). Cooperative locks are **not** kernel wait queues: **`F_SETLKW`** may surface an **`EINTR`-shaped note** when the blocking wait budget elapses or a stale-owner grace window passes — there is no host deadlock detector. With **`BARE_OS_POSIX_SOCKET_FD_BRIDGE=1`**, **`socket`** + **`connect`** may use **`ctx.bare.bareTcp`** for **`SOCK_STREAM`** and **`ctx.bare.bareDgram`** for **`SOCK_DGRAM`** when merged; passive **`SOCK_STREAM`** uses **`bind`**, **`listen`**, **`accept`** (**`bareTcp.Server`**) with **`BARE_OS_POSIX_ACCEPT_QUEUE_MAX`**; accepted stream fds support **`send`/`recv`** with a bounded segment queue (same cap family as **`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**). Bridged UDP supports **`send`**, **`recv`**, and **`recvfrom`** with **`BARE_OS_POSIX_DGRAM_RECVQ_MAX`** / **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**, and **`poll`/`select`** treat the fd readable when the datagram queue is non-empty (listening and TCP-accepted fds use their respective queues).
|
||||||
- **`chown` / `chgrp` / real UIDs across users** — **Single-session** identity; metadata carries **uid/gid** for display and checks, not a multi-user kernel.
|
- **`chown` / `chgrp` / real UIDs across users** — **Single-session** identity; metadata carries **uid/gid** for display and checks, not a multi-user kernel.
|
||||||
- **FIFOs, `mknod`, real devices** — No kernel FIFOs or **`mknod`**; **`mkfifo`** creates **in-memory** channels under **`/run/bare-os/ipc/<name>`** (see **`bare-os-ipc.js`**). Optional **`BARE_OS_IPC_MAX_CHANNELS`** caps distinct channel keys; **`metrics_live.ipcTelemetry`** mirrors FIFO depth, fan-out counts, and quota counters.
|
- **FIFOs, `mknod`, real devices** — No kernel FIFOs or **`mknod`**; **`mkfifo`** creates **in-memory** channels under **`/run/bare-os/ipc/<name>`** (see **`bare-os-ipc.js`**). Optional **`BARE_OS_IPC_MAX_CHANNELS`** caps distinct channel keys; **`metrics_live.ipcTelemetry`** mirrors FIFO depth, fan-out counts, and quota counters.
|
||||||
- **Full POSIX/GNU `xargs`** — Bounded implementation: **`ctx.runBinCommand`** only; **`-0`**, **`-n`** (and **`-nN`**), optional **`-P`** parallelism with effective cap **`min(requested, BARE_OS_XARGS_MAX_PROCS, 32)`** (default **8** when env unset; sequential when **`0`**); stdin, token, and invocation caps (see **`src/xargs.js`**).
|
- **Full POSIX/GNU `xargs`** — Bounded implementation: **`ctx.runBinCommand`** only; **`-0`**, **`-n`** (and **`-nN`**), optional **`-P`** parallelism with effective cap **`min(requested, BARE_OS_XARGS_MAX_PROCS, 32)`** (default **8** when env unset; sequential when **`0`**); stdin, token, and invocation caps (see **`src/xargs.js`**).
|
||||||
@@ -72,7 +72,7 @@ Hyperdrive does not always behave like a POSIX directory tree. Empty directories
|
|||||||
|
|
||||||
### 2.3 Pseudo **`/proc`**, **`/sys`**, **`/run`**, **`/dev`**, and session **`/tmp`**
|
### 2.3 Pseudo **`/proc`**, **`/sys`**, **`/run`**, **`/dev`**, and session **`/tmp`**
|
||||||
|
|
||||||
- **`/proc`**, **`/sys`**, **`/run`**, **`/dev`** — read-only synthetic trees except **`/dev/null`** and **`/dev/zero`** accept writes that are discarded, and **`/dev/shm/<name>`** accepts **`writeFile`** / **`readFile`** / **`unlink`** for **in-memory** named segments (see [POSIX declared profile](../docs/architecture/POSIX_DECLARED_PROFILE.md)). Other pseudo **`writeFile`** / **`unlink`** / **`chmod`** paths fail as documented there. Linux-shaped **synthetic** files include **`/proc/cpuinfo`**, **`/proc/meminfo`**, **`/proc/loadavg`**, **`/proc/net/dev`**, **`/proc/diskstats`**, and **data-backed** **`/proc/self/cgroups`**, **`/proc/net/tcp`**, **`/proc/net/udp`** (session / swarm / quota hints; stable columns where practical). **`/proc/bare_os/`** (stable aliases + **`index.json`** schema **8**, listing Pear/Bare operator JSON from Capability words 6–11 such as **`pear_stage_pointer.json`**, **`bare_module_resolution.json`**, **`pear_doctor_state.json`**, **`bare_boot_phase_map.json`**, …, plus **`syscalls.json`** (schema **5**; stock booter **caches** JSON until warm read-cache invalidation), **`process_table.json`** (**schema 5**: PGID/SID-style fields, **`parentName`**, **`signalRouting`**, initd binding), **`metrics.prom`**, **`protomux.json`** (schema **2** RPC pool / backpressure hints), **`/proc/bare_os_quotas`**, **`/proc/bare_os_resources`**, **`/proc/bare_os_features`**, **`/proc/bare_os_session_stats`**, **`/proc/bare_os_swarm`**, **`/proc/bare_os_replication`**, **`/proc/bare_os_manifest_hints`**, **`/proc/bare_os_peer_health`**, **`/proc/bare_os_staging_slot`**, **`/proc/bare_os_snapshot_hints`**, **`/proc/bare_os_provenance`**, **`/proc/bare_os_pear_ipc_registry`**, **`/proc/bare_os_initd_dag`**, **`/proc/bare_os_initd_graph`**, **`/proc/bare_os_pear_trust`**, **`/proc/bare_os_rlimits`**, **`/proc/bare_os_hdms_health`**, **`/proc/bare_os_metrics_live`** (and **`/proc/bare_os/metrics_live.json`**), **`/proc/bare_os/metrics.prom`** (OpenMetrics text for kernel counters), **`/proc/bare_os_extensions.json`**, **`/proc/bare_os_hdms_hints.json`**, **`/proc/bare_os_capabilities`** (and **`/proc/bare_os_capabilities.json`**), **`/proc/bare_os_bootstrap`**, **`/proc/bare_os_union`**, **`/proc/bare_os_seed_handshake`**, **`/proc/bare_os_virtual_registry`**, **`/proc/self/cgroups`**, **`/proc/self/exe`**, **`/proc/self/fd/0`–`2`**, **`/sys/class/net/lo`**, **`/sys/devices/virtual`**, **`/sys/fs/bare_os/build_id`**, **`/run/bare-os/virtual/*`**, **`/run/bare-os/unit-journal/*.ndjson`**, **`/run/bare-os/kernel-ext-reload.ndjson`** (append-only **`kernelExtReloadSchemaVersion`** lines when **`BARE_OS_KERNEL_EXT_D_HOT_RELOAD`** and **`ctx.bareOsReloadKernelExtDropinsSafe()`** run), and **`/dev/urandom`** (each **`readFile`** of urandom returns a **bounded** buffer; **not** suitable for cryptography unless **`BARE_OS_URANDOM_CRYPTO`** is left at default). Optional union write denials use **`BARE_OS_VFS_UNION_WRITE_DENY`** (see [kernel extensions](../docs/reference/kernel-extensions.md)). With **`BARE_OS_VFS_WATCH_PSEUDO=1`**, **`vfs.watch`** may poll coalesced **`metrics_live`** and **`metrics.prom`**. With **`BARE_OS_VFS_WATCH_SWARM=1`**, **`vfs.watch`** may poll coalesced **`swarm`** / **`replication`** pseudo files. Use **`ctx.bareOsReadProcMetricsLive()`** for the same JSON as **`metrics_live`** without a VFS read. **`/bin/env`** supports **`-S`** / **`--env-file`** when **`BARE_OS_ENV_DASH_S=1`**. Shell **`${…}`** v2 (**`##`**, **`%%`**, **`:=`**, basename **`*/`**) requires **`BARE_OS_SHELL_PARAM_EXPANSION_V2=1`** with param expansion enabled. V3 adds **`:?`** / **`:+`** when **`BARE_OS_SHELL_PARAM_EXPANSION_V3=1`**. Gated **`local`** / read-only **`declare -r`** use **`BARE_OS_SHELL_LOCAL_DECLARE=1`**.
|
- **`/proc`**, **`/sys`**, **`/run`**, **`/dev`** — read-only synthetic trees except **`/dev/null`** and **`/dev/zero`** accept writes that are discarded, and **`/dev/shm/<name>`** accepts **`writeFile`** / **`readFile`** / **`unlink`** for **in-memory** named segments (see [POSIX declared profile](../docs/architecture/POSIX_DECLARED_PROFILE.md)). Other pseudo **`writeFile`** / **`unlink`** / **`chmod`** paths fail as documented there. Linux-shaped **synthetic** files include **`/proc/cpuinfo`**, **`/proc/meminfo`**, **`/proc/loadavg`**, **`/proc/net/dev`**, **`/proc/diskstats`**, and **data-backed** **`/proc/self/cgroups`**, **`/proc/net/tcp`**, **`/proc/net/udp`** (session / swarm / quota hints; stable columns where practical). **`/proc/bare_os/`** (stable aliases + **`index.json`** schema **8**, listing Pear/Bare operator JSON from Capability words 6–11 such as **`pear_stage_pointer.json`**, **`bare_module_resolution.json`**, **`pear_doctor_state.json`**, **`bare_boot_phase_map.json`**, …, plus **`syscalls.json`** (schema **8**; stock booter **caches** JSON until warm read-cache invalidation), **`process_table.json`** (**schema 7**: PGID/SID-style fields, **`parentName`**, **`signalRouting`**, initd binding), **`metrics.prom`**, **`protomux.json`** (schema **2** RPC pool / backpressure hints), **`/proc/bare_os_quotas`**, **`/proc/bare_os_resources`**, **`/proc/bare_os_features`**, **`/proc/bare_os_session_stats`**, **`/proc/bare_os_swarm`**, **`/proc/bare_os_replication`**, **`/proc/bare_os_manifest_hints`**, **`/proc/bare_os_peer_health`**, **`/proc/bare_os_staging_slot`**, **`/proc/bare_os_snapshot_hints`**, **`/proc/bare_os_provenance`**, **`/proc/bare_os_pear_ipc_registry`**, **`/proc/bare_os_initd_dag`**, **`/proc/bare_os_initd_graph`**, **`/proc/bare_os_pear_trust`**, **`/proc/bare_os_rlimits`**, **`/proc/bare_os_hdms_health`**, **`/proc/bare_os_metrics_live`** (and **`/proc/bare_os/metrics_live.json`**), **`/proc/bare_os/metrics.prom`** (OpenMetrics text for kernel counters), **`/proc/bare_os_extensions.json`**, **`/proc/bare_os_hdms_hints.json`**, **`/proc/bare_os_capabilities`** (and **`/proc/bare_os_capabilities.json`**), **`/proc/bare_os_bootstrap`**, **`/proc/bare_os_union`**, **`/proc/bare_os_seed_handshake`**, **`/proc/bare_os_virtual_registry`**, **`/proc/self/cgroups`**, **`/proc/self/exe`**, **`/proc/self/fd/0`–`2`**, **`/sys/class/net/lo`**, **`/sys/devices/virtual`**, **`/sys/fs/bare_os/build_id`**, **`/run/bare-os/virtual/*`**, **`/run/bare-os/unit-journal/*.ndjson`**, **`/run/bare-os/kernel-ext-reload.ndjson`** (append-only **`kernelExtReloadSchemaVersion`** lines when **`BARE_OS_KERNEL_EXT_D_HOT_RELOAD`** and **`ctx.bareOsReloadKernelExtDropinsSafe()`** run), and **`/dev/urandom`** (each **`readFile`** of urandom returns a **bounded** buffer; **not** suitable for cryptography unless **`BARE_OS_URANDOM_CRYPTO`** is left at default). Optional union write denials use **`BARE_OS_VFS_UNION_WRITE_DENY`** (see [kernel extensions](../docs/reference/kernel-extensions.md)). With **`BARE_OS_VFS_WATCH_PSEUDO=1`**, **`vfs.watch`** may poll coalesced **`metrics_live`** and **`metrics.prom`**. With **`BARE_OS_VFS_WATCH_SWARM=1`**, **`vfs.watch`** may poll coalesced **`swarm`** / **`replication`** pseudo files. Use **`ctx.bareOsReadProcMetricsLive()`** for the same JSON as **`metrics_live`** without a VFS read. **`/bin/env`** supports **`-S`** / **`--env-file`** when **`BARE_OS_ENV_DASH_S=1`**. Shell **`${…}`** v2 (**`##`**, **`%%`**, **`:=`**, basename **`*/`**) requires **`BARE_OS_SHELL_PARAM_EXPANSION_V2=1`** with param expansion enabled. V3 adds **`:?`** / **`:+`** when **`BARE_OS_SHELL_PARAM_EXPANSION_V3=1`**. Gated **`local`** / read-only **`declare -r`** use **`BARE_OS_SHELL_LOCAL_DECLARE=1`**.
|
||||||
- **`/tmp`** — writable on the **personal** drive under **`/.bare-os/tmp/<HOME-basename>/…`**, isolated like **`$HOME`** and **`/var/log`**.
|
- **`/tmp`** — writable on the **personal** drive under **`/.bare-os/tmp/<HOME-basename>/…`**, isolated like **`$HOME`** and **`/var/log`**.
|
||||||
|
|
||||||
### 2.4 `chmod` (octal and symbolic)
|
### 2.4 `chmod` (octal and symbolic)
|
||||||
@@ -95,7 +95,7 @@ With **`BARE_OS_VFS_BIN_CACHE=1`**, the booter keeps a bounded LRU of system-dri
|
|||||||
### 2.6 Copy and move
|
### 2.6 Copy and move
|
||||||
|
|
||||||
- **`cp`** — **`-R`/`-r`** recursive copy; follows the same marker convention (skips copying **`.bareos_empty`** as a separate “file” where appropriate).
|
- **`cp`** — **`-R`/`-r`** recursive copy; follows the same marker convention (skips copying **`.bareos_empty`** as a separate “file” where appropriate).
|
||||||
- **`mv`** — Hyperdrive has no atomic **`rename`**; the general case is copy-tree + **`vfs.rm`** on the source. A **single regular file** to a non-directory destination uses **`readFile` → `writeFile` → `unlink`** on the source (same semantics, slightly less overhead than recursive **`rm`**).
|
- **`mv`** — Hyperdrive has no atomic **`rename`**; the general case is copy-tree + **`vfs.rm`** on the source. A **single regular file** to a non-directory destination uses a **two-phase write** (stage as **`.bare-os-mv-tmp.*`** in the **resolved destination directory**, write destination, remove stage, **`unlink`** source) so a failed destination write does not remove the source (see [POSIX declared profile](../docs/architecture/POSIX_DECLARED_PROFILE.md)).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ Beyond **`alias`**, **`unalias`**, **`cd`**, **`export`**, **`login`**, **`logou
|
|||||||
|
|
||||||
## 5. `/bin` utilities (catalog)
|
## 5. `/bin` utilities (catalog)
|
||||||
|
|
||||||
Sources: **`packages/bare-os-coreutils/src/<name>.js`**. **Authoritative sorted list:** **`packages/bare-os-coreutils/lib/commands.mjs`** (**`COREUTILS_COMMANDS`**), consumed by **`build.mjs`**.
|
Sources: **`packages/bare-os-coreutils/src/<name>.js`**. **Authoritative sorted list:** **`packages/bare-os-coreutils/lib/commands.mjs`** (**`COREUTILS_COMMANDS`**), consumed by **`build.mjs`**. **`man(1)`** pages are kept in lockstep with that list: CI runs **`scripts/verify-man-coverage.mjs`** (every Tier-1 **`/bin`** name has merged JSON under **`kernel/share/man/`** after **`npm run build -w bare-os-coreutils`**).
|
||||||
|
|
||||||
### 5.1 Filesystem and links
|
### 5.1 Filesystem and links
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ When **`BARE_OS_VFS_UNION_PREFIXES`** overlays the personal drive on system path
|
|||||||
- **`sum`** — SysV default or **`-r`** BSD 16-bit checksum + 512-byte block counts.
|
- **`sum`** — SysV default or **`-r`** BSD 16-bit checksum + 512-byte block counts.
|
||||||
- **`uniq`** — **`-c`**, **`-d`**, **`-u`** on adjacent lines (sort input first for POSIX-style behavior).
|
- **`uniq`** — **`-c`**, **`-d`**, **`-u`** on adjacent lines (sort input first for POSIX-style behavior).
|
||||||
- **`paste`** — **`-d`** delimiter list, **`-s`** serial (one file’s lines joined per output row).
|
- **`paste`** — **`-d`** delimiter list, **`-s`** serial (one file’s lines joined per output row).
|
||||||
- **`split`** — **`-l`** lines or **`-b`** bytes per chunk; output basename + alphabetic suffix; max files **`BARE_OS_SPLIT_MAX_FILES`** ( **`getconf`** default **10000**).
|
- **`split`** — **`-l`** lines or **`-b`** bytes per chunk; output basename + POSIX-style multi-length **`a`–`z`** suffixes (**`aa`…`zz`**, then **`aaa`**, **`aab`**, …); max files **`BARE_OS_SPLIT_MAX_FILES`** ( **`getconf`** default **10000**).
|
||||||
- **`tac`**, **`rev`** — Reverse line order / reverse characters per line.
|
- **`tac`**, **`rev`** — Reverse line order / reverse characters per line.
|
||||||
- **`expand`**, **`unexpand`** — Uniform tab width (**`-t`** / **`-tN`**); spaces ↔ tabs.
|
- **`expand`**, **`unexpand`** — Uniform tab width (**`-t`** / **`-tN`**); spaces ↔ tabs.
|
||||||
- **`fold`** — **`-w`** fixed column wrap (no word-aware reflow).
|
- **`fold`** — **`-w`** fixed column wrap (no word-aware reflow).
|
||||||
|
|||||||
+32
-2
@@ -90,12 +90,34 @@ function bareOsEmitRaw(ctx, chunk) {
|
|||||||
/**
|
/**
|
||||||
* Move/rename via copy + delete. Hyperdrive has no single-key rename across paths, so
|
* Move/rename via copy + delete. Hyperdrive has no single-key rename across paths, so
|
||||||
* directory trees and cross-location moves are duplicated then removed. A single regular
|
* directory trees and cross-location moves are duplicated then removed. A single regular
|
||||||
* file to a new non-directory path uses read + write + unlink when detected below.
|
* file to a new non-directory path uses a two-phase write: staging buffer bytes under a
|
||||||
|
* unique **`.bare-os-mv-tmp.*`** name in the **resolved destination directory**, writing the final name,
|
||||||
|
* removing the staging file, then unlinking the source — so a failed final write leaves
|
||||||
|
* the source path intact (staging is best-effort removed).
|
||||||
*
|
*
|
||||||
* Documented limitations: cross-volume moves always copy+delete; EXDEV-style behavior is
|
* Documented limitations: cross-volume moves always copy+delete; EXDEV-style behavior is
|
||||||
* implicit. Busy targets, partial copy failures, and union read-only trees surface as
|
* implicit. Busy targets, partial copy failures, and union read-only trees surface as
|
||||||
* generic errors from the VFS. Prefer same-directory renames for smallest blast radius.
|
* generic errors from the VFS. Prefer same-directory renames for smallest blast radius.
|
||||||
*/
|
*/
|
||||||
|
function mvStagingPathForTarget(ctx, target) {
|
||||||
|
const raw =
|
||||||
|
ctx.vfs && typeof ctx.vfs.resolveLogical === 'function'
|
||||||
|
? ctx.vfs.resolveLogical(target)
|
||||||
|
: String(target || '')
|
||||||
|
const trimmed = String(raw || '').replace(/\/+$/, '') || '/'
|
||||||
|
const last = trimmed.lastIndexOf('/')
|
||||||
|
const dir =
|
||||||
|
last < 0 ? '/' : last === 0 ? '/' : trimmed.slice(0, last) || '/'
|
||||||
|
const base =
|
||||||
|
last < 0 ? trimmed : trimmed.slice(last + 1) || 'file'
|
||||||
|
const tag =
|
||||||
|
Date.now().toString(36) +
|
||||||
|
'-' +
|
||||||
|
Math.random().toString(36).slice(2, 10) +
|
||||||
|
Math.random().toString(36).slice(2, 6)
|
||||||
|
const name = '.bare-os-mv-tmp.' + tag + '.' + base
|
||||||
|
return dir === '/' ? '/' + name : dir + '/' + name
|
||||||
|
}
|
||||||
async function mvCopyPath(ctx, from, to, recursive, followSymlink) {
|
async function mvCopyPath(ctx, from, to, recursive, followSymlink) {
|
||||||
const st = await ctx.vfs.lstat(from)
|
const st = await ctx.vfs.lstat(from)
|
||||||
if (!st) return false
|
if (!st) return false
|
||||||
@@ -206,7 +228,15 @@ async function run(ctx, argv) {
|
|||||||
if (singleFileToFile) {
|
if (singleFileToFile) {
|
||||||
const buf = await ctx.vfs.readFile(src)
|
const buf = await ctx.vfs.readFile(src)
|
||||||
if (!buf) throw new Error('cannot read source')
|
if (!buf) throw new Error('cannot read source')
|
||||||
await ctx.vfs.writeFile(target, buf)
|
const stage = mvStagingPathForTarget(ctx, target)
|
||||||
|
await ctx.vfs.writeFile(stage, buf)
|
||||||
|
try {
|
||||||
|
await ctx.vfs.writeFile(target, buf)
|
||||||
|
} catch (e) {
|
||||||
|
await ctx.vfs.unlink(stage).catch(() => {})
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
await ctx.vfs.unlink(stage).catch(() => {})
|
||||||
await ctx.vfs.unlink(src)
|
await ctx.vfs.unlink(src)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-3
@@ -87,11 +87,28 @@ function bareOsEmitRaw(ctx, chunk) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POSIX-style suffix: `aa`…`zz` (676 files), then `aaa`, `aab`, … as needed.
|
||||||
|
* @param {string} prefix
|
||||||
|
* @param {number} i 0-based output index
|
||||||
|
*/
|
||||||
function splitSuffix(prefix, i) {
|
function splitSuffix(prefix, i) {
|
||||||
const a = 'abcdefghijklmnopqrstuvwxyz'
|
const a = 'abcdefghijklmnopqrstuvwxyz'
|
||||||
const hi = Math.floor(i / 26) % 26
|
let idx = i
|
||||||
const lo = i % 26
|
let len = 2
|
||||||
return prefix + a[hi] + a[lo]
|
let span = 26 ** len
|
||||||
|
while (idx >= span) {
|
||||||
|
idx -= span
|
||||||
|
len++
|
||||||
|
span = 26 ** len
|
||||||
|
}
|
||||||
|
let s = ''
|
||||||
|
let n = idx
|
||||||
|
for (let p = 0; p < len; p++) {
|
||||||
|
s = a[n % 26] + s
|
||||||
|
n = Math.floor(n / 26)
|
||||||
|
}
|
||||||
|
return prefix + s
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run(ctx, argv) {
|
async function run(ctx, argv) {
|
||||||
|
|||||||
+5
-2
@@ -88,11 +88,14 @@ function bareOsEmitRaw(ctx, chunk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host spawn).
|
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host fork of arbitrary binaries).
|
||||||
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
||||||
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
||||||
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||||
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race).
|
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race); parallelism is still in-process
|
||||||
|
* over runBinCommand unless the booter/worker stack offloads specific /bin basenames (see BARE_OS_BIN_WORKER_*).
|
||||||
|
* For explicit host subprocess offload of whitelisted utilities, use ctx.bareOsTrySpawnHostSubprocess from custom scripts with
|
||||||
|
* BARE_OS_BIN_WORKER_ALLOW / delegate policy — not automatic from xargs.
|
||||||
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 8,
|
"schemaVersion": 8,
|
||||||
"ctxApiVersion": "1.44.0",
|
"ctxApiVersion": "1.45.0",
|
||||||
"posixProfile": {
|
"posixProfile": {
|
||||||
"id": "bare-os-posix-like",
|
"id": "bare-os-posix-like",
|
||||||
"version": "1.0.9"
|
"version": "1.0.9"
|
||||||
@@ -32,7 +32,19 @@
|
|||||||
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
|
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
|
||||||
},
|
},
|
||||||
"socketMsgSurface": {
|
"socketMsgSurface": {
|
||||||
"schema": 2,
|
"schema": 3,
|
||||||
|
"ancillaryControl": {
|
||||||
|
"supported": false,
|
||||||
|
"errno": "ENOTSUP",
|
||||||
|
"rejectKeys": [
|
||||||
|
"cmsgs",
|
||||||
|
"control",
|
||||||
|
"controllen",
|
||||||
|
"msgHdr.control",
|
||||||
|
"msgHdr.cmsgs"
|
||||||
|
],
|
||||||
|
"note": "Non-empty ancillary fields on sendmsg rejected; recvmsg controllen 0."
|
||||||
|
},
|
||||||
"sendmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" },
|
"sendmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" },
|
||||||
"recvmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" }
|
"recvmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" }
|
||||||
},
|
},
|
||||||
|
|||||||
+198
-198
@@ -7,36 +7,36 @@
|
|||||||
"hypercoreIdEncoding"
|
"hypercoreIdEncoding"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/safetyCatch.js",
|
|
||||||
"keys": [
|
|
||||||
"safetyCatch"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/b4a.js",
|
"path": "/lib/bare/bundles/b4a.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"b4a"
|
"b4a"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/safetyCatch.js",
|
||||||
|
"keys": [
|
||||||
|
"safetyCatch"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/compactEncoding.js",
|
"path": "/lib/bare/bundles/compactEncoding.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"compactEncoding"
|
"compactEncoding"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareUrl.js",
|
|
||||||
"keys": [
|
|
||||||
"bareUrl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/protomux.js",
|
"path": "/lib/bare/bundles/protomux.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"protomux"
|
"protomux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareUrl.js",
|
||||||
|
"keys": [
|
||||||
|
"bareUrl"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePath.js",
|
"path": "/lib/bare/bundles/barePath.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -74,9 +74,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareAddonResolve.js",
|
"path": "/lib/bare/bundles/bareReadline.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareAddonResolve"
|
"bareReadline"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -86,15 +86,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareReadline.js",
|
"path": "/lib/bare/bundles/bareAddonResolve.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareReadline"
|
"bareAddonResolve"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareApk.js",
|
|
||||||
"keys": [
|
|
||||||
"bareApk"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -109,12 +103,6 @@
|
|||||||
"bareAtomics"
|
"bareAtomics"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareAppKit.js",
|
|
||||||
"keys": [
|
|
||||||
"bareAppKit"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareAssert.js",
|
"path": "/lib/bare/bundles/bareAssert.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -122,9 +110,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBmp.js",
|
"path": "/lib/bare/bundles/bareApk.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareBmp"
|
"bareApk"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareAppKit.js",
|
||||||
|
"keys": [
|
||||||
|
"bareAppKit"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -133,12 +127,24 @@
|
|||||||
"fetch"
|
"fetch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareBmp.js",
|
||||||
|
"keys": [
|
||||||
|
"bareBmp"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBundleCompile.js",
|
"path": "/lib/bare/bundles/bareBundleCompile.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareBundleCompile"
|
"bareBundleCompile"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareBuffer.js",
|
||||||
|
"keys": [
|
||||||
|
"bareBuffer"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBluetoothApple.js",
|
"path": "/lib/bare/bundles/bareBluetoothApple.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -151,30 +157,24 @@
|
|||||||
"bareBundle"
|
"bareBundle"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareBuffer.js",
|
|
||||||
"keys": [
|
|
||||||
"bareBuffer"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
|
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareBundleEvaluate"
|
"bareBundleEvaluate"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareBoot.js",
|
|
||||||
"keys": [
|
|
||||||
"bareBoot"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareConsole.js",
|
"path": "/lib/bare/bundles/bareConsole.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareConsole"
|
"bareConsole"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareBoot.js",
|
||||||
|
"keys": [
|
||||||
|
"bareBoot"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBundleId.js",
|
"path": "/lib/bare/bundles/bareBundleId.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -187,18 +187,18 @@
|
|||||||
"bareChannel"
|
"bareChannel"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareDelta.js",
|
|
||||||
"keys": [
|
|
||||||
"bareDelta"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareDebugLog.js",
|
"path": "/lib/bare/bundles/bareDebugLog.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareDebugLog"
|
"bareDebugLog"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareDelta.js",
|
||||||
|
"keys": [
|
||||||
|
"bareDelta"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareDaemon.js",
|
"path": "/lib/bare/bundles/bareDaemon.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -217,6 +217,12 @@
|
|||||||
"bareDns"
|
"bareDns"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareCov.js",
|
||||||
|
"keys": [
|
||||||
|
"bareCov"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareEnv.js",
|
"path": "/lib/bare/bundles/bareEnv.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -235,12 +241,6 @@
|
|||||||
"bareExif"
|
"bareExif"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareCov.js",
|
|
||||||
"keys": [
|
|
||||||
"bareCov"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareFfmpeg.js",
|
"path": "/lib/bare/bundles/bareFfmpeg.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -260,9 +260,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareGif.js",
|
"path": "/lib/bare/bundles/bareFileLogger.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareGif"
|
"bareFileLogger"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -272,9 +272,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareFileLogger.js",
|
"path": "/lib/bare/bundles/bareGif.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareFileLogger"
|
"bareGif"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -290,9 +290,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareHttpParser.js",
|
"path": "/lib/bare/bundles/bareFs.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareHttpParser"
|
"bareFs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -301,24 +301,18 @@
|
|||||||
"bareGtk"
|
"bareGtk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareHttpParser.js",
|
||||||
|
"keys": [
|
||||||
|
"bareHttpParser"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareIco.js",
|
"path": "/lib/bare/bundles/bareIco.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareIco"
|
"bareIco"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareFs.js",
|
|
||||||
"keys": [
|
|
||||||
"bareFs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareHttp1.js",
|
|
||||||
"keys": [
|
|
||||||
"bareHttp1"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareImageResample.js",
|
"path": "/lib/bare/bundles/bareImageResample.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -332,9 +326,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareHttps.js",
|
"path": "/lib/bare/bundles/bareHttp1.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareHttps"
|
"bareHttp1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -344,9 +338,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareIpc.js",
|
"path": "/lib/bare/bundles/bareHttps.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareIpc"
|
"bareHttps"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -355,6 +349,18 @@
|
|||||||
"bareIntl"
|
"bareIntl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareIpc.js",
|
||||||
|
"keys": [
|
||||||
|
"bareIpc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareLogger.js",
|
||||||
|
"keys": [
|
||||||
|
"bareLogger"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareInspector.js",
|
"path": "/lib/bare/bundles/bareInspector.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -367,12 +373,6 @@
|
|||||||
"bareLief"
|
"bareLief"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareLogger.js",
|
|
||||||
"keys": [
|
|
||||||
"bareLogger"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareLink.js",
|
"path": "/lib/bare/bundles/bareLink.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -385,30 +385,30 @@
|
|||||||
"bareMake"
|
"bareMake"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareModule.js",
|
|
||||||
"keys": [
|
|
||||||
"bareModule"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareModuleResolve.js",
|
"path": "/lib/bare/bundles/bareModuleResolve.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareModuleResolve"
|
"bareModuleResolve"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareModuleLexer.js",
|
|
||||||
"keys": [
|
|
||||||
"bareModuleLexer"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareModuleTraverse.js",
|
"path": "/lib/bare/bundles/bareModuleTraverse.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareModuleTraverse"
|
"bareModuleTraverse"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareModule.js",
|
||||||
|
"keys": [
|
||||||
|
"bareModule"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareModuleLexer.js",
|
||||||
|
"keys": [
|
||||||
|
"bareModuleLexer"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareNdk.js",
|
"path": "/lib/bare/bundles/bareNdk.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -439,12 +439,6 @@
|
|||||||
"bareNet"
|
"bareNet"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareMedia.js",
|
|
||||||
"keys": [
|
|
||||||
"bareMedia"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareOs.js",
|
"path": "/lib/bare/bundles/bareOs.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -452,15 +446,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePerformance.js",
|
"path": "/lib/bare/bundles/bareMedia.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"barePerformance"
|
"bareMedia"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/barePackDrive.js",
|
|
||||||
"keys": [
|
|
||||||
"barePackDrive"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -469,12 +457,30 @@
|
|||||||
"barePack"
|
"barePack"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/barePerformance.js",
|
||||||
|
"keys": [
|
||||||
|
"barePerformance"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareNodeRuntime.js",
|
||||||
|
"keys": [
|
||||||
|
"bareNodeRuntime"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePng.js",
|
"path": "/lib/bare/bundles/barePng.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"barePng"
|
"barePng"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/barePackDrive.js",
|
||||||
|
"keys": [
|
||||||
|
"barePackDrive"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePipe.js",
|
"path": "/lib/bare/bundles/barePipe.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -488,15 +494,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareNodeRuntime.js",
|
"path": "/lib/bare/bundles/bareQuerystring.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareNodeRuntime"
|
"bareQuerystring"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareDev.js",
|
|
||||||
"keys": [
|
|
||||||
"bareDev"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -506,9 +506,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareQuerystring.js",
|
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareQuerystring"
|
"bareQueueMicrotask"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -523,24 +523,12 @@
|
|||||||
"bareProcess"
|
"bareProcess"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
|
|
||||||
"keys": [
|
|
||||||
"bareQueueMicrotask"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePromClient.js",
|
"path": "/lib/bare/bundles/barePromClient.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"barePromClient"
|
"barePromClient"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareRpc.js",
|
|
||||||
"keys": [
|
|
||||||
"bareRpc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareRuntime.js",
|
"path": "/lib/bare/bundles/bareRuntime.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -548,15 +536,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSemver.js",
|
"path": "/lib/bare/bundles/bareRpc.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareSemver"
|
"bareRpc"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareSdl.js",
|
|
||||||
"keys": [
|
|
||||||
"bareSdl"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -565,6 +547,18 @@
|
|||||||
"bareRepl"
|
"bareRepl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareSemver.js",
|
||||||
|
"keys": [
|
||||||
|
"bareSemver"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareDev.js",
|
||||||
|
"keys": [
|
||||||
|
"bareDev"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSidecar.js",
|
"path": "/lib/bare/bundles/bareSidecar.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -577,6 +571,12 @@
|
|||||||
"bareSignals"
|
"bareSignals"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareSdl.js",
|
||||||
|
"keys": [
|
||||||
|
"bareSdl"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareRun.js",
|
"path": "/lib/bare/bundles/bareRun.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -589,60 +589,60 @@
|
|||||||
"bareStringDecoder"
|
"bareStringDecoder"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareStorage.js",
|
|
||||||
"keys": [
|
|
||||||
"bareStorage"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareStream.js",
|
"path": "/lib/bare/bundles/bareStream.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareStream"
|
"bareStream"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareStdio.js",
|
|
||||||
"keys": [
|
|
||||||
"bareStdio"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSvg.js",
|
"path": "/lib/bare/bundles/bareSvg.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareSvg"
|
"bareSvg"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareStdio.js",
|
||||||
|
"keys": [
|
||||||
|
"bareStdio"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareStorage.js",
|
||||||
|
"keys": [
|
||||||
|
"bareStorage"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareStructuredClone.js",
|
"path": "/lib/bare/bundles/bareStructuredClone.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareStructuredClone"
|
"bareStructuredClone"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareSystemLogger.js",
|
|
||||||
"keys": [
|
|
||||||
"bareSystemLogger"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareTap.js",
|
|
||||||
"keys": [
|
|
||||||
"bareTap"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareTiff.js",
|
"path": "/lib/bare/bundles/bareTiff.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareTiff"
|
"bareTiff"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareSystemLogger.js",
|
||||||
|
"keys": [
|
||||||
|
"bareSystemLogger"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSubprocess.js",
|
"path": "/lib/bare/bundles/bareSubprocess.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareSubprocess"
|
"bareSubprocess"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareTap.js",
|
||||||
|
"keys": [
|
||||||
|
"bareTap"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareTcp.js",
|
"path": "/lib/bare/bundles/bareTcp.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -655,18 +655,18 @@
|
|||||||
"bareThread"
|
"bareThread"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareTimers.js",
|
|
||||||
"keys": [
|
|
||||||
"bareTimers"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareTpl.js",
|
"path": "/lib/bare/bundles/bareTpl.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareTpl"
|
"bareTpl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareTimers.js",
|
||||||
|
"keys": [
|
||||||
|
"bareTimers"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareType.js",
|
"path": "/lib/bare/bundles/bareType.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -691,12 +691,6 @@
|
|||||||
"bareTty"
|
"bareTty"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareV8.js",
|
|
||||||
"keys": [
|
|
||||||
"bareV8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareUnpack.js",
|
"path": "/lib/bare/bundles/bareUnpack.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -704,9 +698,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareUnionBundle.js",
|
"path": "/lib/bare/bundles/bareV8.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareUnionBundle"
|
"bareV8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareVm.js",
|
||||||
|
"keys": [
|
||||||
|
"bareVm"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -722,21 +722,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareVm.js",
|
"path": "/lib/bare/bundles/bareUnionBundle.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareVm"
|
"bareUnionBundle"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareUtils.js",
|
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareUtils"
|
"bareV8ToIstanbul"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareWebKitGtk.js",
|
|
||||||
"keys": [
|
|
||||||
"bareWebKitGtk"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -745,6 +739,12 @@
|
|||||||
"bareWebp"
|
"bareWebp"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareUtils.js",
|
||||||
|
"keys": [
|
||||||
|
"bareUtils"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareWhich.js",
|
"path": "/lib/bare/bundles/bareWhich.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -752,15 +752,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareWinUi.js",
|
"path": "/lib/bare/bundles/bareWebKitGtk.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareWinUi"
|
"bareWebKitGtk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
|
"path": "/lib/bare/bundles/bareWinUi.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareV8ToIstanbul"
|
"bareWinUi"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -775,6 +775,12 @@
|
|||||||
"bareZlib"
|
"bareZlib"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareWs.js",
|
||||||
|
"keys": [
|
||||||
|
"bareWs"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareZmq.js",
|
"path": "/lib/bare/bundles/bareZmq.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -786,12 +792,6 @@
|
|||||||
"keys": [
|
"keys": [
|
||||||
"bareWorker"
|
"bareWorker"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareWs.js",
|
|
||||||
"keys": [
|
|
||||||
"bareWs"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bundleStats": {
|
"bundleStats": {
|
||||||
@@ -1595,8 +1595,8 @@
|
|||||||
],
|
],
|
||||||
"bundleProvenance": {
|
"bundleProvenance": {
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"generatedAt": "2026-04-05T05:06:01.462Z",
|
"generatedAt": "2026-04-05T05:30:46.127Z",
|
||||||
"gitCommit": "f79db043130bdbfffa8bcca66fd6252c9d17205d",
|
"gitCommit": "c64910d72ee5547302fce1717ffedd42594e4bc4",
|
||||||
"nodeVersion": "v22.22.0",
|
"nodeVersion": "v22.22.0",
|
||||||
"bundleTier": "all",
|
"bundleTier": "all",
|
||||||
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"atMs": 1775365560517,
|
"atMs": 1775367045352,
|
||||||
"commands": [
|
"commands": [
|
||||||
"arch",
|
"arch",
|
||||||
"awk",
|
"awk",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -5,17 +5,20 @@ Authoritative **version alignment** with protocol and telemetry schema numbers l
|
|||||||
## Maintenance
|
## Maintenance
|
||||||
|
|
||||||
- **Host filesystem**: first-party booter and seeder sources use **`import … from '#host-fs'`** / **`#host-path`** (and seeder **`#host-fs-promises`**) so Bare resolves **`bare-fs`** / **`bare-path`** and Node resolves the built-in **`fs`** / **`path`** modules via the default **`imports`** condition. **`bare-fs`** is a direct **`dependencies`** entry of **`bare-os-booter`**. CI: **`scripts/verify-pear-no-static-node-import.mjs`** rejects bare **`fs`** / **`path`** specifiers.
|
- **Host filesystem**: first-party booter and seeder sources use **`import … from '#host-fs'`** / **`#host-path`** (and seeder **`#host-fs-promises`**) so Bare resolves **`bare-fs`** / **`bare-path`** and Node resolves the built-in **`fs`** / **`path`** modules via the default **`imports`** condition. **`bare-fs`** is a direct **`dependencies`** entry of **`bare-os-booter`**. CI: **`scripts/verify-pear-no-static-node-import.mjs`** rejects bare **`fs`** / **`path`** specifiers.
|
||||||
- **POSIX / proc**: **`/proc/bare_os/syscalls.json`** schema **5** (socket-family probes, **`posixXsh`** / **`fdModel`** / **`errnoAlignment`**; JSON text **cached** until **`vfs.bareOsClearWarmReadCaches`**); **`/proc/bare_os/process_table.json`** schema **6** (**`jobControlSemantics`** + **`parentName`**); **`/proc/bare_os/protomux.json`** wire text schema **2**; **`/dev/shm`** in-memory named segments. Protocol export **`BARE_OS_POSIX_PROFILE_*`**.
|
- **POSIX / proc**: **`/proc/bare_os/syscalls.json`** schema **8** (**`posixXsh`**, **`fdModel`**, **`socketMsgSurface`**, **`errnoHints`**; JSON text **cached** until **`vfs.bareOsClearWarmReadCaches`**); **`/proc/bare_os/process_table.json`** schema **7**; **`/proc/bare_os/protomux.json`** wire text schema **2**; **`/dev/shm`** in-memory named segments. Protocol export **`BARE_OS_POSIX_PROFILE_*`**.
|
||||||
- **Blind-relay / pairing / geo proc** (default): **`bareOsProcBlindPeerRelayHintsMinimal`** returns **schema 1** with **`operatorRedacted: true`**. The legacy export **`bareOsProcBlindPeerRelayHintsStub`** was removed; use **`bareOsProcBlindPeerRelayHintsMinimal`** only.
|
- **Blind-relay / pairing / geo proc** (default): **`bareOsProcBlindPeerRelayHintsMinimal`** returns **schema 1** with **`operatorRedacted: true`**. The legacy export **`bareOsProcBlindPeerRelayHintsStub`** was removed; use **`bareOsProcBlindPeerRelayHintsMinimal`** only.
|
||||||
- **Vendored bundles**: post-esbuild **`scripts/sanitize-bare-bundles.mjs`** (from **`bare-os-bare-libs/build.mjs`**) strips CI-forbidden markers and replaces **`node:`** requires in **`bareDev.js`** with **`bare-*`** modules.
|
- **Vendored bundles**: post-esbuild **`scripts/sanitize-bare-bundles.mjs`** (from **`bare-os-bare-libs/build.mjs`**) strips CI-forbidden markers and replaces **`node:`** requires in **`bareDev.js`** with **`bare-*`** modules.
|
||||||
- **Boot hooks (naming)**: canonical **`bareOsRegisterBootStepHook`**, **`bareOsInvokeBootStepHooks`**, **`bareOsEmitBareBootStepHint`**; legacy **`*BootPhase*`** methods remain thin wrappers (**no `bareOsCtxApiVersion` bump**). See [docs/reference/naming-alias-matrix.md](../../docs/reference/naming-alias-matrix.md).
|
- **Boot hooks (naming)**: canonical **`bareOsRegisterBootStepHook`**, **`bareOsInvokeBootStepHooks`**, **`bareOsEmitBareBootStepHint`**; legacy **`*BootPhase*`** methods remain thin wrappers (**no `bareOsCtxApiVersion` bump**). See [docs/reference/naming-alias-matrix.md](../../docs/reference/naming-alias-matrix.md).
|
||||||
- **Pear / Bare**: [`lib/kernel-runner.js`](lib/kernel-runner.js) must not **static**-import **`node:module`** (Bare’s resolver cannot load **`node:`** builtins from a **`pear://`** bundle). Optional **`BARE_OS_BIN_WORKER_OFFLOAD`** now obtains **`createRequire`** via **dynamic** **`import('bare-module')`** when running outside Node.
|
- **Pear / Bare**: [`lib/kernel-runner.js`](lib/kernel-runner.js) must not **static**-import **`node:module`** (Bare’s resolver cannot load **`node:`** builtins from a **`pear://`** bundle). Optional **`BARE_OS_BIN_WORKER_OFFLOAD`** now obtains **`createRequire`** via **dynamic** **`import('bare-module')`** when running outside Node.
|
||||||
- **`baretop`**: optional **`ctx.bareOsReadBareTopSnapshot()`** in [`index.js`](index.js) returns **`{ atMs, files }`** with the same keys as **`BARE_TOP_SNAPSHOT_PROC_ENTRIES`** in **`packages/bare-os-coreutils/lib/baretop-snapshot.js`** — keep those lists in sync when adding operator **`/proc/bare_os`** nodes.
|
- **`baretop`**: optional **`ctx.bareOsReadBareTopSnapshot()`** in [`index.js`](index.js) returns **`{ atMs, files }`** with the same keys as **`BARE_TOP_SNAPSHOT_PROC_ENTRIES`** in **`packages/bare-os-coreutils/lib/baretop-snapshot.js`** — keep those lists in sync when adding operator **`/proc/bare_os`** nodes.
|
||||||
|
- **hrpc allowlist**: shared parser in [`lib/bare-os-hrpc-allowlist.js`](lib/bare-os-hrpc-allowlist.js); **`ctx.bareOsHrpcRequest`** and **`ctx.bareOsHrpcAllowlistProbe`** stay aligned. Host passthrough copies **`BARE_OS_HRPC_ALLOWLIST_JSON`**, **`BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON`**, **`BARE_OS_BLIND_RELAY_TOPOLOGY_JSON`**, **`BARE_OS_MIRROR_DRIVE_COMPOSITION_HINT_JSON`**, **`BARE_OS_REPLICATION_PLAN_JSON`**, and pear-doctor env keys into session env.
|
||||||
|
- **Snapshot hints**: **`ctx.bareOsReadSnapshotHintsJson()`** merges **`BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON`** like **`/proc/bare_os/snapshot_hints.json`**.
|
||||||
|
|
||||||
## Context API (`bareOsCtxApiVersion`)
|
## Context API (`bareOsCtxApiVersion`)
|
||||||
|
|
||||||
| Version | Booter (workspace) | Notes |
|
| Version | Booter (workspace) | Notes |
|
||||||
| ------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
|
| 1.45.0 | 0.1.0 | **`BARE_OS_POSIX_SOCKET_FD_BRIDGE`**: SOCK_STREAM passive **`bind`** / **`listen`** / **`accept`** via **`bareTcp.Server`**; accepted fds use **`send`** / **`recv`** / **`recvfrom`** / **`recvmsg`** with bounded **`tcpRecvQueue`** (same cap family as **`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**); **`poll`/`select`** marks listening fds readable when the accept queue is non-empty; **`BARE_OS_POSIX_ACCEPT_QUEUE_MAX`** caps pending accepts. **`socketMsgSurface` schema 3** adds **`ancillaryControl`** and rejects non-empty **`sendmsg`** ancillary fields with **`ENOTSUP`** + **`ancillaryReject`**. **`shutdown`** closes a listening server or destroys a connected TCP bridge socket. |
|
||||||
| 1.42.0 | 0.1.0 | **`BARE_OS_POSIX_SOCKET_FD_BRIDGE`**: SOCK_DGRAM **`recv`** / **`recvfrom`** with bounded queue (**`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**, **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**); **`poll`/`select`** readiness on bridge UDP fds. **`/proc/bare_os/syscalls.json`** schema **7** + **`socketMsgSurface`**. Optional **`BARE_OS_PROTOMUX_APP_CHANNEL`** pairs **`bare-os-app-v1`** alongside **`bare-os-v1`**. **`guestReplicationPlan`** in **`/proc/bare_os/replication`** from **`BARE_OS_REPLICATION_PLAN_JSON`**. **`sync_window.json`** **`parallelismHint`** (**`BARE_OS_REPLICATION_SYNC_PARALLEL_MAX`**). Blind-relay swarm **`protomuxBackpressure`** (**`BARE_OS_SWARM_PROTOMUX_BACKPRESSURE_COUNT`**). **`BARE_OS_PEER_ALLOWLIST_STRICT`** fail-closed without allowlist. Removed **`bareOsProcBlindPeerRelayHintsStub`** (use **`bareOsProcBlindPeerRelayHintsMinimal`**). Kernel: optional **`pear.multisig.json`** gate before **`kernel.ext.d`** (**`BARE_OS_EXTENSION_MULTISIG_VERIFY`**, **`BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG`**). |
|
| 1.42.0 | 0.1.0 | **`BARE_OS_POSIX_SOCKET_FD_BRIDGE`**: SOCK_DGRAM **`recv`** / **`recvfrom`** with bounded queue (**`BARE_OS_POSIX_DGRAM_RECVQ_MAX`**, **`BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX`**); **`poll`/`select`** readiness on bridge UDP fds. **`/proc/bare_os/syscalls.json`** schema **7** + **`socketMsgSurface`**. Optional **`BARE_OS_PROTOMUX_APP_CHANNEL`** pairs **`bare-os-app-v1`** alongside **`bare-os-v1`**. **`guestReplicationPlan`** in **`/proc/bare_os/replication`** from **`BARE_OS_REPLICATION_PLAN_JSON`**. **`sync_window.json`** **`parallelismHint`** (**`BARE_OS_REPLICATION_SYNC_PARALLEL_MAX`**). Blind-relay swarm **`protomuxBackpressure`** (**`BARE_OS_SWARM_PROTOMUX_BACKPRESSURE_COUNT`**). **`BARE_OS_PEER_ALLOWLIST_STRICT`** fail-closed without allowlist. Removed **`bareOsProcBlindPeerRelayHintsStub`** (use **`bareOsProcBlindPeerRelayHintsMinimal`**). Kernel: optional **`pear.multisig.json`** gate before **`kernel.ext.d`** (**`BARE_OS_EXTENSION_MULTISIG_VERIFY`**, **`BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG`**). |
|
||||||
| 1.41.0 | 0.1.0 | **`BARE_OS_BARE_STDLIB_RESOLVE_CONCURRENCY`** — parallel **`readFile`** prefetch for **`/lib/bare`** drive bundles; eval order stays manifest order. **`vfs.bareOsEvictWarmReadPrefixes`** + **`BARE_OS_VFS_WARM_CACHE_PREFIX_INVALIDATE`** — selective warm-cache eviction when replication core lengths increase; **`metrics_live.replicationLive`** schema **2**. Stock **`ctx.bareOsHrpcRequest`**: optional **`BARE_OS_HRPC_AUDIT`** (audit chain rows), **`BARE_OS_HRPC_EMIT_UNLISTED`** gates **`bare-os:hrpc-request`** for non-stock routes (default off). **`/proc/bare_os/pear_runtime_channel.json`** (word 7). Warm read cache stats schema **2**; gated **`BARE_OS_VFS_HYPERBLOBS_DEDUP`** write telemetry + failure counter. |
|
| 1.41.0 | 0.1.0 | **`BARE_OS_BARE_STDLIB_RESOLVE_CONCURRENCY`** — parallel **`readFile`** prefetch for **`/lib/bare`** drive bundles; eval order stays manifest order. **`vfs.bareOsEvictWarmReadPrefixes`** + **`BARE_OS_VFS_WARM_CACHE_PREFIX_INVALIDATE`** — selective warm-cache eviction when replication core lengths increase; **`metrics_live.replicationLive`** schema **2**. Stock **`ctx.bareOsHrpcRequest`**: optional **`BARE_OS_HRPC_AUDIT`** (audit chain rows), **`BARE_OS_HRPC_EMIT_UNLISTED`** gates **`bare-os:hrpc-request`** for non-stock routes (default off). **`/proc/bare_os/pear_runtime_channel.json`** (word 7). Warm read cache stats schema **2**; gated **`BARE_OS_VFS_HYPERBLOBS_DEDUP`** write telemetry + failure counter. |
|
||||||
| 1.40.0 | 0.1.0 | **`vfs.bareOsEvictLibBareBundlesFromManifest`** + **`ctx.bareOsInvalidateWarmReadCachesFromBareManifestJson`** — manifest-aware **`/lib/bare`** warm-cache eviction; **`bareOsVfsBatchWrite`** uses selective eviction for manifest-only puts. **`/proc/bare_os/replication`** **`liveHyperdrive`** sketch + **`metrics_live.replicationLive`** (**`stallHint`**, core lengths). **`/run/bare-os/boot-perf.json`** schema **3** + **`BARE_OS_BOOT_BUDGET_STDLIB_*`** when bare-stdlib resolution exceeds **`BARE_OS_BOOT_BUDGET_MS_COLD`** / **`BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB`**. **`BARE_OS_SHELL_POSIX_MODE`** grouped **`( … )`** lists. **`bareOsTrySpawnHostSubprocess`** failures include **`errorCode`** / **`causeName`**. NDJSON / OTel string redaction helpers. **`scripts/sync-holepunch-clones.mjs`** NDJSON summary. **`docs/reference/posix-dashboard.md`** generated in pretest. |
|
| 1.40.0 | 0.1.0 | **`vfs.bareOsEvictLibBareBundlesFromManifest`** + **`ctx.bareOsInvalidateWarmReadCachesFromBareManifestJson`** — manifest-aware **`/lib/bare`** warm-cache eviction; **`bareOsVfsBatchWrite`** uses selective eviction for manifest-only puts. **`/proc/bare_os/replication`** **`liveHyperdrive`** sketch + **`metrics_live.replicationLive`** (**`stallHint`**, core lengths). **`/run/bare-os/boot-perf.json`** schema **3** + **`BARE_OS_BOOT_BUDGET_STDLIB_*`** when bare-stdlib resolution exceeds **`BARE_OS_BOOT_BUDGET_MS_COLD`** / **`BARE_OS_BOOT_BUDGET_MS_BARE_STDLIB`**. **`BARE_OS_SHELL_POSIX_MODE`** grouped **`( … )`** lists. **`bareOsTrySpawnHostSubprocess`** failures include **`errorCode`** / **`causeName`**. NDJSON / OTel string redaction helpers. **`scripts/sync-holepunch-clones.mjs`** NDJSON summary. **`docs/reference/posix-dashboard.md`** generated in pretest. |
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ import { buildBareOsBareModuleCryptoStagingProcJson } from './lib/bare-os-proc-b
|
|||||||
import { buildBareOsPearInspectLoggerTlsProcJson } from './lib/bare-os-proc-pear-inspect-logger-tls.js'
|
import { buildBareOsPearInspectLoggerTlsProcJson } from './lib/bare-os-proc-pear-inspect-logger-tls.js'
|
||||||
import { buildBareOsHypercorePackHrpcLifecycleProcJson } from './lib/bare-os-proc-hypercore-pack-hrpc-lifecycle.js'
|
import { buildBareOsHypercorePackHrpcLifecycleProcJson } from './lib/bare-os-proc-hypercore-pack-hrpc-lifecycle.js'
|
||||||
import { createBareOsIpc } from './lib/bare-os-ipc.js'
|
import { createBareOsIpc } from './lib/bare-os-ipc.js'
|
||||||
|
import {
|
||||||
|
parseBareOsHrpcAllowlistJson,
|
||||||
|
bareOsHrpcAllowlistDeniesRoute
|
||||||
|
} from './lib/bare-os-hrpc-allowlist.js'
|
||||||
import {
|
import {
|
||||||
execShellLine,
|
execShellLine,
|
||||||
syncBareOsExitStatusEnv,
|
syncBareOsExitStatusEnv,
|
||||||
@@ -621,6 +625,14 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
'BARE_OS_VFS_WARM_CACHE_PREFIX_INVALIDATE',
|
'BARE_OS_VFS_WARM_CACHE_PREFIX_INVALIDATE',
|
||||||
'BARE_OS_HRPC_AUDIT',
|
'BARE_OS_HRPC_AUDIT',
|
||||||
'BARE_OS_HRPC_EMIT_UNLISTED',
|
'BARE_OS_HRPC_EMIT_UNLISTED',
|
||||||
|
'BARE_OS_HRPC_ALLOWLIST_JSON',
|
||||||
|
'BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON',
|
||||||
|
'BARE_OS_BLIND_RELAY_TOPOLOGY_JSON',
|
||||||
|
'BARE_OS_MIRROR_DRIVE_COMPOSITION_HINT_JSON',
|
||||||
|
'BARE_OS_REPLICATION_PLAN_JSON',
|
||||||
|
'BARE_OS_PEAR_DOCTOR_STATE_JSON',
|
||||||
|
'BARE_OS_PEAR_INSPECT_PROBE',
|
||||||
|
'BARE_OS_PEAR_DOCTOR_MODULE',
|
||||||
'BARE_OS_HYPERDHT_STATS_JSON',
|
'BARE_OS_HYPERDHT_STATS_JSON',
|
||||||
'BARE_OS_RUNBIN_DEFAULT_TIMEOUT_MS',
|
'BARE_OS_RUNBIN_DEFAULT_TIMEOUT_MS',
|
||||||
'BARE_OS_VFS_SNAPSHOTS',
|
'BARE_OS_VFS_SNAPSHOTS',
|
||||||
@@ -1826,7 +1838,38 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
skewEstimateMs: null,
|
skewEstimateMs: null,
|
||||||
source: 'host',
|
source: 'host',
|
||||||
note: 'Optional NTP or peer RTT skew may populate skewEstimateMs in future releases.'
|
note: 'Optional NTP or peer RTT skew may populate skewEstimateMs in future releases.'
|
||||||
}
|
},
|
||||||
|
blindRelayTopology: (() => {
|
||||||
|
const raw = String(
|
||||||
|
shellEnv.BARE_OS_BLIND_RELAY_TOPOLOGY_JSON || ''
|
||||||
|
).trim()
|
||||||
|
if (!raw) return undefined
|
||||||
|
try {
|
||||||
|
const o = JSON.parse(raw)
|
||||||
|
if (!o || typeof o !== 'object' || Array.isArray(o)) {
|
||||||
|
return { schema: 1, note: 'invalid_shape' }
|
||||||
|
}
|
||||||
|
const relay = /** @type {Record<string, unknown>} */ (o)
|
||||||
|
return {
|
||||||
|
schema: 1,
|
||||||
|
relayServicePresent: relay.relayServicePresent === true,
|
||||||
|
routerHintTier:
|
||||||
|
typeof relay.routerHintTier === 'number'
|
||||||
|
? Math.min(99, Math.max(0, Math.floor(relay.routerHintTier)))
|
||||||
|
: undefined,
|
||||||
|
pairingChannelCount:
|
||||||
|
typeof relay.pairingChannelCount === 'number'
|
||||||
|
? Math.min(
|
||||||
|
9999,
|
||||||
|
Math.max(0, Math.floor(relay.pairingChannelCount))
|
||||||
|
)
|
||||||
|
: undefined,
|
||||||
|
note: 'PII-free sketch from BARE_OS_BLIND_RELAY_TOPOLOGY_JSON for blind-relay / router operators.'
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return { schema: 1, parseError: true }
|
||||||
|
}
|
||||||
|
})()
|
||||||
})}\n`
|
})}\n`
|
||||||
},
|
},
|
||||||
procBareOsReplicationText() {
|
procBareOsReplicationText() {
|
||||||
@@ -1840,6 +1883,33 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
liveHyperdrive: buildBareOsReplicationLiveSketch(disk, peers),
|
liveHyperdrive: buildBareOsReplicationLiveSketch(disk, peers),
|
||||||
session: sessionStatsRef,
|
session: sessionStatsRef,
|
||||||
mirrorHint: !!(mk && String(mk).trim()),
|
mirrorHint: !!(mk && String(mk).trim()),
|
||||||
|
mirrorDriveCompositionHint: (() => {
|
||||||
|
const raw = String(
|
||||||
|
shellEnv.BARE_OS_MIRROR_DRIVE_COMPOSITION_HINT_JSON || ''
|
||||||
|
).trim()
|
||||||
|
if (!raw) return undefined
|
||||||
|
try {
|
||||||
|
const o = JSON.parse(raw)
|
||||||
|
if (!o || typeof o !== 'object' || Array.isArray(o)) {
|
||||||
|
return { schema: 1, note: 'invalid_shape' }
|
||||||
|
}
|
||||||
|
const h = /** @type {Record<string, unknown>} */ (o)
|
||||||
|
return {
|
||||||
|
schema: 1,
|
||||||
|
mirrorDrivePattern:
|
||||||
|
typeof h.mirrorDrivePattern === 'string'
|
||||||
|
? String(h.mirrorDrivePattern).slice(0, 256)
|
||||||
|
: undefined,
|
||||||
|
auxiliaryCountHint:
|
||||||
|
typeof h.auxiliaryCountHint === 'number'
|
||||||
|
? Math.min(99, Math.max(0, Math.floor(h.auxiliaryCountHint)))
|
||||||
|
: undefined,
|
||||||
|
note: 'Operator sketch from BARE_OS_MIRROR_DRIVE_COMPOSITION_HINT_JSON (mirror-drive–style composition).'
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return { schema: 1, parseError: true }
|
||||||
|
}
|
||||||
|
})(),
|
||||||
seedReplication: sr && typeof sr === 'object' ? sr : undefined,
|
seedReplication: sr && typeof sr === 'object' ? sr : undefined,
|
||||||
seedManifestHints:
|
seedManifestHints:
|
||||||
disk.seedManifestHints && typeof disk.seedManifestHints === 'object'
|
disk.seedManifestHints && typeof disk.seedManifestHints === 'object'
|
||||||
@@ -2172,6 +2242,19 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
h && typeof h === 'object' && !Array.isArray(h) ? { ...h } : { schema: 1 }
|
h && typeof h === 'object' && !Array.isArray(h) ? { ...h } : { schema: 1 }
|
||||||
o.atMs = Date.now()
|
o.atMs = Date.now()
|
||||||
if (handles.length) o.snapshot_handles = handles
|
if (handles.length) o.snapshot_handles = handles
|
||||||
|
const wfRaw = String(
|
||||||
|
shellEnv.BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON || ''
|
||||||
|
).trim()
|
||||||
|
if (wfRaw) {
|
||||||
|
try {
|
||||||
|
const w = JSON.parse(wfRaw)
|
||||||
|
if (w && typeof w === 'object' && !Array.isArray(w)) {
|
||||||
|
o.corestoreSnapshotWorkflow = w
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
o.corestoreSnapshotWorkflowParseError = true
|
||||||
|
}
|
||||||
|
}
|
||||||
return `${JSON.stringify(o)}\n`
|
return `${JSON.stringify(o)}\n`
|
||||||
},
|
},
|
||||||
procBareOsProvenanceText() {
|
procBareOsProvenanceText() {
|
||||||
@@ -2830,39 +2913,15 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const allowRaw = String(shellEnv.BARE_OS_HRPC_ALLOWLIST_JSON || '').trim()
|
const allowParsed = parseBareOsHrpcAllowlistJson(
|
||||||
if (allowRaw) {
|
String(shellEnv.BARE_OS_HRPC_ALLOWLIST_JSON || '')
|
||||||
try {
|
)
|
||||||
const parsed = JSON.parse(allowRaw)
|
if (allowParsed.parseError) {
|
||||||
/** @type {Set<string>} */
|
throw new Error('bareOsHrpcRequest: invalid BARE_OS_HRPC_ALLOWLIST_JSON')
|
||||||
const allow = new Set()
|
}
|
||||||
if (Array.isArray(parsed)) {
|
if (bareOsHrpcAllowlistDeniesRoute(allowParsed.allow, svc, m)) {
|
||||||
for (const v of parsed) {
|
hrpcAuditAppend({ ok: false, reason: 'allowlist_denied' })
|
||||||
const s = String(v || '').trim()
|
throw new Error('bareOsHrpcRequest: method denied by allowlist')
|
||||||
if (s) allow.add(s)
|
|
||||||
}
|
|
||||||
} else if (parsed && typeof parsed === 'object') {
|
|
||||||
for (const [k, v] of Object.entries(parsed)) {
|
|
||||||
if (v) allow.add(String(k).trim())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allow.size > 0) {
|
|
||||||
const key = `${svc}.${m}`
|
|
||||||
if (!allow.has('*') && !allow.has(`${svc}.*`) && !allow.has(key)) {
|
|
||||||
hrpcAuditAppend({ ok: false, reason: 'allowlist_denied' })
|
|
||||||
throw new Error('bareOsHrpcRequest: method denied by allowlist')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (
|
|
||||||
e &&
|
|
||||||
typeof e === 'object' &&
|
|
||||||
String(e.message || '').includes('allowlist')
|
|
||||||
) {
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
throw new Error('bareOsHrpcRequest: invalid BARE_OS_HRPC_ALLOWLIST_JSON')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svc === 'kernel' && m === 'ping') {
|
if (svc === 'kernel' && m === 'ping') {
|
||||||
@@ -2987,6 +3046,38 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
return 30000
|
return 30000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bareOsPosixAcceptQueueMax(env) {
|
||||||
|
const n = Math.floor(Number(String(env?.BARE_OS_POSIX_ACCEPT_QUEUE_MAX ?? '').trim()) || 0)
|
||||||
|
const v = n > 0 ? n : 64
|
||||||
|
return Math.min(1024, Math.max(1, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
function bareOsPosixAcceptBlockMsMax(env) {
|
||||||
|
return bareOsPosixDgramRecvBlockMsMax(env)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-empty ancillary / control payloads are rejected with ENOTSUP (schema 3 contract).
|
||||||
|
* @param {Record<string, unknown>} args
|
||||||
|
* @returns {string | null} reject reason key for diagnostics, or null if absent/empty
|
||||||
|
*/
|
||||||
|
function bareOsSendmsgAncillaryRejectReason(args) {
|
||||||
|
if (!args || typeof args !== 'object') return null
|
||||||
|
if (Array.isArray(args.cmsgs) && args.cmsgs.length > 0) return 'cmsgs'
|
||||||
|
const ctl = args.control
|
||||||
|
if (ctl instanceof Uint8Array && ctl.byteLength > 0) return 'control'
|
||||||
|
const clen = Number(args.controllen)
|
||||||
|
if (Number.isFinite(clen) && clen > 0) return 'controllen'
|
||||||
|
const mh = args.msgHdr
|
||||||
|
if (mh && typeof mh === 'object') {
|
||||||
|
const mhc = /** @type {Record<string, unknown>} */ (mh).control
|
||||||
|
if (mhc instanceof Uint8Array && mhc.byteLength > 0) return 'msgHdr.control'
|
||||||
|
const c2 = /** @type {Record<string, unknown>} */ (mh).cmsgs
|
||||||
|
if (Array.isArray(c2) && c2.length > 0) return 'msgHdr.cmsgs'
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flatten sendmsg iovec list (bounded) for the SOCK_DGRAM bridge.
|
* Flatten sendmsg iovec list (bounded) for the SOCK_DGRAM bridge.
|
||||||
* @param {Record<string, unknown>} args
|
* @param {Record<string, unknown>} args
|
||||||
@@ -4002,6 +4093,23 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
) {
|
) {
|
||||||
ready.push({ fd, revents: 'r' })
|
ready.push({ fd, revents: 'r' })
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
bridge &&
|
||||||
|
bridge.state === 'connected' &&
|
||||||
|
bridge.transport === 'tcp' &&
|
||||||
|
Array.isArray(bridge.tcpRecvQueue) &&
|
||||||
|
bridge.tcpRecvQueue.length > 0
|
||||||
|
) {
|
||||||
|
ready.push({ fd, revents: 'r' })
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
bridge &&
|
||||||
|
bridge.state === 'listening' &&
|
||||||
|
Array.isArray(bridge.acceptQueue) &&
|
||||||
|
bridge.acceptQueue.length > 0
|
||||||
|
) {
|
||||||
|
ready.push({ fd, revents: 'r' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { ok: true, ready, waitedMs: 0 }
|
return { ok: true, ready, waitedMs: 0 }
|
||||||
@@ -5148,20 +5256,342 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
transport: 'tcp'
|
transport: 'tcp'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (name === 'bind') {
|
||||||
name === 'bind' ||
|
const fd = Number(args.fd)
|
||||||
name === 'listen' ||
|
if (!Number.isFinite(fd)) {
|
||||||
name === 'accept' ||
|
return {
|
||||||
name === 'shutdown'
|
ok: false,
|
||||||
) {
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'bind: fd required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const k = String(fd >>> 0)
|
||||||
|
const slot =
|
||||||
|
this.bareOsSocketBridgeByFd &&
|
||||||
|
typeof this.bareOsSocketBridgeByFd === 'object'
|
||||||
|
? this.bareOsSocketBridgeByFd[k]
|
||||||
|
: null
|
||||||
|
const isDgram = Number(slot?.sockType ?? slot?.type ?? 1) === 2
|
||||||
|
if (isDgram) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'ENOTSUP',
|
||||||
|
errnoHint: 'ENOTSUP',
|
||||||
|
posixAlignment: 'ENOTSUP',
|
||||||
|
note:
|
||||||
|
'bind: SOCK_DGRAM bridge uses connect(); passive UDP bind is not implemented.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!slot || slot.state !== 'created') {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'bind: requires SOCK_STREAM bridge socket in created state.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const port = Number(args.port)
|
||||||
|
const host = String(
|
||||||
|
args.host || args.address || '0.0.0.0'
|
||||||
|
).trim() || '0.0.0.0'
|
||||||
|
if (!Number.isFinite(port) || port < 0 || port > 65535) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'bind: port required (0–65535)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slot.bindPort = port
|
||||||
|
slot.bindHost = host
|
||||||
|
slot.state = 'bound'
|
||||||
|
this.bareOsLogicalFds[k] =
|
||||||
|
'bare-os-socket-bridge:tcp-bound:' + host + ':' + port
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
op: name,
|
||||||
|
fd,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
port,
|
||||||
|
host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name === 'listen') {
|
||||||
|
const fd = Number(args.fd)
|
||||||
|
if (!Number.isFinite(fd)) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'listen: fd required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const k = String(fd >>> 0)
|
||||||
|
const slot =
|
||||||
|
this.bareOsSocketBridgeByFd &&
|
||||||
|
typeof this.bareOsSocketBridgeByFd === 'object'
|
||||||
|
? this.bareOsSocketBridgeByFd[k]
|
||||||
|
: null
|
||||||
|
if (!slot || slot.state !== 'bound') {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'listen: call bind(2) on the bridge fd first.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const TcpServer =
|
||||||
|
bareLibrary.bareTcp &&
|
||||||
|
bareLibrary.bareTcp.Server &&
|
||||||
|
typeof bareLibrary.bareTcp.Server === 'function'
|
||||||
|
? bareLibrary.bareTcp.Server
|
||||||
|
: null
|
||||||
|
if (!TcpServer) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'ENOTSUP',
|
||||||
|
errnoHint: 'ENOTSUP',
|
||||||
|
posixAlignment: 'ENOTSUP',
|
||||||
|
note:
|
||||||
|
'listen: bareTcp.Server not merged in ctx.bare (bare-tcp bundle).'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const backlog = Math.min(
|
||||||
|
511,
|
||||||
|
Math.max(1, Math.floor(Number(args.backlog) || 511))
|
||||||
|
)
|
||||||
|
const acceptQmax = bareOsPosixAcceptQueueMax(shellEnv)
|
||||||
|
const dgramQmax = bareOsPosixDgramRecvQueueMax(shellEnv)
|
||||||
|
const server = new TcpServer()
|
||||||
|
slot.acceptQueue = []
|
||||||
|
server.on('connection', (sock) => {
|
||||||
|
if (!Array.isArray(slot.acceptQueue)) return
|
||||||
|
if (slot.acceptQueue.length >= acceptQmax) {
|
||||||
|
try {
|
||||||
|
sock.destroy?.()
|
||||||
|
} catch (_) {}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const wrap = {
|
||||||
|
sock,
|
||||||
|
tcpRecvQueue: [],
|
||||||
|
tcpRecvDropped: 0
|
||||||
|
}
|
||||||
|
sock.on('data', (message) => {
|
||||||
|
let u8 =
|
||||||
|
message instanceof Uint8Array
|
||||||
|
? message
|
||||||
|
: b4a.from(message)
|
||||||
|
if (u8.byteLength > 1024 * 1024)
|
||||||
|
u8 = u8.slice(0, 1024 * 1024)
|
||||||
|
if (wrap.tcpRecvQueue.length >= dgramQmax) {
|
||||||
|
wrap.tcpRecvDropped = (wrap.tcpRecvDropped || 0) + 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wrap.tcpRecvQueue.push({ buf: u8.slice() })
|
||||||
|
})
|
||||||
|
slot.acceptQueue.push(wrap)
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
server.once('error', reject)
|
||||||
|
server.once('listening', resolve)
|
||||||
|
server.listen(slot.bindPort, slot.bindHost, backlog)
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EADDRINUSE',
|
||||||
|
errnoHint: 'EADDRINUSE',
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
note: String(e && e.message ? e.message : e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slot.server = server
|
||||||
|
slot.state = 'listening'
|
||||||
|
this.bareOsLogicalFds[k] =
|
||||||
|
'bare-os-socket-bridge:tcp-listen:' +
|
||||||
|
slot.bindHost +
|
||||||
|
':' +
|
||||||
|
slot.bindPort
|
||||||
|
const addr =
|
||||||
|
server.address && typeof server.address === 'function'
|
||||||
|
? server.address()
|
||||||
|
: null
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
op: name,
|
||||||
|
fd,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
address: addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name === 'accept') {
|
||||||
|
const fd = Number(args.fd)
|
||||||
|
if (!Number.isFinite(fd)) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'accept: listening fd required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const k = String(fd >>> 0)
|
||||||
|
const slot =
|
||||||
|
this.bareOsSocketBridgeByFd &&
|
||||||
|
typeof this.bareOsSocketBridgeByFd === 'object'
|
||||||
|
? this.bareOsSocketBridgeByFd[k]
|
||||||
|
: null
|
||||||
|
if (!slot || slot.state !== 'listening') {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'accept: fd must be a listening SOCK_STREAM bridge socket.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const nonblock =
|
||||||
|
(this.bareOsLogicalFdFlags[k] & 0x800) === 0x800
|
||||||
|
const blockMax = bareOsPosixAcceptBlockMsMax(shellEnv)
|
||||||
|
const t0 = Date.now()
|
||||||
|
while (true) {
|
||||||
|
const q = slot.acceptQueue
|
||||||
|
if (Array.isArray(q) && q.length > 0) {
|
||||||
|
const wrap = q.shift()
|
||||||
|
const sock = wrap && wrap.sock
|
||||||
|
if (!sock) continue
|
||||||
|
const st = this.bareOsPosixFdSimState
|
||||||
|
const newFd = st.nextFd++
|
||||||
|
const nk = String(newFd)
|
||||||
|
this.bareOsSocketBridgeByFd[nk] = {
|
||||||
|
state: 'connected',
|
||||||
|
sock,
|
||||||
|
transport: 'tcp',
|
||||||
|
sockType: 1,
|
||||||
|
type: 1,
|
||||||
|
tcpRecvQueue: wrap.tcpRecvQueue,
|
||||||
|
tcpRecvDropped: wrap.tcpRecvDropped || 0
|
||||||
|
}
|
||||||
|
this.bareOsRegisterLogicalFd(
|
||||||
|
newFd,
|
||||||
|
'bare-os-socket-bridge:tcp-accepted'
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
op: name,
|
||||||
|
fd: newFd,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
listenFd: fd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nonblock) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EAGAIN',
|
||||||
|
errnoHint: 'EAGAIN',
|
||||||
|
posixAlignment: 'EAGAIN',
|
||||||
|
bridge: true,
|
||||||
|
note: 'accept: no connection ready (O_NONBLOCK)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Date.now() - t0 >= blockMax) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EAGAIN',
|
||||||
|
errnoHint: 'EAGAIN',
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
bridge: true,
|
||||||
|
note:
|
||||||
|
'accept: timed out waiting (same budget as BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await new Promise((r) => setTimeout(r, 10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name === 'shutdown') {
|
||||||
|
const fd = Number(args.fd)
|
||||||
|
if (!Number.isFinite(fd)) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'shutdown: fd required'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const k = String(fd >>> 0)
|
||||||
|
const slot =
|
||||||
|
this.bareOsSocketBridgeByFd &&
|
||||||
|
typeof this.bareOsSocketBridgeByFd === 'object'
|
||||||
|
? this.bareOsSocketBridgeByFd[k]
|
||||||
|
: null
|
||||||
|
if (!slot) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: name,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'shutdown: not a bridge fd'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slot.state === 'listening' && slot.server) {
|
||||||
|
try {
|
||||||
|
slot.server.close?.()
|
||||||
|
} catch (_) {}
|
||||||
|
slot.server = null
|
||||||
|
if (Array.isArray(slot.acceptQueue)) {
|
||||||
|
for (const w of slot.acceptQueue) {
|
||||||
|
try {
|
||||||
|
w.sock?.destroy?.()
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
slot.acceptQueue = []
|
||||||
|
}
|
||||||
|
slot.state = 'closed'
|
||||||
|
delete this.bareOsSocketBridgeByFd[k]
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
op: name,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slot.state === 'connected' && slot.sock) {
|
||||||
|
try {
|
||||||
|
slot.sock.destroy?.()
|
||||||
|
} catch (_) {}
|
||||||
|
slot.state = 'closed'
|
||||||
|
delete this.bareOsSocketBridgeByFd[k]
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
op: name,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial'
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
op: name,
|
op: name,
|
||||||
code: 'ENOTSUP',
|
code: 'ENOTSUP',
|
||||||
errnoHint: 'ENOTSUP',
|
errnoHint: 'ENOTSUP',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'ENOTSUP',
|
||||||
note:
|
note: 'shutdown: bridge fd not connected or listening.'
|
||||||
'Bridge mode implements socket+connect via bareTcp (stream) or bareDgram (UDP); use ctx.bare / Hyperswarm for listen/accept servers.'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -5193,7 +5623,7 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
!slot ||
|
!slot ||
|
||||||
slot.state !== 'connected' ||
|
slot.state !== 'connected' ||
|
||||||
!slot.sock ||
|
!slot.sock ||
|
||||||
slot.transport !== 'udp'
|
(slot.transport !== 'udp' && slot.transport !== 'tcp')
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
@@ -5202,12 +5632,184 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
errnoHint: 'ENOTSUP',
|
errnoHint: 'ENOTSUP',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'ENOTSUP',
|
||||||
note:
|
note:
|
||||||
'Bridge send/sendmsg/recv/recvfrom/recvmsg supported for connected SOCK_DGRAM fds only; use Hyperswarm streams for TCP payload I/O.'
|
'Bridge send/sendmsg/recv/recvfrom/recvmsg supported for connected SOCK_DGRAM or SOCK_STREAM (accepted) fds.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (slot.transport === 'tcp') {
|
||||||
|
if (logicalOp === 'send' || logicalOp === 'sendmsg') {
|
||||||
|
let payload
|
||||||
|
if (logicalOp === 'sendmsg') {
|
||||||
|
const anc = bareOsSendmsgAncillaryRejectReason(
|
||||||
|
args && typeof args === 'object'
|
||||||
|
? /** @type {Record<string, unknown>} */ (args)
|
||||||
|
: {}
|
||||||
|
)
|
||||||
|
if (anc) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: 'sendmsg',
|
||||||
|
code: 'ENOTSUP',
|
||||||
|
errnoHint: 'ENOTSUP',
|
||||||
|
posixAlignment: 'ENOTSUP',
|
||||||
|
ancillaryReject: anc,
|
||||||
|
note:
|
||||||
|
'sendmsg: ancillary control messages not implemented on TCP bridge.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const f = bareOsFlattenSendmsgIovs(args)
|
||||||
|
if (!f.ok) return f.err
|
||||||
|
payload = f.buf
|
||||||
|
} else {
|
||||||
|
payload = args.buf ?? args.buffer ?? args.data
|
||||||
|
if (payload == null) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: logicalOp,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof payload === 'string')
|
||||||
|
payload = b4a.from(String(payload), 'utf8')
|
||||||
|
if (!(payload instanceof Uint8Array)) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: logicalOp,
|
||||||
|
code: 'EINVAL',
|
||||||
|
errnoHint: 'EINVAL',
|
||||||
|
note: 'send: buf must be Uint8Array or string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const w = slot.sock.write(payload, (err) =>
|
||||||
|
err ? reject(err) : resolve(undefined)
|
||||||
|
)
|
||||||
|
if (w === false) {
|
||||||
|
slot.sock.once('drain', () => resolve(undefined))
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
op: logicalOp,
|
||||||
|
fd,
|
||||||
|
bytesSent: payload.byteLength,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
transport: 'tcp'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const maxBuf = Math.max(
|
||||||
|
1,
|
||||||
|
Math.min(
|
||||||
|
Number(args.len ?? args.length ?? args.max ?? 65536) || 65536,
|
||||||
|
1024 * 1024
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const nonblock =
|
||||||
|
(this.bareOsLogicalFdFlags[k] & 0x800) === 0x800
|
||||||
|
const t0 = Date.now()
|
||||||
|
const blockMax = bareOsPosixAcceptBlockMsMax(shellEnv)
|
||||||
|
while (true) {
|
||||||
|
const q = slot.tcpRecvQueue
|
||||||
|
if (Array.isArray(q) && q.length > 0) {
|
||||||
|
const row = q.shift()
|
||||||
|
if (row && row.buf instanceof Uint8Array) {
|
||||||
|
let out = row.buf
|
||||||
|
if (out.byteLength > maxBuf) {
|
||||||
|
const rest = out.slice(maxBuf)
|
||||||
|
out = out.slice(0, maxBuf)
|
||||||
|
q.unshift({ buf: rest })
|
||||||
|
}
|
||||||
|
const base = {
|
||||||
|
ok: true,
|
||||||
|
op: logicalOp,
|
||||||
|
fd,
|
||||||
|
bytesReceived: out.byteLength,
|
||||||
|
buf: out,
|
||||||
|
bridge: true,
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
transport: 'tcp',
|
||||||
|
tcpRecvDropped: slot.tcpRecvDropped || 0
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
logicalOp === 'recvfrom' ||
|
||||||
|
logicalOp === 'recvmsg'
|
||||||
|
) {
|
||||||
|
base.address = slot.sock.remoteAddress
|
||||||
|
base.port = slot.sock.remotePort
|
||||||
|
}
|
||||||
|
if (logicalOp === 'recvmsg') {
|
||||||
|
base.msgHdr = {
|
||||||
|
schema: 1,
|
||||||
|
name:
|
||||||
|
slot.sock.remoteAddress != null
|
||||||
|
? {
|
||||||
|
address: String(slot.sock.remoteAddress || ''),
|
||||||
|
port: Number(slot.sock.remotePort) >>> 0
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
flags: 0,
|
||||||
|
controllen: 0,
|
||||||
|
note:
|
||||||
|
'TCP bridge: single flat buffer; ancillary ENOTSUP-shaped.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nonblock) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: logicalOp,
|
||||||
|
code: 'EAGAIN',
|
||||||
|
errnoHint: 'EAGAIN',
|
||||||
|
posixAlignment: 'EAGAIN',
|
||||||
|
bridge: true,
|
||||||
|
note: 'recv: no data ready (O_NONBLOCK)',
|
||||||
|
tcpRecvDropped: slot.tcpRecvDropped || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Date.now() - t0 >= blockMax) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: logicalOp,
|
||||||
|
code: 'EAGAIN',
|
||||||
|
errnoHint: 'EAGAIN',
|
||||||
|
posixAlignment: 'partial',
|
||||||
|
bridge: true,
|
||||||
|
note:
|
||||||
|
'recv: timed out waiting for TCP segment (BARE_OS_POSIX_DGRAM_RECV_BLOCK_MS_MAX budget)',
|
||||||
|
tcpRecvDropped: slot.tcpRecvDropped || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await new Promise((r) => setTimeout(r, 10))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (logicalOp === 'send' || logicalOp === 'sendmsg') {
|
if (logicalOp === 'send' || logicalOp === 'sendmsg') {
|
||||||
let payload
|
let payload
|
||||||
if (logicalOp === 'sendmsg') {
|
if (logicalOp === 'sendmsg') {
|
||||||
|
const anc = bareOsSendmsgAncillaryRejectReason(
|
||||||
|
args && typeof args === 'object'
|
||||||
|
? /** @type {Record<string, unknown>} */ (args)
|
||||||
|
: {}
|
||||||
|
)
|
||||||
|
if (anc) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
op: 'sendmsg',
|
||||||
|
code: 'ENOTSUP',
|
||||||
|
errnoHint: 'ENOTSUP',
|
||||||
|
posixAlignment: 'ENOTSUP',
|
||||||
|
ancillaryReject: anc,
|
||||||
|
note:
|
||||||
|
'sendmsg: ancillary control messages (cmsgs/control/controllen/msgHdr.*) are not implemented on the socket FD bridge; use payload-only send or bare IPC.'
|
||||||
|
}
|
||||||
|
}
|
||||||
const f = bareOsFlattenSendmsgIovs(args)
|
const f = bareOsFlattenSendmsgIovs(args)
|
||||||
if (!f.ok) return f.err
|
if (!f.ok) return f.err
|
||||||
payload = f.buf
|
payload = f.buf
|
||||||
@@ -5529,6 +6131,19 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
h && typeof h === 'object' && !Array.isArray(h) ? { ...h } : { schema: 1 }
|
h && typeof h === 'object' && !Array.isArray(h) ? { ...h } : { schema: 1 }
|
||||||
o.atMs = Date.now()
|
o.atMs = Date.now()
|
||||||
if (handles.length) o.snapshot_handles = handles
|
if (handles.length) o.snapshot_handles = handles
|
||||||
|
const wfRaw = String(
|
||||||
|
shellEnv.BARE_OS_CORESTORE_SNAPSHOT_WORKFLOW_JSON || ''
|
||||||
|
).trim()
|
||||||
|
if (wfRaw) {
|
||||||
|
try {
|
||||||
|
const w = JSON.parse(wfRaw)
|
||||||
|
if (w && typeof w === 'object' && !Array.isArray(w)) {
|
||||||
|
o.corestoreSnapshotWorkflow = w
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
o.corestoreSnapshotWorkflowParseError = true
|
||||||
|
}
|
||||||
|
}
|
||||||
return o
|
return o
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -6582,19 +7197,20 @@ async function executeKernel(disk, store, swarm, initSource) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
bareOsHrpcAllowlistProbe() {
|
bareOsHrpcAllowlistProbe() {
|
||||||
const raw = String(shellEnv.BARE_OS_HRPC_ALLOWLIST_JSON || '').trim()
|
const parsed = parseBareOsHrpcAllowlistJson(
|
||||||
if (raw) {
|
String(shellEnv.BARE_OS_HRPC_ALLOWLIST_JSON || '')
|
||||||
try {
|
)
|
||||||
return {
|
if (parsed.parseError) {
|
||||||
ok: true,
|
return {
|
||||||
source: 'env',
|
ok: false,
|
||||||
allowlist: JSON.parse(raw)
|
note: 'invalid BARE_OS_HRPC_ALLOWLIST_JSON'
|
||||||
}
|
}
|
||||||
} catch {
|
}
|
||||||
return {
|
if (parsed.allow && parsed.allow.size > 0) {
|
||||||
ok: false,
|
return {
|
||||||
note: 'invalid BARE_OS_HRPC_ALLOWLIST_JSON'
|
ok: true,
|
||||||
}
|
source: 'env',
|
||||||
|
allowlist: [...parsed.allow].sort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
* Semantic version of the booter `ctx` contract for custom kernels.
|
* Semantic version of the booter `ctx` contract for custom kernels.
|
||||||
* Bump when adding/removing/renaming documented `ctx` fields or changing behavior.
|
* Bump when adding/removing/renaming documented `ctx` fields or changing behavior.
|
||||||
*/
|
*/
|
||||||
export const BARE_OS_CTX_API_VERSION = '1.44.0'
|
export const BARE_OS_CTX_API_VERSION = '1.45.0'
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Parse optional **`BARE_OS_HRPC_ALLOWLIST_JSON`** for stock **`ctx.bareOsHrpcRequest`**.
|
||||||
|
* @param {string} raw
|
||||||
|
* @returns {{ allow: Set<string> | null, parseError: boolean }}
|
||||||
|
*/
|
||||||
|
export function parseBareOsHrpcAllowlistJson(raw) {
|
||||||
|
const s = String(raw || '').trim()
|
||||||
|
if (!s) return { allow: null, parseError: false }
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(s)
|
||||||
|
/** @type {Set<string>} */
|
||||||
|
const allow = new Set()
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
for (const v of parsed) {
|
||||||
|
const x = String(v || '').trim()
|
||||||
|
if (x) allow.add(x)
|
||||||
|
}
|
||||||
|
} else if (parsed && typeof parsed === 'object') {
|
||||||
|
for (const [k, v] of Object.entries(parsed)) {
|
||||||
|
if (v) allow.add(String(k).trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { allow: allow.size > 0 ? allow : null, parseError: false }
|
||||||
|
} catch {
|
||||||
|
return { allow: null, parseError: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Set<string> | null} allow
|
||||||
|
* @param {string} svc
|
||||||
|
* @param {string} method
|
||||||
|
* @returns {boolean} true when the route is denied by a non-empty allowlist
|
||||||
|
*/
|
||||||
|
export function bareOsHrpcAllowlistDeniesRoute(allow, svc, method) {
|
||||||
|
if (!allow || allow.size === 0) return false
|
||||||
|
const key = `${svc}.${method}`
|
||||||
|
return !allow.has('*') && !allow.has(`${svc}.*`) && !allow.has(key)
|
||||||
|
}
|
||||||
@@ -28,9 +28,14 @@ export function buildBareOsPearInspectLoggerTlsProcJson(id, env, runtimeHints) {
|
|||||||
switch (id) {
|
switch (id) {
|
||||||
case 'pear_doctor_state':
|
case 'pear_doctor_state':
|
||||||
return {
|
return {
|
||||||
schema: 1,
|
schema: 2,
|
||||||
state: parseJsonEnv('BARE_OS_PEAR_DOCTOR_STATE_JSON'),
|
state: parseJsonEnv('BARE_OS_PEAR_DOCTOR_STATE_JSON'),
|
||||||
note: 'pear-doctor operator health sketch.',
|
runtimeVersion: esc('BARE_OS_PEAR_RUNTIME_VERSION') || undefined,
|
||||||
|
pearInspectProbe:
|
||||||
|
esc('BARE_OS_PEAR_INSPECT_PROBE') === '1' ||
|
||||||
|
esc('BARE_OS_PEAR_INSPECT_PROBE') === 'true',
|
||||||
|
pearDoctorModuleHint: esc('BARE_OS_PEAR_DOCTOR_MODULE') || undefined,
|
||||||
|
note: 'pear-doctor + pear-runtime parity (schema 2): merge env with pear-inspect / pear-runtime-updater host wiring.',
|
||||||
atMs: now
|
atMs: now
|
||||||
}
|
}
|
||||||
case 'pear_workshop_flags':
|
case 'pear_workshop_flags':
|
||||||
|
|||||||
@@ -350,25 +350,34 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
|||||||
name: 'bind',
|
name: 'bind',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: ['ctx.bareOsSyscall("bind")', 'ENOSYS-shaped probe'],
|
mapsTo: [
|
||||||
errnoHint: 'ENOSYS'
|
'ctx.bareOsSyscall("bind")',
|
||||||
|
'SOCK_STREAM bridge: port+host before listen (SOCK_DGRAM bind ENOTSUP)'
|
||||||
|
],
|
||||||
|
errnoHint: 'EINVAL'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'listen',
|
name: 'listen',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: ['ctx.bareOsSyscall("listen")', 'ENOSYS-shaped probe'],
|
mapsTo: [
|
||||||
errnoHint: 'ENOSYS'
|
'ctx.bareOsSyscall("listen")',
|
||||||
|
'bareTcp.Server.listen when BARE_OS_POSIX_SOCKET_FD_BRIDGE'
|
||||||
|
],
|
||||||
|
errnoHint: 'EADDRINUSE'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'accept',
|
name: 'accept',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: ['ctx.bareOsSyscall("accept")', 'ENOSYS-shaped probe'],
|
mapsTo: [
|
||||||
errnoHint: 'ENOSYS'
|
'ctx.bareOsSyscall("accept")',
|
||||||
|
'dequeue accepted TCP socket to new logical fd; EAGAIN when empty + O_NONBLOCK'
|
||||||
|
],
|
||||||
|
errnoHint: 'EAGAIN'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'connect',
|
name: 'connect',
|
||||||
@@ -382,18 +391,21 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
|||||||
name: 'send',
|
name: 'send',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: ['ctx.bareOsSyscall("send")', 'ENOSYS-shaped probe'],
|
mapsTo: [
|
||||||
|
'ctx.bareOsSyscall("send")',
|
||||||
|
'SOCK_DGRAM + SOCK_STREAM (accepted) bridge write'
|
||||||
|
],
|
||||||
errnoHint: 'ENOSYS'
|
errnoHint: 'ENOSYS'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'recv',
|
name: 'recv',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: [
|
mapsTo: [
|
||||||
'ctx.bareOsSyscall("recv")',
|
'ctx.bareOsSyscall("recv")',
|
||||||
'SOCK_DGRAM bridge dequeue (BARE_OS_POSIX_SOCKET_FD_BRIDGE)'
|
'SOCK_DGRAM bridge dequeue; SOCK_STREAM accepted fd tcpRecvQueue (BARE_OS_POSIX_SOCKET_FD_BRIDGE)'
|
||||||
],
|
],
|
||||||
errnoHint: 'ENOSYS'
|
errnoHint: 'ENOSYS'
|
||||||
},
|
},
|
||||||
@@ -401,10 +413,10 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
|||||||
name: 'recvfrom',
|
name: 'recvfrom',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: [
|
mapsTo: [
|
||||||
'ctx.bareOsSyscall("recvfrom")',
|
'ctx.bareOsSyscall("recvfrom")',
|
||||||
'SOCK_DGRAM bridge + peer address fields when available'
|
'SOCK_DGRAM bridge + peer address; SOCK_STREAM accepted + remoteAddress/remotePort'
|
||||||
],
|
],
|
||||||
errnoHint: 'ENOSYS'
|
errnoHint: 'ENOSYS'
|
||||||
},
|
},
|
||||||
@@ -415,7 +427,7 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
|||||||
posixAlignment: 'partial',
|
posixAlignment: 'partial',
|
||||||
mapsTo: [
|
mapsTo: [
|
||||||
'ctx.bareOsSyscall("sendmsg")',
|
'ctx.bareOsSyscall("sendmsg")',
|
||||||
'SOCK_DGRAM bridge flattened iovs (BARE_OS_POSIX_SOCKET_FD_BRIDGE); ancillary CMSGS ENOTSUP'
|
'SOCK_DGRAM + SOCK_STREAM bridge flattened iovs (BARE_OS_POSIX_SOCKET_FD_BRIDGE); ancillary CMSGS ENOTSUP'
|
||||||
],
|
],
|
||||||
errnoHint: 'ENOSYS'
|
errnoHint: 'ENOSYS'
|
||||||
},
|
},
|
||||||
@@ -426,7 +438,7 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
|||||||
posixAlignment: 'partial',
|
posixAlignment: 'partial',
|
||||||
mapsTo: [
|
mapsTo: [
|
||||||
'ctx.bareOsSyscall("recvmsg")',
|
'ctx.bareOsSyscall("recvmsg")',
|
||||||
'SOCK_DGRAM bridge + msgHdr.name from rinfo; scatter iov / SCM_RIGHTS ENOTSUP'
|
'SOCK_DGRAM bridge + msgHdr.name from rinfo; SOCK_STREAM accepted + remote addr; scatter iov / SCM_RIGHTS ENOTSUP'
|
||||||
],
|
],
|
||||||
errnoHint: 'ENOSYS'
|
errnoHint: 'ENOSYS'
|
||||||
},
|
},
|
||||||
@@ -434,9 +446,12 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
|
|||||||
name: 'shutdown',
|
name: 'shutdown',
|
||||||
category: 'ipc',
|
category: 'ipc',
|
||||||
stability: 'experimental',
|
stability: 'experimental',
|
||||||
posixAlignment: 'ENOTSUP',
|
posixAlignment: 'partial',
|
||||||
mapsTo: ['ctx.bareOsSyscall("shutdown")', 'ENOSYS-shaped probe'],
|
mapsTo: [
|
||||||
errnoHint: 'ENOSYS'
|
'ctx.bareOsSyscall("shutdown")',
|
||||||
|
'TCP bridge: destroy socket or close listening Server'
|
||||||
|
],
|
||||||
|
errnoHint: 'EINVAL'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|||||||
@@ -33,16 +33,29 @@ export function buildBareOsSyscallsProcJson(p) {
|
|||||||
namesCsv: bareOsPosixXshOpsCsv()
|
namesCsv: bareOsPosixXshOpsCsv()
|
||||||
},
|
},
|
||||||
socketMsgSurface: {
|
socketMsgSurface: {
|
||||||
schema: 2,
|
schema: 3,
|
||||||
|
ancillaryControl: {
|
||||||
|
supported: false,
|
||||||
|
errno: 'ENOTSUP',
|
||||||
|
rejectKeys: [
|
||||||
|
'cmsgs',
|
||||||
|
'control',
|
||||||
|
'controllen',
|
||||||
|
'msgHdr.control',
|
||||||
|
'msgHdr.cmsgs'
|
||||||
|
],
|
||||||
|
note:
|
||||||
|
'Booter returns ENOTSUP before send when non-empty ancillary fields are present; recvmsg always reports controllen 0.'
|
||||||
|
},
|
||||||
sendmsg: {
|
sendmsg: {
|
||||||
bridgePartial: true,
|
bridgePartial: true,
|
||||||
defaultErrno: 'ENOTSUP',
|
defaultErrno: 'ENOTSUP',
|
||||||
note: 'With BARE_OS_POSIX_SOCKET_FD_BRIDGE and SOCK_DGRAM, sendmsg flattens bounded iovs into one datagram; flags and ancillary CMSGS remain ENOTSUP.'
|
note: 'With BARE_OS_POSIX_SOCKET_FD_BRIDGE and SOCK_DGRAM, sendmsg flattens bounded iovs into one datagram; non-empty ancillary CMSGS rejected with ENOTSUP + ancillaryReject (schema 3).'
|
||||||
},
|
},
|
||||||
recvmsg: {
|
recvmsg: {
|
||||||
bridgePartial: true,
|
bridgePartial: true,
|
||||||
defaultErrno: 'ENOTSUP',
|
defaultErrno: 'ENOTSUP',
|
||||||
note: 'With bridge + SOCK_DGRAM, recvmsg returns buf + msgHdr.name from rinfo; SCM_RIGHTS / scatter iov ENOTSUP.'
|
note: 'With bridge + SOCK_DGRAM, recvmsg returns buf + msgHdr.name from rinfo; SCM_RIGHTS / scatter iov / ancillary recv ENOTSUP-shaped (controllen 0).'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
errnoHints: bareOsErrnoTableForProc(),
|
errnoHints: bareOsErrnoTableForProc(),
|
||||||
@@ -101,6 +114,7 @@ export function buildBareOsSyscallsProcJson(p) {
|
|||||||
'F_SETLKW',
|
'F_SETLKW',
|
||||||
'cooperative advisory locks per absolute path (or fd→path); session-scoped',
|
'cooperative advisory locks per absolute path (or fd→path); session-scoped',
|
||||||
'optional F_SETLKW blocking wait when BARE_OS_POSIX_FCNTL_BLOCKING_WAIT (cap BARE_OS_FCNTL_LOCK_WAIT_MS_MAX)',
|
'optional F_SETLKW blocking wait when BARE_OS_POSIX_FCNTL_BLOCKING_WAIT (cap BARE_OS_FCNTL_LOCK_WAIT_MS_MAX)',
|
||||||
|
'waiters wake FIFO on unlock; no host deadlock detection; starvation possible under heavy writer churn',
|
||||||
'O_APPEND 0x400',
|
'O_APPEND 0x400',
|
||||||
'O_NONBLOCK 0x800',
|
'O_NONBLOCK 0x800',
|
||||||
'bareOsLogicalFdFlags per fd string key'
|
'bareOsLogicalFdFlags per fd string key'
|
||||||
@@ -118,7 +132,7 @@ export function buildBareOsSyscallsProcJson(p) {
|
|||||||
socketFamily: {
|
socketFamily: {
|
||||||
mapsTo: [
|
mapsTo: [
|
||||||
'ctx.bareOsSyscall("socket"|"bind"|"listen"|"accept"|"connect"|"send"|"recv"|"recvfrom"|"shutdown")',
|
'ctx.bareOsSyscall("socket"|"bind"|"listen"|"accept"|"connect"|"send"|"recv"|"recvfrom"|"shutdown")',
|
||||||
'BARE_OS_POSIX_SOCKET_FD_BRIDGE=1: SOCK_STREAM+connect via bareTcp; SOCK_DGRAM+connect+send+recv+recvfrom via bareDgram (UDX) with bounded recv queue; bind/listen/accept ENOTSUP-shaped in bridge'
|
'BARE_OS_POSIX_SOCKET_FD_BRIDGE=1: SOCK_STREAM connect via bareTcp.Socket; passive SOCK_STREAM bind+listen+accept via bareTcp.Server (accepted fds use TCP recv queue + poll/select); SOCK_DGRAM connect+send+recv+recvfrom via bareDgram (UDX); BARE_OS_POSIX_ACCEPT_QUEUE_MAX caps pending accepts'
|
||||||
],
|
],
|
||||||
notKernelSockets: true
|
notKernelSockets: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,8 +224,25 @@ export async function registerIdentity(ctx, passphrase) {
|
|||||||
*/
|
*/
|
||||||
export async function unlockIdentity(ctx, passphrase) {
|
export async function unlockIdentity(ctx, passphrase) {
|
||||||
const buf = await ctx.personalDrive.get(ACCOUNT_PATH)
|
const buf = await ctx.personalDrive.get(ACCOUNT_PATH)
|
||||||
if (!buf) throw new Error('No account — use: login --new <passphrase>')
|
if (!buf) {
|
||||||
const { publicKey, secretKey } = decodeAccount(passphrase, b4a.from(buf))
|
const e = new Error('No account — use: login --new <passphrase>')
|
||||||
|
/** @type {Error & { code?: string }} */ (e).code =
|
||||||
|
'BARE_OS_IDENTITY_NO_ACCOUNT'
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
let publicKey
|
||||||
|
let secretKey
|
||||||
|
try {
|
||||||
|
;({ publicKey, secretKey } = decodeAccount(passphrase, b4a.from(buf)))
|
||||||
|
} catch (err) {
|
||||||
|
const e = new Error(
|
||||||
|
'Passphrase does not unlock this account (wrong passphrase or unreadable account file).'
|
||||||
|
)
|
||||||
|
const ee = /** @type {Error & { code?: string, cause?: unknown }} */ (e)
|
||||||
|
ee.code = 'BARE_OS_IDENTITY_PASSPHRASE_REJECTED'
|
||||||
|
ee.cause = err
|
||||||
|
throw e
|
||||||
|
}
|
||||||
wipeSecret(ctx)
|
wipeSecret(ctx)
|
||||||
await applyUnlockedEnv(ctx, publicKey, secretKey)
|
await applyUnlockedEnv(ctx, publicKey, secretKey)
|
||||||
await ensureBareDir(ctx)
|
await ensureBareDir(ctx)
|
||||||
|
|||||||
@@ -1114,6 +1114,12 @@ async function execParsedPipeline(ctx, pipeline) {
|
|||||||
let stdinText = typeof ctx.shellStdin === 'string' ? ctx.shellStdin : null
|
let stdinText = typeof ctx.shellStdin === 'string' ? ctx.shellStdin : null
|
||||||
/** Last completed pipeline stage exit (POSIX default: status of last stage; optional pipefail). */
|
/** Last completed pipeline stage exit (POSIX default: status of last stage; optional pipefail). */
|
||||||
let pipelineLastExit = 0
|
let pipelineLastExit = 0
|
||||||
|
/** True when **`BARE_OS_SHELL_PIPEFAIL`** is already set or set by a stage prefix in this pipeline. */
|
||||||
|
let pipelineWantsPipefail =
|
||||||
|
env.BARE_OS_SHELL_PIPEFAIL === '1' ||
|
||||||
|
env.BARE_OS_SHELL_PIPEFAIL === 'true'
|
||||||
|
/** First non-zero stage exit when pipefail is active (handbook: first failing stage wins). */
|
||||||
|
let pipefailFirstNonZero = 0
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (let pi = 0; pi < pipeline.length; pi++) {
|
for (let pi = 0; pi < pipeline.length; pi++) {
|
||||||
@@ -1267,6 +1273,12 @@ async function execParsedPipeline(ctx, pipeline) {
|
|||||||
}
|
}
|
||||||
env[k] = expandWord(val, env)
|
env[k] = expandWord(val, env)
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
env.BARE_OS_SHELL_PIPEFAIL === '1' ||
|
||||||
|
env.BARE_OS_SHELL_PIPEFAIL === 'true'
|
||||||
|
) {
|
||||||
|
pipelineWantsPipefail = true
|
||||||
|
}
|
||||||
|
|
||||||
if (!cmd.argv.length) {
|
if (!cmd.argv.length) {
|
||||||
ctx.exitCode = 0
|
ctx.exitCode = 0
|
||||||
@@ -1701,11 +1713,12 @@ async function execParsedPipeline(ctx, pipeline) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pipelineLastExit = Number(ctx.exitCode) || 0
|
pipelineLastExit = Number(ctx.exitCode) || 0
|
||||||
const pipefail =
|
if (
|
||||||
env.BARE_OS_SHELL_PIPEFAIL === '1' ||
|
pipelineWantsPipefail &&
|
||||||
env.BARE_OS_SHELL_PIPEFAIL === 'true'
|
pipefailFirstNonZero === 0 &&
|
||||||
if (pipefail && pipelineLastExit !== 0) {
|
pipelineLastExit !== 0
|
||||||
return 'ok'
|
) {
|
||||||
|
pipefailFirstNonZero = pipelineLastExit
|
||||||
}
|
}
|
||||||
if (ctx.bareOsPipelineStageError) {
|
if (ctx.bareOsPipelineStageError) {
|
||||||
delete ctx.bareOsPipelineStageError
|
delete ctx.bareOsPipelineStageError
|
||||||
@@ -1716,7 +1729,11 @@ async function execParsedPipeline(ctx, pipeline) {
|
|||||||
ctx.shellStdin = stdinText ?? undefined
|
ctx.shellStdin = stdinText ?? undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.exitCode = pipelineLastExit
|
ctx.exitCode = pipelineWantsPipefail
|
||||||
|
? pipefailFirstNonZero !== 0
|
||||||
|
? pipefailFirstNonZero
|
||||||
|
: pipelineLastExit
|
||||||
|
: pipelineLastExit
|
||||||
return 'ok'
|
return 'ok'
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ctx.console.error((e && e.message) || String(e))
|
ctx.console.error((e && e.message) || String(e))
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ import {
|
|||||||
import { parseUnitDropInText } from './lib/bare-initd-user.js'
|
import { parseUnitDropInText } from './lib/bare-initd-user.js'
|
||||||
import { bareOsProcessTableSnapshot } from './lib/bare-os-process-table.js'
|
import { bareOsProcessTableSnapshot } from './lib/bare-os-process-table.js'
|
||||||
import { buildBareOsSyscallsProcJson } from './lib/bare-os-syscalls-proc-json.js'
|
import { buildBareOsSyscallsProcJson } from './lib/bare-os-syscalls-proc-json.js'
|
||||||
|
import {
|
||||||
|
parseBareOsHrpcAllowlistJson,
|
||||||
|
bareOsHrpcAllowlistDeniesRoute
|
||||||
|
} from './lib/bare-os-hrpc-allowlist.js'
|
||||||
import { buildBareOsProtomuxExtensionsProcJson } from './lib/bare-os-protomux-extensions-proc.js'
|
import { buildBareOsProtomuxExtensionsProcJson } from './lib/bare-os-protomux-extensions-proc.js'
|
||||||
import { createBareOsDiskOsBridge } from './lib/bare-os-disk-os-bridge.js'
|
import { createBareOsDiskOsBridge } from './lib/bare-os-disk-os-bridge.js'
|
||||||
import { buildBareOsReplicationLiveSketch } from './lib/bare-os-replication-proc-live.js'
|
import { buildBareOsReplicationLiveSketch } from './lib/bare-os-replication-proc-live.js'
|
||||||
@@ -1329,10 +1333,75 @@ test('buildBareOsSyscallsProcJson exposes posixLike fd mapping', async (t) => {
|
|||||||
t.ok(j.posixXsh.namesCsv.includes('sendmsg'))
|
t.ok(j.posixXsh.namesCsv.includes('sendmsg'))
|
||||||
t.ok(j.posixXsh.namesCsv.includes('recvmsg'))
|
t.ok(j.posixXsh.namesCsv.includes('recvmsg'))
|
||||||
t.ok(j.posixXsh.namesCsv.includes('shutdown'))
|
t.ok(j.posixXsh.namesCsv.includes('shutdown'))
|
||||||
|
t.is(j.socketMsgSurface?.schema, 3)
|
||||||
|
t.is(j.socketMsgSurface?.ancillaryControl?.supported, false)
|
||||||
|
t.is(j.socketMsgSurface?.ancillaryControl?.errno, 'ENOTSUP')
|
||||||
|
t.ok(Array.isArray(j.socketMsgSurface?.ancillaryControl?.rejectKeys))
|
||||||
const xsh = j.opsDetail.filter((r) => r.posixAlignment)
|
const xsh = j.opsDetail.filter((r) => r.posixAlignment)
|
||||||
t.ok(xsh.length >= 10)
|
t.ok(xsh.length >= 10)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('parseBareOsHrpcAllowlistJson + bareOsHrpcAllowlistDeniesRoute', async (t) => {
|
||||||
|
t.is(parseBareOsHrpcAllowlistJson('').allow, null)
|
||||||
|
t.is(parseBareOsHrpcAllowlistJson(' ').allow, null)
|
||||||
|
const a1 = parseBareOsHrpcAllowlistJson('["kernel.ping"]')
|
||||||
|
t.ok(a1.allow && a1.allow.has('kernel.ping'))
|
||||||
|
t.ok(bareOsHrpcAllowlistDeniesRoute(a1.allow, 'kernel', 'capabilities'))
|
||||||
|
t.absent(bareOsHrpcAllowlistDeniesRoute(a1.allow, 'kernel', 'ping'))
|
||||||
|
const a2 = parseBareOsHrpcAllowlistJson('{"kernel.ping":true}')
|
||||||
|
t.ok(a2.allow && a2.allow.has('kernel.ping'))
|
||||||
|
const a3 = parseBareOsHrpcAllowlistJson('{"*":true}')
|
||||||
|
t.ok(a3.allow && a3.allow.has('*'))
|
||||||
|
t.absent(bareOsHrpcAllowlistDeniesRoute(a3.allow, 'vfs', 'readText'))
|
||||||
|
const a4 = parseBareOsHrpcAllowlistJson('{"kernel.*":true}')
|
||||||
|
t.absent(bareOsHrpcAllowlistDeniesRoute(a4.allow, 'kernel', 'capabilities'))
|
||||||
|
t.ok(bareOsHrpcAllowlistDeniesRoute(a4.allow, 'vfs', 'readText'))
|
||||||
|
t.ok(parseBareOsHrpcAllowlistJson('{').parseError)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('pear_doctor_state proc JSON schema 2 parity fields', async (t) => {
|
||||||
|
const j = buildBareOsPearInspectLoggerTlsProcJson(
|
||||||
|
'pear_doctor_state',
|
||||||
|
{
|
||||||
|
BARE_OS_PEAR_DOCTOR_STATE_JSON: '{"ok":true}',
|
||||||
|
BARE_OS_PEAR_RUNTIME_VERSION: '1.2.3',
|
||||||
|
BARE_OS_PEAR_INSPECT_PROBE: '1',
|
||||||
|
BARE_OS_PEAR_DOCTOR_MODULE: 'pear-doctor'
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
t.is(j.schema, 2)
|
||||||
|
t.is(j.runtimeVersion, '1.2.3')
|
||||||
|
t.is(j.pearInspectProbe, true)
|
||||||
|
t.is(j.pearDoctorModuleHint, 'pear-doctor')
|
||||||
|
t.ok(j.state && typeof j.state === 'object')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('split suffix rolls past zz into three-letter names', async (t) => {
|
||||||
|
const a = 'abcdefghijklmnopqrstuvwxyz'
|
||||||
|
function suffix(i) {
|
||||||
|
let idx = i
|
||||||
|
let len = 2
|
||||||
|
let span = 26 ** len
|
||||||
|
while (idx >= span) {
|
||||||
|
idx -= span
|
||||||
|
len++
|
||||||
|
span = 26 ** len
|
||||||
|
}
|
||||||
|
let s = ''
|
||||||
|
let n = idx
|
||||||
|
for (let p = 0; p < len; p++) {
|
||||||
|
s = a[n % 26] + s
|
||||||
|
n = Math.floor(n / 26)
|
||||||
|
}
|
||||||
|
return 'x' + s
|
||||||
|
}
|
||||||
|
t.is(suffix(0), 'xaa')
|
||||||
|
t.is(suffix(675), 'xzz')
|
||||||
|
t.is(suffix(676), 'xaaa')
|
||||||
|
t.is(suffix(677), 'xaab')
|
||||||
|
})
|
||||||
|
|
||||||
test('disk.os replication_snapshot and replication_operator_sketch RPCs', async (t) => {
|
test('disk.os replication_snapshot and replication_operator_sketch RPCs', async (t) => {
|
||||||
const dir = testCorestoreDir('diskosrpc')
|
const dir = testCorestoreDir('diskosrpc')
|
||||||
const store = new Corestore(dir)
|
const store = new Corestore(dir)
|
||||||
@@ -3250,6 +3319,16 @@ async function run(ctx, argv) {
|
|||||||
t.is(ran.join(','), 'false,last', 'pipeline runs both stages')
|
t.is(ran.join(','), 'false,last', 'pipeline runs both stages')
|
||||||
t.is(ctx.exitCode, 0, 'POSIX-like: pipeline exit status is last stage')
|
t.is(ctx.exitCode, 0, 'POSIX-like: pipeline exit status is last stage')
|
||||||
|
|
||||||
|
ran.length = 0
|
||||||
|
ctx.exitCode = 0
|
||||||
|
await execShellLine(ctx, 'BARE_OS_SHELL_PIPEFAIL=1 false | last')
|
||||||
|
t.is(ran.join(','), 'false,last')
|
||||||
|
t.is(
|
||||||
|
ctx.exitCode,
|
||||||
|
1,
|
||||||
|
'pipefail: failure in an earlier stage overrides last stage success'
|
||||||
|
)
|
||||||
|
|
||||||
await store.close()
|
await store.close()
|
||||||
rmSync(dir, { recursive: true, force: true })
|
rmSync(dir, { recursive: true, force: true })
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
/**
|
/**
|
||||||
* Move/rename via copy + delete. Hyperdrive has no single-key rename across paths, so
|
* Move/rename via copy + delete. Hyperdrive has no single-key rename across paths, so
|
||||||
* directory trees and cross-location moves are duplicated then removed. A single regular
|
* directory trees and cross-location moves are duplicated then removed. A single regular
|
||||||
* file to a new non-directory path uses read + write + unlink when detected below.
|
* file to a new non-directory path uses a two-phase write: staging buffer bytes under a
|
||||||
|
* unique **`.bare-os-mv-tmp.*`** name in the **resolved destination directory**, writing the final name,
|
||||||
|
* removing the staging file, then unlinking the source — so a failed final write leaves
|
||||||
|
* the source path intact (staging is best-effort removed).
|
||||||
*
|
*
|
||||||
* Documented limitations: cross-volume moves always copy+delete; EXDEV-style behavior is
|
* Documented limitations: cross-volume moves always copy+delete; EXDEV-style behavior is
|
||||||
* implicit. Busy targets, partial copy failures, and union read-only trees surface as
|
* implicit. Busy targets, partial copy failures, and union read-only trees surface as
|
||||||
* generic errors from the VFS. Prefer same-directory renames for smallest blast radius.
|
* generic errors from the VFS. Prefer same-directory renames for smallest blast radius.
|
||||||
*/
|
*/
|
||||||
|
function mvStagingPathForTarget(ctx, target) {
|
||||||
|
const raw =
|
||||||
|
ctx.vfs && typeof ctx.vfs.resolveLogical === 'function'
|
||||||
|
? ctx.vfs.resolveLogical(target)
|
||||||
|
: String(target || '')
|
||||||
|
const trimmed = String(raw || '').replace(/\/+$/, '') || '/'
|
||||||
|
const last = trimmed.lastIndexOf('/')
|
||||||
|
const dir =
|
||||||
|
last < 0 ? '/' : last === 0 ? '/' : trimmed.slice(0, last) || '/'
|
||||||
|
const base =
|
||||||
|
last < 0 ? trimmed : trimmed.slice(last + 1) || 'file'
|
||||||
|
const tag =
|
||||||
|
Date.now().toString(36) +
|
||||||
|
'-' +
|
||||||
|
Math.random().toString(36).slice(2, 10) +
|
||||||
|
Math.random().toString(36).slice(2, 6)
|
||||||
|
const name = '.bare-os-mv-tmp.' + tag + '.' + base
|
||||||
|
return dir === '/' ? '/' + name : dir + '/' + name
|
||||||
|
}
|
||||||
async function mvCopyPath(ctx, from, to, recursive, followSymlink) {
|
async function mvCopyPath(ctx, from, to, recursive, followSymlink) {
|
||||||
const st = await ctx.vfs.lstat(from)
|
const st = await ctx.vfs.lstat(from)
|
||||||
if (!st) return false
|
if (!st) return false
|
||||||
@@ -117,7 +139,15 @@ async function run(ctx, argv) {
|
|||||||
if (singleFileToFile) {
|
if (singleFileToFile) {
|
||||||
const buf = await ctx.vfs.readFile(src)
|
const buf = await ctx.vfs.readFile(src)
|
||||||
if (!buf) throw new Error('cannot read source')
|
if (!buf) throw new Error('cannot read source')
|
||||||
await ctx.vfs.writeFile(target, buf)
|
const stage = mvStagingPathForTarget(ctx, target)
|
||||||
|
await ctx.vfs.writeFile(stage, buf)
|
||||||
|
try {
|
||||||
|
await ctx.vfs.writeFile(target, buf)
|
||||||
|
} catch (e) {
|
||||||
|
await ctx.vfs.unlink(stage).catch(() => {})
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
await ctx.vfs.unlink(stage).catch(() => {})
|
||||||
await ctx.vfs.unlink(src)
|
await ctx.vfs.unlink(src)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* POSIX-style suffix: `aa`…`zz` (676 files), then `aaa`, `aab`, … as needed.
|
||||||
|
* @param {string} prefix
|
||||||
|
* @param {number} i 0-based output index
|
||||||
|
*/
|
||||||
function splitSuffix(prefix, i) {
|
function splitSuffix(prefix, i) {
|
||||||
const a = 'abcdefghijklmnopqrstuvwxyz'
|
const a = 'abcdefghijklmnopqrstuvwxyz'
|
||||||
const hi = Math.floor(i / 26) % 26
|
let idx = i
|
||||||
const lo = i % 26
|
let len = 2
|
||||||
return prefix + a[hi] + a[lo]
|
let span = 26 ** len
|
||||||
|
while (idx >= span) {
|
||||||
|
idx -= span
|
||||||
|
len++
|
||||||
|
span = 26 ** len
|
||||||
|
}
|
||||||
|
let s = ''
|
||||||
|
let n = idx
|
||||||
|
for (let p = 0; p < len; p++) {
|
||||||
|
s = a[n % 26] + s
|
||||||
|
n = Math.floor(n / 26)
|
||||||
|
}
|
||||||
|
return prefix + s
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run(ctx, argv) {
|
async function run(ctx, argv) {
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host spawn).
|
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host fork of arbitrary binaries).
|
||||||
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
||||||
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
||||||
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||||
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race).
|
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race); parallelism is still in-process
|
||||||
|
* over runBinCommand unless the booter/worker stack offloads specific /bin basenames (see BARE_OS_BIN_WORKER_*).
|
||||||
|
* For explicit host subprocess offload of whitelisted utilities, use ctx.bareOsTrySpawnHostSubprocess from custom scripts with
|
||||||
|
* BARE_OS_BIN_WORKER_ALLOW / delegate policy — not automatic from xargs.
|
||||||
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ Cross-package **version alignment** (ctx API, feature-bits doc, lifecycle schema
|
|||||||
## Documentation (rolling)
|
## Documentation (rolling)
|
||||||
|
|
||||||
- **Seed RPC** — [`lib/channel.js`](lib/channel.js) rejects unknown **`bare_os.*`** method short names against **`BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET`** (**`bare_os.rpc_unknown_method`**); boot policy / env may add **`denySeedRpcMethods`** denials on the booter path. See [`docs/architecture/KERNEL_CONTRACT.md`](../../docs/architecture/KERNEL_CONTRACT.md).
|
- **Seed RPC** — [`lib/channel.js`](lib/channel.js) rejects unknown **`bare_os.*`** method short names against **`BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET`** (**`bare_os.rpc_unknown_method`**); boot policy / env may add **`denySeedRpcMethods`** denials on the booter path. See [`docs/architecture/KERNEL_CONTRACT.md`](../../docs/architecture/KERNEL_CONTRACT.md).
|
||||||
- **Stock hrpc routes** — Documented in **`KERNEL_CONTRACT`**: **`kernel.ping`**, **`kernel.capabilities`**, **`vfs.readText`**, **`bare_os.echo`**, **`bare_os.disk_os_hints`** (validated **`service` / `method` / `payload`**; optional **`BARE_OS_HRPC_ALLOWLIST_JSON`**).
|
- **Stock hrpc routes** — Documented in **`KERNEL_CONTRACT`**: **`kernel.ping`**, **`kernel.capabilities`**, **`vfs.readText`**, **`bare_os.echo`**, **`bare_os.disk_os_hints`** (validated **`service` / `method` / `payload`**; optional **`BARE_OS_HRPC_ALLOWLIST_JSON`** per [`docs/schemas/bare-os-hrpc-allowlist.schema.json`](../../docs/schemas/bare-os-hrpc-allowlist.schema.json); deny-by-default for non-stock routes unless the host replaces **`ctx.bareOsHrpcRequest`** or enables **`BARE_OS_HRPC_EMIT_UNLISTED`**).
|
||||||
|
- **Wire stack pins** — Booter **`protomux`** / **`hyperswarm`** resolved versions are recorded in [`packages/bare-os-booter/fixtures/protomux-hyperswarm-lock.json`](../packages/bare-os-booter/fixtures/protomux-hyperswarm-lock.json); bump with intentional dependency upgrades and full **`npm test`**.
|
||||||
|
|
||||||
## 0.9.0
|
## 0.9.0
|
||||||
|
|
||||||
|
|||||||
@@ -90,12 +90,34 @@ function bareOsEmitRaw(ctx, chunk) {
|
|||||||
/**
|
/**
|
||||||
* Move/rename via copy + delete. Hyperdrive has no single-key rename across paths, so
|
* Move/rename via copy + delete. Hyperdrive has no single-key rename across paths, so
|
||||||
* directory trees and cross-location moves are duplicated then removed. A single regular
|
* directory trees and cross-location moves are duplicated then removed. A single regular
|
||||||
* file to a new non-directory path uses read + write + unlink when detected below.
|
* file to a new non-directory path uses a two-phase write: staging buffer bytes under a
|
||||||
|
* unique **`.bare-os-mv-tmp.*`** name in the **resolved destination directory**, writing the final name,
|
||||||
|
* removing the staging file, then unlinking the source — so a failed final write leaves
|
||||||
|
* the source path intact (staging is best-effort removed).
|
||||||
*
|
*
|
||||||
* Documented limitations: cross-volume moves always copy+delete; EXDEV-style behavior is
|
* Documented limitations: cross-volume moves always copy+delete; EXDEV-style behavior is
|
||||||
* implicit. Busy targets, partial copy failures, and union read-only trees surface as
|
* implicit. Busy targets, partial copy failures, and union read-only trees surface as
|
||||||
* generic errors from the VFS. Prefer same-directory renames for smallest blast radius.
|
* generic errors from the VFS. Prefer same-directory renames for smallest blast radius.
|
||||||
*/
|
*/
|
||||||
|
function mvStagingPathForTarget(ctx, target) {
|
||||||
|
const raw =
|
||||||
|
ctx.vfs && typeof ctx.vfs.resolveLogical === 'function'
|
||||||
|
? ctx.vfs.resolveLogical(target)
|
||||||
|
: String(target || '')
|
||||||
|
const trimmed = String(raw || '').replace(/\/+$/, '') || '/'
|
||||||
|
const last = trimmed.lastIndexOf('/')
|
||||||
|
const dir =
|
||||||
|
last < 0 ? '/' : last === 0 ? '/' : trimmed.slice(0, last) || '/'
|
||||||
|
const base =
|
||||||
|
last < 0 ? trimmed : trimmed.slice(last + 1) || 'file'
|
||||||
|
const tag =
|
||||||
|
Date.now().toString(36) +
|
||||||
|
'-' +
|
||||||
|
Math.random().toString(36).slice(2, 10) +
|
||||||
|
Math.random().toString(36).slice(2, 6)
|
||||||
|
const name = '.bare-os-mv-tmp.' + tag + '.' + base
|
||||||
|
return dir === '/' ? '/' + name : dir + '/' + name
|
||||||
|
}
|
||||||
async function mvCopyPath(ctx, from, to, recursive, followSymlink) {
|
async function mvCopyPath(ctx, from, to, recursive, followSymlink) {
|
||||||
const st = await ctx.vfs.lstat(from)
|
const st = await ctx.vfs.lstat(from)
|
||||||
if (!st) return false
|
if (!st) return false
|
||||||
@@ -206,7 +228,15 @@ async function run(ctx, argv) {
|
|||||||
if (singleFileToFile) {
|
if (singleFileToFile) {
|
||||||
const buf = await ctx.vfs.readFile(src)
|
const buf = await ctx.vfs.readFile(src)
|
||||||
if (!buf) throw new Error('cannot read source')
|
if (!buf) throw new Error('cannot read source')
|
||||||
await ctx.vfs.writeFile(target, buf)
|
const stage = mvStagingPathForTarget(ctx, target)
|
||||||
|
await ctx.vfs.writeFile(stage, buf)
|
||||||
|
try {
|
||||||
|
await ctx.vfs.writeFile(target, buf)
|
||||||
|
} catch (e) {
|
||||||
|
await ctx.vfs.unlink(stage).catch(() => {})
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
await ctx.vfs.unlink(stage).catch(() => {})
|
||||||
await ctx.vfs.unlink(src)
|
await ctx.vfs.unlink(src)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,11 +87,28 @@ function bareOsEmitRaw(ctx, chunk) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POSIX-style suffix: `aa`…`zz` (676 files), then `aaa`, `aab`, … as needed.
|
||||||
|
* @param {string} prefix
|
||||||
|
* @param {number} i 0-based output index
|
||||||
|
*/
|
||||||
function splitSuffix(prefix, i) {
|
function splitSuffix(prefix, i) {
|
||||||
const a = 'abcdefghijklmnopqrstuvwxyz'
|
const a = 'abcdefghijklmnopqrstuvwxyz'
|
||||||
const hi = Math.floor(i / 26) % 26
|
let idx = i
|
||||||
const lo = i % 26
|
let len = 2
|
||||||
return prefix + a[hi] + a[lo]
|
let span = 26 ** len
|
||||||
|
while (idx >= span) {
|
||||||
|
idx -= span
|
||||||
|
len++
|
||||||
|
span = 26 ** len
|
||||||
|
}
|
||||||
|
let s = ''
|
||||||
|
let n = idx
|
||||||
|
for (let p = 0; p < len; p++) {
|
||||||
|
s = a[n % 26] + s
|
||||||
|
n = Math.floor(n / 26)
|
||||||
|
}
|
||||||
|
return prefix + s
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run(ctx, argv) {
|
async function run(ctx, argv) {
|
||||||
|
|||||||
@@ -88,11 +88,14 @@ function bareOsEmitRaw(ctx, chunk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host spawn).
|
* Bounded xargs for Bare OS: invokes ctx.runBinCommand only (no host fork of arbitrary binaries).
|
||||||
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
* Limits: stdin 256KiB, 4096 whitespace/null tokens, 128 args per invocation,
|
||||||
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
* 64 invocations per run. Exceeding limits is a fatal error (exit 125).
|
||||||
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
* Supports -0/--null, -n, -L (lines per invocation; mutually exclusive with -n), -I repl (replace repl in utility argv; implies -n 1 unless -n given).
|
||||||
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race).
|
* -P N runs up to N batches in parallel (each batch uses a shallow ctx clone so exitCode does not race); parallelism is still in-process
|
||||||
|
* over runBinCommand unless the booter/worker stack offloads specific /bin basenames (see BARE_OS_BIN_WORKER_*).
|
||||||
|
* For explicit host subprocess offload of whitelisted utilities, use ctx.bareOsTrySpawnHostSubprocess from custom scripts with
|
||||||
|
* BARE_OS_BIN_WORKER_ALLOW / delegate policy — not automatic from xargs.
|
||||||
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
* Max -P is min(requested, BARE_OS_XARGS_MAX_PROCS env, 32); default cap 8 when env unset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 8,
|
"schemaVersion": 8,
|
||||||
"ctxApiVersion": "1.44.0",
|
"ctxApiVersion": "1.45.0",
|
||||||
"posixProfile": {
|
"posixProfile": {
|
||||||
"id": "bare-os-posix-like",
|
"id": "bare-os-posix-like",
|
||||||
"version": "1.0.9"
|
"version": "1.0.9"
|
||||||
@@ -32,7 +32,19 @@
|
|||||||
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
|
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
|
||||||
},
|
},
|
||||||
"socketMsgSurface": {
|
"socketMsgSurface": {
|
||||||
"schema": 2,
|
"schema": 3,
|
||||||
|
"ancillaryControl": {
|
||||||
|
"supported": false,
|
||||||
|
"errno": "ENOTSUP",
|
||||||
|
"rejectKeys": [
|
||||||
|
"cmsgs",
|
||||||
|
"control",
|
||||||
|
"controllen",
|
||||||
|
"msgHdr.control",
|
||||||
|
"msgHdr.cmsgs"
|
||||||
|
],
|
||||||
|
"note": "Non-empty ancillary fields on sendmsg rejected; recvmsg controllen 0."
|
||||||
|
},
|
||||||
"sendmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" },
|
"sendmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" },
|
||||||
"recvmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" }
|
"recvmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" }
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,36 +7,36 @@
|
|||||||
"hypercoreIdEncoding"
|
"hypercoreIdEncoding"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/safetyCatch.js",
|
|
||||||
"keys": [
|
|
||||||
"safetyCatch"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/b4a.js",
|
"path": "/lib/bare/bundles/b4a.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"b4a"
|
"b4a"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/safetyCatch.js",
|
||||||
|
"keys": [
|
||||||
|
"safetyCatch"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/compactEncoding.js",
|
"path": "/lib/bare/bundles/compactEncoding.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"compactEncoding"
|
"compactEncoding"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareUrl.js",
|
|
||||||
"keys": [
|
|
||||||
"bareUrl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/protomux.js",
|
"path": "/lib/bare/bundles/protomux.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"protomux"
|
"protomux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareUrl.js",
|
||||||
|
"keys": [
|
||||||
|
"bareUrl"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePath.js",
|
"path": "/lib/bare/bundles/barePath.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -74,9 +74,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareAddonResolve.js",
|
"path": "/lib/bare/bundles/bareReadline.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareAddonResolve"
|
"bareReadline"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -86,15 +86,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareReadline.js",
|
"path": "/lib/bare/bundles/bareAddonResolve.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareReadline"
|
"bareAddonResolve"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareApk.js",
|
|
||||||
"keys": [
|
|
||||||
"bareApk"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -109,12 +103,6 @@
|
|||||||
"bareAtomics"
|
"bareAtomics"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareAppKit.js",
|
|
||||||
"keys": [
|
|
||||||
"bareAppKit"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareAssert.js",
|
"path": "/lib/bare/bundles/bareAssert.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -122,9 +110,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBmp.js",
|
"path": "/lib/bare/bundles/bareApk.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareBmp"
|
"bareApk"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareAppKit.js",
|
||||||
|
"keys": [
|
||||||
|
"bareAppKit"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -133,12 +127,24 @@
|
|||||||
"fetch"
|
"fetch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareBmp.js",
|
||||||
|
"keys": [
|
||||||
|
"bareBmp"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBundleCompile.js",
|
"path": "/lib/bare/bundles/bareBundleCompile.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareBundleCompile"
|
"bareBundleCompile"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareBuffer.js",
|
||||||
|
"keys": [
|
||||||
|
"bareBuffer"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBluetoothApple.js",
|
"path": "/lib/bare/bundles/bareBluetoothApple.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -151,30 +157,24 @@
|
|||||||
"bareBundle"
|
"bareBundle"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareBuffer.js",
|
|
||||||
"keys": [
|
|
||||||
"bareBuffer"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
|
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareBundleEvaluate"
|
"bareBundleEvaluate"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareBoot.js",
|
|
||||||
"keys": [
|
|
||||||
"bareBoot"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareConsole.js",
|
"path": "/lib/bare/bundles/bareConsole.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareConsole"
|
"bareConsole"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareBoot.js",
|
||||||
|
"keys": [
|
||||||
|
"bareBoot"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareBundleId.js",
|
"path": "/lib/bare/bundles/bareBundleId.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -187,18 +187,18 @@
|
|||||||
"bareChannel"
|
"bareChannel"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareDelta.js",
|
|
||||||
"keys": [
|
|
||||||
"bareDelta"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareDebugLog.js",
|
"path": "/lib/bare/bundles/bareDebugLog.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareDebugLog"
|
"bareDebugLog"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareDelta.js",
|
||||||
|
"keys": [
|
||||||
|
"bareDelta"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareDaemon.js",
|
"path": "/lib/bare/bundles/bareDaemon.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -217,6 +217,12 @@
|
|||||||
"bareDns"
|
"bareDns"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareCov.js",
|
||||||
|
"keys": [
|
||||||
|
"bareCov"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareEnv.js",
|
"path": "/lib/bare/bundles/bareEnv.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -235,12 +241,6 @@
|
|||||||
"bareExif"
|
"bareExif"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareCov.js",
|
|
||||||
"keys": [
|
|
||||||
"bareCov"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareFfmpeg.js",
|
"path": "/lib/bare/bundles/bareFfmpeg.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -260,9 +260,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareGif.js",
|
"path": "/lib/bare/bundles/bareFileLogger.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareGif"
|
"bareFileLogger"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -272,9 +272,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareFileLogger.js",
|
"path": "/lib/bare/bundles/bareGif.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareFileLogger"
|
"bareGif"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -290,9 +290,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareHttpParser.js",
|
"path": "/lib/bare/bundles/bareFs.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareHttpParser"
|
"bareFs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -301,24 +301,18 @@
|
|||||||
"bareGtk"
|
"bareGtk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareHttpParser.js",
|
||||||
|
"keys": [
|
||||||
|
"bareHttpParser"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareIco.js",
|
"path": "/lib/bare/bundles/bareIco.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareIco"
|
"bareIco"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareFs.js",
|
|
||||||
"keys": [
|
|
||||||
"bareFs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareHttp1.js",
|
|
||||||
"keys": [
|
|
||||||
"bareHttp1"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareImageResample.js",
|
"path": "/lib/bare/bundles/bareImageResample.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -332,9 +326,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareHttps.js",
|
"path": "/lib/bare/bundles/bareHttp1.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareHttps"
|
"bareHttp1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -344,9 +338,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareIpc.js",
|
"path": "/lib/bare/bundles/bareHttps.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareIpc"
|
"bareHttps"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -355,6 +349,18 @@
|
|||||||
"bareIntl"
|
"bareIntl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareIpc.js",
|
||||||
|
"keys": [
|
||||||
|
"bareIpc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareLogger.js",
|
||||||
|
"keys": [
|
||||||
|
"bareLogger"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareInspector.js",
|
"path": "/lib/bare/bundles/bareInspector.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -367,12 +373,6 @@
|
|||||||
"bareLief"
|
"bareLief"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareLogger.js",
|
|
||||||
"keys": [
|
|
||||||
"bareLogger"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareLink.js",
|
"path": "/lib/bare/bundles/bareLink.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -385,30 +385,30 @@
|
|||||||
"bareMake"
|
"bareMake"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareModule.js",
|
|
||||||
"keys": [
|
|
||||||
"bareModule"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareModuleResolve.js",
|
"path": "/lib/bare/bundles/bareModuleResolve.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareModuleResolve"
|
"bareModuleResolve"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareModuleLexer.js",
|
|
||||||
"keys": [
|
|
||||||
"bareModuleLexer"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareModuleTraverse.js",
|
"path": "/lib/bare/bundles/bareModuleTraverse.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareModuleTraverse"
|
"bareModuleTraverse"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareModule.js",
|
||||||
|
"keys": [
|
||||||
|
"bareModule"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareModuleLexer.js",
|
||||||
|
"keys": [
|
||||||
|
"bareModuleLexer"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareNdk.js",
|
"path": "/lib/bare/bundles/bareNdk.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -439,12 +439,6 @@
|
|||||||
"bareNet"
|
"bareNet"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareMedia.js",
|
|
||||||
"keys": [
|
|
||||||
"bareMedia"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareOs.js",
|
"path": "/lib/bare/bundles/bareOs.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -452,15 +446,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePerformance.js",
|
"path": "/lib/bare/bundles/bareMedia.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"barePerformance"
|
"bareMedia"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/barePackDrive.js",
|
|
||||||
"keys": [
|
|
||||||
"barePackDrive"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -469,12 +457,30 @@
|
|||||||
"barePack"
|
"barePack"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/barePerformance.js",
|
||||||
|
"keys": [
|
||||||
|
"barePerformance"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareNodeRuntime.js",
|
||||||
|
"keys": [
|
||||||
|
"bareNodeRuntime"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePng.js",
|
"path": "/lib/bare/bundles/barePng.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"barePng"
|
"barePng"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/barePackDrive.js",
|
||||||
|
"keys": [
|
||||||
|
"barePackDrive"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePipe.js",
|
"path": "/lib/bare/bundles/barePipe.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -488,15 +494,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareNodeRuntime.js",
|
"path": "/lib/bare/bundles/bareQuerystring.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareNodeRuntime"
|
"bareQuerystring"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareDev.js",
|
|
||||||
"keys": [
|
|
||||||
"bareDev"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -506,9 +506,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareQuerystring.js",
|
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareQuerystring"
|
"bareQueueMicrotask"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -523,24 +523,12 @@
|
|||||||
"bareProcess"
|
"bareProcess"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
|
|
||||||
"keys": [
|
|
||||||
"bareQueueMicrotask"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/barePromClient.js",
|
"path": "/lib/bare/bundles/barePromClient.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"barePromClient"
|
"barePromClient"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareRpc.js",
|
|
||||||
"keys": [
|
|
||||||
"bareRpc"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareRuntime.js",
|
"path": "/lib/bare/bundles/bareRuntime.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -548,15 +536,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSemver.js",
|
"path": "/lib/bare/bundles/bareRpc.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareSemver"
|
"bareRpc"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareSdl.js",
|
|
||||||
"keys": [
|
|
||||||
"bareSdl"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -565,6 +547,18 @@
|
|||||||
"bareRepl"
|
"bareRepl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareSemver.js",
|
||||||
|
"keys": [
|
||||||
|
"bareSemver"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareDev.js",
|
||||||
|
"keys": [
|
||||||
|
"bareDev"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSidecar.js",
|
"path": "/lib/bare/bundles/bareSidecar.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -577,6 +571,12 @@
|
|||||||
"bareSignals"
|
"bareSignals"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareSdl.js",
|
||||||
|
"keys": [
|
||||||
|
"bareSdl"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareRun.js",
|
"path": "/lib/bare/bundles/bareRun.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -589,60 +589,60 @@
|
|||||||
"bareStringDecoder"
|
"bareStringDecoder"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareStorage.js",
|
|
||||||
"keys": [
|
|
||||||
"bareStorage"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareStream.js",
|
"path": "/lib/bare/bundles/bareStream.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareStream"
|
"bareStream"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareStdio.js",
|
|
||||||
"keys": [
|
|
||||||
"bareStdio"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSvg.js",
|
"path": "/lib/bare/bundles/bareSvg.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareSvg"
|
"bareSvg"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareStdio.js",
|
||||||
|
"keys": [
|
||||||
|
"bareStdio"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareStorage.js",
|
||||||
|
"keys": [
|
||||||
|
"bareStorage"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareStructuredClone.js",
|
"path": "/lib/bare/bundles/bareStructuredClone.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareStructuredClone"
|
"bareStructuredClone"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareSystemLogger.js",
|
|
||||||
"keys": [
|
|
||||||
"bareSystemLogger"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareTap.js",
|
|
||||||
"keys": [
|
|
||||||
"bareTap"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareTiff.js",
|
"path": "/lib/bare/bundles/bareTiff.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareTiff"
|
"bareTiff"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareSystemLogger.js",
|
||||||
|
"keys": [
|
||||||
|
"bareSystemLogger"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareSubprocess.js",
|
"path": "/lib/bare/bundles/bareSubprocess.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareSubprocess"
|
"bareSubprocess"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareTap.js",
|
||||||
|
"keys": [
|
||||||
|
"bareTap"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareTcp.js",
|
"path": "/lib/bare/bundles/bareTcp.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -655,18 +655,18 @@
|
|||||||
"bareThread"
|
"bareThread"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareTimers.js",
|
|
||||||
"keys": [
|
|
||||||
"bareTimers"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareTpl.js",
|
"path": "/lib/bare/bundles/bareTpl.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareTpl"
|
"bareTpl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareTimers.js",
|
||||||
|
"keys": [
|
||||||
|
"bareTimers"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareType.js",
|
"path": "/lib/bare/bundles/bareType.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -691,12 +691,6 @@
|
|||||||
"bareTty"
|
"bareTty"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareV8.js",
|
|
||||||
"keys": [
|
|
||||||
"bareV8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareUnpack.js",
|
"path": "/lib/bare/bundles/bareUnpack.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -704,9 +698,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareUnionBundle.js",
|
"path": "/lib/bare/bundles/bareV8.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareUnionBundle"
|
"bareV8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareVm.js",
|
||||||
|
"keys": [
|
||||||
|
"bareVm"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -722,21 +722,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareVm.js",
|
"path": "/lib/bare/bundles/bareUnionBundle.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareVm"
|
"bareUnionBundle"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareUtils.js",
|
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareUtils"
|
"bareV8ToIstanbul"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareWebKitGtk.js",
|
|
||||||
"keys": [
|
|
||||||
"bareWebKitGtk"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -745,6 +739,12 @@
|
|||||||
"bareWebp"
|
"bareWebp"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareUtils.js",
|
||||||
|
"keys": [
|
||||||
|
"bareUtils"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareWhich.js",
|
"path": "/lib/bare/bundles/bareWhich.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -752,15 +752,15 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareWinUi.js",
|
"path": "/lib/bare/bundles/bareWebKitGtk.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareWinUi"
|
"bareWebKitGtk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
|
"path": "/lib/bare/bundles/bareWinUi.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
"bareV8ToIstanbul"
|
"bareWinUi"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -775,6 +775,12 @@
|
|||||||
"bareZlib"
|
"bareZlib"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/lib/bare/bundles/bareWs.js",
|
||||||
|
"keys": [
|
||||||
|
"bareWs"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/lib/bare/bundles/bareZmq.js",
|
"path": "/lib/bare/bundles/bareZmq.js",
|
||||||
"keys": [
|
"keys": [
|
||||||
@@ -786,12 +792,6 @@
|
|||||||
"keys": [
|
"keys": [
|
||||||
"bareWorker"
|
"bareWorker"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/lib/bare/bundles/bareWs.js",
|
|
||||||
"keys": [
|
|
||||||
"bareWs"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bundleStats": {
|
"bundleStats": {
|
||||||
@@ -1595,8 +1595,8 @@
|
|||||||
],
|
],
|
||||||
"bundleProvenance": {
|
"bundleProvenance": {
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"generatedAt": "2026-04-05T05:06:01.462Z",
|
"generatedAt": "2026-04-05T05:30:46.127Z",
|
||||||
"gitCommit": "f79db043130bdbfffa8bcca66fd6252c9d17205d",
|
"gitCommit": "c64910d72ee5547302fce1717ffedd42594e4bc4",
|
||||||
"nodeVersion": "v22.22.0",
|
"nodeVersion": "v22.22.0",
|
||||||
"bundleTier": "all",
|
"bundleTier": "all",
|
||||||
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"atMs": 1775365560517,
|
"atMs": 1775367045352,
|
||||||
"commands": [
|
"commands": [
|
||||||
"arch",
|
"arch",
|
||||||
"awk",
|
"awk",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -251,6 +251,12 @@ Writes **[`docs/audit/holepunch-clone-sync-report.json`](../docs/audit/holepunch
|
|||||||
|
|
||||||
Runs on every **`pretest`**. For each repo basename listed in **`repos`** inside **[`docs/audit/holepunch-drift-repos.json`](../docs/audit/holepunch-drift-repos.json)**, checks that **`origin/main`** is an ancestor of **`HEAD`** (clone not behind remote). With an empty **`repos`** array, the script is a no-op. The same file carries **`suggestedCriticalRepos`** (wire stack hints); copy those into **`repos`** when you maintain local clones and want CI to enforce freshness. Set **`BARE_OS_HOLEPUNCH_DRIFT_CHECK=0`** to skip the script entirely (e.g. offline sandboxes). **`sync-holepunch-clones.mjs`** echoes **`suggestedCriticalRepos`** into **`holepunch-clone-sync-report.json`** for review.
|
Runs on every **`pretest`**. For each repo basename listed in **`repos`** inside **[`docs/audit/holepunch-drift-repos.json`](../docs/audit/holepunch-drift-repos.json)**, checks that **`origin/main`** is an ancestor of **`HEAD`** (clone not behind remote). With an empty **`repos`** array, the script is a no-op. The same file carries **`suggestedCriticalRepos`** (wire stack hints); copy those into **`repos`** when you maintain local clones and want CI to enforce freshness. Set **`BARE_OS_HOLEPUNCH_DRIFT_CHECK=0`** to skip the script entirely (e.g. offline sandboxes). **`sync-holepunch-clones.mjs`** echoes **`suggestedCriticalRepos`** into **`holepunch-clone-sync-report.json`** for review.
|
||||||
|
|
||||||
|
## `gen-bare-holepunch-catalog.mjs`
|
||||||
|
|
||||||
|
**Usage:** `node scripts/gen-bare-holepunch-catalog.mjs` (also **`npm run gen:bare-catalog`** / **`npm run gen:bare-catalog:check`** from the repo root)
|
||||||
|
|
||||||
|
Scans a local Holepunch mirror ( **`HOLEPUNCH_MIRROR`** or default under the repo) for **`holepunchto/bare-*`** repos, merges npm **`latest`** metadata and **[`scripts/bare-catalog-overrides.json`](bare-catalog-overrides.json)**, and writes **[`docs/bare-holepunch-catalog.json`](../docs/bare-holepunch-catalog.json)**. Follow with **`npm run sync:bare-manifest`** and **`npm install`** so **[`packages/bare-os-booter/lib/bare-module-manifest.json`](../packages/bare-os-booter/lib/bare-module-manifest.json)** and booter **`optionalDependencies`** stay aligned. CI **`gen:bare-catalog:check`** ensures the committed catalog does not drift.
|
||||||
|
|
||||||
## `verify-bundle-throws.mjs`
|
## `verify-bundle-throws.mjs`
|
||||||
|
|
||||||
**Usage:** `node scripts/verify-bundle-throws.mjs`
|
**Usage:** `node scripts/verify-bundle-throws.mjs`
|
||||||
|
|||||||
Reference in New Issue
Block a user