Implement the 20-track POSIX + P2P roadmap: booter, protocol, coreutils, docs,

and seeder/kernel parity.

Booter / ctx (1.44.0)
- bareOsReadPearRuntimeSnapshotJson; hrpc stock routes documented (kernel.*,
  vfs.readText, bare_os.echo, bare_os.disk_os_hints).
- Peer admission: BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST + meta.dhtAddressClass;
  shouldAttemptPeer(peerKey, meta).
- Optional BARE_OS_VFS_WARM_CACHE_INVALIDATE_ON_APPEND on system drive cores.
- maybeMergeBareFromDrive: path dedupe + early exit when manifest keys satisfied.
- identity-account: zero UTF-8 passphrase buffer after PBKDF2 (string path).

Shell / utilities
- BARE_OS_SHELL_ERREXIT and set -e / set +e; tests in bare-os-booter/test.js.
- expand: comma-separated POSIX-style tab stops; man page + coreutils tests.

Tooling / docs
- kernel-microbench vfs: warmReplicationPathClassify sketch.
- holepunch-drift-repos suggestedCriticalRepos; sync-holepunch-clones report.
- scripts/README: pretest maintainer runbook; handbook/12 P2P vs POSIX.
- KERNEL_CONTRACT, environment appendix, PLACEHOLDER_BASELINE (multisig gate),
  compatibility matrix, posix artifacts, syscalls.example.json, seeder sync.

Requires: npm run pretest && npm test (already green in session).
This commit is contained in:
Raven Scott
2026-04-05 01:06:59 -04:00
parent f79db04313
commit c64910d72e
60 changed files with 1762 additions and 638 deletions
+414 -35
View File
@@ -676,6 +676,8 @@ async function executeKernel(disk, store, swarm, initSource) {
'BARE_OS_NET_TRANSPORT_STATS_JSON',
'BARE_OS_UDX_TUNING_JSON',
'BARE_OS_HYPERSWARM_TUNING_JSON',
'BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST',
'BARE_OS_VFS_WARM_CACHE_INVALIDATE_ON_APPEND',
'BARE_OS_KERNEL_DEBUG',
'BARE_OS_PEAR_INSPECT',
'BARE_OS_KERNEL_PROFILE_WARM',
@@ -1077,15 +1079,55 @@ async function executeKernel(disk, store, swarm, initSource) {
return `${JSON.stringify(o)}\n`
},
procBareOsPearCorestoreHrpcJsonText(pearCorestoreHrpcProcId) {
const peers = disk.peers ? [...disk.peers] : []
const o = buildBareOsPearCorestoreHrpcProcJson(
String(pearCorestoreHrpcProcId || ''),
shellEnv,
bareOsBlindRelayRuntimeHintsForProc()
{
...bareOsBlindRelayRuntimeHintsForProc(),
protomuxWireShape: {
schema: 1,
bareOsV1MessageKinds: [
'read',
'data',
'gossip',
'search_req',
'search_res',
'rpc_req',
'rpc_res'
],
peerMuxSessions: peers.length,
note: 'Matches protomux.json wireShape.bareOsV1MessageKinds; peerMuxSessions is live Hyperswarm peer count with bare-os-v1 channels.'
}
}
)
return `${JSON.stringify(o)}\n`
},
procBareOsBareRuntimeProtoMuxJsonText(bareRuntimeProtoMuxProcId) {
const o = buildBareOsBareRuntimeProtoMuxProcJson(String(bareRuntimeProtoMuxProcId || ''), shellEnv)
const peers = disk.peers ? [...disk.peers] : []
const rt = protomuxAliasRegistry.snapshot()
const o = buildBareOsBareRuntimeProtoMuxProcJson(
String(bareRuntimeProtoMuxProcId || ''),
shellEnv,
{
seedProtomuxRpcPoolHint:
disk.seedProtomuxRpcPoolHint &&
typeof disk.seedProtomuxRpcPoolHint === 'object'
? disk.seedProtomuxRpcPoolHint
: undefined,
protomuxWireCorrelate: {
schema: 1,
peerMuxSessions: peers.length,
backpressureEmitCount: bareOsProtomuxBackpressureCounter.count,
aliasPairCount:
rt.aliases && typeof rt.aliases === 'object'
? Object.keys(rt.aliases).length
: 0,
bareOsV1WireMessageKinds: 7,
note: 'Live booter aggregates; compare to /proc/bare_os/protomux.json operatorMetrics and swarm.peerCount.'
}
}
)
return `${JSON.stringify(o)}\n`
},
procBareOsBareModuleCryptoStagingJsonText(bareModuleCryptoStagingProcId) {
@@ -1756,6 +1798,21 @@ async function executeKernel(disk, store, swarm, initSource) {
mode: String(shellEnv.BARE_OS_NAT_TRAVERSAL_MODE || 'auto').trim(),
note: 'Host HyperDHT / UDX populate hole-punch outcomes; see net_summary.transport.'
},
dhtAddressClassAllowlist: (() => {
const raw = String(
shellEnv.BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST || ''
).trim()
if (!raw) return undefined
const classes = raw
.split(',')
.map((s) => s.trim().toLowerCase())
.filter(Boolean)
return {
schema: 1,
classes,
note: 'Operator hint (hyperdht-addressstyle) recorded for discovery policy; stock Hyperswarm still uses topic + allowlist keys — enforce in custom hosts if needed.'
}
})(),
swarmLeaveOrdering: {
schema: 1,
initdReverseStopFirst:
@@ -2469,7 +2526,7 @@ async function executeKernel(disk, store, swarm, initSource) {
note: 'Stable Protomux channel ordering for bare-os-v1 seed/booter wire.'
},
operatorMetrics: {
schema: 1,
schema: 2,
aliasPairCount:
rt.aliases && typeof rt.aliases === 'object'
? Object.keys(rt.aliases).length
@@ -2482,7 +2539,9 @@ async function executeKernel(disk, store, swarm, initSource) {
? Object.keys(rt.reverseIndex).length
: 0,
backpressureEmitCount: bareOsProtomuxBackpressureCounter.count,
note: 'Wire byte counters live on Protomux channels; booter surfaces registry shape plus backpressureEmitCount from ctx.bareOsEmitProtomuxBackpressure.',
peerMuxSessions: peers.length,
bareOsV1LogicalChannelsPerPeer: 7,
note: 'Schema 2 adds peerMuxSessions and bareOsV1LogicalChannelsPerPeer (fixed bare-os-v1 message kinds). Wire byte counters live on Protomux channels; booter surfaces registry shape plus backpressureEmitCount from ctx.bareOsEmitProtomuxBackpressure.',
backpressureEvent: 'bare-os:protomux-backpressure',
backpressureEmit: 'ctx.bareOsEmitProtomuxBackpressure'
},
@@ -2520,6 +2579,31 @@ async function executeKernel(disk, store, swarm, initSource) {
vfsOrigClearWarmReadCaches()
}
const warmInvOnAppend =
shellEnv.BARE_OS_VFS_WARM_CACHE_INVALIDATE_ON_APPEND === '1' ||
shellEnv.BARE_OS_VFS_WARM_CACHE_INVALIDATE_ON_APPEND === 'true'
if (
warmInvOnAppend &&
disk?.drive &&
vfs &&
typeof vfs.bareOsClearWarmReadCaches === 'function'
) {
const onAppend = () => {
vfs.bareOsClearWarmReadCaches()
bareOsKernelMetricInc('vfs.warm_read_cache_invalidate_hypercore_append')
}
try {
const c0 = disk.drive.core
if (c0 && typeof c0.on === 'function') c0.on('append', onAppend)
const c1 = disk.drive.blobs && disk.drive.blobs.core
if (c1 && typeof c1.on === 'function' && c1 !== c0) {
c1.on('append', onAppend)
}
} catch {
/* optional: drive stack may not expose EventEmitter cores */
}
}
emitBooterBootPhase('vfs')
Object.assign(bootReadyStateRef.subsystems, {
vfs: { ready: true, atMs: Date.now() },
@@ -2813,6 +2897,25 @@ async function executeKernel(disk, store, swarm, initSource) {
text: b4a.toString(buf, 'utf8')
}
}
if (svc === 'bare_os' && m === 'echo') {
hrpcAuditAppend({ ok: true, route: 'bare_os.echo' })
return { ok: true, payload }
}
if (svc === 'bare_os' && m === 'disk_os_hints') {
if (!disk?.os || typeof disk.os.execRpc !== 'function') {
hrpcAuditAppend({ ok: false, reason: 'disk_os_unavailable' })
throw new Error('bareOsHrpcRequest: disk.os bridge unavailable')
}
const txt = await disk.os.execRpc('bare_os', 'disk_os_hints', [])
let parsed = null
try {
parsed = JSON.parse(txt)
} catch {
parsed = { error: 'invalid_json' }
}
hrpcAuditAppend({ ok: true, route: 'bare_os.disk_os_hints' })
return { ok: true, text: txt, json: parsed }
}
const emitUnlisted =
shellEnv.BARE_OS_HRPC_EMIT_UNLISTED === '1' ||
@@ -2884,6 +2987,91 @@ async function executeKernel(disk, store, swarm, initSource) {
return 30000
}
/**
* Flatten sendmsg iovec list (bounded) for the SOCK_DGRAM bridge.
* @param {Record<string, unknown>} args
* @returns {{ ok: true, buf: Uint8Array } | { ok: false, err: Record<string, unknown> }}
*/
function bareOsFlattenSendmsgIovs(args) {
const maxIovs = 16
const maxPer = 65536
const maxTotal = 1024 * 1024
const iovs = Array.isArray(args.iovs) ? args.iovs : []
let total = 0
/** @type {Uint8Array[]} */
const parts = []
for (const iov of iovs.slice(0, maxIovs)) {
if (!iov || typeof iov !== 'object') continue
const io = /** @type {Record<string, unknown>} */ (iov)
let chunk = io.buf ?? io.buffer ?? io.data
if (chunk == null) continue
if (typeof chunk === 'string') chunk = b4a.from(chunk, 'utf8')
if (!(chunk instanceof Uint8Array)) {
return {
ok: false,
err: {
ok: false,
op: 'sendmsg',
code: 'EINVAL',
errnoHint: 'EINVAL',
posixAlignment: 'ENOTSUP',
note: 'sendmsg: each iov buf must be Uint8Array or string'
}
}
}
const slice = chunk.byteLength > maxPer ? chunk.slice(0, maxPer) : chunk
if (total + slice.byteLength > maxTotal) {
return {
ok: false,
err: {
ok: false,
op: 'sendmsg',
code: 'EMSGSIZE',
errnoHint: 'EMSGSIZE',
posixAlignment: 'partial',
note: 'sendmsg: total iov length exceeds cap'
}
}
}
parts.push(slice)
total += slice.byteLength
}
if (parts.length === 0 && args.buf != null) {
let chunk = args.buf
if (typeof chunk === 'string') chunk = b4a.from(chunk, 'utf8')
if (!(chunk instanceof Uint8Array)) {
return {
ok: false,
err: {
ok: false,
op: 'sendmsg',
code: 'EINVAL',
errnoHint: 'EINVAL'
}
}
}
const buf =
chunk.byteLength > maxTotal ? chunk.slice(0, maxTotal) : chunk
return { ok: true, buf }
}
if (parts.length === 0) {
return {
ok: false,
err: {
ok: false,
op: 'sendmsg',
code: 'EINVAL',
errnoHint: 'EINVAL',
note: 'sendmsg: args.iovs or args.buf required'
}
}
}
return {
ok: true,
buf: parts.length === 1 ? parts[0] : b4a.concat(parts)
}
}
function bareOsFcntlLockWaitMsMax(env) {
const raw = String(env?.BARE_OS_FCNTL_LOCK_WAIT_MS_MAX ?? '').trim()
const n = Math.floor(Number(raw))
@@ -3967,6 +4155,134 @@ async function executeKernel(disk, store, swarm, initSource) {
const v = this.bareOsPathconf(String(args.path || '/'), pconfName)
return { name: pconfName, value: v }
}
if (name === 'mq_open') {
const ipc = bareOsIpc
if (!ipc || typeof ipc.mqOpen !== 'function') {
return {
ok: false,
op: name,
code: 'ENOSYS',
errnoHint: 'ENOSYS',
note: 'IPC message queues unavailable'
}
}
const qname = String(args.name || args.pathname || '').trim()
if (!qname) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL',
note: 'mq_open: name required'
}
}
const r = ipc.mqOpen(qname, {
maxmsg: args.maxmsg,
maxBytes: args.maxBytes
})
return { ok: true, op: name, ...r }
}
if (name === 'mq_send') {
const ipc = bareOsIpc
if (!ipc || typeof ipc.mqSend !== 'function') {
return {
ok: false,
op: name,
code: 'ENOSYS',
errnoHint: 'ENOSYS'
}
}
const qname = String(args.name || '').trim()
if (!qname) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL'
}
}
if (!ipc.mqAttrs(qname)) {
ipc.mqOpen(qname, {
maxmsg: args.maxmsg,
maxBytes: args.maxBytes
})
}
let body = args.data ?? args.buf ?? args.buffer
if (body == null) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL',
note: 'mq_send: data required'
}
}
if (typeof body === 'string') body = b4a.from(body, 'utf8')
if (!(body instanceof Uint8Array)) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL'
}
}
const prio = Number(args.prio) || 0
try {
ipc.mqSend(qname, prio, body)
return { ok: true, op: name, bytes: body.byteLength }
} catch (e) {
const em = e && /** @type {Error} */ (e).message
if (em && (em.includes('full') || em.includes('exceeds'))) {
return {
ok: false,
op: name,
code: 'EAGAIN',
errnoHint: 'EAGAIN',
posixAlignment: 'partial',
note: String(em)
}
}
throw e
}
}
if (name === 'mq_receive') {
const ipc = bareOsIpc
if (!ipc || typeof ipc.mqReceive !== 'function') {
return {
ok: false,
op: name,
code: 'ENOSYS',
errnoHint: 'ENOSYS'
}
}
const qname = String(args.name || '').trim()
if (!qname) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL'
}
}
const row = ipc.mqReceive(qname)
if (!row) {
return {
ok: false,
op: name,
code: 'EAGAIN',
errnoHint: 'EAGAIN',
posixAlignment: 'partial',
note: 'mq_receive: queue empty or unknown (mq_open first)'
}
}
return {
ok: true,
op: name,
prio: row.prio,
data: row.data,
bytesReceived: row.data.byteLength
}
}
if (name === 'readFile') {
const p = String(args.path || '').trim()
if (!p.startsWith('/')) throw new Error('bareOsSyscall: absolute path required')
@@ -4649,8 +4965,10 @@ async function executeKernel(disk, store, swarm, initSource) {
name === 'accept' ||
name === 'connect' ||
name === 'send' ||
name === 'sendmsg' ||
name === 'recv' ||
name === 'recvfrom' ||
name === 'recvmsg' ||
name === 'shutdown'
) {
if (wantPosixSocketFdBridge(shellEnv)) {
@@ -4846,16 +5164,23 @@ async function executeKernel(disk, store, swarm, initSource) {
'Bridge mode implements socket+connect via bareTcp (stream) or bareDgram (UDP); use ctx.bare / Hyperswarm for listen/accept servers.'
}
}
if (name === 'send' || name === 'recv' || name === 'recvfrom') {
if (
name === 'send' ||
name === 'sendmsg' ||
name === 'recv' ||
name === 'recvfrom' ||
name === 'recvmsg'
) {
const logicalOp = name
const fd = Number(args.fd)
if (!Number.isFinite(fd)) {
return {
ok: false,
op: name,
op: logicalOp,
code: 'EINVAL',
errnoHint: 'EINVAL',
posixAlignment: 'ENOTSUP',
note: 'send/recv/recvfrom: fd required'
note: 'send/sendmsg/recv/recvfrom/recvmsg: fd required'
}
}
const k = String(fd >>> 0)
@@ -4872,33 +5197,40 @@ async function executeKernel(disk, store, swarm, initSource) {
) {
return {
ok: false,
op: name,
op: logicalOp,
code: 'ENOTSUP',
errnoHint: 'ENOTSUP',
posixAlignment: 'ENOTSUP',
note:
'Bridge send/recv/recvfrom supported for connected SOCK_DGRAM fds only; use Hyperswarm streams for TCP payload I/O.'
'Bridge send/sendmsg/recv/recvfrom/recvmsg supported for connected SOCK_DGRAM fds only; use Hyperswarm streams for TCP payload I/O.'
}
}
if (name === 'send') {
let payload = args.buf ?? args.buffer ?? args.data
if (payload == null) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL'
if (logicalOp === 'send' || logicalOp === 'sendmsg') {
let payload
if (logicalOp === 'sendmsg') {
const f = bareOsFlattenSendmsgIovs(args)
if (!f.ok) return f.err
payload = f.buf
} else {
payload = args.buf ?? args.buffer ?? args.data
if (payload == null) {
return {
ok: false,
op: logicalOp,
code: 'EINVAL',
errnoHint: 'EINVAL'
}
}
}
if (typeof payload === 'string')
payload = b4a.from(String(payload), 'utf8')
if (!(payload instanceof Uint8Array)) {
return {
ok: false,
op: name,
code: 'EINVAL',
errnoHint: 'EINVAL',
note: 'send: buf must be Uint8Array or string'
if (typeof payload === 'string')
payload = b4a.from(String(payload), 'utf8')
if (!(payload instanceof Uint8Array)) {
return {
ok: false,
op: logicalOp,
code: 'EINVAL',
errnoHint: 'EINVAL',
note: 'send: buf must be Uint8Array or string'
}
}
}
await new Promise((resolve, reject) => {
@@ -4912,7 +5244,7 @@ async function executeKernel(disk, store, swarm, initSource) {
})
return {
ok: true,
op: name,
op: logicalOp,
fd,
bytesSent: payload.byteLength,
bridge: true,
@@ -4928,7 +5260,8 @@ async function executeKernel(disk, store, swarm, initSource) {
)
const nonblock =
(this.bareOsLogicalFdFlags[k] & 0x800) === 0x800
const wantFrom = name === 'recvfrom'
const wantFrom =
logicalOp === 'recvfrom' || logicalOp === 'recvmsg'
const t0 = Date.now()
const blockMax = bareOsPosixDgramRecvBlockMsMax(shellEnv)
while (true) {
@@ -4944,7 +5277,7 @@ async function executeKernel(disk, store, swarm, initSource) {
}
const base = {
ok: true,
op: name,
op: logicalOp,
fd,
bytesReceived: out.byteLength,
buf: out,
@@ -4957,13 +5290,28 @@ async function executeKernel(disk, store, swarm, initSource) {
base.address = row.rinfo.address
base.port = row.rinfo.port
}
if (logicalOp === 'recvmsg') {
base.msgHdr = {
schema: 1,
name: row.rinfo
? {
address: String(row.rinfo.address || ''),
port: Number(row.rinfo.port) >>> 0
}
: null,
flags: 0,
controllen: 0,
note:
'SCM_RIGHTS / ancillary data ENOTSUP; single flat buffer in buf (no scatter iov split).'
}
}
return base
}
}
if (nonblock) {
return {
ok: false,
op: name,
op: logicalOp,
code: 'EAGAIN',
errnoHint: 'EAGAIN',
posixAlignment: 'EAGAIN',
@@ -4975,7 +5323,7 @@ async function executeKernel(disk, store, swarm, initSource) {
if (Date.now() - t0 >= blockMax) {
return {
ok: false,
op: name,
op: logicalOp,
code: 'EAGAIN',
errnoHint: 'EAGAIN',
posixAlignment: 'partial',
@@ -5019,9 +5367,27 @@ async function executeKernel(disk, store, swarm, initSource) {
}
throw new Error(`bareOsSyscall: unsupported op "${name}"`)
},
/** Peer admission against optional `BARE_OS_PEER_ALLOWLIST_HEX`. */
bareOsEvaluatePeerAdmission(peerKeyHex) {
return evaluateBareOsPeerAdmission(shellEnv, String(peerKeyHex || ''))
/**
* Peer admission against optional `BARE_OS_PEER_ALLOWLIST_HEX` and
* `BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST` when `meta.dhtAddressClass` is supplied.
*/
bareOsEvaluatePeerAdmission(peerKeyHex, meta) {
return evaluateBareOsPeerAdmission(
shellEnv,
String(peerKeyHex || ''),
meta && typeof meta === 'object' ? meta : undefined
)
},
/** Parsed non-secret `BARE_OS_PEAR_RUNTIME_SNAPSHOT_JSON` for Pear drift checks. */
bareOsReadPearRuntimeSnapshotJson() {
const raw = String(shellEnv.BARE_OS_PEAR_RUNTIME_SNAPSHOT_JSON || '').trim()
if (!raw) return null
try {
const o = JSON.parse(raw)
return o && typeof o === 'object' && !Array.isArray(o) ? o : null
} catch {
return null
}
},
/** Stable sort for replication / OTA fetch ordering. */
bareOsPrioritizeReplicationPaths(paths) {
@@ -6884,6 +7250,9 @@ async function executeKernel(disk, store, swarm, initSource) {
disk.os = createBareOsDiskOsBridge({
drive: disk.drive,
auxiliaryDrives: Array.isArray(disk.auxiliaryDrives)
? disk.auxiliaryDrives
: [],
bareOsIpc,
ctxApiVersion: BARE_OS_CTX_API_VERSION,
systemRevision: ctx.bareOsSystemRevision,
@@ -6892,6 +7261,16 @@ async function executeKernel(disk, store, swarm, initSource) {
disk.seedReplicationStatus &&
typeof disk.seedReplicationStatus === 'object'
? disk.seedReplicationStatus
: null,
seedMirrorDriveHintV2:
disk.seedMirrorDriveHintV2 &&
typeof disk.seedMirrorDriveHintV2 === 'object'
? disk.seedMirrorDriveHintV2
: null,
seedHttpDhtProxyHint:
disk.seedHttpDhtProxyHint &&
typeof disk.seedHttpDhtProxyHint === 'object'
? disk.seedHttpDhtProxyHint
: null
})
@@ -2,4 +2,4 @@
* Semantic version of the booter `ctx` contract for custom kernels.
* Bump when adding/removing/renaming documented `ctx` fields or changing behavior.
*/
export const BARE_OS_CTX_API_VERSION = '1.42.0'
export const BARE_OS_CTX_API_VERSION = '1.44.0'
@@ -351,13 +351,28 @@ export async function maybeMergeBareFromDrive(shellEnv, vfs, target) {
await withDriveBundleGlobalRequire(async () => {
/** @type {{ path: string, keys: string[] }[]} */
const work = []
/** @type {Set<string>} */
const seenPaths = new Set()
let allKeysSatisfied = true
for (const b of bundles) {
const path = typeof b?.path === 'string' ? b.path : ''
const keys = Array.isArray(b?.keys) ? b.keys : []
if (!path.startsWith('/lib/bare/')) continue
if (seenPaths.has(path)) continue
seenPaths.add(path)
for (const k of keys) {
if (typeof k === 'string' && k && target[k] === undefined) {
allKeysSatisfied = false
}
}
work.push({ path, keys })
}
if (work.length > 0 && allKeysSatisfied) {
await tryBareFetchImportWhenDriveMissing(target)
return
}
/** @type {{ path: string, keys: string[], source: string | null }[]} */
const prepared = []
for (let i = 0; i < work.length; ) {
+6 -1
View File
@@ -414,7 +414,12 @@ export interface BareOsKernelContext {
op: string,
args?: Record<string, unknown>
): Promise<unknown>
bareOsEvaluatePeerAdmission?(peerKeyHex: string): Record<string, unknown>
bareOsEvaluatePeerAdmission?(
peerKeyHex: string,
meta?: { dhtAddressClass?: string }
): Record<string, unknown>
/** Non-secret Pear runtime snapshot from **`BARE_OS_PEAR_RUNTIME_SNAPSHOT_JSON`** (parse errors → **`null`**). */
bareOsReadPearRuntimeSnapshotJson?(): Record<string, unknown> | null
bareOsPrioritizeReplicationPaths?(paths: string[]): string[]
bareOsVfsBatchWrite?(
puts: {
@@ -9,14 +9,48 @@ import { BareOsKernelError } from './bare-os-errors.js'
const MAX_SEARCH_RESULTS = 256
/**
* @param {import('hyperdrive').default | null | undefined} drive
* @param {string} q normalized lowercase query
* @param {string[]} matches mutates
* @param {number} cap
*/
async function collectSearchMatches(drive, q, matches, cap) {
if (!drive || typeof drive.list !== 'function') return
try {
for await (const ent of drive.list('/', { recursive: true })) {
const key = String(ent.key || '')
if (!key) continue
const norm = key.startsWith('/') ? key : `/${key}`
if (norm.toLowerCase().includes(q)) {
matches.push(norm)
if (matches.length >= cap) break
}
}
} catch {
/* drive list failure — skip this drive */
}
}
/**
* @param {number} ms
* @returns {Promise<void>}
*/
function sleepMs(ms) {
return new Promise((r) => setTimeout(r, ms))
}
/**
* @param {{
* drive: import('hyperdrive').default | null | undefined
* auxiliaryDrives?: import('hyperdrive').default[] | null | undefined
* bareOsIpc: { list?: () => string[] } | null | undefined
* ctxApiVersion: string
* systemRevision: Readonly<{ currentId?: string; pendingId?: string; slot?: string }> | null | undefined
* bootStartedMs: number
* seedReplicationStatus?: Record<string, unknown> | null
* seedMirrorDriveHintV2?: Record<string, unknown> | null
* seedHttpDhtProxyHint?: Record<string, unknown> | null
* }} opts
*/
export function createBareOsDiskOsBridge(opts) {
@@ -26,25 +60,32 @@ export function createBareOsDiskOsBridge(opts) {
* @returns {Promise<string[]>}
*/
async searchLocal(query) {
const drive = opts.drive
const q = String(query || '').trim().toLowerCase()
if (!q || !drive || typeof drive.list !== 'function') return []
/** @type {string[]} */
const matches = []
try {
for await (const ent of drive.list('/', { recursive: true })) {
const key = String(ent.key || '')
if (!key) continue
const norm = key.startsWith('/') ? key : `/${key}`
if (norm.toLowerCase().includes(q)) {
matches.push(norm)
if (matches.length >= MAX_SEARCH_RESULTS) break
}
if (!q) return []
const env = globalThis.process?.env
const throttleMs = Math.max(
0,
Math.min(500, Number(env?.BARE_OS_DISK_OS_SEARCH_THROTTLE_MS) || 0)
)
/** @type {import('hyperdrive').default[]} */
const drives = [opts.drive]
if (Array.isArray(opts.auxiliaryDrives)) {
for (const d of opts.auxiliaryDrives) {
if (d && typeof d.list === 'function') drives.push(d)
}
} catch {
return matches
}
return matches
/** @type {string[]} */
const raw = []
for (let i = 0; i < drives.length && raw.length < MAX_SEARCH_RESULTS; i++) {
if (i > 0 && throttleMs > 0) await sleepMs(throttleMs)
await collectSearchMatches(
drives[i],
q,
raw,
MAX_SEARCH_RESULTS - raw.length
)
}
return [...new Set(raw)]
},
/**
@@ -103,6 +144,29 @@ export function createBareOsDiskOsBridge(opts) {
return JSON.stringify({ args: a })
}
if (mod === 'bare_os' && meth === 'disk_os_hints') {
const aux = Array.isArray(opts.auxiliaryDrives)
? opts.auxiliaryDrives.filter((d) => d && typeof d.list === 'function')
.length
: 0
return JSON.stringify({
schema: 1,
ok: true,
auxiliaryDriveCount: aux,
mirrorDriveHintV2:
opts.seedMirrorDriveHintV2 &&
typeof opts.seedMirrorDriveHintV2 === 'object'
? opts.seedMirrorDriveHintV2
: null,
httpDhtProxyHint:
opts.seedHttpDhtProxyHint &&
typeof opts.seedHttpDhtProxyHint === 'object'
? opts.seedHttpDhtProxyHint
: null,
note: 'Advisory seed/mirror/http-dht-proxy hints for operators; guests do not apply these automatically.'
})
}
if (mod === 'bare_os' && meth === 'replication_snapshot') {
const drive = opts.drive
if (!drive) {
@@ -1,45 +1,104 @@
/**
* Optional peer admission gate from **`BARE_OS_PEER_ALLOWLIST_HEX`**
* (comma-separated hex public keys; empty = allow all).
*
* When **`BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST`** is set and callers pass
* **`dhtAddressClass`** (hyperdht-addressstyle hint), the class must appear in
* the allow list after the key gate passes.
*
* @param {Record<string, unknown> | null | undefined} env
* @param {string} peerKeyHex
* @param {{ dhtAddressClass?: string } | null | undefined} [meta]
*/
export function evaluateBareOsPeerAdmission(env, peerKeyHex) {
export function evaluateBareOsPeerAdmission(env, peerKeyHex, meta = undefined) {
const raw = String(env?.BARE_OS_PEER_ALLOWLIST_HEX || '').trim()
const strict =
env?.BARE_OS_PEER_ALLOWLIST_STRICT === '1' ||
env?.BARE_OS_PEER_ALLOWLIST_STRICT === 'true'
/** @type {{ schema: number, verdict: string, note?: string, allowlistSize?: number, strictProfile?: boolean, atMs?: number, dhtAddressClassGate?: Record<string, unknown> }} */
let base
if (!raw) {
if (strict) {
return {
base = {
schema: 1,
verdict: 'deny',
note:
'BARE_OS_PEER_ALLOWLIST_STRICT is set but BARE_OS_PEER_ALLOWLIST_HEX is empty — no peers admitted.'
}
} else {
base = {
schema: 1,
verdict: 'allow',
note: 'No allowlist; all peers admitted (subject to Hyperswarm topic).'
}
}
return {
} else {
const want = String(peerKeyHex || '')
.trim()
.toLowerCase()
.replace(/^0x/, '')
const set = new Set(
raw
.split(/[\s,]+/)
.map((s) => s.trim().toLowerCase().replace(/^0x/, ''))
.filter(Boolean)
)
const ok = want && set.has(want)
base = {
schema: 1,
verdict: 'allow',
note: 'No allowlist; all peers admitted (subject to Hyperswarm topic).'
verdict: ok ? 'allow' : 'deny',
allowlistSize: set.size,
strictProfile: strict || undefined,
atMs: Date.now()
}
}
const want = String(peerKeyHex || '')
const classRaw = String(env?.BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST || '').trim()
if (!classRaw) {
if (base.atMs == null) base.atMs = Date.now()
return base
}
const allowClasses = new Set(
classRaw.split(',').map((s) => s.trim().toLowerCase()).filter(Boolean)
)
if (allowClasses.size === 0) {
if (base.atMs == null) base.atMs = Date.now()
return base
}
const cls = String(meta?.dhtAddressClass || '')
.trim()
.toLowerCase()
.replace(/^0x/, '')
const set = new Set(
raw
.split(/[\s,]+/)
.map((s) => s.trim().toLowerCase().replace(/^0x/, ''))
.filter(Boolean)
)
const ok = want && set.has(want)
if (!cls) {
return {
...base,
atMs: base.atMs ?? Date.now(),
dhtAddressClassGate: {
schema: 1,
mode: 'no_peer_class_hint',
note: 'BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST is set but caller did not supply dhtAddressClass — stock Hyperswarm path does not classify peers; allow key verdict only.'
}
}
}
if (!allowClasses.has(cls)) {
return {
schema: 1,
verdict: 'deny',
reason: 'dht_address_class',
dhtAddressClass: cls,
allowedClasses: [...allowClasses],
note: 'Peer DHT address class not listed in BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST.',
atMs: Date.now()
}
}
if (base.verdict === 'deny') return base
return {
schema: 1,
verdict: ok ? 'allow' : 'deny',
allowlistSize: set.size,
strictProfile: strict || undefined,
atMs: Date.now()
...base,
atMs: base.atMs ?? Date.now(),
dhtAddressClassGate: { schema: 1, mode: 'allow', class: cls }
}
}
@@ -2,8 +2,12 @@
* Capability word 8 optional `/proc/bare_os/*.json` payloads (env-injected; bounded, non-secret).
* @param {string} id
* @param {Record<string, string>} env
* @param {{
* protomuxWireCorrelate?: Record<string, unknown> | null
* seedProtomuxRpcPoolHint?: Record<string, unknown> | null
* }} [runtimeHints]
*/
export function buildBareOsBareRuntimeProtoMuxProcJson(id, env) {
export function buildBareOsBareRuntimeProtoMuxProcJson(id, env, runtimeHints) {
const now = Date.now()
const esc = (k) => String(env[k] ?? '').trim()
@@ -54,10 +58,22 @@ export function buildBareOsBareRuntimeProtoMuxProcJson(id, env) {
note: 'bare-kit capability flags from env.',
atMs: now
}
case 'protomux_rpc_pool_health':
case 'protomux_rpc_pool_health': {
const envHealth = parseJsonEnv('BARE_OS_PROTOMUX_RPC_POOL_HEALTH_JSON')
const seedHint =
runtimeHints?.seedProtomuxRpcPoolHint &&
typeof runtimeHints.seedProtomuxRpcPoolHint === 'object'
? runtimeHints.seedProtomuxRpcPoolHint
: null
return {
schema: 2,
health: parseJsonEnv('BARE_OS_PROTOMUX_RPC_POOL_HEALTH_JSON'),
health: envHealth,
seedProtomuxRpcPoolHintEcho: !envHealth ? seedHint : undefined,
protomuxWireCorrelate:
runtimeHints?.protomuxWireCorrelate &&
typeof runtimeHints.protomuxWireCorrelate === 'object'
? runtimeHints.protomuxWireCorrelate
: undefined,
replicationBackpressure: parseJsonEnv(
'BARE_OS_REPLICATION_BACKPRESSURE_JSON'
),
@@ -67,9 +83,10 @@ export function buildBareOsBareRuntimeProtoMuxProcJson(id, env) {
return Number.isFinite(n) ? n : null
})(),
note:
'Schema 2 correlates optional replication backpressure JSON with pool health; bareOsEmitProtomuxBackpressure stamps BARE_OS_LAST_PROTOMUX_BACKPRESSURE_MS.',
'Schema 2 correlates optional replication backpressure JSON with pool health; bareOsEmitProtomuxBackpressure stamps BARE_OS_LAST_PROTOMUX_BACKPRESSURE_MS. When health env is unset, seedProtomuxRpcPoolHintEcho mirrors the seeder RPC hint. protomuxWireCorrelate links live peer/backpressure/alias counts to protomux.json operatorMetrics.',
atMs: now
}
}
case 'http_dht_proxy_route':
return {
schema: 1,
@@ -7,7 +7,10 @@ import {
* Capability word 7 optional `/proc/bare_os/*.json` payloads (env-injected; bounded, non-secret).
* @param {string} id
* @param {Record<string, string>} env
* @param {{ swarm?: Record<string, unknown> | null }} [runtimeHints]
* @param {{
* swarm?: Record<string, unknown> | null
* protomuxWireShape?: Record<string, unknown> | null
* }} [runtimeHints]
*/
export function buildBareOsPearCorestoreHrpcProcJson(id, env, runtimeHints) {
const now = Date.now()
@@ -57,7 +60,12 @@ export function buildBareOsPearCorestoreHrpcProcJson(id, env, runtimeHints) {
return {
schema: 1,
channels: parseJsonEnv('BARE_OS_PROTOMUX_CHANNELS_JSON'),
note: 'Bounded protomux channel name inventory.',
wireShapeSummary:
runtimeHints?.protomuxWireShape &&
typeof runtimeHints.protomuxWireShape === 'object'
? runtimeHints.protomuxWireShape
: undefined,
note: 'Bounded protomux channel name inventory; wireShapeSummary mirrors bare-os-v1 wire kinds + live peer mux count when the booter supplies runtimeHints.',
atMs: now
}
case 'hrpc_bridge_health':
@@ -179,7 +179,7 @@ export function bareOsProcessTableSnapshot(opts = {}) {
return {
schema: 7,
schemaVersion: 7,
note: 'Synthetic rows; Bare OS guests do not expose host OS processes. v7 documents logical shell wait skipping completed jobs alongside syscalls.json schema 7 / profile 1.0.8. v6 jobControlSemantics (pipefail / posix mode env mirrors). v5 parentName/initd rows unchanged.',
note: 'Synthetic rows; Bare OS guests do not expose host OS processes. v7 documents logical shell wait skipping completed jobs alongside syscalls.json schema 8 / profile 1.0.9. v6 jobControlSemantics (pipefail / posix mode env mirrors). v5 parentName/initd rows unchanged.',
signalModel: {
schema: 1,
note: 'Virtual deliveries via ctx.bareOsSendSignal (not full sigaction/sigprocmask).',
@@ -26,6 +26,13 @@ export function buildBareOsReplicationLiveSketch(disk, peerCount) {
} catch {
personalCoreLength = null
}
let auxiliaryDriveCount = 0
try {
if (disk && Array.isArray(disk.auxiliaryDrives))
auxiliaryDriveCount = disk.auxiliaryDrives.length
} catch {
auxiliaryDriveCount = 0
}
const stallHint =
peerCount === 0
? 'no_peers'
@@ -33,10 +40,11 @@ export function buildBareOsReplicationLiveSketch(disk, peerCount) {
? 'length_unavailable'
: 'ok'
return {
schema: 1,
schema: 2,
systemCoreLength,
personalCoreLength,
auxiliaryDriveCount,
stallHint,
note: 'Append-only core lengths are non-secret progress hints; not a full replication telemetry plane.'
note: 'Schema 2 adds auxiliaryDriveCount (read-only mirror Hyperdrives under /mirror/aux*). Append-only core lengths are non-secret progress hints; aligns with corestore-snapshot / multi-drive replication operator workflows — not a full telemetry plane.'
}
}
@@ -36,9 +36,10 @@ export class BareOsSwarmConnectionManager {
/**
* @param {string} peerKey
* @param {{ dhtAddressClass?: string } | null | undefined} [meta]
*/
shouldAttemptPeer(peerKey) {
return this._engine.shouldAttemptPeer(peerKey)
shouldAttemptPeer(peerKey, meta) {
return this._engine.shouldAttemptPeer(peerKey, meta)
}
/**
@@ -150,12 +150,13 @@ export class BareOsSwarmPeerPolicyEngine {
/**
* @param {string} peerKey
* @param {{ dhtAddressClass?: string } | null | undefined} [meta]
* @returns {boolean} false when peer is in ban window or reconnect budget exhausted
*/
shouldAttemptPeer(peerKey) {
shouldAttemptPeer(peerKey, meta) {
const k = this._key(peerKey)
if (this._env) {
const adm = evaluateBareOsPeerAdmission(this._env, k)
const adm = evaluateBareOsPeerAdmission(this._env, k, meta)
if (adm.verdict === 'deny') return false
}
const st = this._peers.get(k)
@@ -98,6 +98,22 @@ export const BARE_OS_SYSCALL_OPS_DETAIL = Object.freeze([
mapsTo: ['stream.read'],
errnoHint: 'ENOSYS'
},
{
name: 'sendmsg',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'ENOTSUP',
mapsTo: ['flattened iovec send on SOCK_DGRAM bridge'],
errnoHint: 'ENOSYS'
},
{
name: 'recvmsg',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'ENOTSUP',
mapsTo: ['SOCK_DGRAM bridge datagram + msgHdr envelope'],
errnoHint: 'ENOSYS'
},
{
name: 'shutdown',
category: 'ipc',
@@ -143,6 +159,30 @@ export const BARE_OS_SYSCALL_OPS_DETAIL = Object.freeze([
'bounded concatenated write to posix-pipe write FD (BARE_OS_POSIX_FD_SIM)'
],
errnoHint: 'EINVAL'
},
{
name: 'mq_open',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'partial',
mapsTo: ['ctx.bareOsSyscall("mq_open")', 'bareOsIpc.mqOpen'],
errnoHint: 'EINVAL'
},
{
name: 'mq_send',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'partial',
mapsTo: ['ctx.bareOsSyscall("mq_send")', 'bareOsIpc.mqSend'],
errnoHint: 'EAGAIN'
},
{
name: 'mq_receive',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'partial',
mapsTo: ['ctx.bareOsSyscall("mq_receive")', 'bareOsIpc.mqReceive'],
errnoHint: 'EAGAIN'
}
])
@@ -368,6 +408,28 @@ export const BARE_OS_POSIX_XSH_OPS_DETAIL = Object.freeze([
],
errnoHint: 'ENOSYS'
},
{
name: 'sendmsg',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'partial',
mapsTo: [
'ctx.bareOsSyscall("sendmsg")',
'SOCK_DGRAM bridge flattened iovs (BARE_OS_POSIX_SOCKET_FD_BRIDGE); ancillary CMSGS ENOTSUP'
],
errnoHint: 'ENOSYS'
},
{
name: 'recvmsg',
category: 'ipc',
stability: 'experimental',
posixAlignment: 'partial',
mapsTo: [
'ctx.bareOsSyscall("recvmsg")',
'SOCK_DGRAM bridge + msgHdr.name from rinfo; scatter iov / SCM_RIGHTS ENOTSUP'
],
errnoHint: 'ENOSYS'
},
{
name: 'shutdown',
category: 'ipc',
@@ -18,7 +18,7 @@ import { bareOsErrnoTableForProc } from './bare-os-posix-errno.js'
*/
export function buildBareOsSyscallsProcJson(p) {
return {
schemaVersion: 7,
schemaVersion: 8,
ctxApiVersion: p.ctxApiVersion,
posixProfile: {
id: BARE_OS_POSIX_PROFILE_ID,
@@ -29,18 +29,20 @@ export function buildBareOsSyscallsProcJson(p) {
opsDetail: [...BARE_OS_SYSCALL_OPS_DETAIL_FULL],
posixXsh: {
schema: 2,
note: 'POSIX.1 XSH-style names: logical names in opsDetail; socket family are ctx.bareOsSyscall ops returning ENOSYS-shaped results (not kernel socket FDs). readv/writev are partial posix-pipe facades; getsockopt/setsockopt are ENOSYS-shaped probes. SOCK_DGRAM bridge supports recv/recvfrom with bounded queue (BARE_OS_POSIX_DGRAM_RECVQ_MAX).',
note: 'POSIX.1 XSH-style names: logical names in opsDetail; socket family are ctx.bareOsSyscall ops returning ENOSYS-shaped results (not kernel socket FDs). readv/writev are partial posix-pipe facades; getsockopt/setsockopt are ENOSYS-shaped probes. SOCK_DGRAM bridge supports send/sendmsg/recv/recvfrom/recvmsg with bounded queue (BARE_OS_POSIX_DGRAM_RECVQ_MAX); sendmsg/recvmsg omit ancillary control messages.',
namesCsv: bareOsPosixXshOpsCsv()
},
socketMsgSurface: {
schema: 1,
schema: 2,
sendmsg: {
bridgePartial: true,
defaultErrno: 'ENOTSUP',
note: 'Flags / iovec / ancillary CMSGS are not modeled; use send or ctx.bare networking.'
note: 'With BARE_OS_POSIX_SOCKET_FD_BRIDGE and SOCK_DGRAM, sendmsg flattens bounded iovs into one datagram; flags and ancillary CMSGS remain ENOTSUP.'
},
recvmsg: {
bridgePartial: true,
defaultErrno: 'ENOTSUP',
note: 'recvmsg with SCM_RIGHTS is ENOTSUP; SOCK_DGRAM bridge recv/recvfrom return flat buffers only.'
note: 'With bridge + SOCK_DGRAM, recvmsg returns buf + msgHdr.name from rinfo; SCM_RIGHTS / scatter iov ENOTSUP.'
}
},
errnoHints: bareOsErrnoTableForProc(),
@@ -74,6 +76,13 @@ export function buildBareOsSyscallsProcJson(p) {
mapsTo: ['mkfifo + /run/bare-os/ipc/* in-memory queues'],
notOnHyperdrive: true
},
mq: {
mapsTo: [
'ctx.bareOsSyscall("mq_open"|"mq_send"|"mq_receive")',
'bareOsIpc POSIX-like named queues (priority sort; bounded maxmsg/maxBytes)'
],
partial: true
},
dup: {
mapsTo: ['ctx.bareOsRegisterLogicalFd copy of target string'],
partial: true
@@ -123,10 +123,13 @@ export function openBytes(key32, boxed) {
* @param {number} iterations
*/
function deriveKey(passphrase, salt, iterations) {
const pass =
typeof passphrase === 'string'
? b4a.from(passphrase, 'utf8')
: u8(passphrase)
if (typeof passphrase === 'string') {
const pass = b4a.from(passphrase, 'utf8')
const out = u8(pbkdf2Sync(pass, u8(salt), iterations, 32, 'sha256'))
secureZero(pass)
return out
}
const pass = u8(passphrase)
return u8(pbkdf2Sync(pass, u8(salt), iterations, 32, 'sha256'))
}
+15 -1
View File
@@ -1396,10 +1396,14 @@ async function execParsedPipeline(ctx, pipeline) {
env.BARE_OS_SHELL_NOGLOB = '1'
} else if (args.length === 1 && args[0] === '+f') {
delete env.BARE_OS_SHELL_NOGLOB
} else if (args.length === 1 && args[0] === '-e') {
env.BARE_OS_SHELL_ERREXIT = '1'
} else if (args.length === 1 && args[0] === '+e') {
delete env.BARE_OS_SHELL_ERREXIT
} else {
origErr.call(
ctx.console,
'set: unsupported arguments (only -f / +f for noglob)'
'set: unsupported arguments (only -f / +f / -e / +e)'
)
ctx.exitCode = 1
}
@@ -2567,6 +2571,16 @@ async function execShellLineInner(ctx, rawTrimmed) {
syncBareOsExitStatusEnv(ctx)
return 'exit'
}
const shE = ctx.vfs?.env
if (
shE &&
(shE.BARE_OS_SHELL_ERREXIT === '1' ||
shE.BARE_OS_SHELL_ERREXIT === 'true') &&
(Number(ctx.exitCode) || 0) !== 0
) {
syncBareOsExitStatusEnv(ctx)
return 'ok'
}
}
}
syncBareOsExitStatusEnv(ctx)
+46 -3
View File
@@ -5,6 +5,41 @@ import {
PROTOCOL_APP_CHANNEL_NAME
} from 'bare-os-protocol/constants.js'
/**
* Host-side booter log for swarm disk (stderr JSON when BARE_OS_BOOT_TRACE=json|ndjson; else stderr or console.warn).
* @param {'info'|'warn'} level
* @param {string} message
* @param {Record<string, unknown> | null} [detail]
*/
function emitSwarmDiskHostLog(level, message, detail = null) {
const env = globalThis.process?.env
const trace =
env &&
(env.BARE_OS_BOOT_TRACE === 'json' || env.BARE_OS_BOOT_TRACE === 'ndjson')
const err = globalThis.process?.stderr
if (trace && err && typeof err.write === 'function') {
err.write(
`${JSON.stringify({
type: 'booterHost',
bootTraceSchemaVersion: 2,
component: 'swarm_disk',
level,
message,
detail,
ts: Date.now()
})}\n`
)
}
if (level === 'warn') {
if (typeof console.warn === 'function') console.warn(message)
else if (err && typeof err.write === 'function') err.write(`${message}\n`)
return
}
const line = `[bare-os-booter][swarm-disk] ${message}`
if (err && typeof err.write === 'function') err.write(`${line}\n`)
else if (typeof console.info === 'function') console.info(line)
}
export class SwarmDisk {
constructor() {
this.localRAM = new Map()
@@ -146,11 +181,19 @@ export class SwarmDisk {
await this.personalDrive.ready()
}
if (!this.personalDrive.writable) {
console.warn(
'[bare-os-booter] Personal Hyperdrive is not writable — identity and $HOME writes will fail. Check Corestore path permissions and that no other process holds the store read-only.'
emitSwarmDiskHostLog(
'warn',
'[bare-os-booter] Personal Hyperdrive is not writable — identity and $HOME writes will fail. Check Corestore path permissions and that no other process holds the store read-only.',
{
writable: false,
idPrefix: b4a.toString(this.personalDrive.id, 'hex').slice(0, 16)
}
)
}
console.log('Personal drive:', this.personalDrive.id.slice(0, 16) + '...')
emitSwarmDiskHostLog('info', 'Personal Hyperdrive mounted; joining swarm discovery', {
idPrefix: b4a.toString(this.personalDrive.id, 'hex').slice(0, 16),
writable: this.personalDrive.writable
})
swarm.join(this.personalDrive.discoveryKey)
}
+141 -6
View File
@@ -95,6 +95,7 @@ import { buildBareOsSyscallsProcJson } from './lib/bare-os-syscalls-proc-json.js
import { buildBareOsProtomuxExtensionsProcJson } from './lib/bare-os-protomux-extensions-proc.js'
import { createBareOsDiskOsBridge } from './lib/bare-os-disk-os-bridge.js'
import { buildBareOsReplicationLiveSketch } from './lib/bare-os-replication-proc-live.js'
import { evaluateBareOsPeerAdmission } from './lib/bare-os-peer-admission.js'
import { buildBareOsReplicationOperatorSurfaceProcJson } from './lib/bare-os-proc-replication-operator-surface.js'
import {
DEFAULT_CURL_USER_AGENT,
@@ -983,7 +984,7 @@ test('vfs lstat personal file includes mode uid user mtime', async (t) => {
rmSync(dir, { recursive: true, force: true })
})
test('vfs syscalls.json uses schema 6 when provider wired', async (t) => {
test('vfs syscalls.json uses schema 7 when provider wired', async (t) => {
const dir = testCorestoreDir('syscallsproc')
const store = new Corestore(dir)
const sys = new Hyperdrive(store)
@@ -991,7 +992,7 @@ test('vfs syscalls.json uses schema 6 when provider wired', async (t) => {
await sys.ready()
await personal.ready()
const sample = {
schemaVersion: 7,
schemaVersion: 8,
ctxApiVersion: BARE_OS_CTX_API_VERSION,
ops: ['readFile'],
errnoHints: { ENOENT: 2 },
@@ -1012,7 +1013,7 @@ test('vfs syscalls.json uses schema 6 when provider wired', async (t) => {
)
const buf = await vfs.readFile('/proc/bare_os/syscalls.json')
const j = JSON.parse(b4a.toString(buf))
t.is(j.schemaVersion, 7)
t.is(j.schemaVersion, 8)
t.ok(j.fdModel && j.fdModel.schema === 1)
t.ok(j.signalModel && Array.isArray(j.signalModel.names))
await store.close()
@@ -1216,16 +1217,19 @@ test('buildBareOsReplicationLiveSketch reads hyperdrive core lengths', async (t)
await drive.ready()
await personal.ready()
const sk0 = buildBareOsReplicationLiveSketch(
{ drive, personalDrive: personal },
{ drive, personalDrive: personal, auxiliaryDrives: [personal] },
0
)
t.is(sk0.schema, 1)
t.is(sk0.schema, 2)
t.is(sk0.auxiliaryDriveCount, 1)
t.is(sk0.stallHint, 'no_peers')
t.ok(typeof sk0.systemCoreLength === 'number')
const sk1 = buildBareOsReplicationLiveSketch(
{ drive, personalDrive: personal },
1
)
t.is(sk1.schema, 2)
t.is(sk1.auxiliaryDriveCount, 0)
t.is(sk1.stallHint, 'ok')
await store.close()
rmSync(dir, { recursive: true, force: true })
@@ -1243,6 +1247,45 @@ test('protomux_rpc_pool_health proc uses schema 2 and backpressure correlation f
t.is(j.lastProtomuxBackpressureMs, 99)
})
test('protomux_rpc_pool_health echoes seed pool hint and wire correlate when env health absent', async (t) => {
const j = buildBareOsBareRuntimeProtoMuxProcJson(
'protomux_rpc_pool_health',
{},
{
seedProtomuxRpcPoolHint: { schema: 1, depth: 2 },
protomuxWireCorrelate: {
schema: 1,
peerMuxSessions: 3,
backpressureEmitCount: 5,
aliasPairCount: 1,
bareOsV1WireMessageKinds: 7
}
}
)
t.is(j.schema, 2)
t.is(j.health, null)
t.is(j.seedProtomuxRpcPoolHintEcho?.depth, 2)
t.is(j.protomuxWireCorrelate?.peerMuxSessions, 3)
t.is(j.protomuxWireCorrelate?.backpressureEmitCount, 5)
})
test('protomux_channels proc includes wireShapeSummary from runtime hints', async (t) => {
const j = buildBareOsPearCorestoreHrpcProcJson(
'protomux_channels',
{},
{
protomuxWireShape: {
schema: 1,
bareOsV1MessageKinds: ['read', 'rpc_req'],
peerMuxSessions: 2
}
}
)
t.is(j.schema, 1)
t.is(j.wireShapeSummary?.peerMuxSessions, 2)
t.ok(Array.isArray(j.wireShapeSummary?.bareOsV1MessageKinds))
})
test('pathnameExpandShellWord caps matches with BARE_OS_GLOB_MAX_MATCHES', async (t) => {
const names = ['f0', 'f1', 'f2', 'f3', 'f4']
const vfs = {
@@ -1270,7 +1313,7 @@ test('pathnameExpandShellWord caps matches with BARE_OS_GLOB_MAX_MATCHES', async
test('buildBareOsSyscallsProcJson exposes posixLike fd mapping', async (t) => {
const j = buildBareOsSyscallsProcJson({ ctxApiVersion: BARE_OS_CTX_API_VERSION })
t.is(j.schemaVersion, 7)
t.is(j.schemaVersion, 8)
t.ok(j.fdModel && j.fdModel.posixLike && j.fdModel.posixLike.pipe)
t.ok(j.fdModel.posixLike.read && j.fdModel.posixLike.write)
t.ok(j.fdModel.posixLike.fcntl)
@@ -1283,6 +1326,8 @@ test('buildBareOsSyscallsProcJson exposes posixLike fd mapping', async (t) => {
t.ok(j.posixXsh.namesCsv.includes('readv'))
t.ok(j.posixXsh.namesCsv.includes('writev'))
t.ok(j.posixXsh.namesCsv.includes('socket'))
t.ok(j.posixXsh.namesCsv.includes('sendmsg'))
t.ok(j.posixXsh.namesCsv.includes('recvmsg'))
t.ok(j.posixXsh.namesCsv.includes('shutdown'))
const xsh = j.opsDetail.filter((r) => r.posixAlignment)
t.ok(xsh.length >= 10)
@@ -1323,6 +1368,40 @@ test('disk.os replication_snapshot and replication_operator_sketch RPCs', async
rmSync(dir, { recursive: true, force: true })
})
test('disk.os searchLocal merges auxiliary drives and disk_os_hints RPC', async (t) => {
const dir = testCorestoreDir('diskossearch')
const store = new Corestore(dir)
const drive = new Hyperdrive(store)
const auxStore = store.namespace('auxs')
const aux = new Hyperdrive(auxStore)
await drive.ready()
await aux.ready()
await drive.put('/sys/x_only', b4a.from('1'))
await aux.put('/mirror/y_aux', b4a.from('2'))
const bridge = createBareOsDiskOsBridge({
drive,
auxiliaryDrives: [aux],
bareOsIpc: { list: () => [] },
ctxApiVersion: BARE_OS_CTX_API_VERSION,
systemRevision: null,
bootStartedMs: Date.now(),
seedMirrorDriveHintV2: { schema: 2, note: 't' },
seedHttpDhtProxyHint: { routes: 1 }
})
const m = await bridge.searchLocal('y_aux')
t.ok(m.some((p) => p.includes('y_aux')))
const m2 = await bridge.searchLocal('x_only')
t.ok(m2.some((p) => p.includes('x_only')))
const h = await bridge.execRpc('bare_os', 'disk_os_hints', [])
const hj = JSON.parse(h)
t.is(hj.schema, 1)
t.is(hj.auxiliaryDriveCount, 1)
t.is(hj.mirrorDriveHintV2?.schema, 2)
t.is(hj.httpDhtProxyHint?.routes, 1)
await store.close()
rmSync(dir, { recursive: true, force: true })
})
test('ls -l long listing uses session user and regular file mode', async (t) => {
const lsPath = path.join(__dirname, '../../kernel/bin/ls')
const lsSrc = await readFile(lsPath, 'utf8')
@@ -2260,6 +2339,62 @@ test('syncBareOsExitStatusEnv and execShellLine update env', async (t) => {
rmSync(dir, { recursive: true, force: true })
})
test('execShellLine BARE_OS_SHELL_ERREXIT skips after failed command', async (t) => {
const dir = testCorestoreDir('errexit')
const store = new Corestore(dir)
const drive = new Hyperdrive(store)
const personal = new Hyperdrive(store.namespace('pex-e'))
await drive.ready()
await personal.ready()
await drive.put(
'/bin/false',
b4a.from(`async function run(ctx) { ctx.exitCode = 1 }`)
)
await drive.put(
'/bin/true',
b4a.from(`async function run(ctx) { ctx.exitCode = 0 }`)
)
await drive.put(
'/bin/echo',
b4a.from(
`async function run(ctx, argv) { ctx.console.log(argv.slice(1).join(' ')) }`
)
)
const logs = []
const ctx = testCtx(drive, personal)
ctx.console = {
log: (m) => logs.push(String(m)),
error: (...a) => logs.push(a.map(String).join(' '))
}
ctx.vfs.env.BARE_OS_SHELL_ERREXIT = '1'
await execShellLine(ctx, 'false; echo AFTER')
t.ok(!logs.some((l) => l.includes('AFTER')))
logs.length = 0
ctx.exitCode = 0
await execShellLine(ctx, 'true; echo OK')
t.ok(logs.some((l) => l.includes('OK')))
logs.length = 0
ctx.exitCode = 0
delete ctx.vfs.env.BARE_OS_SHELL_ERREXIT
await execShellLine(ctx, 'set -e; false; echo NEVER')
t.ok(!logs.some((l) => l.includes('NEVER')))
await store.close()
rmSync(dir, { recursive: true, force: true })
})
test('evaluateBareOsPeerAdmission honors dhtAddressClass with allowlist', async (t) => {
const env = {
BARE_OS_PEER_ALLOWLIST_HEX: '',
BARE_OS_DHT_ADDRESS_CLASS_ALLOWLIST: 'ipv4,relay'
}
const deny = evaluateBareOsPeerAdmission(env, 'aa', {
dhtAddressClass: 'ipv6'
})
t.is(deny.verdict, 'deny')
const ok = evaluateBareOsPeerAdmission(env, 'aa', { dhtAddressClass: 'ipv4' })
t.is(ok.verdict, 'allow')
})
test('BARE_OS_CTX_API_VERSION is semver-shaped', async (t) => {
t.ok(/^\d+\.\d+\.\d+$/.test(BARE_OS_CTX_API_VERSION))
})
@@ -2,14 +2,13 @@
"name": "expand",
"section": 1,
"title": "expand",
"synopsis": [
"expand [OPTION]... [OPERAND]..."
"synopsis": ["expand [-t LIST] [FILE]..."],
"description": "Convert tabs to spaces. One -t width uses uniform stops; a comma-separated increasing list uses POSIX-style tab stops (repeating interval from the last two stops).",
"options": [
{
"flag": "-t LIST",
"meaning": "Tab width or comma-separated tab stops (e.g. 8 or 1,4,8)."
}
],
"description": "Bare OS implementation of expand. Full behavior is defined in packages/bare-os-coreutils/src/expand.js.",
"options": [],
"keywords": [
"expand",
"bare-os",
"coreutils"
]
"keywords": ["expand", "bare-os", "coreutils"]
}
+1 -1
View File
@@ -6,6 +6,6 @@
"description": "Build JS /bin utilities for bare-operating-system (concat + stage to kernel/)",
"scripts": {
"build": "node ./scripts/ensure-man-pages.mjs && node ./build.mjs",
"test": "node ./test/help-bin-list.test.mjs && node ./test/edit-key-parse.test.mjs && node ./test/edit-teardown.test.mjs && node ./test/baretop-bundle.test.mjs && node ./test/baretop-fixture.test.mjs && node ./test/posix-test-int-compare.test.mjs && node ./test/posix-utils-edge.test.mjs && node ./test/posix-golden-issue7.test.mjs && node ./test/getconf-pathconf-union-mirror.test.mjs && node ./test/getconf-posix-shm.test.mjs && node ./test/awk-sed-posix-smoke.test.mjs && node ./test/xattr-acl-utils.test.mjs && node ./test/xcu-issue7-sweep.test.mjs"
"test": "node ./test/help-bin-list.test.mjs && node ./test/edit-key-parse.test.mjs && node ./test/edit-teardown.test.mjs && node ./test/baretop-bundle.test.mjs && node ./test/baretop-fixture.test.mjs && node ./test/posix-test-int-compare.test.mjs && node ./test/posix-utils-edge.test.mjs && node ./test/posix-golden-issue7.test.mjs && node ./test/getconf-pathconf-union-mirror.test.mjs && node ./test/getconf-posix-shm.test.mjs && node ./test/awk-sed-posix-smoke.test.mjs && node ./test/xattr-acl-utils.test.mjs && node ./test/xcu-issue7-sweep.test.mjs && node ./test/expand-tab-stops.test.mjs"
}
}
+43 -10
View File
@@ -1,19 +1,50 @@
function parseUniformWidth(tabArg) {
const n = parseInt(String(tabArg).split(',')[0].trim(), 10)
return Number.isFinite(n) && n > 0 ? n : 8
/**
* @param {string} tabArg
* @returns {number[]}
*/
function parseTabStops(tabArg) {
const raw = String(tabArg || '').trim()
if (!raw) return [8]
const parts = raw.split(',')
/** @type {number[]} */
const out = []
for (const p of parts) {
const n = parseInt(p.trim(), 10)
if (Number.isFinite(n) && n > 0) out.push(n)
}
if (!out.length) return [8]
out.sort((a, b) => a - b)
/** @type {number[]} */
const uniq = []
for (const x of out) {
if (uniq.length === 0 || uniq[uniq.length - 1] !== x) uniq.push(x)
}
return uniq
}
function nextTabCol(col, w) {
return (Math.floor(col / w) + 1) * w
function nextTabStop(col, stops) {
if (stops.length === 1) {
const w = stops[0]
return (Math.floor(col / w) + 1) * w
}
for (const s of stops) {
if (s > col) return s
}
const last = stops[stops.length - 1]
const prev = stops[stops.length - 2]
const step = Math.max(1, last - prev)
let x = last
while (x <= col) x += step
return x
}
function expandLine(line, w) {
function expandLine(line, stops) {
let col = 0
let out = ''
for (let i = 0; i < line.length; i++) {
const ch = line[i]
if (ch === '\t') {
const target = nextTabCol(col, w)
const target = nextTabStop(col, stops)
while (col < target) {
out += ' '
col++
@@ -34,7 +65,9 @@ async function run(ctx, argv) {
const a = argv[i]
if (a === '-h' || a === '--help') {
ctx.console.log(
'usage: expand [-t N] [FILE]...\nConvert tabs to spaces (uniform tab width N, default 8).'
'usage: expand [-t LIST] [FILE]...\n' +
'Convert tabs to spaces. -t takes one width (e.g. 8) or a comma-separated ' +
'increasing tab stop list (e.g. 1,4,8); with multiple stops, later intervals repeat.'
)
return
}
@@ -57,7 +90,7 @@ async function run(ctx, argv) {
}
paths.push(a)
}
const w = parseUniformWidth(tabArg)
const stops = parseTabStops(tabArg)
const b4 = ctx.b4a
function proc(text) {
const lines = text.split('\n')
@@ -65,7 +98,7 @@ async function run(ctx, argv) {
const isLast = li === lines.length - 1
const line = lines[li]
if (isLast && line === '' && lines.length > 1) continue
ctx.console.log(expandLine(line, w))
ctx.console.log(expandLine(line, stops))
}
}
if (!paths.length) {
+2 -2
View File
@@ -62,10 +62,10 @@ const CONF = {
_PC_2_SYMLINKS: '1',
/** Comma-separated `ctx.bareOsSyscall` op names implemented in stock booter. */
BARE_OS_SYSCALL_OPS:
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,pathconf,posixPoll,readFile,readdir,readlink,readv,recv,recvfrom,rename,rmdir,select,send,setsockopt,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile,writev',
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,mq_open,mq_receive,mq_send,pathconf,posixPoll,readFile,readdir,readlink,readv,recv,recvfrom,recvmsg,rename,rmdir,select,send,sendmsg,setsockopt,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile,writev',
/** POSIX.1 XSH-style names documented in `/proc/bare_os/syscalls.json` opsDetail (socket family are syscall probes returning ENOSYS-shaped results). */
BARE_OS_POSIX_XSH_OPS:
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,shutdown',
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown',
/** Encodings accepted by `/bin/iconv` (subset; case-insensitive names). */
BARE_OS_ICONV_ENCODINGS: 'UTF-8,ISO-8859-1,UTF-16LE,UTF-16BE',
/** Synthetic process table JSON path (logical VFS). */
@@ -0,0 +1,59 @@
/**
* expand -t comma-separated tab stops
*/
import { readFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import test from 'brittle'
import b4a from 'b4a'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
async function loadBin(name) {
const runtime = await readFile(
path.join(__dirname, '../lib/runtime.js'),
'utf8'
)
const body = await readFile(
path.join(__dirname, `../src/${name}.js`),
'utf8'
)
return new AsyncFunction(
'ctx',
'argv',
`${runtime}\n${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
)
}
function createCtx() {
const logs = []
return {
b4a,
exitCode: 0,
vfs: { async stat() { return null } },
console: {
log: (m) => logs.push(String(m)),
error: (m) => logs.push(String(m))
},
_logs: logs
}
}
test('expand -t 1,5 maps two leading tabs to five spaces before text', async (t) => {
const run = await loadBin('expand')
const ctx = createCtx()
ctx.shellStdin = '\t\tfoo'
await run(ctx, ['expand', '-t', '1,5'])
t.is(ctx.exitCode, 0)
t.is(ctx._logs.join('\n'), ' foo')
})
test('expand -t 8 uniform matches single-stop width', async (t) => {
const run = await loadBin('expand')
const ctx = createCtx()
ctx.shellStdin = '\tx'
await run(ctx, ['expand', '-t', '8'])
t.is(ctx._logs.join('\n'), ' x')
})
+1
View File
@@ -5,6 +5,7 @@ Cross-package **version alignment** (ctx API, feature-bits doc, lifecycle schema
## Documentation (rolling)
- **Seed RPC** — [`lib/channel.js`](lib/channel.js) rejects unknown **`bare_os.*`** method short names against **`BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET`** (**`bare_os.rpc_unknown_method`**); boot policy / env may add **`denySeedRpcMethods`** denials on the booter path. See [`docs/architecture/KERNEL_CONTRACT.md`](../../docs/architecture/KERNEL_CONTRACT.md).
- **Stock hrpc routes** — Documented in **`KERNEL_CONTRACT`**: **`kernel.ping`**, **`kernel.capabilities`**, **`vfs.readText`**, **`bare_os.echo`**, **`bare_os.disk_os_hints`** (validated **`service` / `method` / `payload`**; optional **`BARE_OS_HRPC_ALLOWLIST_JSON`**).
## 0.9.0
@@ -4,7 +4,7 @@
*/
/** Semver for the documented POSIX-like surface (handbook ch.9 + environment appendix). */
export const BARE_OS_POSIX_PROFILE_VERSION = '1.0.8'
export const BARE_OS_POSIX_PROFILE_VERSION = '1.0.9'
/** Short identifier for telemetry and `/proc` mirrors. */
export const BARE_OS_POSIX_PROFILE_ID = 'bare-os-posix-like'
+43 -10
View File
@@ -87,22 +87,53 @@ function bareOsEmitRaw(ctx, chunk) {
return false
}
function parseUniformWidth(tabArg) {
const n = parseInt(String(tabArg).split(',')[0].trim(), 10)
return Number.isFinite(n) && n > 0 ? n : 8
/**
* @param {string} tabArg
* @returns {number[]}
*/
function parseTabStops(tabArg) {
const raw = String(tabArg || '').trim()
if (!raw) return [8]
const parts = raw.split(',')
/** @type {number[]} */
const out = []
for (const p of parts) {
const n = parseInt(p.trim(), 10)
if (Number.isFinite(n) && n > 0) out.push(n)
}
if (!out.length) return [8]
out.sort((a, b) => a - b)
/** @type {number[]} */
const uniq = []
for (const x of out) {
if (uniq.length === 0 || uniq[uniq.length - 1] !== x) uniq.push(x)
}
return uniq
}
function nextTabCol(col, w) {
return (Math.floor(col / w) + 1) * w
function nextTabStop(col, stops) {
if (stops.length === 1) {
const w = stops[0]
return (Math.floor(col / w) + 1) * w
}
for (const s of stops) {
if (s > col) return s
}
const last = stops[stops.length - 1]
const prev = stops[stops.length - 2]
const step = Math.max(1, last - prev)
let x = last
while (x <= col) x += step
return x
}
function expandLine(line, w) {
function expandLine(line, stops) {
let col = 0
let out = ''
for (let i = 0; i < line.length; i++) {
const ch = line[i]
if (ch === '\t') {
const target = nextTabCol(col, w)
const target = nextTabStop(col, stops)
while (col < target) {
out += ' '
col++
@@ -123,7 +154,9 @@ async function run(ctx, argv) {
const a = argv[i]
if (a === '-h' || a === '--help') {
ctx.console.log(
'usage: expand [-t N] [FILE]...\nConvert tabs to spaces (uniform tab width N, default 8).'
'usage: expand [-t LIST] [FILE]...\n' +
'Convert tabs to spaces. -t takes one width (e.g. 8) or a comma-separated ' +
'increasing tab stop list (e.g. 1,4,8); with multiple stops, later intervals repeat.'
)
return
}
@@ -146,7 +179,7 @@ async function run(ctx, argv) {
}
paths.push(a)
}
const w = parseUniformWidth(tabArg)
const stops = parseTabStops(tabArg)
const b4 = ctx.b4a
function proc(text) {
const lines = text.split('\n')
@@ -154,7 +187,7 @@ async function run(ctx, argv) {
const isLast = li === lines.length - 1
const line = lines[li]
if (isLast && line === '' && lines.length > 1) continue
ctx.console.log(expandLine(line, w))
ctx.console.log(expandLine(line, stops))
}
}
if (!paths.length) {
+2 -2
View File
@@ -151,10 +151,10 @@ const CONF = {
_PC_2_SYMLINKS: '1',
/** Comma-separated `ctx.bareOsSyscall` op names implemented in stock booter. */
BARE_OS_SYSCALL_OPS:
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,pathconf,posixPoll,readFile,readdir,readlink,readv,recv,recvfrom,rename,rmdir,select,send,setsockopt,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile,writev',
'accept,access,bind,chdir,chmod,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,mq_open,mq_receive,mq_send,pathconf,posixPoll,readFile,readdir,readlink,readv,recv,recvfrom,recvmsg,rename,rmdir,select,send,sendmsg,setsockopt,shutdown,socket,stat,symlink,truncate,umask,umount,unlink,utimes,writeFile,writev',
/** POSIX.1 XSH-style names documented in `/proc/bare_os/syscalls.json` opsDetail (socket family are syscall probes returning ENOSYS-shaped results). */
BARE_OS_POSIX_XSH_OPS:
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,shutdown',
'open,close,read,write,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown',
/** Encodings accepted by `/bin/iconv` (subset; case-insensitive names). */
BARE_OS_ICONV_ENCODINGS: 'UTF-8,ISO-8859-1,UTF-16LE,UTF-16BE',
/** Synthetic process table JSON path (logical VFS). */
@@ -1,9 +1,9 @@
{
"schemaVersion": 7,
"ctxApiVersion": "1.42.0",
"schemaVersion": 8,
"ctxApiVersion": "1.44.0",
"posixProfile": {
"id": "bare-os-posix-like",
"version": "1.0.8"
"version": "1.0.9"
},
"ops": ["readFile", "writeFile", "socket"],
"opsDetail": [
@@ -28,34 +28,26 @@
],
"posixXsh": {
"schema": 2,
"note": "POSIX.1 XSH-style names; socket bridge may implement SOCK_DGRAM recv/recvfrom when BARE_OS_POSIX_SOCKET_FD_BRIDGE.",
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,shutdown"
"note": "POSIX.1 XSH-style names; socket bridge may implement SOCK_DGRAM sendmsg/recvmsg when BARE_OS_POSIX_SOCKET_FD_BRIDGE.",
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
},
"socketMsgSurface": {
"schema": 1,
"sendmsg": { "defaultErrno": "ENOTSUP" },
"recvmsg": { "defaultErrno": "ENOTSUP" }
"schema": 2,
"sendmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" },
"recvmsg": { "bridgePartial": true, "defaultErrno": "ENOTSUP" }
},
"errnoHints": {
"ENOENT": 2,
"EACCES": 13,
"ENOSYS": 38
"EAGAIN": 11
},
"fdModel": {
"schema": 1,
"note": "Integer FDs index logical VFS/IPC targets in the guest.",
"stdio": [0, 1, 2],
"register": "ctx.bareOsRegisterLogicalFd",
"processTablePath": "/proc/bare_os/process_table.json",
"processTableSchema": 7
},
"signalModel": {
"schema": 1,
"note": "ctx.bareOsSendSignal delivers to synthetic pids.",
"names": ["HUP", "INT", "KILL", "TERM"]
},
"caps": {
"note": "example"
"names": ["INT", "TERM"]
},
"atMs": 0
}
@@ -1,18 +1,18 @@
{
"version": 1,
"bundles": [
{
"path": "/lib/bare/bundles/safetyCatch.js",
"keys": [
"safetyCatch"
]
},
{
"path": "/lib/bare/bundles/hypercoreIdEncoding.js",
"keys": [
"hypercoreIdEncoding"
]
},
{
"path": "/lib/bare/bundles/safetyCatch.js",
"keys": [
"safetyCatch"
]
},
{
"path": "/lib/bare/bundles/b4a.js",
"keys": [
@@ -37,18 +37,18 @@
"protomux"
]
},
{
"path": "/lib/bare/bundles/bareEncoding.js",
"keys": [
"bareEncoding"
]
},
{
"path": "/lib/bare/bundles/barePath.js",
"keys": [
"barePath"
]
},
{
"path": "/lib/bare/bundles/bareEncoding.js",
"keys": [
"bareEncoding"
]
},
{
"path": "/lib/bare/bundles/bareEvents.js",
"keys": [
@@ -67,24 +67,12 @@
"bareAbortController"
]
},
{
"path": "/lib/bare/bundles/bareReadline.js",
"keys": [
"bareReadline"
]
},
{
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"keys": [
"bareAnsiEscapes"
]
},
{
"path": "/lib/bare/bundles/bareCrypto.js",
"keys": [
"bareCrypto"
]
},
{
"path": "/lib/bare/bundles/bareAddonResolve.js",
"keys": [
@@ -92,27 +80,15 @@
]
},
{
"path": "/lib/bare/bundles/fetch.js",
"path": "/lib/bare/bundles/bareCrypto.js",
"keys": [
"fetch"
"bareCrypto"
]
},
{
"path": "/lib/bare/bundles/bareAssert.js",
"path": "/lib/bare/bundles/bareReadline.js",
"keys": [
"bareAssert"
]
},
{
"path": "/lib/bare/bundles/bareAppKit.js",
"keys": [
"bareAppKit"
]
},
{
"path": "/lib/bare/bundles/bareAtomics.js",
"keys": [
"bareAtomics"
"bareReadline"
]
},
{
@@ -127,12 +103,36 @@
"bareAsyncHooks"
]
},
{
"path": "/lib/bare/bundles/bareAtomics.js",
"keys": [
"bareAtomics"
]
},
{
"path": "/lib/bare/bundles/bareAppKit.js",
"keys": [
"bareAppKit"
]
},
{
"path": "/lib/bare/bundles/bareAssert.js",
"keys": [
"bareAssert"
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"keys": [
"bareBmp"
]
},
{
"path": "/lib/bare/bundles/fetch.js",
"keys": [
"fetch"
]
},
{
"path": "/lib/bare/bundles/bareBundleCompile.js",
"keys": [
@@ -140,9 +140,9 @@
]
},
{
"path": "/lib/bare/bundles/bareBuffer.js",
"path": "/lib/bare/bundles/bareBluetoothApple.js",
"keys": [
"bareBuffer"
"bareBluetoothApple"
]
},
{
@@ -152,9 +152,9 @@
]
},
{
"path": "/lib/bare/bundles/bareBluetoothApple.js",
"path": "/lib/bare/bundles/bareBuffer.js",
"keys": [
"bareBluetoothApple"
"bareBuffer"
]
},
{
@@ -163,6 +163,12 @@
"bareBundleEvaluate"
]
},
{
"path": "/lib/bare/bundles/bareBoot.js",
"keys": [
"bareBoot"
]
},
{
"path": "/lib/bare/bundles/bareConsole.js",
"keys": [
@@ -176,15 +182,9 @@
]
},
{
"path": "/lib/bare/bundles/bareBoot.js",
"path": "/lib/bare/bundles/bareChannel.js",
"keys": [
"bareBoot"
]
},
{
"path": "/lib/bare/bundles/bareDebugLog.js",
"keys": [
"bareDebugLog"
"bareChannel"
]
},
{
@@ -194,9 +194,9 @@
]
},
{
"path": "/lib/bare/bundles/bareChannel.js",
"path": "/lib/bare/bundles/bareDebugLog.js",
"keys": [
"bareChannel"
"bareDebugLog"
]
},
{
@@ -206,9 +206,9 @@
]
},
{
"path": "/lib/bare/bundles/bareCov.js",
"path": "/lib/bare/bundles/bareDiagnosticsChannel.js",
"keys": [
"bareCov"
"bareDiagnosticsChannel"
]
},
{
@@ -217,18 +217,18 @@
"bareDns"
]
},
{
"path": "/lib/bare/bundles/bareDiagnosticsChannel.js",
"keys": [
"bareDiagnosticsChannel"
]
},
{
"path": "/lib/bare/bundles/bareEnv.js",
"keys": [
"bareEnv"
]
},
{
"path": "/lib/bare/bundles/bareDgram.js",
"keys": [
"bareDgram"
]
},
{
"path": "/lib/bare/bundles/bareExif.js",
"keys": [
@@ -236,9 +236,9 @@
]
},
{
"path": "/lib/bare/bundles/bareDgram.js",
"path": "/lib/bare/bundles/bareCov.js",
"keys": [
"bareDgram"
"bareCov"
]
},
{
@@ -253,18 +253,6 @@
"bareFfmpegEncodings"
]
},
{
"path": "/lib/bare/bundles/bareFormData.js",
"keys": [
"bareFormData"
]
},
{
"path": "/lib/bare/bundles/bareFileLogger.js",
"keys": [
"bareFileLogger"
]
},
{
"path": "/lib/bare/bundles/bareFormat.js",
"keys": [
@@ -278,9 +266,15 @@
]
},
{
"path": "/lib/bare/bundles/bareHeif.js",
"path": "/lib/bare/bundles/bareFormData.js",
"keys": [
"bareHeif"
"bareFormData"
]
},
{
"path": "/lib/bare/bundles/bareFileLogger.js",
"keys": [
"bareFileLogger"
]
},
{
@@ -289,6 +283,12 @@
"bareHrtime"
]
},
{
"path": "/lib/bare/bundles/bareHeif.js",
"keys": [
"bareHeif"
]
},
{
"path": "/lib/bare/bundles/bareHttpParser.js",
"keys": [
@@ -301,6 +301,12 @@
"bareGtk"
]
},
{
"path": "/lib/bare/bundles/bareIco.js",
"keys": [
"bareIco"
]
},
{
"path": "/lib/bare/bundles/bareFs.js",
"keys": [
@@ -308,9 +314,9 @@
]
},
{
"path": "/lib/bare/bundles/bareIco.js",
"path": "/lib/bare/bundles/bareHttp1.js",
"keys": [
"bareIco"
"bareHttp1"
]
},
{
@@ -325,12 +331,6 @@
"bareInspect"
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"keys": [
"bareHttp1"
]
},
{
"path": "/lib/bare/bundles/bareHttps.js",
"keys": [
@@ -343,12 +343,6 @@
"bareJpeg"
]
},
{
"path": "/lib/bare/bundles/bareIntl.js",
"keys": [
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareIpc.js",
"keys": [
@@ -356,21 +350,15 @@
]
},
{
"path": "/lib/bare/bundles/bareLogger.js",
"path": "/lib/bare/bundles/bareIntl.js",
"keys": [
"bareLogger"
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareMake.js",
"path": "/lib/bare/bundles/bareInspector.js",
"keys": [
"bareMake"
]
},
{
"path": "/lib/bare/bundles/bareLink.js",
"keys": [
"bareLink"
"bareInspector"
]
},
{
@@ -380,9 +368,27 @@
]
},
{
"path": "/lib/bare/bundles/bareInspector.js",
"path": "/lib/bare/bundles/bareLogger.js",
"keys": [
"bareInspector"
"bareLogger"
]
},
{
"path": "/lib/bare/bundles/bareLink.js",
"keys": [
"bareLink"
]
},
{
"path": "/lib/bare/bundles/bareMake.js",
"keys": [
"bareMake"
]
},
{
"path": "/lib/bare/bundles/bareModule.js",
"keys": [
"bareModule"
]
},
{
@@ -403,30 +409,24 @@
"bareModuleTraverse"
]
},
{
"path": "/lib/bare/bundles/bareModule.js",
"keys": [
"bareModule"
]
},
{
"path": "/lib/bare/bundles/bareNdk.js",
"keys": [
"bareNdk"
]
},
{
"path": "/lib/bare/bundles/bareNodeFetch.js",
"keys": [
"bareNodeFetch"
]
},
{
"path": "/lib/bare/bundles/bareNative.js",
"keys": [
"bareNative"
]
},
{
"path": "/lib/bare/bundles/bareNodeFetch.js",
"keys": [
"bareNodeFetch"
]
},
{
"path": "/lib/bare/bundles/bareOpen.js",
"keys": [
@@ -439,12 +439,6 @@
"bareNet"
]
},
{
"path": "/lib/bare/bundles/bareOs.js",
"keys": [
"bareOs"
]
},
{
"path": "/lib/bare/bundles/bareMedia.js",
"keys": [
@@ -452,9 +446,9 @@
]
},
{
"path": "/lib/bare/bundles/barePipe.js",
"path": "/lib/bare/bundles/bareOs.js",
"keys": [
"barePipe"
"bareOs"
]
},
{
@@ -464,15 +458,15 @@
]
},
{
"path": "/lib/bare/bundles/barePack.js",
"path": "/lib/bare/bundles/barePackDrive.js",
"keys": [
"barePack"
"barePackDrive"
]
},
{
"path": "/lib/bare/bundles/bareDev.js",
"path": "/lib/bare/bundles/barePack.js",
"keys": [
"bareDev"
"barePack"
]
},
{
@@ -482,21 +476,9 @@
]
},
{
"path": "/lib/bare/bundles/barePackDrive.js",
"path": "/lib/bare/bundles/barePipe.js",
"keys": [
"barePackDrive"
]
},
{
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"keys": [
"bareNodeRuntime"
]
},
{
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"keys": [
"bareQueueMicrotask"
"barePipe"
]
},
{
@@ -506,9 +488,15 @@
]
},
{
"path": "/lib/bare/bundles/bareQuerystring.js",
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"keys": [
"bareQuerystring"
"bareNodeRuntime"
]
},
{
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareDev"
]
},
{
@@ -517,6 +505,12 @@
"barePrebuild"
]
},
{
"path": "/lib/bare/bundles/bareQuerystring.js",
"keys": [
"bareQuerystring"
]
},
{
"path": "/lib/bare/bundles/bareRealm.js",
"keys": [
@@ -530,9 +524,9 @@
]
},
{
"path": "/lib/bare/bundles/bareRuntime.js",
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"keys": [
"bareRuntime"
"bareQueueMicrotask"
]
},
{
@@ -548,15 +542,15 @@
]
},
{
"path": "/lib/bare/bundles/bareSemver.js",
"path": "/lib/bare/bundles/bareRuntime.js",
"keys": [
"bareSemver"
"bareRuntime"
]
},
{
"path": "/lib/bare/bundles/bareRun.js",
"path": "/lib/bare/bundles/bareSemver.js",
"keys": [
"bareRun"
"bareSemver"
]
},
{
@@ -571,6 +565,12 @@
"bareRepl"
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"keys": [
"bareSidecar"
]
},
{
"path": "/lib/bare/bundles/bareSignals.js",
"keys": [
@@ -578,9 +578,9 @@
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"path": "/lib/bare/bundles/bareRun.js",
"keys": [
"bareSidecar"
"bareRun"
]
},
{
@@ -589,18 +589,18 @@
"bareStringDecoder"
]
},
{
"path": "/lib/bare/bundles/bareStream.js",
"keys": [
"bareStream"
]
},
{
"path": "/lib/bare/bundles/bareStorage.js",
"keys": [
"bareStorage"
]
},
{
"path": "/lib/bare/bundles/bareStream.js",
"keys": [
"bareStream"
]
},
{
"path": "/lib/bare/bundles/bareStdio.js",
"keys": [
@@ -625,6 +625,12 @@
"bareSystemLogger"
]
},
{
"path": "/lib/bare/bundles/bareTap.js",
"keys": [
"bareTap"
]
},
{
"path": "/lib/bare/bundles/bareTiff.js",
"keys": [
@@ -638,9 +644,9 @@
]
},
{
"path": "/lib/bare/bundles/bareTap.js",
"path": "/lib/bare/bundles/bareTcp.js",
"keys": [
"bareTap"
"bareTcp"
]
},
{
@@ -649,12 +655,6 @@
"bareThread"
]
},
{
"path": "/lib/bare/bundles/bareTpl.js",
"keys": [
"bareTpl"
]
},
{
"path": "/lib/bare/bundles/bareTimers.js",
"keys": [
@@ -662,9 +662,9 @@
]
},
{
"path": "/lib/bare/bundles/bareTcp.js",
"path": "/lib/bare/bundles/bareTpl.js",
"keys": [
"bareTcp"
"bareTpl"
]
},
{
@@ -674,9 +674,9 @@
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"path": "/lib/bare/bundles/bareTls.js",
"keys": [
"bareTty"
"bareTls"
]
},
{
@@ -686,15 +686,9 @@
]
},
{
"path": "/lib/bare/bundles/bareUnpack.js",
"path": "/lib/bare/bundles/bareTty.js",
"keys": [
"bareUnpack"
]
},
{
"path": "/lib/bare/bundles/bareTls.js",
"keys": [
"bareTls"
"bareTty"
]
},
{
@@ -704,15 +698,9 @@
]
},
{
"path": "/lib/bare/bundles/bareWalkHandles.js",
"path": "/lib/bare/bundles/bareUnpack.js",
"keys": [
"bareWalkHandles"
]
},
{
"path": "/lib/bare/bundles/bareVm.js",
"keys": [
"bareVm"
"bareUnpack"
]
},
{
@@ -721,6 +709,12 @@
"bareUnionBundle"
]
},
{
"path": "/lib/bare/bundles/bareWalkHandles.js",
"keys": [
"bareWalkHandles"
]
},
{
"path": "/lib/bare/bundles/bareWebKit.js",
"keys": [
@@ -728,15 +722,9 @@
]
},
{
"path": "/lib/bare/bundles/bareWebp.js",
"path": "/lib/bare/bundles/bareVm.js",
"keys": [
"bareWebp"
]
},
{
"path": "/lib/bare/bundles/bareWebKitGtk.js",
"keys": [
"bareWebKitGtk"
"bareVm"
]
},
{
@@ -746,9 +734,15 @@
]
},
{
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"path": "/lib/bare/bundles/bareWebKitGtk.js",
"keys": [
"bareV8ToIstanbul"
"bareWebKitGtk"
]
},
{
"path": "/lib/bare/bundles/bareWebp.js",
"keys": [
"bareWebp"
]
},
{
@@ -757,12 +751,6 @@
"bareWhich"
]
},
{
"path": "/lib/bare/bundles/bareXdiff.js",
"keys": [
"bareXdiff"
]
},
{
"path": "/lib/bare/bundles/bareWinUi.js",
"keys": [
@@ -770,15 +758,21 @@
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"keys": [
"bareZlib"
"bareV8ToIstanbul"
]
},
{
"path": "/lib/bare/bundles/bareWs.js",
"path": "/lib/bare/bundles/bareXdiff.js",
"keys": [
"bareWs"
"bareXdiff"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"keys": [
"bareZlib"
]
},
{
@@ -792,6 +786,12 @@
"keys": [
"bareWorker"
]
},
{
"path": "/lib/bare/bundles/bareWs.js",
"keys": [
"bareWs"
]
}
],
"bundleStats": {
@@ -1595,8 +1595,8 @@
],
"bundleProvenance": {
"schemaVersion": 1,
"generatedAt": "2026-04-05T04:44:22.123Z",
"gitCommit": "0d732bd41b18be65434f47d5e97d19f7080bcb62",
"generatedAt": "2026-04-05T05:06:01.462Z",
"gitCommit": "f79db043130bdbfffa8bcca66fd6252c9d17205d",
"nodeVersion": "v22.22.0",
"bundleTier": "all",
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
@@ -1,6 +1,6 @@
{
"schema": 1,
"atMs": 1775364261427,
"atMs": 1775365560517,
"commands": [
"arch",
"awk",
File diff suppressed because one or more lines are too long