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:
@@ -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-address–style) 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
@@ -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-address–style 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'))
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
@@ -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'
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user