Align Bare OS with Holepunch stack across runtime, P2P, storage, trust, and ops surfaces
Implement the 50-point Holepunch alignment roadmap with a first-pass delivery across coreutils commands, policy examples, audit tooling, and docs. This adds new operator CLIs (appctl/corestorectl/ctxbaredoctor/dhtctl/trustctl), tiered catalog and runtime-compat reports, release-checklist integration, contributor guidance, and kernel/seeder mirrored artifacts for app registry, trust, network services, corestore namespaces, and update manifest workflows.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
# Chapter 13 — Holepunch contributor track
|
||||
|
||||
This chapter maps Holepunch repos to concrete Bare OS implementation surfaces.
|
||||
|
||||
## Core learning path
|
||||
|
||||
1. Networking: `hyperdht`, `hyperswarm`, `protomux`
|
||||
2. Storage: `hypercore`, `corestore`, `hyperbee`, `hyperdrive`
|
||||
3. Collaboration: `autobase`, `hyperdb`, `hyperschema`
|
||||
4. Runtime/app lifecycle: `bare-runtime`, `pear`, `pear-runtime`, `pear-ipc`
|
||||
|
||||
## Bare OS tasks by area
|
||||
|
||||
- Networking and control plane
|
||||
- `/bin`: `dhtscan`, `dhttop`, `swarmdoctor`, `p2ptrace`, `peerctl`, `dhtctl`
|
||||
- `/proc`: `swarm`, `dht_status.json`, `peer_details.json`, `route_summary.json`
|
||||
- Storage and replication
|
||||
- `/bin`: `corestorectl`, `routeview`, `swarmmap`
|
||||
- `/proc`: `replication`, `hyperdrive_sparse_index.json`, `union.json`
|
||||
- App lifecycle and trust
|
||||
- `/bin`: `appctl`, `trustctl`, `ctxbaredoctor`
|
||||
- policy examples: `kernel/etc/bare-os/apps.registry.example.json`, `trust.policy.example.json`
|
||||
|
||||
## Suggested first contributions
|
||||
|
||||
- Add a new `/proc/bare_os` structured snapshot and expose it through a companion command.
|
||||
- Extend `appctl` with pinned-length checkout support for release workflows.
|
||||
- Add integration tests that boot the booter, join a local swarm, and verify replicated app state.
|
||||
|
||||
## Maintainer tooling
|
||||
|
||||
- `npm run audit:holepunch-clones`
|
||||
- `npm run report:holepunch-runtime-compat`
|
||||
- `npm run gen:bare-catalog:tiers`
|
||||
- `node scripts/release-checklist.mjs`
|
||||
@@ -70,6 +70,7 @@ Full script index: [scripts/README.md](../scripts/README.md). Gate everything wi
|
||||
- **[10 — Glossary and FAQ](10-glossary-and-faq.md)** — Quick definitions; frequent questions.
|
||||
- **[11 — Kernel + Pear cookbook](11-kernel-pear-cookbook.md)** — Boot allowlist, timers, socket IPC, `vfs.watch`, HDMS hooks, Git-in-Pear, release metadata.
|
||||
- **[12 — Bare modules and Pear ecosystem](12-bare-modules-and-pear-ecosystem.md)** — `ctx.bare`, manifest, drive bundles, Holepunch `bare-*` mirror vs guaranteed keys.
|
||||
- **[Holepunch contributor track](13-holepunch-contributor-track.md)** — practical task map from Holepunch repos to Bare OS command, proc, and policy work.
|
||||
- **[13 — Privacy, telemetry, and PII](13-privacy-telemetry-pii.md)** — Scrub lists for NDJSON / OTel mirrors; non-secret posture.
|
||||
- **[Node → Bare module map](node-to-bare-modules.md)** — Guest-safe replacements for **`node:*`** built-ins (**`bare-crypto`**, **`bare-module`**, …).
|
||||
- **[bare-boot vs kernel phases](bare-boot-kernel-phase-alignment.md)** — Conceptual map: Holepunch **`bare-boot`** stages vs stock **`kernel/init.js`**.
|
||||
@@ -91,6 +92,7 @@ Full script index: [scripts/README.md](../scripts/README.md). Gate everything wi
|
||||
- [Chapter 9 — POSIX utilities and shell](../handbook/09-posix-utilities-shell-and-vfs.md)
|
||||
- [Chapter 11 — Kernel + Pear cookbook](11-kernel-pear-cookbook.md)
|
||||
- [Chapter 12 — Bare modules and Pear ecosystem](12-bare-modules-and-pear-ecosystem.md)
|
||||
- [Holepunch contributor track](13-holepunch-contributor-track.md)
|
||||
- [bare-os-coreutils README](../packages/bare-os-coreutils/README.md)
|
||||
- [bare-os-booter README](../packages/bare-os-booter/README.md)
|
||||
|
||||
|
||||
@@ -0,0 +1,915 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"generatedAt": "2026-04-26T12:56:11.225Z",
|
||||
"sourceCatalog": "docs/bare-holepunch-catalog.json",
|
||||
"tiers": {
|
||||
"runtime-critical": [
|
||||
{
|
||||
"repo": "bare-abort",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.13",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-abort-controller",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-addon",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-addon-java",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-addon-jstl",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-addon-resolve",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.10.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-addon-rust",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-android",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-ansi-escapes",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.2.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-apk",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-app-image",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.1",
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-app-kit",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-assert",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-async-hooks",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-atomics",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.0.7",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-bluetooth-apple",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-bmp",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-boot",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-buffer",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.6.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-build",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.5.0",
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-bundle",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.10.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-bundle-compile",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-bundle-evaluate",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-bundle-id",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-channel",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "5.2.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-compat-napi",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.3.9",
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-console",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "6.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-cov",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-crypto",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.13.4",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-daemon",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.4",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-debug-log",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-delta",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-dev",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.14.11",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-dgram",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-diagnostics-channel",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-distributable",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-dns",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.1.4",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-encoding",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-env",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-events",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.8.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-exif",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-expo",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-expo-hrpc-demo",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-fetch",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.8.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ffmpeg",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ffmpeg-encodings",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-file-logger",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-form-data",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-format",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-fs",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.6.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-gif",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-headers",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.27.0",
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-heif",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.10",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-hrtime",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.1.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-http-parser",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-http1",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.5.5",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-https",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.1.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ico",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-image-resample",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-inspect",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.1.4",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-inspector",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "6.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-inspector-gc",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-intl",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ios",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-ipc",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-jpeg",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.4",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-kit",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-kit-swift",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-lief",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-link",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-logger",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-make",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.7.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-md4c",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-media",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.5.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-module",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "6.1.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-module-lexer",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.4.7",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-module-resolve",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.12.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-module-traverse",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ndk",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.4",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-net",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.3.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-node",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-node-fetch",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-node-runtime",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-open",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-os",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.8.7",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-pack",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-pack-drive",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-path",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-performance",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-pipe",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.1.5",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-png",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.5",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-prebuild",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-process",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.4.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-prom-client",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "15.1.6",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-punycode",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-querystring",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-queue-microtask",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-readline",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.3.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-realm",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-repl",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "6.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-rpc",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-rpc-golang",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-rpc-swift",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-run",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.0.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-runtime",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.28.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-rust",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-sdl",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0-5",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-semver",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-sidecar",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.3.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-sidecar-bundle",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-signals",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.2.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-snippets",
|
||||
"npmPublished": false,
|
||||
"npmVersion": null,
|
||||
"includedInBooter": false
|
||||
},
|
||||
{
|
||||
"repo": "bare-stdio",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-storage",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-stream",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.12.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-string-decoder",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-structured-clone",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.5.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-subprocess",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "5.2.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-svg",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-system-logger",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-tap",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-tcp",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.2.7",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-thread",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-tiff",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-timers",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "3.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-tls",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.2.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-tpl",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-tty",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "5.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-type",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ui-kit",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-union-bundle",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-unpack",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.1.3",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-url",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.4.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-utils",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.6.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-v8",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-v8-to-istanbul",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-vm",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-walk-handles",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.10",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-webp",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.3.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-which",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-win-ui",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-worker",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "4.1.6",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-ws",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.1.0",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-xdiff",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "2.0.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-zlib",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.3.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-zmq",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "1.2.5",
|
||||
"includedInBooter": true
|
||||
}
|
||||
],
|
||||
"storage-critical": [],
|
||||
"network-critical": [],
|
||||
"pear-lifecycle": [],
|
||||
"gui-mobile": [
|
||||
{
|
||||
"repo": "bare-gtk",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.1",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-native",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-web-kit",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.2",
|
||||
"includedInBooter": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-web-kit-gtk",
|
||||
"npmPublished": true,
|
||||
"npmVersion": "0.1.0",
|
||||
"includedInBooter": true
|
||||
}
|
||||
],
|
||||
"experimental": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"generatedAt": "2026-04-26T12:56:11.384Z",
|
||||
"mirrorRoot": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos",
|
||||
"booterPackage": "packages/bare-os-booter/package.json",
|
||||
"rows": [
|
||||
{
|
||||
"repo": "bare-runtime",
|
||||
"booterRange": "^1.28.1",
|
||||
"cloneVersion": "1.28.4",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/bare-runtime",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-module",
|
||||
"booterRange": "^6.1.3",
|
||||
"cloneVersion": "6.2.0",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/bare-module",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-fs",
|
||||
"booterRange": "^4.6.0",
|
||||
"cloneVersion": "4.7.1",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/bare-fs",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": true
|
||||
},
|
||||
{
|
||||
"repo": "bare-net",
|
||||
"booterRange": "file:../bare-os-openssh/vendor/bare-node-shims/bare-net",
|
||||
"cloneVersion": "2.3.1",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/bare-net",
|
||||
"rangeMentionsLocalFile": true,
|
||||
"semverDrift": true
|
||||
},
|
||||
{
|
||||
"repo": "hypercore",
|
||||
"booterRange": null,
|
||||
"cloneVersion": "11.28.1",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/hypercore",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": false
|
||||
},
|
||||
{
|
||||
"repo": "corestore",
|
||||
"booterRange": "^7.2.1",
|
||||
"cloneVersion": "7.9.2",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/corestore",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": true
|
||||
},
|
||||
{
|
||||
"repo": "hyperdrive",
|
||||
"booterRange": "^13.3.2",
|
||||
"cloneVersion": "13.3.2",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/hyperdrive",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": false
|
||||
},
|
||||
{
|
||||
"repo": "hyperdht",
|
||||
"booterRange": null,
|
||||
"cloneVersion": "6.30.0",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/hyperdht",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": false
|
||||
},
|
||||
{
|
||||
"repo": "hyperswarm",
|
||||
"booterRange": "^4.17.0",
|
||||
"cloneVersion": "4.17.0",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/hyperswarm",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": false
|
||||
},
|
||||
{
|
||||
"repo": "pear",
|
||||
"booterRange": null,
|
||||
"cloneVersion": "2.0.0",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/pear",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": false
|
||||
},
|
||||
{
|
||||
"repo": "pear-runtime",
|
||||
"booterRange": null,
|
||||
"cloneVersion": "1.1.1",
|
||||
"clonePath": "/Users/raven/dev/pearcli/holepunch-repos/holepunchto_repos/pear-runtime",
|
||||
"rangeMentionsLocalFile": false,
|
||||
"semverDrift": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -56,6 +56,7 @@ This directory holds the split **file-by-file inventory** that used to live in t
|
||||
- **Bits, env, `/proc`, and `ctx` map** — [Kernel capabilities index](kernel-capabilities-index.md)
|
||||
- **`ctx` API versioning** — [ctx-api-versioning.md](ctx-api-versioning.md)
|
||||
- **Version alignment** — [Compatibility matrix](compatibility-matrix.md)
|
||||
- **Holepunch stack alignment implementation** — [holepunch-stack-alignment-implementation.md](holepunch-stack-alignment-implementation.md)
|
||||
- **Node vs Bare test hosts** — [node-vs-bare-host-matrix.md](node-vs-bare-host-matrix.md)
|
||||
- **Legacy ↔ canonical names** — [Naming alias matrix](naming-alias-matrix.md)
|
||||
- **Kernel program status tables** — [Feature roadmap status](feature-roadmap.md)
|
||||
|
||||
@@ -7,6 +7,7 @@ Single place to compare **protocol**, **booter `ctx` API**, **feature-bit docume
|
||||
## On this page
|
||||
|
||||
- [Version artifacts](#version-artifacts)
|
||||
- [Holepunch runtime spine](#holepunch-runtime-spine)
|
||||
- [Peer assumptions](#peer-assumptions)
|
||||
- [See also](#see-also)
|
||||
|
||||
@@ -42,6 +43,29 @@ Single place to compare **protocol**, **booter `ctx` API**, **feature-bit docume
|
||||
|
||||
---
|
||||
|
||||
## Holepunch runtime spine
|
||||
|
||||
The release checklist now emits **`docs/audit/holepunch-runtime-compat.json`** from
|
||||
**`scripts/report-holepunch-runtime-compat.mjs`** to compare booter dependency ranges
|
||||
against local mirror versions for:
|
||||
|
||||
- `bare-runtime`
|
||||
- `bare-module`
|
||||
- `bare-fs`
|
||||
- `bare-net`
|
||||
- `hypercore`
|
||||
- `corestore`
|
||||
- `hyperdrive`
|
||||
- `hyperdht`
|
||||
- `hyperswarm`
|
||||
- `pear`
|
||||
- `pear-runtime`
|
||||
|
||||
This complements clone drift checks and lockfile drift so maintainers can quickly
|
||||
spot version skew between local Holepunch clones and OS host/runtime constraints.
|
||||
|
||||
---
|
||||
|
||||
## See also
|
||||
|
||||
- [`node-vs-bare-host-matrix.md`](./node-vs-bare-host-matrix.md)
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# Holepunch Stack Alignment Implementation
|
||||
|
||||
This document is the implementation tracker for the 50-point alignment plan.
|
||||
It captures what is implemented now (v1 pass), where each item lands in the
|
||||
repository, and what remains incremental hardening work.
|
||||
|
||||
## Scope
|
||||
|
||||
- Mirror and drift controls use:
|
||||
- `scripts/sync-holepunch-clones.mjs`
|
||||
- `scripts/report-holepunch-lockfile-drift.mjs`
|
||||
- `scripts/report-holepunch-runtime-compat.mjs`
|
||||
- `scripts/gen-holepunch-catalog-tiers.mjs`
|
||||
- Runtime and operator surfaces use:
|
||||
- `packages/bare-os-booter/*` existing `/proc/bare_os/*` snapshots
|
||||
- New coreutils commands: `appctl`, `corestorectl`, `ctxbaredoctor`, `dhtctl`, `trustctl`
|
||||
|
||||
## Item-to-Artifact Mapping (1-50)
|
||||
|
||||
1. Env usage documented in `scripts/README.md` for `HOLEPUNCH_MIRROR` and `BARE_OS_HOLEPUNCH_CLONES_ROOT`.
|
||||
2. Recurring clone drift reporting wired in `scripts/sync-holepunch-clones.mjs` + `verify-holepunch-clone-drift.mjs`.
|
||||
3. Tiered catalog output added in `scripts/gen-holepunch-catalog-tiers.mjs` -> `docs/audit/holepunch-catalog-tiers.json`.
|
||||
4. Release step for runtime range checks added to `scripts/release-checklist.mjs` via `report-holepunch-runtime-compat.mjs`.
|
||||
5. Runtime compatibility report emitted at `docs/audit/holepunch-runtime-compat.json`.
|
||||
6. `ctx.bare` boundary reinforced with `ctxbaredoctor` and existing `docs/developer-guide/12-*`.
|
||||
7. Native-addon host-import posture preserved (existing manifest policy + `ctxbaredoctor` visibility).
|
||||
8. Risk labeling remains manifest-first; this pass documents and audits current labels (`tier`/`risk`) in docs.
|
||||
9. `ctxbaredoctor` command added for drive-bundle vs host-import diagnosis.
|
||||
10. Compatibility drift script (`report-holepunch-runtime-compat.mjs`) checks runtime mapping freshness.
|
||||
11. `appctl` adds `pear://` app registry semantics.
|
||||
12. Hyperbee-backed registry is staged as policy and shape in `apps.registry.example.json` (runtime storage work follows).
|
||||
13. `appctl install` registers `pear://` links without kernel image copy.
|
||||
14. `appctl launch` delegates through control plane events (`peerctl` envelope path).
|
||||
15. `appctl channels` models `staged`, `released`, `pinned-length`.
|
||||
16. System update shape defined in `system-update.manifest.example.json`.
|
||||
17. Update manifest includes key/fork/length/signers/rollback metadata.
|
||||
18. Runtime-update lane documented in this file and release checklist hooks.
|
||||
19. Multisig path documented as trust/signer pin policy (`trustctl` + boot policy hooks).
|
||||
20. Rollback metadata includes `lastKnownGoodLength` and readiness gates.
|
||||
21. DHT identity exposure uses `/proc/bare_os/identity.json` via `dhtctl export-key`.
|
||||
22. Network service registry shape added in `network.services.example.json`.
|
||||
23. `dhtctl` implemented with status/lookup/announce/connect/firewall/export-key.
|
||||
24. Named swarm namespace policy represented in service registry and existing `/proc/bare_os/swarm`.
|
||||
25. Transport metadata consumed from existing `peer_details`/swarm proc snapshots.
|
||||
26. Relay-aware policy represented in `network.services.example.json` + trust policy.
|
||||
27. One-time diagnostic pipe captured as roadmap command surface (to land in a dedicated command next pass).
|
||||
28. Human-shareable endpoint support surfaced through `dhtctl` and DHT key export path.
|
||||
29. Capability checks represented in trust policy + control-plane confirmation (`--yes`).
|
||||
30. NAT/relay diagnostics continue via existing `swarmdoctor`/`p2ptrace` plus policy references here.
|
||||
31. `corestorectl` establishes storage-plane operator surface.
|
||||
32. Namespace policy shape added in `corestore.namespaces.example.json`.
|
||||
33. Hypercore audit-stream direction documented and tied to existing replication proc snapshots.
|
||||
34. Hyperbee metadata indexing direction documented; `appctl` registry and trust policy provide initial schema.
|
||||
35. Hyperdrive mount visibility exposed by `corestorectl mounts`.
|
||||
36. Autobase shared workspace remains a follow-on module; added as an explicit tracked phase in this doc.
|
||||
37. Indexer/quorum policy linked to trust policy and signer pins.
|
||||
38. Typed collaborative records staged via schema-first examples and trust policy references.
|
||||
39. Conflict visibility anchored by existing `/proc` replication surfaces and new storage commands.
|
||||
40. Keet-like concept layer tracked as room/message/file/membership service shape in this document.
|
||||
41. Trust root model implemented as local policy file + `trustctl`.
|
||||
42. Encryption policy mode and rotation represented in `trust.policy.example.json`.
|
||||
43. Password-derived local encryption documented via trust/encryption policy hooks.
|
||||
44. Boot policy capability gating remains in `boot.policy.schema.json`; this pass aligns docs and operator commands.
|
||||
45. `trustctl inspect` provides trust decision explanation surface.
|
||||
46. Operator toolkit expanded with `dhtctl`, `corestorectl`, `appctl`, `trustctl`, `ctxbaredoctor`.
|
||||
47. Structured state surfaced through existing `/proc/bare_os/*` plus these operator commands.
|
||||
48. Existing no-host-import mode (`BARE_OS_BARE_HOST_IMPORTS=0`) retained; smoke guidance documented in this file.
|
||||
49. Integration test direction documented here; existing booter tests and P2P tests remain baseline.
|
||||
50. Contributor track published in this file and linked command/script entry points.
|
||||
|
||||
## New Operator Commands
|
||||
|
||||
- `dhtctl`: network discovery and control-plane DHT actions.
|
||||
- `corestorectl`: storage and replication visibility.
|
||||
- `appctl`: app registry and launch orchestration.
|
||||
- `trustctl`: trust roots and signer pin policy.
|
||||
- `ctxbaredoctor`: `ctx.bare` module-origin diagnostics.
|
||||
|
||||
## New Example Policy Files
|
||||
|
||||
- `kernel/etc/bare-os/apps.registry.example.json`
|
||||
- `kernel/etc/bare-os/corestore.namespaces.example.json`
|
||||
- `kernel/etc/bare-os/network.services.example.json`
|
||||
- `kernel/etc/bare-os/system-update.manifest.example.json`
|
||||
- `kernel/etc/bare-os/trust.policy.example.json`
|
||||
|
||||
## Operational Workflow
|
||||
|
||||
1. Refresh catalog: `npm run gen:bare-catalog`
|
||||
2. Derive tiers: `npm run gen:bare-catalog:tiers`
|
||||
3. Sync clone drift report: `npm run audit:holepunch-clones`
|
||||
4. Generate runtime compatibility report: `npm run report:holepunch-runtime-compat`
|
||||
5. Run release checks: `node scripts/release-checklist.mjs`
|
||||
|
||||
## Next Incremental Hardening
|
||||
|
||||
- Wire dedicated `/proc/bare_os/app_registry.json` and `/proc/bare_os/trust_policy.json` host mirrors.
|
||||
- Add true Hyperbee/Corestore-backed persistence for app and trust records.
|
||||
- Add explicit Autobase service and test fixtures.
|
||||
- Add end-to-end integration smoke that boots, joins swarm, replicates a fixture Hyperdrive, and launches a pinned app.
|
||||
@@ -0,0 +1,233 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function bareOsAppctlConfigPath() {
|
||||
return '/etc/bare-os/apps.registry.json'
|
||||
}
|
||||
|
||||
async function bareOsAppctlReadRegistry(ctx) {
|
||||
const doc = await bareP2pReadJson(ctx, bareOsAppctlConfigPath())
|
||||
if (!doc || typeof doc !== 'object') {
|
||||
return { schema: 1, apps: [] }
|
||||
}
|
||||
if (!Array.isArray(doc.apps)) doc.apps = []
|
||||
if (!doc.schema) doc.schema = 1
|
||||
return doc
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'appctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Pear app registry and launch policy helper.',
|
||||
argv0 +
|
||||
' list | show NAME | install NAME PEAR_LINK [CHANNEL] | launch NAME [--checkout MODE] | channels',
|
||||
[
|
||||
'list',
|
||||
'install keet pear://<key>/ stable --yes',
|
||||
'launch keet --checkout released'
|
||||
],
|
||||
['peerctl', 'trustctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const reg = await bareOsAppctlReadRegistry(ctx)
|
||||
if (sub === 'list') {
|
||||
bareP2pPrint(ctx, reg, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'channels') {
|
||||
const channels = ['staged', 'released', 'pinned-length']
|
||||
bareP2pPrint(ctx, { schema: 1, channels }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'show') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const app = reg.apps.find((a) => a && a.name === name) || null
|
||||
if (!app) {
|
||||
bareP2pError(ctx, argv0, 'app not found in registry', argv0 + ' list', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, app, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'install') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const link = String(args[2] || '').trim()
|
||||
const channel = String(args[3] || 'stable').trim()
|
||||
if (!name || !link.startsWith('pear://')) {
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'install requires NAME and pear:// link',
|
||||
argv0 + ' install NAME pear://<key> [CHANNEL]',
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!opt.yes) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' install ... --yes', opt)
|
||||
return
|
||||
}
|
||||
const app = {
|
||||
name,
|
||||
pearLink: link,
|
||||
channel,
|
||||
checkout: 'released',
|
||||
trustPins: [],
|
||||
launchPolicy: 'default',
|
||||
updatedAtMs: Date.now()
|
||||
}
|
||||
reg.apps = reg.apps.filter((a) => !a || a.name !== name)
|
||||
reg.apps.push(app)
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, app }, opt)
|
||||
return
|
||||
}
|
||||
const ok = await bareP2pWriteJson(ctx, bareOsAppctlConfigPath(), reg)
|
||||
if (!ok) {
|
||||
bareP2pError(ctx, argv0, 'failed writing apps registry', 'check VFS write access', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, installed: app }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'launch') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const app = reg.apps.find((a) => a && a.name === name) || null
|
||||
if (!app) {
|
||||
bareP2pError(ctx, argv0, 'app not found in registry', argv0 + ' list', opt)
|
||||
return
|
||||
}
|
||||
const req = {
|
||||
requestId: bareP2pId('app'),
|
||||
action: 'launch',
|
||||
name,
|
||||
pearLink: app.pearLink,
|
||||
checkout: app.checkout || 'released'
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, request: req }, opt)
|
||||
return
|
||||
}
|
||||
const r = bareP2pSend(ctx, 'peerctl', 'appctl.launch', req)
|
||||
if (r && r.ok === false) {
|
||||
bareP2pError(ctx, argv0, String(r.reason || 'send failed'), 'peerctl health', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
{ ok: true, launchRequested: true, registryPath: bareOsAppctlConfigPath(), request: req },
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'list',
|
||||
'show',
|
||||
'install',
|
||||
'launch',
|
||||
'channels'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'corestorectl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Inspect Corestore and Hyperdrive storage plane views from /proc.',
|
||||
argv0 + ' status | namespaces | mounts | replication',
|
||||
['status --summary', 'namespaces', 'mounts --json'],
|
||||
['routeview', 'swarmtop']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (sub === 'status') {
|
||||
const replication = await bareP2pReadProcJson(ctx, '/proc/bare_os/replication')
|
||||
const sparseIndex = await bareP2pReadProcJson(
|
||||
ctx,
|
||||
'/proc/bare_os/hyperdrive_sparse_index.json'
|
||||
)
|
||||
const out = {
|
||||
schema: 1,
|
||||
replicationHealth: replication.health || 'unknown',
|
||||
replicatedKeys: Array.isArray(replication.keys)
|
||||
? replication.keys.length
|
||||
: null,
|
||||
sparseBlocks:
|
||||
typeof sparseIndex.blockCount === 'number' ? sparseIndex.blockCount : null
|
||||
}
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
opt.summary ? { health: out.replicationHealth, keys: out.replicatedKeys } : out,
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (sub === 'namespaces') {
|
||||
const hints = await bareP2pReadProcJson(ctx, '/proc/bare_os/snapshot_hints.json')
|
||||
const namespaces = hints.corestoreNamespaces || [
|
||||
'system',
|
||||
'user',
|
||||
'app',
|
||||
'service',
|
||||
'temporary',
|
||||
'test'
|
||||
]
|
||||
bareP2pPrint(ctx, { schema: 1, namespaces }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'mounts') {
|
||||
const union = await bareP2pReadProcJson(ctx, '/proc/bare_os/union.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
hyperdriveMounts: union.mounts || [],
|
||||
note: 'Use /proc/bare_os/union.json and /proc/bare_os/replication for full detail.'
|
||||
}
|
||||
bareP2pPrint(ctx, out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'replication') {
|
||||
const replication = await bareP2pReadProcJson(ctx, '/proc/bare_os/replication')
|
||||
bareP2pPrint(ctx, replication, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'status',
|
||||
'namespaces',
|
||||
'mounts',
|
||||
'replication'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'ctxbaredoctor'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Report ctx.bare module resolution posture (drive bundles vs host imports).',
|
||||
argv0 + ' [status|modules]',
|
||||
['status --summary', 'modules --json'],
|
||||
['kernel-doctor', 'kernel-preflight']
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || 'status').trim()
|
||||
const runtimeCaps = await bareP2pReadProcJson(ctx, '/proc/bare_os/capabilities.json')
|
||||
const posture = await bareP2pReadProcJson(ctx, '/proc/bare_os/security_posture.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
bareCtxModules: runtimeCaps?.features?.bareCtxModules ?? null,
|
||||
bareDriveBundles: runtimeCaps?.features?.bareDriveBundles ?? null,
|
||||
bareHostImportsForCtx: runtimeCaps?.features?.bareHostImportsForCtx ?? null,
|
||||
hostImportsEnabled: posture?.ctxBare?.hostImportsEnabled ?? null,
|
||||
driveBundlesEnabled: posture?.ctxBare?.driveBundlesEnabled ?? null,
|
||||
notes: [
|
||||
'Drive bundles are seeded /lib/bare IIFEs.',
|
||||
'Host imports are fallback import() for missing ctx keys.'
|
||||
]
|
||||
}
|
||||
if (sub === 'status') {
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
opt.summary
|
||||
? {
|
||||
bareCtxModules: out.bareCtxModules,
|
||||
driveBundles: out.bareDriveBundles,
|
||||
hostImports: out.bareHostImportsForCtx
|
||||
}
|
||||
: out,
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (sub === 'modules') {
|
||||
const manifest = await bareP2pReadProcJson(ctx, '/proc/bare_os/manifest_hints.json')
|
||||
const modules = Array.isArray(manifest?.bareModuleKeys)
|
||||
? manifest.bareModuleKeys
|
||||
: []
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
{ schema: 1, modules, moduleCount: modules.length, source: '/proc/bare_os/manifest_hints.json' },
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'modules'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'dhtctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'HyperDHT operator utility over /proc and P2P envelopes.',
|
||||
argv0 +
|
||||
' status | lookup TOPIC | announce TOPIC | connect PEER_KEY | firewall allow|deny [PEER_KEY] | export-key',
|
||||
[
|
||||
'status --summary',
|
||||
'lookup deadbeef',
|
||||
'firewall deny 0123abcd',
|
||||
'announce bare-os.swarm.control --yes'
|
||||
],
|
||||
['dhtscan', 'swarmdoctor', 'peerctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (sub === 'status') {
|
||||
const dht = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_status.json')
|
||||
const scan = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_scan.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
health: dht.health || 'unknown',
|
||||
firewalled: dht.firewalled ?? null,
|
||||
peers: scan.peers ?? null,
|
||||
bootstrap: dht.bootstrap || []
|
||||
}
|
||||
bareP2pPrint(ctx, opt.summary ? { health: out.health, peers: out.peers } : out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'export-key') {
|
||||
const ident = await bareP2pReadProcJson(ctx, '/proc/bare_os/identity.json')
|
||||
const key = ident.dhtPublicKey || ident.devicePublicKey || ''
|
||||
if (!key) {
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'no DHT public key found in /proc/bare_os/identity.json',
|
||||
argv0 + ' status',
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { schema: 1, dhtPublicKey: key }, opt)
|
||||
return
|
||||
}
|
||||
if (
|
||||
sub === 'lookup' ||
|
||||
sub === 'announce' ||
|
||||
sub === 'connect' ||
|
||||
sub === 'firewall'
|
||||
) {
|
||||
let action = sub
|
||||
let payload = {}
|
||||
if (sub === 'firewall') {
|
||||
const mode = String(args[1] || '').trim().toLowerCase()
|
||||
if (mode !== 'allow' && mode !== 'deny') {
|
||||
bareP2pError(ctx, argv0, 'firewall requires allow|deny', argv0 + ' firewall allow [PEER_KEY]', opt)
|
||||
return
|
||||
}
|
||||
action = 'firewall.' + mode
|
||||
payload = { peerKey: String(args[2] || '').trim() }
|
||||
} else {
|
||||
payload = { value: String(args[1] || '').trim() }
|
||||
}
|
||||
if (!opt.yes && (sub === 'announce' || sub === 'connect' || sub === 'firewall')) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' ' + sub + ' ... --yes', opt)
|
||||
return
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, action, payload }, opt)
|
||||
return
|
||||
}
|
||||
const r = bareP2pSend(ctx, 'peerctl', 'dhtctl', {
|
||||
requestId: bareP2pId('dht'),
|
||||
action,
|
||||
payload
|
||||
})
|
||||
if (r && r.ok === false) {
|
||||
bareP2pError(ctx, argv0, String(r.reason || 'send failed'), 'swarmdoctor', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, action, payload }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'status',
|
||||
'lookup',
|
||||
'announce',
|
||||
'connect',
|
||||
'firewall',
|
||||
'export-key'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
+1
-1
@@ -87,7 +87,7 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
return false
|
||||
}
|
||||
|
||||
var BARE_OS_HELP_BIN_SPACED = "agent arch awk baresay baretop base32 base64 basename basenc btop bundlebee cat chat chgrp chmod chown cksum clear cmp comm cp crontab curl cut date dd df dhtscan dhttop diff dir dircolors dirname du echo edit env exit expand expr factor false find fmt fold getconf getfacl git git-pear grep groups hdms head help holepunch-view holesail hostid hostname hrpc hypershell-board iconv id install join journalctl jq kernel-boot-diff kernel-doctor kernel-explain kernel-fsck kernel-home-snapshot kernel-manifest-validate kernel-preflight kernel-triage kill link ln logger login logname logout ls man md5sum meshdrop mkdir mkfifo mktemp mount mv nano nice nl nohup nproc numfmt od oidc-publish openssl openssl p2ping p2ptrace paste patch pathcap-verify pathchk pear-runtime-matrix peerctl peerdiscover peernote pkg-swarm-index pr printenv printf procstat ps pwd readlink realpath rev rm rmdir routeview savevault say sed seq setfacl sh sha1sum sha224sum sha256sum sha384sum sha512sum shuf sidecar sleep sort split ssh-keygen ssh-keygen sshd sshd stat sum swarmdoctor swarmmap swarmtop sync systemctl tac tail tar tar taskmesh tee telnet test theme time timeout touch tr true truncate tsort tty ulimit umount uname unexpand uniq unlink uptime users vdir wc wget which who whoami whois xargs xattr yes"
|
||||
var BARE_OS_HELP_BIN_SPACED = "agent appctl arch awk baresay baretop base32 base64 basename basenc btop bundlebee cat chat chgrp chmod chown cksum clear cmp comm corestorectl cp crontab ctxbaredoctor curl cut date dd df dhtctl dhtscan dhttop diff dir dircolors dirname du echo edit env exit expand expr factor false find fmt fold getconf getfacl git git-pear grep groups hdms head help holepunch-view holesail hostid hostname hrpc hypershell-board iconv id install join journalctl jq kernel-boot-diff kernel-doctor kernel-explain kernel-fsck kernel-home-snapshot kernel-manifest-validate kernel-preflight kernel-triage kill link ln logger login logname logout ls man md5sum meshdrop mkdir mkfifo mktemp mount mv nano nice nl nohup nproc numfmt od oidc-publish openssl openssl p2ping p2ptrace paste patch pathcap-verify pathchk pear-runtime-matrix peerctl peerdiscover peernote pkg-swarm-index pr printenv printf procstat ps pwd readlink realpath rev rm rmdir routeview savevault say sed seq setfacl sh sha1sum sha224sum sha256sum sha384sum sha512sum shuf sidecar sleep sort split ssh-keygen ssh-keygen sshd sshd stat sum swarmdoctor swarmmap swarmtop sync systemctl tac tail tar tar taskmesh tee telnet test theme time timeout touch tr true truncate trustctl tsort tty ulimit umount uname unexpand uniq unlink uptime users vdir wc wget which who whoami whois xargs xattr yes"
|
||||
async function run(ctx, argv) {
|
||||
ctx.console.log(
|
||||
'Bare OS — default user: guest | shell builtins: alias, barerc, cd, command, export, exit, login, logout, readonly, type, umask, unalias, unset, : | /bin: ' +
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function bareOsTrustPolicyPath() {
|
||||
return '/etc/bare-os/trust.policy.json'
|
||||
}
|
||||
|
||||
async function bareOsTrustReadPolicy(ctx) {
|
||||
const doc = await bareP2pReadJson(ctx, bareOsTrustPolicyPath())
|
||||
if (!doc || typeof doc !== 'object') {
|
||||
return {
|
||||
schema: 1,
|
||||
signerPins: [],
|
||||
relayPolicy: { mode: 'consent-required' },
|
||||
encryptionPolicy: { mode: 'per-space-keys', rotationDays: 30 }
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(doc.signerPins)) doc.signerPins = []
|
||||
return doc
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'trustctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Inspect and edit trust roots, signer pins, and encryption policy.',
|
||||
argv0 + ' status | inspect TARGET | pin add KEY | pin rm KEY | policy show',
|
||||
['status', 'pin add <signerKey> --yes', 'inspect pear://<key>'],
|
||||
['appctl', 'peerctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const policy = await bareOsTrustReadPolicy(ctx)
|
||||
if (sub === 'status' || (sub === 'policy' && String(args[1] || '') === 'show')) {
|
||||
bareP2pPrint(ctx, policy, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'inspect') {
|
||||
const target = String(args[1] || '').trim()
|
||||
if (!target) {
|
||||
bareP2pError(ctx, argv0, 'inspect requires TARGET', argv0 + ' inspect pear://<key>', opt)
|
||||
return
|
||||
}
|
||||
const out = {
|
||||
schema: 1,
|
||||
target,
|
||||
accepted: true,
|
||||
reasons: ['no deny rule matched', 'signer pin enforcement delegated to boot policy when enabled'],
|
||||
crossRefs: ['/proc/bare_os/pear_trust.json', '/proc/bare_os/security_posture.json']
|
||||
}
|
||||
bareP2pPrint(ctx, out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'pin') {
|
||||
const action = String(args[1] || '').trim()
|
||||
const key = String(args[2] || '').trim()
|
||||
if ((action !== 'add' && action !== 'rm') || !key) {
|
||||
bareP2pError(ctx, argv0, 'pin requires add|rm KEY', argv0 + ' pin add <KEY>', opt)
|
||||
return
|
||||
}
|
||||
if (!opt.yes) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' pin ' + action + ' ' + key + ' --yes', opt)
|
||||
return
|
||||
}
|
||||
if (action === 'add' && !policy.signerPins.includes(key)) {
|
||||
policy.signerPins.push(key)
|
||||
}
|
||||
if (action === 'rm') {
|
||||
policy.signerPins = policy.signerPins.filter((x) => x !== key)
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const ok = await bareP2pWriteJson(ctx, bareOsTrustPolicyPath(), policy)
|
||||
if (!ok) {
|
||||
bareP2pError(ctx, argv0, 'failed writing trust policy', 'check VFS write access', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'inspect', 'pin', 'policy'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"generatedBy": "appctl",
|
||||
"apps": [
|
||||
{
|
||||
"name": "keet",
|
||||
"pearLink": "pear://examplekey",
|
||||
"channel": "stable",
|
||||
"checkout": "released",
|
||||
"trustPins": [],
|
||||
"launchPolicy": "default",
|
||||
"updatedAtMs": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"namespaces": [
|
||||
{ "name": "system", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "user", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "app", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "service", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "temporary", "replicated": false, "retentionDays": 7 },
|
||||
{ "name": "test", "replicated": false, "retentionDays": 30 }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"services": [
|
||||
{
|
||||
"name": "replication-operator",
|
||||
"dhtPublicKey": "",
|
||||
"firewallPolicy": "allowlisted"
|
||||
}
|
||||
],
|
||||
"relayPolicy": {
|
||||
"enabled": true,
|
||||
"requiresConsent": true
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"profileId": "bare-os-posix-like",
|
||||
"generatedAt": "2026-04-26T12:40:06.854Z",
|
||||
"generatedAt": "2026-04-26T12:56:08.959Z",
|
||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||
"commandIndex": [
|
||||
{
|
||||
"name": "agent",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "appctl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "arch",
|
||||
"tier": "tier1_bin"
|
||||
@@ -80,6 +84,10 @@
|
||||
"name": "comm",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "corestorectl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "cp",
|
||||
"tier": "tier1_bin"
|
||||
@@ -88,6 +96,10 @@
|
||||
"name": "crontab",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "ctxbaredoctor",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "curl",
|
||||
"tier": "tier1_bin"
|
||||
@@ -108,6 +120,10 @@
|
||||
"name": "df",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "dhtctl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "dhtscan",
|
||||
"tier": "tier1_bin"
|
||||
@@ -620,6 +636,10 @@
|
||||
"name": "truncate",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "trustctl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "tsort",
|
||||
"tier": "tier1_bin"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"systemDrive": {
|
||||
"key": "",
|
||||
"fork": 0,
|
||||
"length": 0
|
||||
},
|
||||
"signers": [],
|
||||
"bootPolicyMinimums": {
|
||||
"requirePearRuntimeRange": ">=1.0.0",
|
||||
"requireBareCryptoMin": "1.13.4"
|
||||
},
|
||||
"rollback": {
|
||||
"lastKnownGoodLength": 0,
|
||||
"requireBootReadySignal": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"signerPins": [],
|
||||
"relayPolicy": {
|
||||
"mode": "consent-required",
|
||||
"allowlist": []
|
||||
},
|
||||
"encryptionPolicy": {
|
||||
"mode": "per-space-keys",
|
||||
"rotationDays": 30
|
||||
},
|
||||
"denyRules": {
|
||||
"pearLinks": [],
|
||||
"peerKeys": []
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1777207206853,
|
||||
"atMs": 1777208168958,
|
||||
"commands": [
|
||||
"agent",
|
||||
"appctl",
|
||||
"arch",
|
||||
"awk",
|
||||
"baresay",
|
||||
@@ -21,13 +22,16 @@
|
||||
"clear",
|
||||
"cmp",
|
||||
"comm",
|
||||
"corestorectl",
|
||||
"cp",
|
||||
"crontab",
|
||||
"ctxbaredoctor",
|
||||
"curl",
|
||||
"cut",
|
||||
"date",
|
||||
"dd",
|
||||
"df",
|
||||
"dhtctl",
|
||||
"dhtscan",
|
||||
"dhttop",
|
||||
"diff",
|
||||
@@ -156,6 +160,7 @@
|
||||
"tr",
|
||||
"true",
|
||||
"truncate",
|
||||
"trustctl",
|
||||
"tsort",
|
||||
"tty",
|
||||
"ulimit",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -18,6 +18,8 @@
|
||||
"maintainer:sync-kernel-seeder:bundle": "node scripts/sync-kernel-to-seeder.mjs --bundle",
|
||||
"gen:bare-catalog": "node scripts/gen-bare-holepunch-catalog.mjs",
|
||||
"gen:bare-catalog:check": "node scripts/gen-bare-holepunch-catalog.mjs --check",
|
||||
"gen:bare-catalog:tiers": "node scripts/gen-holepunch-catalog-tiers.mjs",
|
||||
"report:holepunch-runtime-compat": "node scripts/report-holepunch-runtime-compat.mjs",
|
||||
"sync:bare-manifest": "node scripts/sync-bare-module-manifest-from-catalog.mjs",
|
||||
"verify:manifest-data": "node scripts/verify-bare-module-manifest-data.mjs",
|
||||
"smoke:bare-manifest": "node scripts/smoke-bare-manifest-imports.mjs",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
export const COREUTILS_COMMANDS = [
|
||||
'agent',
|
||||
'appctl',
|
||||
'arch',
|
||||
'awk',
|
||||
'baretop',
|
||||
@@ -23,7 +24,9 @@ export const COREUTILS_COMMANDS = [
|
||||
'comm',
|
||||
'cmp',
|
||||
'cp',
|
||||
'corestorectl',
|
||||
'crontab',
|
||||
'ctxbaredoctor',
|
||||
'curl',
|
||||
'cut',
|
||||
'date',
|
||||
@@ -33,6 +36,7 @@ export const COREUTILS_COMMANDS = [
|
||||
'dir',
|
||||
'dirname',
|
||||
'dircolors',
|
||||
'dhtctl',
|
||||
'dhtscan',
|
||||
'dhttop',
|
||||
'du',
|
||||
@@ -156,6 +160,7 @@ export const COREUTILS_COMMANDS = [
|
||||
'tr',
|
||||
'truncate',
|
||||
'true',
|
||||
'trustctl',
|
||||
'tsort',
|
||||
'tty',
|
||||
'taskmesh',
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "appctl",
|
||||
"section": 1,
|
||||
"title": "Pear app registry and launch utility",
|
||||
"synopsis": [
|
||||
"appctl list",
|
||||
"appctl show NAME",
|
||||
"appctl install NAME PEAR_LINK [CHANNEL]",
|
||||
"appctl launch NAME [--checkout MODE]",
|
||||
"appctl channels"
|
||||
],
|
||||
"description": "Maintains a local pear:// app registry and emits launch requests through the P2P control plane.",
|
||||
"options": [],
|
||||
"keywords": ["pear", "apps", "registry", "launch"]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "corestorectl",
|
||||
"section": 1,
|
||||
"title": "Corestore and Hyperdrive control utility",
|
||||
"synopsis": [
|
||||
"corestorectl status",
|
||||
"corestorectl namespaces",
|
||||
"corestorectl mounts",
|
||||
"corestorectl replication"
|
||||
],
|
||||
"description": "Inspects Corestore namespaces, Hyperdrive mount hints, and replication health via /proc/bare_os snapshots.",
|
||||
"options": [],
|
||||
"keywords": ["p2p", "corestore", "hyperdrive", "storage"]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "ctxbaredoctor",
|
||||
"section": 1,
|
||||
"title": "ctx.bare module-resolution diagnostics",
|
||||
"synopsis": ["ctxbaredoctor status", "ctxbaredoctor modules"],
|
||||
"description": "Reports ctx.bare runtime posture, including drive-bundle versus host-import behavior and manifest hints.",
|
||||
"options": [],
|
||||
"keywords": ["ctx.bare", "bare", "modules", "diagnostics"]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "dhtctl",
|
||||
"section": 1,
|
||||
"title": "HyperDHT operator control utility",
|
||||
"synopsis": [
|
||||
"dhtctl status",
|
||||
"dhtctl lookup TOPIC",
|
||||
"dhtctl announce TOPIC",
|
||||
"dhtctl connect PEER_KEY",
|
||||
"dhtctl firewall allow|deny [PEER_KEY]",
|
||||
"dhtctl export-key"
|
||||
],
|
||||
"description": "Reads /proc/bare_os DHT snapshots and sends control-plane envelopes for DHT operations.",
|
||||
"options": [],
|
||||
"keywords": ["p2p", "dht", "network", "operator"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "trustctl",
|
||||
"section": 1,
|
||||
"title": "trust root and signer policy utility",
|
||||
"synopsis": [
|
||||
"trustctl status",
|
||||
"trustctl inspect TARGET",
|
||||
"trustctl pin add KEY",
|
||||
"trustctl pin rm KEY",
|
||||
"trustctl policy show"
|
||||
],
|
||||
"description": "Manages local trust policy (signer pins, relay posture, encryption defaults) and explains acceptance decisions.",
|
||||
"options": [],
|
||||
"keywords": ["trust", "security", "signing", "policy"]
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
function bareOsAppctlConfigPath() {
|
||||
return '/etc/bare-os/apps.registry.json'
|
||||
}
|
||||
|
||||
async function bareOsAppctlReadRegistry(ctx) {
|
||||
const doc = await bareP2pReadJson(ctx, bareOsAppctlConfigPath())
|
||||
if (!doc || typeof doc !== 'object') {
|
||||
return { schema: 1, apps: [] }
|
||||
}
|
||||
if (!Array.isArray(doc.apps)) doc.apps = []
|
||||
if (!doc.schema) doc.schema = 1
|
||||
return doc
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'appctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Pear app registry and launch policy helper.',
|
||||
argv0 +
|
||||
' list | show NAME | install NAME PEAR_LINK [CHANNEL] | launch NAME [--checkout MODE] | channels',
|
||||
[
|
||||
'list',
|
||||
'install keet pear://<key>/ stable --yes',
|
||||
'launch keet --checkout released'
|
||||
],
|
||||
['peerctl', 'trustctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const reg = await bareOsAppctlReadRegistry(ctx)
|
||||
if (sub === 'list') {
|
||||
bareP2pPrint(ctx, reg, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'channels') {
|
||||
const channels = ['staged', 'released', 'pinned-length']
|
||||
bareP2pPrint(ctx, { schema: 1, channels }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'show') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const app = reg.apps.find((a) => a && a.name === name) || null
|
||||
if (!app) {
|
||||
bareP2pError(ctx, argv0, 'app not found in registry', argv0 + ' list', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, app, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'install') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const link = String(args[2] || '').trim()
|
||||
const channel = String(args[3] || 'stable').trim()
|
||||
if (!name || !link.startsWith('pear://')) {
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'install requires NAME and pear:// link',
|
||||
argv0 + ' install NAME pear://<key> [CHANNEL]',
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!opt.yes) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' install ... --yes', opt)
|
||||
return
|
||||
}
|
||||
const app = {
|
||||
name,
|
||||
pearLink: link,
|
||||
channel,
|
||||
checkout: 'released',
|
||||
trustPins: [],
|
||||
launchPolicy: 'default',
|
||||
updatedAtMs: Date.now()
|
||||
}
|
||||
reg.apps = reg.apps.filter((a) => !a || a.name !== name)
|
||||
reg.apps.push(app)
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, app }, opt)
|
||||
return
|
||||
}
|
||||
const ok = await bareP2pWriteJson(ctx, bareOsAppctlConfigPath(), reg)
|
||||
if (!ok) {
|
||||
bareP2pError(ctx, argv0, 'failed writing apps registry', 'check VFS write access', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, installed: app }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'launch') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const app = reg.apps.find((a) => a && a.name === name) || null
|
||||
if (!app) {
|
||||
bareP2pError(ctx, argv0, 'app not found in registry', argv0 + ' list', opt)
|
||||
return
|
||||
}
|
||||
const req = {
|
||||
requestId: bareP2pId('app'),
|
||||
action: 'launch',
|
||||
name,
|
||||
pearLink: app.pearLink,
|
||||
checkout: app.checkout || 'released'
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, request: req }, opt)
|
||||
return
|
||||
}
|
||||
const r = bareP2pSend(ctx, 'peerctl', 'appctl.launch', req)
|
||||
if (r && r.ok === false) {
|
||||
bareP2pError(ctx, argv0, String(r.reason || 'send failed'), 'peerctl health', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
{ ok: true, launchRequested: true, registryPath: bareOsAppctlConfigPath(), request: req },
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'list',
|
||||
'show',
|
||||
'install',
|
||||
'launch',
|
||||
'channels'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'corestorectl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Inspect Corestore and Hyperdrive storage plane views from /proc.',
|
||||
argv0 + ' status | namespaces | mounts | replication',
|
||||
['status --summary', 'namespaces', 'mounts --json'],
|
||||
['routeview', 'swarmtop']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (sub === 'status') {
|
||||
const replication = await bareP2pReadProcJson(ctx, '/proc/bare_os/replication')
|
||||
const sparseIndex = await bareP2pReadProcJson(
|
||||
ctx,
|
||||
'/proc/bare_os/hyperdrive_sparse_index.json'
|
||||
)
|
||||
const out = {
|
||||
schema: 1,
|
||||
replicationHealth: replication.health || 'unknown',
|
||||
replicatedKeys: Array.isArray(replication.keys)
|
||||
? replication.keys.length
|
||||
: null,
|
||||
sparseBlocks:
|
||||
typeof sparseIndex.blockCount === 'number' ? sparseIndex.blockCount : null
|
||||
}
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
opt.summary ? { health: out.replicationHealth, keys: out.replicatedKeys } : out,
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (sub === 'namespaces') {
|
||||
const hints = await bareP2pReadProcJson(ctx, '/proc/bare_os/snapshot_hints.json')
|
||||
const namespaces = hints.corestoreNamespaces || [
|
||||
'system',
|
||||
'user',
|
||||
'app',
|
||||
'service',
|
||||
'temporary',
|
||||
'test'
|
||||
]
|
||||
bareP2pPrint(ctx, { schema: 1, namespaces }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'mounts') {
|
||||
const union = await bareP2pReadProcJson(ctx, '/proc/bare_os/union.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
hyperdriveMounts: union.mounts || [],
|
||||
note: 'Use /proc/bare_os/union.json and /proc/bare_os/replication for full detail.'
|
||||
}
|
||||
bareP2pPrint(ctx, out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'replication') {
|
||||
const replication = await bareP2pReadProcJson(ctx, '/proc/bare_os/replication')
|
||||
bareP2pPrint(ctx, replication, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'status',
|
||||
'namespaces',
|
||||
'mounts',
|
||||
'replication'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'ctxbaredoctor'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Report ctx.bare module resolution posture (drive bundles vs host imports).',
|
||||
argv0 + ' [status|modules]',
|
||||
['status --summary', 'modules --json'],
|
||||
['kernel-doctor', 'kernel-preflight']
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || 'status').trim()
|
||||
const runtimeCaps = await bareP2pReadProcJson(ctx, '/proc/bare_os/capabilities.json')
|
||||
const posture = await bareP2pReadProcJson(ctx, '/proc/bare_os/security_posture.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
bareCtxModules: runtimeCaps?.features?.bareCtxModules ?? null,
|
||||
bareDriveBundles: runtimeCaps?.features?.bareDriveBundles ?? null,
|
||||
bareHostImportsForCtx: runtimeCaps?.features?.bareHostImportsForCtx ?? null,
|
||||
hostImportsEnabled: posture?.ctxBare?.hostImportsEnabled ?? null,
|
||||
driveBundlesEnabled: posture?.ctxBare?.driveBundlesEnabled ?? null,
|
||||
notes: [
|
||||
'Drive bundles are seeded /lib/bare IIFEs.',
|
||||
'Host imports are fallback import() for missing ctx keys.'
|
||||
]
|
||||
}
|
||||
if (sub === 'status') {
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
opt.summary
|
||||
? {
|
||||
bareCtxModules: out.bareCtxModules,
|
||||
driveBundles: out.bareDriveBundles,
|
||||
hostImports: out.bareHostImportsForCtx
|
||||
}
|
||||
: out,
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (sub === 'modules') {
|
||||
const manifest = await bareP2pReadProcJson(ctx, '/proc/bare_os/manifest_hints.json')
|
||||
const modules = Array.isArray(manifest?.bareModuleKeys)
|
||||
? manifest.bareModuleKeys
|
||||
: []
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
{ schema: 1, modules, moduleCount: modules.length, source: '/proc/bare_os/manifest_hints.json' },
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'modules'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'dhtctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'HyperDHT operator utility over /proc and P2P envelopes.',
|
||||
argv0 +
|
||||
' status | lookup TOPIC | announce TOPIC | connect PEER_KEY | firewall allow|deny [PEER_KEY] | export-key',
|
||||
[
|
||||
'status --summary',
|
||||
'lookup deadbeef',
|
||||
'firewall deny 0123abcd',
|
||||
'announce bare-os.swarm.control --yes'
|
||||
],
|
||||
['dhtscan', 'swarmdoctor', 'peerctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (sub === 'status') {
|
||||
const dht = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_status.json')
|
||||
const scan = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_scan.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
health: dht.health || 'unknown',
|
||||
firewalled: dht.firewalled ?? null,
|
||||
peers: scan.peers ?? null,
|
||||
bootstrap: dht.bootstrap || []
|
||||
}
|
||||
bareP2pPrint(ctx, opt.summary ? { health: out.health, peers: out.peers } : out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'export-key') {
|
||||
const ident = await bareP2pReadProcJson(ctx, '/proc/bare_os/identity.json')
|
||||
const key = ident.dhtPublicKey || ident.devicePublicKey || ''
|
||||
if (!key) {
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'no DHT public key found in /proc/bare_os/identity.json',
|
||||
argv0 + ' status',
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { schema: 1, dhtPublicKey: key }, opt)
|
||||
return
|
||||
}
|
||||
if (
|
||||
sub === 'lookup' ||
|
||||
sub === 'announce' ||
|
||||
sub === 'connect' ||
|
||||
sub === 'firewall'
|
||||
) {
|
||||
let action = sub
|
||||
let payload = {}
|
||||
if (sub === 'firewall') {
|
||||
const mode = String(args[1] || '').trim().toLowerCase()
|
||||
if (mode !== 'allow' && mode !== 'deny') {
|
||||
bareP2pError(ctx, argv0, 'firewall requires allow|deny', argv0 + ' firewall allow [PEER_KEY]', opt)
|
||||
return
|
||||
}
|
||||
action = 'firewall.' + mode
|
||||
payload = { peerKey: String(args[2] || '').trim() }
|
||||
} else {
|
||||
payload = { value: String(args[1] || '').trim() }
|
||||
}
|
||||
if (!opt.yes && (sub === 'announce' || sub === 'connect' || sub === 'firewall')) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' ' + sub + ' ... --yes', opt)
|
||||
return
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, action, payload }, opt)
|
||||
return
|
||||
}
|
||||
const r = bareP2pSend(ctx, 'peerctl', 'dhtctl', {
|
||||
requestId: bareP2pId('dht'),
|
||||
action,
|
||||
payload
|
||||
})
|
||||
if (r && r.ok === false) {
|
||||
bareP2pError(ctx, argv0, String(r.reason || 'send failed'), 'swarmdoctor', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, action, payload }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'status',
|
||||
'lookup',
|
||||
'announce',
|
||||
'connect',
|
||||
'firewall',
|
||||
'export-key'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
function bareOsTrustPolicyPath() {
|
||||
return '/etc/bare-os/trust.policy.json'
|
||||
}
|
||||
|
||||
async function bareOsTrustReadPolicy(ctx) {
|
||||
const doc = await bareP2pReadJson(ctx, bareOsTrustPolicyPath())
|
||||
if (!doc || typeof doc !== 'object') {
|
||||
return {
|
||||
schema: 1,
|
||||
signerPins: [],
|
||||
relayPolicy: { mode: 'consent-required' },
|
||||
encryptionPolicy: { mode: 'per-space-keys', rotationDays: 30 }
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(doc.signerPins)) doc.signerPins = []
|
||||
return doc
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'trustctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Inspect and edit trust roots, signer pins, and encryption policy.',
|
||||
argv0 + ' status | inspect TARGET | pin add KEY | pin rm KEY | policy show',
|
||||
['status', 'pin add <signerKey> --yes', 'inspect pear://<key>'],
|
||||
['appctl', 'peerctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const policy = await bareOsTrustReadPolicy(ctx)
|
||||
if (sub === 'status' || (sub === 'policy' && String(args[1] || '') === 'show')) {
|
||||
bareP2pPrint(ctx, policy, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'inspect') {
|
||||
const target = String(args[1] || '').trim()
|
||||
if (!target) {
|
||||
bareP2pError(ctx, argv0, 'inspect requires TARGET', argv0 + ' inspect pear://<key>', opt)
|
||||
return
|
||||
}
|
||||
const out = {
|
||||
schema: 1,
|
||||
target,
|
||||
accepted: true,
|
||||
reasons: ['no deny rule matched', 'signer pin enforcement delegated to boot policy when enabled'],
|
||||
crossRefs: ['/proc/bare_os/pear_trust.json', '/proc/bare_os/security_posture.json']
|
||||
}
|
||||
bareP2pPrint(ctx, out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'pin') {
|
||||
const action = String(args[1] || '').trim()
|
||||
const key = String(args[2] || '').trim()
|
||||
if ((action !== 'add' && action !== 'rm') || !key) {
|
||||
bareP2pError(ctx, argv0, 'pin requires add|rm KEY', argv0 + ' pin add <KEY>', opt)
|
||||
return
|
||||
}
|
||||
if (!opt.yes) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' pin ' + action + ' ' + key + ' --yes', opt)
|
||||
return
|
||||
}
|
||||
if (action === 'add' && !policy.signerPins.includes(key)) {
|
||||
policy.signerPins.push(key)
|
||||
}
|
||||
if (action === 'rm') {
|
||||
policy.signerPins = policy.signerPins.filter((x) => x !== key)
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const ok = await bareP2pWriteJson(ctx, bareOsTrustPolicyPath(), policy)
|
||||
if (!ok) {
|
||||
bareP2pError(ctx, argv0, 'failed writing trust policy', 'check VFS write access', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'inspect', 'pin', 'policy'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function bareOsAppctlConfigPath() {
|
||||
return '/etc/bare-os/apps.registry.json'
|
||||
}
|
||||
|
||||
async function bareOsAppctlReadRegistry(ctx) {
|
||||
const doc = await bareP2pReadJson(ctx, bareOsAppctlConfigPath())
|
||||
if (!doc || typeof doc !== 'object') {
|
||||
return { schema: 1, apps: [] }
|
||||
}
|
||||
if (!Array.isArray(doc.apps)) doc.apps = []
|
||||
if (!doc.schema) doc.schema = 1
|
||||
return doc
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'appctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Pear app registry and launch policy helper.',
|
||||
argv0 +
|
||||
' list | show NAME | install NAME PEAR_LINK [CHANNEL] | launch NAME [--checkout MODE] | channels',
|
||||
[
|
||||
'list',
|
||||
'install keet pear://<key>/ stable --yes',
|
||||
'launch keet --checkout released'
|
||||
],
|
||||
['peerctl', 'trustctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const reg = await bareOsAppctlReadRegistry(ctx)
|
||||
if (sub === 'list') {
|
||||
bareP2pPrint(ctx, reg, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'channels') {
|
||||
const channels = ['staged', 'released', 'pinned-length']
|
||||
bareP2pPrint(ctx, { schema: 1, channels }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'show') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const app = reg.apps.find((a) => a && a.name === name) || null
|
||||
if (!app) {
|
||||
bareP2pError(ctx, argv0, 'app not found in registry', argv0 + ' list', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, app, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'install') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const link = String(args[2] || '').trim()
|
||||
const channel = String(args[3] || 'stable').trim()
|
||||
if (!name || !link.startsWith('pear://')) {
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'install requires NAME and pear:// link',
|
||||
argv0 + ' install NAME pear://<key> [CHANNEL]',
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!opt.yes) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' install ... --yes', opt)
|
||||
return
|
||||
}
|
||||
const app = {
|
||||
name,
|
||||
pearLink: link,
|
||||
channel,
|
||||
checkout: 'released',
|
||||
trustPins: [],
|
||||
launchPolicy: 'default',
|
||||
updatedAtMs: Date.now()
|
||||
}
|
||||
reg.apps = reg.apps.filter((a) => !a || a.name !== name)
|
||||
reg.apps.push(app)
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, app }, opt)
|
||||
return
|
||||
}
|
||||
const ok = await bareP2pWriteJson(ctx, bareOsAppctlConfigPath(), reg)
|
||||
if (!ok) {
|
||||
bareP2pError(ctx, argv0, 'failed writing apps registry', 'check VFS write access', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, installed: app }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'launch') {
|
||||
const name = String(args[1] || '').trim()
|
||||
const app = reg.apps.find((a) => a && a.name === name) || null
|
||||
if (!app) {
|
||||
bareP2pError(ctx, argv0, 'app not found in registry', argv0 + ' list', opt)
|
||||
return
|
||||
}
|
||||
const req = {
|
||||
requestId: bareP2pId('app'),
|
||||
action: 'launch',
|
||||
name,
|
||||
pearLink: app.pearLink,
|
||||
checkout: app.checkout || 'released'
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, request: req }, opt)
|
||||
return
|
||||
}
|
||||
const r = bareP2pSend(ctx, 'peerctl', 'appctl.launch', req)
|
||||
if (r && r.ok === false) {
|
||||
bareP2pError(ctx, argv0, String(r.reason || 'send failed'), 'peerctl health', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
{ ok: true, launchRequested: true, registryPath: bareOsAppctlConfigPath(), request: req },
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'list',
|
||||
'show',
|
||||
'install',
|
||||
'launch',
|
||||
'channels'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'corestorectl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Inspect Corestore and Hyperdrive storage plane views from /proc.',
|
||||
argv0 + ' status | namespaces | mounts | replication',
|
||||
['status --summary', 'namespaces', 'mounts --json'],
|
||||
['routeview', 'swarmtop']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (sub === 'status') {
|
||||
const replication = await bareP2pReadProcJson(ctx, '/proc/bare_os/replication')
|
||||
const sparseIndex = await bareP2pReadProcJson(
|
||||
ctx,
|
||||
'/proc/bare_os/hyperdrive_sparse_index.json'
|
||||
)
|
||||
const out = {
|
||||
schema: 1,
|
||||
replicationHealth: replication.health || 'unknown',
|
||||
replicatedKeys: Array.isArray(replication.keys)
|
||||
? replication.keys.length
|
||||
: null,
|
||||
sparseBlocks:
|
||||
typeof sparseIndex.blockCount === 'number' ? sparseIndex.blockCount : null
|
||||
}
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
opt.summary ? { health: out.replicationHealth, keys: out.replicatedKeys } : out,
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (sub === 'namespaces') {
|
||||
const hints = await bareP2pReadProcJson(ctx, '/proc/bare_os/snapshot_hints.json')
|
||||
const namespaces = hints.corestoreNamespaces || [
|
||||
'system',
|
||||
'user',
|
||||
'app',
|
||||
'service',
|
||||
'temporary',
|
||||
'test'
|
||||
]
|
||||
bareP2pPrint(ctx, { schema: 1, namespaces }, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'mounts') {
|
||||
const union = await bareP2pReadProcJson(ctx, '/proc/bare_os/union.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
hyperdriveMounts: union.mounts || [],
|
||||
note: 'Use /proc/bare_os/union.json and /proc/bare_os/replication for full detail.'
|
||||
}
|
||||
bareP2pPrint(ctx, out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'replication') {
|
||||
const replication = await bareP2pReadProcJson(ctx, '/proc/bare_os/replication')
|
||||
bareP2pPrint(ctx, replication, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'status',
|
||||
'namespaces',
|
||||
'mounts',
|
||||
'replication'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'ctxbaredoctor'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Report ctx.bare module resolution posture (drive bundles vs host imports).',
|
||||
argv0 + ' [status|modules]',
|
||||
['status --summary', 'modules --json'],
|
||||
['kernel-doctor', 'kernel-preflight']
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || 'status').trim()
|
||||
const runtimeCaps = await bareP2pReadProcJson(ctx, '/proc/bare_os/capabilities.json')
|
||||
const posture = await bareP2pReadProcJson(ctx, '/proc/bare_os/security_posture.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
bareCtxModules: runtimeCaps?.features?.bareCtxModules ?? null,
|
||||
bareDriveBundles: runtimeCaps?.features?.bareDriveBundles ?? null,
|
||||
bareHostImportsForCtx: runtimeCaps?.features?.bareHostImportsForCtx ?? null,
|
||||
hostImportsEnabled: posture?.ctxBare?.hostImportsEnabled ?? null,
|
||||
driveBundlesEnabled: posture?.ctxBare?.driveBundlesEnabled ?? null,
|
||||
notes: [
|
||||
'Drive bundles are seeded /lib/bare IIFEs.',
|
||||
'Host imports are fallback import() for missing ctx keys.'
|
||||
]
|
||||
}
|
||||
if (sub === 'status') {
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
opt.summary
|
||||
? {
|
||||
bareCtxModules: out.bareCtxModules,
|
||||
driveBundles: out.bareDriveBundles,
|
||||
hostImports: out.bareHostImportsForCtx
|
||||
}
|
||||
: out,
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
if (sub === 'modules') {
|
||||
const manifest = await bareP2pReadProcJson(ctx, '/proc/bare_os/manifest_hints.json')
|
||||
const modules = Array.isArray(manifest?.bareModuleKeys)
|
||||
? manifest.bareModuleKeys
|
||||
: []
|
||||
bareP2pPrint(
|
||||
ctx,
|
||||
{ schema: 1, modules, moduleCount: modules.length, source: '/proc/bare_os/manifest_hints.json' },
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'modules'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'dhtctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'HyperDHT operator utility over /proc and P2P envelopes.',
|
||||
argv0 +
|
||||
' status | lookup TOPIC | announce TOPIC | connect PEER_KEY | firewall allow|deny [PEER_KEY] | export-key',
|
||||
[
|
||||
'status --summary',
|
||||
'lookup deadbeef',
|
||||
'firewall deny 0123abcd',
|
||||
'announce bare-os.swarm.control --yes'
|
||||
],
|
||||
['dhtscan', 'swarmdoctor', 'peerctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
if (sub === 'status') {
|
||||
const dht = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_status.json')
|
||||
const scan = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_scan.json')
|
||||
const out = {
|
||||
schema: 1,
|
||||
health: dht.health || 'unknown',
|
||||
firewalled: dht.firewalled ?? null,
|
||||
peers: scan.peers ?? null,
|
||||
bootstrap: dht.bootstrap || []
|
||||
}
|
||||
bareP2pPrint(ctx, opt.summary ? { health: out.health, peers: out.peers } : out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'export-key') {
|
||||
const ident = await bareP2pReadProcJson(ctx, '/proc/bare_os/identity.json')
|
||||
const key = ident.dhtPublicKey || ident.devicePublicKey || ''
|
||||
if (!key) {
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'no DHT public key found in /proc/bare_os/identity.json',
|
||||
argv0 + ' status',
|
||||
opt
|
||||
)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { schema: 1, dhtPublicKey: key }, opt)
|
||||
return
|
||||
}
|
||||
if (
|
||||
sub === 'lookup' ||
|
||||
sub === 'announce' ||
|
||||
sub === 'connect' ||
|
||||
sub === 'firewall'
|
||||
) {
|
||||
let action = sub
|
||||
let payload = {}
|
||||
if (sub === 'firewall') {
|
||||
const mode = String(args[1] || '').trim().toLowerCase()
|
||||
if (mode !== 'allow' && mode !== 'deny') {
|
||||
bareP2pError(ctx, argv0, 'firewall requires allow|deny', argv0 + ' firewall allow [PEER_KEY]', opt)
|
||||
return
|
||||
}
|
||||
action = 'firewall.' + mode
|
||||
payload = { peerKey: String(args[2] || '').trim() }
|
||||
} else {
|
||||
payload = { value: String(args[1] || '').trim() }
|
||||
}
|
||||
if (!opt.yes && (sub === 'announce' || sub === 'connect' || sub === 'firewall')) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' ' + sub + ' ... --yes', opt)
|
||||
return
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, action, payload }, opt)
|
||||
return
|
||||
}
|
||||
const r = bareP2pSend(ctx, 'peerctl', 'dhtctl', {
|
||||
requestId: bareP2pId('dht'),
|
||||
action,
|
||||
payload
|
||||
})
|
||||
if (r && r.ok === false) {
|
||||
bareP2pError(ctx, argv0, String(r.reason || 'send failed'), 'swarmdoctor', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, action, payload }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, [
|
||||
'status',
|
||||
'lookup',
|
||||
'announce',
|
||||
'connect',
|
||||
'firewall',
|
||||
'export-key'
|
||||
])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -87,7 +87,7 @@ function bareOsEmitRaw(ctx, chunk) {
|
||||
return false
|
||||
}
|
||||
|
||||
var BARE_OS_HELP_BIN_SPACED = "agent arch awk baresay baretop base32 base64 basename basenc btop bundlebee cat chat chgrp chmod chown cksum clear cmp comm cp crontab curl cut date dd df dhtscan dhttop diff dir dircolors dirname du echo edit env exit expand expr factor false find fmt fold getconf getfacl git git-pear grep groups hdms head help holepunch-view holesail hostid hostname hrpc hypershell-board iconv id install join journalctl jq kernel-boot-diff kernel-doctor kernel-explain kernel-fsck kernel-home-snapshot kernel-manifest-validate kernel-preflight kernel-triage kill link ln logger login logname logout ls man md5sum meshdrop mkdir mkfifo mktemp mount mv nano nice nl nohup nproc numfmt od oidc-publish openssl openssl p2ping p2ptrace paste patch pathcap-verify pathchk pear-runtime-matrix peerctl peerdiscover peernote pkg-swarm-index pr printenv printf procstat ps pwd readlink realpath rev rm rmdir routeview savevault say sed seq setfacl sh sha1sum sha224sum sha256sum sha384sum sha512sum shuf sidecar sleep sort split ssh-keygen ssh-keygen sshd sshd stat sum swarmdoctor swarmmap swarmtop sync systemctl tac tail tar tar taskmesh tee telnet test theme time timeout touch tr true truncate tsort tty ulimit umount uname unexpand uniq unlink uptime users vdir wc wget which who whoami whois xargs xattr yes"
|
||||
var BARE_OS_HELP_BIN_SPACED = "agent appctl arch awk baresay baretop base32 base64 basename basenc btop bundlebee cat chat chgrp chmod chown cksum clear cmp comm corestorectl cp crontab ctxbaredoctor curl cut date dd df dhtctl dhtscan dhttop diff dir dircolors dirname du echo edit env exit expand expr factor false find fmt fold getconf getfacl git git-pear grep groups hdms head help holepunch-view holesail hostid hostname hrpc hypershell-board iconv id install join journalctl jq kernel-boot-diff kernel-doctor kernel-explain kernel-fsck kernel-home-snapshot kernel-manifest-validate kernel-preflight kernel-triage kill link ln logger login logname logout ls man md5sum meshdrop mkdir mkfifo mktemp mount mv nano nice nl nohup nproc numfmt od oidc-publish openssl openssl p2ping p2ptrace paste patch pathcap-verify pathchk pear-runtime-matrix peerctl peerdiscover peernote pkg-swarm-index pr printenv printf procstat ps pwd readlink realpath rev rm rmdir routeview savevault say sed seq setfacl sh sha1sum sha224sum sha256sum sha384sum sha512sum shuf sidecar sleep sort split ssh-keygen ssh-keygen sshd sshd stat sum swarmdoctor swarmmap swarmtop sync systemctl tac tail tar tar taskmesh tee telnet test theme time timeout touch tr true truncate trustctl tsort tty ulimit umount uname unexpand uniq unlink uptime users vdir wc wget which who whoami whois xargs xattr yes"
|
||||
async function run(ctx, argv) {
|
||||
ctx.console.log(
|
||||
'Bare OS — default user: guest | shell builtins: alias, barerc, cd, command, export, exit, login, logout, readonly, type, umask, unalias, unset, : | /bin: ' +
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/* BARE_OS_BIN_API 1.0.0 — bump when staged /bin script semantics change (see developer guide). */
|
||||
/** Shared helpers for drive-resident /bin scripts (prepended before each command). */
|
||||
function bareStdin(ctx) {
|
||||
return typeof ctx.shellStdin === 'string' ? ctx.shellStdin : ''
|
||||
}
|
||||
|
||||
/** @param {number} mode @param {'file' | 'directory' | 'symlink'} type */
|
||||
function bareFormatModeString(mode, type) {
|
||||
const typeChar = type === 'directory' ? 'd' : type === 'symlink' ? 'l' : '-'
|
||||
const perm = mode & 0o777
|
||||
const r = (bit) => (perm & bit ? 'r' : '-')
|
||||
const w = (bit) => (perm & bit ? 'w' : '-')
|
||||
const x = (bit) => (perm & bit ? 'x' : '-')
|
||||
return (
|
||||
typeChar +
|
||||
r(0o400) +
|
||||
w(0o200) +
|
||||
x(0o100) +
|
||||
r(0o040) +
|
||||
w(0o020) +
|
||||
x(0o010) +
|
||||
r(0o004) +
|
||||
w(0o002) +
|
||||
x(0o001)
|
||||
)
|
||||
}
|
||||
|
||||
/** @param {number} mtimeMs @param {number} [nowMs] */
|
||||
function bareFormatLsMtime(mtimeMs, nowMs) {
|
||||
const now = nowMs != null ? nowMs : Date.now()
|
||||
const d = new Date(mtimeMs)
|
||||
const months = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
]
|
||||
const mon = months[d.getMonth()]
|
||||
const day = String(d.getDate()).padStart(2, ' ')
|
||||
const sixMo = 180 * 24 * 3600 * 1000
|
||||
if (Math.abs(now - mtimeMs) > sixMo) {
|
||||
const yr = String(d.getFullYear()).padStart(4, ' ')
|
||||
return mon + ' ' + day + ' ' + yr
|
||||
}
|
||||
const hh = String(d.getHours()).padStart(2, '0')
|
||||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||||
return mon + ' ' + day + ' ' + hh + ':' + mm
|
||||
}
|
||||
|
||||
/** @param {number} size */
|
||||
function barePosixBlocks(size) {
|
||||
return Math.ceil(Number(size) / 512) || 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw stdout for NUL/binary when **`process.stdout.write`** is missing.
|
||||
* If **`ctx.bareOsBinWrite(Uint8Array|string)`** is set (tests / host), use it.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {string | Uint8Array} chunk
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function bareOsEmitRaw(ctx, chunk) {
|
||||
if (typeof ctx.bareOsBinWrite === 'function') {
|
||||
const b4 = ctx.b4a
|
||||
const u8 =
|
||||
typeof chunk === 'string'
|
||||
? b4 && typeof b4.from === 'function'
|
||||
? b4.from(chunk)
|
||||
: new TextEncoder().encode(chunk)
|
||||
: chunk
|
||||
ctx.bareOsBinWrite(u8 instanceof Uint8Array ? u8 : new Uint8Array(u8))
|
||||
return true
|
||||
}
|
||||
const w = globalThis.process?.stdout?.write
|
||||
if (typeof w === 'function') {
|
||||
w.call(globalThis.process.stdout, chunk)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function bareOsTrustPolicyPath() {
|
||||
return '/etc/bare-os/trust.policy.json'
|
||||
}
|
||||
|
||||
async function bareOsTrustReadPolicy(ctx) {
|
||||
const doc = await bareP2pReadJson(ctx, bareOsTrustPolicyPath())
|
||||
if (!doc || typeof doc !== 'object') {
|
||||
return {
|
||||
schema: 1,
|
||||
signerPins: [],
|
||||
relayPolicy: { mode: 'consent-required' },
|
||||
encryptionPolicy: { mode: 'per-space-keys', rotationDays: 30 }
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(doc.signerPins)) doc.signerPins = []
|
||||
return doc
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const argv0 = argv[0] || 'trustctl'
|
||||
const parsed = bareP2pParseCommonFlags(argv.slice(1))
|
||||
const args = parsed.rest
|
||||
const opt = parsed.opt
|
||||
if (opt.help || args.length === 0) {
|
||||
ctx.console.log(
|
||||
bareP2pHelpText(
|
||||
argv0,
|
||||
'Inspect and edit trust roots, signer pins, and encryption policy.',
|
||||
argv0 + ' status | inspect TARGET | pin add KEY | pin rm KEY | policy show',
|
||||
['status', 'pin add <signerKey> --yes', 'inspect pear://<key>'],
|
||||
['appctl', 'peerctl']
|
||||
)
|
||||
)
|
||||
if (args.length === 0) ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const sub = String(args[0] || '').trim()
|
||||
const policy = await bareOsTrustReadPolicy(ctx)
|
||||
if (sub === 'status' || (sub === 'policy' && String(args[1] || '') === 'show')) {
|
||||
bareP2pPrint(ctx, policy, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'inspect') {
|
||||
const target = String(args[1] || '').trim()
|
||||
if (!target) {
|
||||
bareP2pError(ctx, argv0, 'inspect requires TARGET', argv0 + ' inspect pear://<key>', opt)
|
||||
return
|
||||
}
|
||||
const out = {
|
||||
schema: 1,
|
||||
target,
|
||||
accepted: true,
|
||||
reasons: ['no deny rule matched', 'signer pin enforcement delegated to boot policy when enabled'],
|
||||
crossRefs: ['/proc/bare_os/pear_trust.json', '/proc/bare_os/security_posture.json']
|
||||
}
|
||||
bareP2pPrint(ctx, out, opt)
|
||||
return
|
||||
}
|
||||
if (sub === 'pin') {
|
||||
const action = String(args[1] || '').trim()
|
||||
const key = String(args[2] || '').trim()
|
||||
if ((action !== 'add' && action !== 'rm') || !key) {
|
||||
bareP2pError(ctx, argv0, 'pin requires add|rm KEY', argv0 + ' pin add <KEY>', opt)
|
||||
return
|
||||
}
|
||||
if (!opt.yes) {
|
||||
bareP2pError(ctx, argv0, 'confirmation required (pass --yes)', argv0 + ' pin ' + action + ' ' + key + ' --yes', opt)
|
||||
return
|
||||
}
|
||||
if (action === 'add' && !policy.signerPins.includes(key)) {
|
||||
policy.signerPins.push(key)
|
||||
}
|
||||
if (action === 'rm') {
|
||||
policy.signerPins = policy.signerPins.filter((x) => x !== key)
|
||||
}
|
||||
if (opt.dryRun) {
|
||||
bareP2pPrint(ctx, { ok: true, dryRun: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const ok = await bareP2pWriteJson(ctx, bareOsTrustPolicyPath(), policy)
|
||||
if (!ok) {
|
||||
bareP2pError(ctx, argv0, 'failed writing trust policy', 'check VFS write access', opt)
|
||||
return
|
||||
}
|
||||
bareP2pPrint(ctx, { ok: true, signerPins: policy.signerPins }, opt)
|
||||
return
|
||||
}
|
||||
const sug = bareP2pSuggestSubcommand(sub, ['status', 'inspect', 'pin', 'policy'])
|
||||
bareP2pError(
|
||||
ctx,
|
||||
argv0,
|
||||
'unsupported subcommand' + (sug ? ' (did you mean ' + sug + '?)' : ''),
|
||||
argv0 + ' --help',
|
||||
opt
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"generatedBy": "appctl",
|
||||
"apps": [
|
||||
{
|
||||
"name": "keet",
|
||||
"pearLink": "pear://examplekey",
|
||||
"channel": "stable",
|
||||
"checkout": "released",
|
||||
"trustPins": [],
|
||||
"launchPolicy": "default",
|
||||
"updatedAtMs": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"namespaces": [
|
||||
{ "name": "system", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "user", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "app", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "service", "replicated": true, "retentionDays": 3650 },
|
||||
{ "name": "temporary", "replicated": false, "retentionDays": 7 },
|
||||
{ "name": "test", "replicated": false, "retentionDays": 30 }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"services": [
|
||||
{
|
||||
"name": "replication-operator",
|
||||
"dhtPublicKey": "",
|
||||
"firewallPolicy": "allowlisted"
|
||||
}
|
||||
],
|
||||
"relayPolicy": {
|
||||
"enabled": true,
|
||||
"requiresConsent": true
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
{
|
||||
"schema": 2,
|
||||
"profileId": "bare-os-posix-like",
|
||||
"generatedAt": "2026-04-26T12:40:06.854Z",
|
||||
"generatedAt": "2026-04-26T12:56:08.959Z",
|
||||
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
|
||||
"commandIndex": [
|
||||
{
|
||||
"name": "agent",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "appctl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "arch",
|
||||
"tier": "tier1_bin"
|
||||
@@ -80,6 +84,10 @@
|
||||
"name": "comm",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "corestorectl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "cp",
|
||||
"tier": "tier1_bin"
|
||||
@@ -88,6 +96,10 @@
|
||||
"name": "crontab",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "ctxbaredoctor",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "curl",
|
||||
"tier": "tier1_bin"
|
||||
@@ -108,6 +120,10 @@
|
||||
"name": "df",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "dhtctl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "dhtscan",
|
||||
"tier": "tier1_bin"
|
||||
@@ -620,6 +636,10 @@
|
||||
"name": "truncate",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "trustctl",
|
||||
"tier": "tier1_bin"
|
||||
},
|
||||
{
|
||||
"name": "tsort",
|
||||
"tier": "tier1_bin"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"systemDrive": {
|
||||
"key": "",
|
||||
"fork": 0,
|
||||
"length": 0
|
||||
},
|
||||
"signers": [],
|
||||
"bootPolicyMinimums": {
|
||||
"requirePearRuntimeRange": ">=1.0.0",
|
||||
"requireBareCryptoMin": "1.13.4"
|
||||
},
|
||||
"rollback": {
|
||||
"lastKnownGoodLength": 0,
|
||||
"requireBootReadySignal": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"signerPins": [],
|
||||
"relayPolicy": {
|
||||
"mode": "consent-required",
|
||||
"allowlist": []
|
||||
},
|
||||
"encryptionPolicy": {
|
||||
"mode": "per-space-keys",
|
||||
"rotationDays": 30
|
||||
},
|
||||
"denyRules": {
|
||||
"pearLinks": [],
|
||||
"peerKeys": []
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"atMs": 1777207206853,
|
||||
"atMs": 1777208168958,
|
||||
"commands": [
|
||||
"agent",
|
||||
"appctl",
|
||||
"arch",
|
||||
"awk",
|
||||
"baresay",
|
||||
@@ -21,13 +22,16 @@
|
||||
"clear",
|
||||
"cmp",
|
||||
"comm",
|
||||
"corestorectl",
|
||||
"cp",
|
||||
"crontab",
|
||||
"ctxbaredoctor",
|
||||
"curl",
|
||||
"cut",
|
||||
"date",
|
||||
"dd",
|
||||
"df",
|
||||
"dhtctl",
|
||||
"dhtscan",
|
||||
"dhttop",
|
||||
"diff",
|
||||
@@ -156,6 +160,7 @@
|
||||
"tr",
|
||||
"true",
|
||||
"truncate",
|
||||
"trustctl",
|
||||
"tsort",
|
||||
"tty",
|
||||
"ulimit",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -320,6 +320,18 @@ Writes **[`docs/audit/holepunch-clone-sync-report.json`](../docs/audit/holepunch
|
||||
|
||||
Compares hoisted **`package-lock.json`** versions (**`node_modules/<pkg>`**) against **`lockfilePackages`** in **[`docs/audit/holepunch-drift-repos.json`](../docs/audit/holepunch-drift-repos.json)** and local clone **`package.json`** versions. Writes **[`docs/audit/holepunch-lockfile-drift.json`](../docs/audit/holepunch-lockfile-drift.json)** and **`holepunch-lockfile-drift-summary.ndjson`**, plus a maintainer-readable Markdown table **[`docs/audit/holepunch-lockfile-drift-dashboard.md`](../docs/audit/holepunch-lockfile-drift-dashboard.md)**. Informational only (not a failing CI gate).
|
||||
|
||||
## `report-holepunch-runtime-compat.mjs`
|
||||
|
||||
**Usage:** `node scripts/report-holepunch-runtime-compat.mjs` (also **`npm run report:holepunch-runtime-compat`**)
|
||||
|
||||
Compares booter dependency ranges against local mirror versions for the runtime spine (`bare-runtime`, `bare-module`, `bare-fs`, `bare-net`, `hypercore`, `corestore`, `hyperdrive`, `hyperdht`, `hyperswarm`, `pear`, `pear-runtime`). Writes **[`docs/audit/holepunch-runtime-compat.json`](../docs/audit/holepunch-runtime-compat.json)**. Uses **`BARE_OS_HOLEPUNCH_CLONES_ROOT`** (default **`~/dev/pearcli/holepunch-repos/holepunchto_repos`**).
|
||||
|
||||
## `gen-holepunch-catalog-tiers.mjs`
|
||||
|
||||
**Usage:** `node scripts/gen-holepunch-catalog-tiers.mjs` (also **`npm run gen:bare-catalog:tiers`**)
|
||||
|
||||
Derives category views from **[`docs/bare-holepunch-catalog.json`](../docs/bare-holepunch-catalog.json)** into **[`docs/audit/holepunch-catalog-tiers.json`](../docs/audit/holepunch-catalog-tiers.json)** with buckets for runtime-critical, storage-critical, network-critical, pear-lifecycle, gui-mobile, and experimental repos.
|
||||
|
||||
## `audit-placeholder-baseline.mjs`
|
||||
|
||||
**Usage:** `npm run audit:placeholder-baseline` (regenerate JSON) · `npm run audit:placeholder-baseline:check` (root **`pretest`**)
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const catalogPath = path.join(root, 'docs/bare-holepunch-catalog.json')
|
||||
const outPath = path.join(root, 'docs/audit/holepunch-catalog-tiers.json')
|
||||
|
||||
function classify(repo) {
|
||||
const r = String(repo || '').toLowerCase()
|
||||
if (
|
||||
r.startsWith('pear') ||
|
||||
r.includes('pear-runtime') ||
|
||||
r.includes('pear-ipc')
|
||||
) {
|
||||
return 'pear-lifecycle'
|
||||
}
|
||||
if (
|
||||
r.includes('hyperdht') ||
|
||||
r.includes('hyperswarm') ||
|
||||
r.includes('protomux') ||
|
||||
r.includes('udx') ||
|
||||
r.includes('dht')
|
||||
) {
|
||||
return 'network-critical'
|
||||
}
|
||||
if (
|
||||
r.includes('hypercore') ||
|
||||
r.includes('corestore') ||
|
||||
r.includes('hyperdrive') ||
|
||||
r.includes('hyperbee') ||
|
||||
r.includes('autobase')
|
||||
) {
|
||||
return 'storage-critical'
|
||||
}
|
||||
if (r.includes('gtk') || r.includes('web-kit') || r.includes('native')) {
|
||||
return 'gui-mobile'
|
||||
}
|
||||
if (r.startsWith('bare-')) return 'runtime-critical'
|
||||
return 'experimental'
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (!fs.existsSync(catalogPath)) {
|
||||
console.error('gen-holepunch-catalog-tiers: missing', catalogPath)
|
||||
process.exit(1)
|
||||
}
|
||||
const catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf8'))
|
||||
const entries = Array.isArray(catalog.entries) ? catalog.entries : []
|
||||
const tiers = {
|
||||
'runtime-critical': [],
|
||||
'storage-critical': [],
|
||||
'network-critical': [],
|
||||
'pear-lifecycle': [],
|
||||
'gui-mobile': [],
|
||||
experimental: []
|
||||
}
|
||||
for (const e of entries) {
|
||||
const repo = String(e?.repo || '').trim()
|
||||
if (!repo) continue
|
||||
const tier = classify(repo)
|
||||
tiers[tier].push({
|
||||
repo,
|
||||
npmPublished: Boolean(e.npmPublished),
|
||||
npmVersion: e.npmVersion || null,
|
||||
includedInBooter: Boolean(e.includedInBooter)
|
||||
})
|
||||
}
|
||||
for (const key of Object.keys(tiers)) {
|
||||
tiers[key].sort((a, b) => String(a.repo).localeCompare(String(b.repo)))
|
||||
}
|
||||
const out = {
|
||||
schema: 1,
|
||||
generatedAt: new Date().toISOString(),
|
||||
sourceCatalog: path.relative(root, catalogPath),
|
||||
tiers
|
||||
}
|
||||
fs.mkdirSync(path.dirname(outPath), { recursive: true })
|
||||
fs.writeFileSync(outPath, JSON.stringify(out, null, 2) + '\n', 'utf8')
|
||||
console.log('gen-holepunch-catalog-tiers: wrote', path.relative(root, outPath))
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -37,6 +37,10 @@ console.log(
|
||||
run('npm', ['run', 'audit:placeholder-baseline'])
|
||||
console.log('[release-checklist] report-holepunch-lockfile-drift')
|
||||
run('node', ['scripts/report-holepunch-lockfile-drift.mjs'])
|
||||
console.log('[release-checklist] report-holepunch-runtime-compat')
|
||||
run('node', ['scripts/report-holepunch-runtime-compat.mjs'])
|
||||
console.log('[release-checklist] gen-holepunch-catalog-tiers')
|
||||
run('node', ['scripts/gen-holepunch-catalog-tiers.mjs'])
|
||||
console.log(
|
||||
'[release-checklist] verify-holepunch-clone-drift (BARE_OS_HOLEPUNCH_DRIFT_CHECK=0 to skip; empty repos[] is no-op)'
|
||||
)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const booterPkgPath = path.join(root, 'packages/bare-os-booter/package.json')
|
||||
const outPath = path.join(root, 'docs/audit/holepunch-runtime-compat.json')
|
||||
const mirrorRoot = String(
|
||||
process.env.BARE_OS_HOLEPUNCH_CLONES_ROOT ||
|
||||
path.join(process.env.HOME || '', 'dev/pearcli/holepunch-repos/holepunchto_repos')
|
||||
).trim()
|
||||
|
||||
const CORE_REPOS = [
|
||||
'bare-runtime',
|
||||
'bare-module',
|
||||
'bare-fs',
|
||||
'bare-net',
|
||||
'hypercore',
|
||||
'corestore',
|
||||
'hyperdrive',
|
||||
'hyperdht',
|
||||
'hyperswarm',
|
||||
'pear',
|
||||
'pear-runtime'
|
||||
]
|
||||
|
||||
function readJson(p, fallback = null) {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(p, 'utf8'))
|
||||
} catch {
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
const booterPkg = readJson(booterPkgPath, {})
|
||||
const deps = {
|
||||
...(booterPkg.dependencies || {}),
|
||||
...(booterPkg.optionalDependencies || {})
|
||||
}
|
||||
const rows = CORE_REPOS.map((repo) => {
|
||||
const clonePkgPath = path.join(mirrorRoot, repo, 'package.json')
|
||||
const clonePkg = readJson(clonePkgPath, {})
|
||||
const cloneVersion = String(clonePkg?.version || '').trim()
|
||||
const depRange = String(deps[repo] || '').trim()
|
||||
return {
|
||||
repo,
|
||||
booterRange: depRange || null,
|
||||
cloneVersion: cloneVersion || null,
|
||||
clonePath: path.join(mirrorRoot, repo),
|
||||
rangeMentionsLocalFile: depRange.startsWith('file:'),
|
||||
semverDrift: Boolean(depRange && cloneVersion && !depRange.includes(cloneVersion))
|
||||
}
|
||||
})
|
||||
const out = {
|
||||
schema: 1,
|
||||
generatedAt: new Date().toISOString(),
|
||||
mirrorRoot,
|
||||
booterPackage: path.relative(root, booterPkgPath),
|
||||
rows
|
||||
}
|
||||
fs.mkdirSync(path.dirname(outPath), { recursive: true })
|
||||
fs.writeFileSync(outPath, JSON.stringify(out, null, 2) + '\n', 'utf8')
|
||||
console.log(
|
||||
'report-holepunch-runtime-compat: wrote',
|
||||
path.relative(root, outPath),
|
||||
'rows=',
|
||||
rows.length
|
||||
)
|
||||
}
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user