chore(booter): complete P2P/POSIX roadmap — ctx 1.48, VFS, shell, docs
- Bump bareOsCtxApiVersion to 1.48.0; sync CHANGELOG, compatibility matrix, syscalls.example.json, ctx d.ts, generated ctx-client helper - POSIX: getconf _SC_NPROCESSORS_ONLN; shell set -o pipefail + BARE_OS_PIPESTATUS; posix_utilities schema v2 + JSON Schema; generated dashboard refresh - Host/subprocess: bare-subprocess then Node child_process spawn; optional backend on ctx.bareOsTrySpawnHostSubprocess; bin-worker WASM wall budget - VFS: BARE_OS_VFS_SYSTEM_IMAGE_WRITE for system image writes + warm-cache eviction path; guest /.bare/account EACCES test; environ TOKEN redaction test - Docs: corestore snapshot non-goal in package-bare-os-booter; PEAR-RUN links → docs/PEAR-RUN.md; POSIX pretest matrix in scripts/README + dev guide; environment appendix (PIPESTATUS, WASM_MS, system image write) - Seeder: keep kernel/ mirror in sync after bundle + coreutils builds Verified: npm test -w bare-os-booter, npm run pretest
This commit is contained in:
@@ -2576,6 +2576,49 @@ async function verifyKernelExtSignerPinsForScript(
|
||||
return !strictPol
|
||||
}
|
||||
|
||||
/**
|
||||
* Append one NDJSON line to `/run/bare-os/kernel-ext-audit.ndjson` (strict boot diagnostics).
|
||||
* @param {Record<string, unknown>} ctx
|
||||
* @param {Record<string, unknown>} row
|
||||
*/
|
||||
async function appendKernelExtAuditNdjson(ctx, row) {
|
||||
if (
|
||||
!ctx.vfs ||
|
||||
typeof ctx.vfs.readFile !== 'function' ||
|
||||
typeof ctx.vfs.writeFile !== 'function' ||
|
||||
!ctx.b4a
|
||||
) {
|
||||
return
|
||||
}
|
||||
const line =
|
||||
JSON.stringify({
|
||||
schema: 1,
|
||||
type: 'kernelExtAudit',
|
||||
atMs: Date.now(),
|
||||
sessionId: String((ctx.env && ctx.env.BARE_OS_SESSION_ID) || ''),
|
||||
...row
|
||||
}) + '\n'
|
||||
try {
|
||||
let prev = ''
|
||||
try {
|
||||
prev = ctx.b4a.toString(
|
||||
await ctx.vfs.readFile('/run/bare-os/kernel-ext-audit.ndjson')
|
||||
)
|
||||
} catch {
|
||||
/* absent */
|
||||
}
|
||||
const maxBytes = 96 * 1024
|
||||
let next = prev + line
|
||||
if (next.length > maxBytes) next = next.slice(-maxBytes)
|
||||
await ctx.vfs.writeFile(
|
||||
'/run/bare-os/kernel-ext-audit.ndjson',
|
||||
ctx.b4a.from(next)
|
||||
)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional `/etc/bare-os/kernel.ext.d/*.json` with `{ "scripts": ["/lib/bare-os/extensions/foo.js"] }`.
|
||||
* @param {Record<string, unknown>} ctx
|
||||
@@ -2696,6 +2739,11 @@ async function runKernelExtDropins(ctx, opts = {}) {
|
||||
'kernelExt.denyId',
|
||||
`[kernel.ext.d] denied by policy id: ${extId}`
|
||||
)
|
||||
await appendKernelExtAuditNdjson(ctx, {
|
||||
event: 'deny_id',
|
||||
extId,
|
||||
dropin: name
|
||||
})
|
||||
continue
|
||||
}
|
||||
const scripts = pol.scripts
|
||||
@@ -2786,7 +2834,14 @@ async function runKernelExtDropins(ctx, opts = {}) {
|
||||
'kernelExt.conflict',
|
||||
`[kernel.ext.d] conflict: extension "${e.extId}" conflictsWith "${c}"`
|
||||
)
|
||||
if (strictPol) return false
|
||||
if (strictPol) {
|
||||
await appendKernelExtAuditNdjson(ctx, {
|
||||
event: 'conflict',
|
||||
extId: e.extId,
|
||||
conflictsWith: c
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2813,7 +2868,13 @@ async function runKernelExtDropins(ctx, opts = {}) {
|
||||
'[kernel.ext.d] dependency cycle in extension drop-ins; ext ids: ' +
|
||||
topo.cycleExtIds.join(', ')
|
||||
)
|
||||
if (strictPol) return false
|
||||
if (strictPol) {
|
||||
await appendKernelExtAuditNdjson(ctx, {
|
||||
event: 'dependency_cycle',
|
||||
cycleExtIds: [...topo.cycleExtIds].sort()
|
||||
})
|
||||
return false
|
||||
}
|
||||
ordered = [...collected].sort((a, b) => a.file.localeCompare(b.file))
|
||||
} else {
|
||||
ordered = topo.ordered
|
||||
@@ -3274,9 +3335,12 @@ async function maybeWriteBootPerfJson(ctx, bootT0, stageLog) {
|
||||
: undefined
|
||||
let schema = stages ? 2 : 1
|
||||
if (stdlibWall != null || stdlibBudget != null) schema = Math.max(schema, 3)
|
||||
schema = Math.max(schema, 4)
|
||||
const row =
|
||||
JSON.stringify({
|
||||
schema,
|
||||
bootGraphJsonPath: '/proc/bare_os/boot_graph.json',
|
||||
stageLogSnapshot: [...stageLog],
|
||||
coldWallMs: wall,
|
||||
bootBudgetMsCold: budget,
|
||||
withinBudget: budget == null ? null : wall <= budget,
|
||||
@@ -3492,7 +3556,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('rc.profile(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
if (!shouldSkipBootStage(ctx, 'rc')) {
|
||||
await bootTimed(
|
||||
ctx,
|
||||
@@ -3505,7 +3572,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('rc(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
if (!shouldSkipBootStage(ctx, 'rc.d')) {
|
||||
await bootTimed(
|
||||
ctx,
|
||||
@@ -3518,7 +3588,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('rc.d(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
if (!shouldSkipBootStage(ctx, 'rc.local')) {
|
||||
await bootTimed(
|
||||
ctx,
|
||||
@@ -3531,7 +3604,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('rc.local(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
if (!shouldSkipBootStage(ctx, 'kernel.d')) {
|
||||
await bootTimed(
|
||||
ctx,
|
||||
@@ -3544,7 +3620,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('kernel.d(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
if (!shouldSkipBootStage(ctx, 'kernel.ext.d')) {
|
||||
await bootTimed(
|
||||
ctx,
|
||||
@@ -3557,7 +3636,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('kernel.ext.d(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
await bootTimed(
|
||||
ctx,
|
||||
'banner',
|
||||
@@ -3578,7 +3660,10 @@ async function start(ctx) {
|
||||
} else {
|
||||
stageLog.push('onboot(skipped)')
|
||||
}
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
await bootTimed(
|
||||
ctx,
|
||||
'selftest',
|
||||
@@ -3587,7 +3672,10 @@ async function start(ctx) {
|
||||
},
|
||||
stageLog
|
||||
)
|
||||
if (!bootOk) return
|
||||
if (!bootOk) {
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
return
|
||||
}
|
||||
publishBootReady(ctx, stageLog)
|
||||
await maybeWriteBootPerfJson(ctx, bootT0, stageLog)
|
||||
if (kernelExtHotReloadEnabled(ctx)) {
|
||||
|
||||
Reference in New Issue
Block a user