feat: complete 20-track kernel roadmap (P2P ops, POSIX, HRPC, CI, docs)

- Add optional Holepunch clone lag gate (holepunch-freshness-gate.json,
  verify-holepunch-clone-freshness.mjs) and wire into pretest/docs.
- Extend stock ctx.bareOsHrpcRequest with disk.os replication routes;
  bump hrpc_allowlist_sketch proc to schema 2 with stockRoutes list.
- Security posture: blindRelayAudit; hyper_multisig_trust_pointer schema 2
  + vault multisig continuity env; login/unlock audit hook.
- Syscalls schema 9 alignment (JSON schema, compatibility matrix, conformance
  matrix clock_gettime); boot budget telemetry schema 2 in metrics_live.
- Coreutils hostname -s/--short man/options; rebuild kernel bins/man.
- POSIX + P2P dashboard section in docs/README; handbook/DOCUMENTATION/
  release-checklist/OTA/KERNEL_CONTRACT/PEAR-RUN and related reference updates.
- verify-boot-policy-extension-signer-pins: scan kernel init fragments.

Note: vendor drift section removed from kernel/lib/bare/README.md (intentional).
This commit is contained in:
Raven Scott
2026-04-05 14:17:20 -04:00
parent c15e8fa5be
commit 8bde745191
87 changed files with 7385 additions and 6725 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ Files in this directory are **read from disk by the seeder** (or copied into `pa
## Editing workflow
**Do not edit `kernel/init.js` by hand.** It is generated from `kernel/lib/boot/*.js` (sorted) plus `kernel/lib/init/init-main.js` via `npm run bundle:kernel` (`scripts/bundle-kernel-init.mjs`). CI and `npm run verify:init-bundle` fail when the file drifts. Edit the fragments under `lib/boot/` and `lib/init/` only, then bundle and rsync to `packages/bare-os-seeder/kernel/` for Pear parity.
**Do not edit `kernel/init.js` by hand.** It is generated from `kernel/lib/boot/*.js` (sorted), `kernel/lib/init/fragments/*.js` (sorted), and `kernel/lib/init/init-main.js` via `npm run bundle:kernel` (`scripts/bundle-kernel-init.mjs`). CI and `npm run verify:init-bundle` fail when the file drifts. Edit the fragments under `lib/boot/`, `lib/init/fragments/`, and `lib/init/` only, then bundle and rsync to `packages/bare-os-seeder/kernel/` for Pear parity. See `lib/init/STRUCTURE.md`.
1. Change sources under `kernel/` or `packages/bare-os-coreutils/src/`.
2. Run `npm run build -w bare-os-coreutils` to refresh `kernel/bin/*`.
+2 -2
View File
@@ -183,10 +183,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,mq_open,mq_receive,mq_send,nanosleep,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',
'accept,access,bind,chdir,chmod,clock_gettime,connect,exists,fcntl,fdatasync,fsync,ftruncate,getcwd,getsockopt,kill,link,listen,lstat,mkdir,mount,mq_open,mq_receive,mq_send,nanosleep,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,nanosleep,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown',
'open,close,read,write,lseek,nanosleep,clock_gettime,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). */
+13 -1
View File
@@ -88,10 +88,22 @@ function bareOsEmitRaw(ctx, chunk) {
}
async function run(ctx, argv) {
const h =
let h =
globalThis.process?.env?.HOSTNAME ||
globalThis.process?.env?.COMPUTERNAME ||
ctx.vfs.env.HOSTNAME ||
'bare-os'
h = String(h)
let shortOnly = false
for (let i = 1; i < argv.length; i++) {
const a = String(argv[i] || '')
if (a === '-s' || a === '--short') shortOnly = true
else if (a === '-f' || a === '--fqdn') shortOnly = false
else if (a === '--') break
}
if (shortOnly) {
const dot = h.indexOf('.')
if (dot > 0) h = h.slice(0, dot)
}
ctx.console.log(h)
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"schema": 2,
"profileId": "bare-os-posix-like",
"generatedAt": "2026-04-05T17:48:11.632Z",
"generatedAt": "2026-04-05T18:15:46.515Z",
"note": "Sparse POSIX Issue 7 coverage hints for /bin utilities. Omitted command names are not yet profiled here.",
"commandIndex": [
{
+3 -3
View File
@@ -1,9 +1,9 @@
{
"schemaVersion": 8,
"schemaVersion": 9,
"ctxApiVersion": "1.50.0",
"posixProfile": {
"id": "bare-os-posix-like",
"version": "1.0.14"
"version": "1.0.15"
},
"ops": ["readFile", "writeFile", "socket"],
"opsDetail": [
@@ -29,7 +29,7 @@
"posixXsh": {
"schema": 2,
"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,nanosleep,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
"namesCsv": "open,close,read,write,readv,writev,getsockopt,setsockopt,lseek,nanosleep,clock_gettime,pipe,dup,dup2,fcntl,poll,select,umask,socket,bind,listen,accept,connect,send,recv,recvfrom,sendmsg,recvmsg,shutdown"
},
"socketMsgSurface": {
"schema": 4,
+1127 -1097
View File
File diff suppressed because it is too large Load Diff
+212 -212
View File
@@ -38,9 +38,9 @@
]
},
{
"path": "/lib/bare/bundles/bareEvents.js",
"path": "/lib/bare/bundles/bareEncoding.js",
"keys": [
"bareEvents"
"bareEncoding"
]
},
{
@@ -50,15 +50,9 @@
]
},
{
"path": "/lib/bare/bundles/bareEncoding.js",
"path": "/lib/bare/bundles/bareEvents.js",
"keys": [
"bareEncoding"
]
},
{
"path": "/lib/bare/bundles/bareAbort.js",
"keys": [
"bareAbort"
"bareEvents"
]
},
{
@@ -68,15 +62,9 @@
]
},
{
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"path": "/lib/bare/bundles/bareAbort.js",
"keys": [
"bareAnsiEscapes"
]
},
{
"path": "/lib/bare/bundles/bareAddonResolve.js",
"keys": [
"bareAddonResolve"
"bareAbort"
]
},
{
@@ -85,6 +73,12 @@
"bareReadline"
]
},
{
"path": "/lib/bare/bundles/bareAddonResolve.js",
"keys": [
"bareAddonResolve"
]
},
{
"path": "/lib/bare/bundles/bareCrypto.js",
"keys": [
@@ -92,9 +86,9 @@
]
},
{
"path": "/lib/bare/bundles/bareAtomics.js",
"path": "/lib/bare/bundles/bareAnsiEscapes.js",
"keys": [
"bareAtomics"
"bareAnsiEscapes"
]
},
{
@@ -110,15 +104,9 @@
]
},
{
"path": "/lib/bare/bundles/fetch.js",
"path": "/lib/bare/bundles/bareAtomics.js",
"keys": [
"fetch"
]
},
{
"path": "/lib/bare/bundles/bareApk.js",
"keys": [
"bareApk"
"bareAtomics"
]
},
{
@@ -128,15 +116,21 @@
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"path": "/lib/bare/bundles/bareApk.js",
"keys": [
"bareBmp"
"bareApk"
]
},
{
"path": "/lib/bare/bundles/bareBundleCompile.js",
"path": "/lib/bare/bundles/fetch.js",
"keys": [
"bareBundleCompile"
"fetch"
]
},
{
"path": "/lib/bare/bundles/bareBmp.js",
"keys": [
"bareBmp"
]
},
{
@@ -146,15 +140,15 @@
]
},
{
"path": "/lib/bare/bundles/bareBundle.js",
"path": "/lib/bare/bundles/bareBundleCompile.js",
"keys": [
"bareBundle"
"bareBundleCompile"
]
},
{
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
"path": "/lib/bare/bundles/bareBundle.js",
"keys": [
"bareBundleEvaluate"
"bareBundle"
]
},
{
@@ -164,9 +158,9 @@
]
},
{
"path": "/lib/bare/bundles/bareBoot.js",
"path": "/lib/bare/bundles/bareBundleEvaluate.js",
"keys": [
"bareBoot"
"bareBundleEvaluate"
]
},
{
@@ -175,6 +169,12 @@
"bareBundleId"
]
},
{
"path": "/lib/bare/bundles/bareBoot.js",
"keys": [
"bareBoot"
]
},
{
"path": "/lib/bare/bundles/bareConsole.js",
"keys": [
@@ -188,9 +188,9 @@
]
},
{
"path": "/lib/bare/bundles/bareDelta.js",
"path": "/lib/bare/bundles/bareDaemon.js",
"keys": [
"bareDelta"
"bareDaemon"
]
},
{
@@ -200,9 +200,15 @@
]
},
{
"path": "/lib/bare/bundles/bareDaemon.js",
"path": "/lib/bare/bundles/bareDelta.js",
"keys": [
"bareDaemon"
"bareDelta"
]
},
{
"path": "/lib/bare/bundles/bareDiagnosticsChannel.js",
"keys": [
"bareDiagnosticsChannel"
]
},
{
@@ -212,9 +218,9 @@
]
},
{
"path": "/lib/bare/bundles/bareDiagnosticsChannel.js",
"path": "/lib/bare/bundles/bareCov.js",
"keys": [
"bareDiagnosticsChannel"
"bareCov"
]
},
{
@@ -235,12 +241,6 @@
"bareDgram"
]
},
{
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
"keys": [
"bareFfmpegEncodings"
]
},
{
"path": "/lib/bare/bundles/bareFfmpeg.js",
"keys": [
@@ -248,21 +248,15 @@
]
},
{
"path": "/lib/bare/bundles/bareCov.js",
"path": "/lib/bare/bundles/bareFfmpegEncodings.js",
"keys": [
"bareCov"
"bareFfmpegEncodings"
]
},
{
"path": "/lib/bare/bundles/bareGif.js",
"path": "/lib/bare/bundles/bareFormat.js",
"keys": [
"bareGif"
]
},
{
"path": "/lib/bare/bundles/bareFileLogger.js",
"keys": [
"bareFileLogger"
"bareFormat"
]
},
{
@@ -272,9 +266,15 @@
]
},
{
"path": "/lib/bare/bundles/bareFormat.js",
"path": "/lib/bare/bundles/bareFileLogger.js",
"keys": [
"bareFormat"
"bareFileLogger"
]
},
{
"path": "/lib/bare/bundles/bareGif.js",
"keys": [
"bareGif"
]
},
{
@@ -289,12 +289,6 @@
"bareHrtime"
]
},
{
"path": "/lib/bare/bundles/bareFs.js",
"keys": [
"bareFs"
]
},
{
"path": "/lib/bare/bundles/bareHeif.js",
"keys": [
@@ -308,15 +302,9 @@
]
},
{
"path": "/lib/bare/bundles/bareIco.js",
"path": "/lib/bare/bundles/bareFs.js",
"keys": [
"bareIco"
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"keys": [
"bareHttp1"
"bareFs"
]
},
{
@@ -326,9 +314,9 @@
]
},
{
"path": "/lib/bare/bundles/bareHttps.js",
"path": "/lib/bare/bundles/bareIco.js",
"keys": [
"bareHttps"
"bareIco"
]
},
{
@@ -337,6 +325,18 @@
"bareInspect"
]
},
{
"path": "/lib/bare/bundles/bareHttp1.js",
"keys": [
"bareHttp1"
]
},
{
"path": "/lib/bare/bundles/bareHttps.js",
"keys": [
"bareHttps"
]
},
{
"path": "/lib/bare/bundles/bareJpeg.js",
"keys": [
@@ -349,12 +349,6 @@
"bareIntl"
]
},
{
"path": "/lib/bare/bundles/bareLief.js",
"keys": [
"bareLief"
]
},
{
"path": "/lib/bare/bundles/bareIpc.js",
"keys": [
@@ -362,9 +356,9 @@
]
},
{
"path": "/lib/bare/bundles/bareLink.js",
"path": "/lib/bare/bundles/bareLief.js",
"keys": [
"bareLink"
"bareLief"
]
},
{
@@ -380,9 +374,9 @@
]
},
{
"path": "/lib/bare/bundles/bareMake.js",
"path": "/lib/bare/bundles/bareLink.js",
"keys": [
"bareMake"
"bareLink"
]
},
{
@@ -391,12 +385,6 @@
"bareModuleLexer"
]
},
{
"path": "/lib/bare/bundles/bareModule.js",
"keys": [
"bareModule"
]
},
{
"path": "/lib/bare/bundles/bareModuleResolve.js",
"keys": [
@@ -404,15 +392,15 @@
]
},
{
"path": "/lib/bare/bundles/bareModuleTraverse.js",
"path": "/lib/bare/bundles/bareMake.js",
"keys": [
"bareModuleTraverse"
"bareMake"
]
},
{
"path": "/lib/bare/bundles/bareMedia.js",
"path": "/lib/bare/bundles/bareModule.js",
"keys": [
"bareMedia"
"bareModule"
]
},
{
@@ -421,12 +409,6 @@
"bareNdk"
]
},
{
"path": "/lib/bare/bundles/bareNodeFetch.js",
"keys": [
"bareNodeFetch"
]
},
{
"path": "/lib/bare/bundles/bareNative.js",
"keys": [
@@ -434,9 +416,15 @@
]
},
{
"path": "/lib/bare/bundles/bareOpen.js",
"path": "/lib/bare/bundles/bareNodeFetch.js",
"keys": [
"bareOpen"
"bareNodeFetch"
]
},
{
"path": "/lib/bare/bundles/bareModuleTraverse.js",
"keys": [
"bareModuleTraverse"
]
},
{
@@ -445,12 +433,42 @@
"bareNet"
]
},
{
"path": "/lib/bare/bundles/bareMedia.js",
"keys": [
"bareMedia"
]
},
{
"path": "/lib/bare/bundles/bareOs.js",
"keys": [
"bareOs"
]
},
{
"path": "/lib/bare/bundles/bareOpen.js",
"keys": [
"bareOpen"
]
},
{
"path": "/lib/bare/bundles/barePerformance.js",
"keys": [
"barePerformance"
]
},
{
"path": "/lib/bare/bundles/barePipe.js",
"keys": [
"barePipe"
]
},
{
"path": "/lib/bare/bundles/barePng.js",
"keys": [
"barePng"
]
},
{
"path": "/lib/bare/bundles/barePack.js",
"keys": [
@@ -464,33 +482,9 @@
]
},
{
"path": "/lib/bare/bundles/barePerformance.js",
"path": "/lib/bare/bundles/barePrebuild.js",
"keys": [
"barePerformance"
]
},
{
"path": "/lib/bare/bundles/barePng.js",
"keys": [
"barePng"
]
},
{
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"keys": [
"bareNodeRuntime"
]
},
{
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareDev"
]
},
{
"path": "/lib/bare/bundles/barePipe.js",
"keys": [
"barePipe"
"barePrebuild"
]
},
{
@@ -506,15 +500,9 @@
]
},
{
"path": "/lib/bare/bundles/barePrebuild.js",
"path": "/lib/bare/bundles/bareProcess.js",
"keys": [
"barePrebuild"
]
},
{
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"keys": [
"bareQueueMicrotask"
"bareProcess"
]
},
{
@@ -524,21 +512,9 @@
]
},
{
"path": "/lib/bare/bundles/bareProcess.js",
"path": "/lib/bare/bundles/bareQueueMicrotask.js",
"keys": [
"bareProcess"
]
},
{
"path": "/lib/bare/bundles/bareRuntime.js",
"keys": [
"bareRuntime"
]
},
{
"path": "/lib/bare/bundles/bareRpc.js",
"keys": [
"bareRpc"
"bareQueueMicrotask"
]
},
{
@@ -548,21 +524,27 @@
]
},
{
"path": "/lib/bare/bundles/bareSdl.js",
"path": "/lib/bare/bundles/bareNodeRuntime.js",
"keys": [
"bareSdl"
"bareNodeRuntime"
]
},
{
"path": "/lib/bare/bundles/bareRepl.js",
"path": "/lib/bare/bundles/bareDev.js",
"keys": [
"bareRepl"
"bareDev"
]
},
{
"path": "/lib/bare/bundles/bareSemver.js",
"path": "/lib/bare/bundles/bareRpc.js",
"keys": [
"bareSemver"
"bareRpc"
]
},
{
"path": "/lib/bare/bundles/bareRuntime.js",
"keys": [
"bareRuntime"
]
},
{
@@ -572,9 +554,21 @@
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"path": "/lib/bare/bundles/bareRepl.js",
"keys": [
"bareSidecar"
"bareRepl"
]
},
{
"path": "/lib/bare/bundles/bareSdl.js",
"keys": [
"bareSdl"
]
},
{
"path": "/lib/bare/bundles/bareSemver.js",
"keys": [
"bareSemver"
]
},
{
@@ -583,24 +577,30 @@
"bareSignals"
]
},
{
"path": "/lib/bare/bundles/bareSidecar.js",
"keys": [
"bareSidecar"
]
},
{
"path": "/lib/bare/bundles/bareStringDecoder.js",
"keys": [
"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/bareSvg.js",
"keys": [
@@ -613,6 +613,12 @@
"bareStdio"
]
},
{
"path": "/lib/bare/bundles/bareSystemLogger.js",
"keys": [
"bareSystemLogger"
]
},
{
"path": "/lib/bare/bundles/bareStructuredClone.js",
"keys": [
@@ -620,9 +626,9 @@
]
},
{
"path": "/lib/bare/bundles/bareTiff.js",
"path": "/lib/bare/bundles/bareTcp.js",
"keys": [
"bareTiff"
"bareTcp"
]
},
{
@@ -631,12 +637,6 @@
"bareSubprocess"
]
},
{
"path": "/lib/bare/bundles/bareSystemLogger.js",
"keys": [
"bareSystemLogger"
]
},
{
"path": "/lib/bare/bundles/bareTap.js",
"keys": [
@@ -644,15 +644,15 @@
]
},
{
"path": "/lib/bare/bundles/bareThread.js",
"path": "/lib/bare/bundles/bareTiff.js",
"keys": [
"bareThread"
"bareTiff"
]
},
{
"path": "/lib/bare/bundles/bareTcp.js",
"path": "/lib/bare/bundles/bareThread.js",
"keys": [
"bareTcp"
"bareThread"
]
},
{
@@ -673,12 +673,6 @@
"bareType"
]
},
{
"path": "/lib/bare/bundles/bareUiKit.js",
"keys": [
"bareUiKit"
]
},
{
"path": "/lib/bare/bundles/bareTls.js",
"keys": [
@@ -686,9 +680,9 @@
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"path": "/lib/bare/bundles/bareUiKit.js",
"keys": [
"bareTty"
"bareUiKit"
]
},
{
@@ -697,6 +691,12 @@
"bareUnpack"
]
},
{
"path": "/lib/bare/bundles/bareTty.js",
"keys": [
"bareTty"
]
},
{
"path": "/lib/bare/bundles/bareV8.js",
"keys": [
@@ -721,12 +721,6 @@
"bareWalkHandles"
]
},
{
"path": "/lib/bare/bundles/bareWebKitGtk.js",
"keys": [
"bareWebKitGtk"
]
},
{
"path": "/lib/bare/bundles/bareUnionBundle.js",
"keys": [
@@ -739,6 +733,12 @@
"bareUtils"
]
},
{
"path": "/lib/bare/bundles/bareWebKitGtk.js",
"keys": [
"bareWebKitGtk"
]
},
{
"path": "/lib/bare/bundles/bareWebp.js",
"keys": [
@@ -751,6 +751,12 @@
"bareWhich"
]
},
{
"path": "/lib/bare/bundles/bareWinUi.js",
"keys": [
"bareWinUi"
]
},
{
"path": "/lib/bare/bundles/bareV8ToIstanbul.js",
"keys": [
@@ -764,21 +770,9 @@
]
},
{
"path": "/lib/bare/bundles/bareWinUi.js",
"path": "/lib/bare/bundles/bareWs.js",
"keys": [
"bareWinUi"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"keys": [
"bareZlib"
]
},
{
"path": "/lib/bare/bundles/bareWorker.js",
"keys": [
"bareWorker"
"bareWs"
]
},
{
@@ -788,9 +782,15 @@
]
},
{
"path": "/lib/bare/bundles/bareWs.js",
"path": "/lib/bare/bundles/bareWorker.js",
"keys": [
"bareWs"
"bareWorker"
]
},
{
"path": "/lib/bare/bundles/bareZlib.js",
"keys": [
"bareZlib"
]
}
],
@@ -1595,8 +1595,8 @@
],
"bundleProvenance": {
"schemaVersion": 1,
"generatedAt": "2026-04-05T17:48:12.581Z",
"gitCommit": "551d68ac6cdb72c4a51c0cac56e882cdb53fb900",
"generatedAt": "2026-04-05T18:15:47.509Z",
"gitCommit": "c15e8fa5be4e6d014a383cff12024e5525e11bbd",
"nodeVersion": "v22.22.0",
"bundleTier": "all",
"normativeManifest": "packages/bare-os-booter/lib/bare-module-manifest.json",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schema": 1,
"atMs": 1775411291632,
"atMs": 1775412946515,
"commands": [
"arch",
"awk",
+1 -1
View File
@@ -1,7 +1,7 @@
/**
* Boot preamble: cooperative lock FSM constants + `invokeCtxBootHooks`.
* This file is the **only** source for these symbols; `kernel/init.js` is generated by
* `node scripts/bundle-kernel-init.mjs` (concat `lib/boot/*.js` in sorted order, then `lib/init/init-main.js`).
* `node scripts/bundle-kernel-init.mjs` (concat `lib/boot/*.js`, `lib/init/fragments/*.js`, then `lib/init/init-main.js`).
* CI: `scripts/verify-init-bundle-recipe.mjs` / `verify-kernel-seeder-parity.mjs`.
*/
/** Boot transaction journal row state (resume / audit / rollback FSM). */
+17 -9
View File
@@ -1,13 +1,21 @@
# Stock kernel internal layout (`/boot/init.js`)
The shipped kernel is a **single** Hyperdrive file evaluated with `AsyncFunction` (see `packages/bare-os-booter/lib/kernel-runner.js`). The editable bulk of that script lives in **`init-main.js`** in this directory (staged on the image as **`/lib/init/init-main.js`**); `scripts/bundle-kernel-init.mjs` concatenates `kernel/lib/boot/*.js` + **`init-main.js`** → repo-root **`kernel/init.js`** (staged as **`/boot/init.js`**). Logical modules map to regions of `kernel/init.js` for maintenance:
The shipped kernel is a **single** Hyperdrive file evaluated with `AsyncFunction` (see `packages/bare-os-booter/lib/kernel-runner.js`). Sources are concatenated by [`scripts/bundle-kernel-init.mjs`](../../../scripts/bundle-kernel-init.mjs) in this order:
| Concern | Responsibility |
| --- | --- |
| Boot policy & env gates | `applyBootPolicyFile`, skip sets, ABI checks |
| RC runners | `runRcLines`, `kernel.d`, `kernel.ext.d` |
| Extensions | `runKernelExtDropins`, topological ordering |
| Selftest | `kernel.d` / `selftest.d` harness |
| Interactive loop | readline / REPL after boot stages |
1. **`kernel/lib/boot/*.js`** (sorted) — preamble (`BARE_OS_BOOT_TXN_STATE`, multisig shape, `invokeCtxBootHooks`).
2. **`kernel/lib/init/fragments/*.js`** (sorted) — large cohesive regions:
- **`20-init-boot-policy.js`** — semver helpers, skip merge, `kernel.d` env guards, **`applyBootPolicyFile`**.
- **`30-init-kernel-extensions.js`** — **`runKernelExtDropins`**, topological ordering, signer pins, multisig gate.
3. **`kernel/lib/init/init-main.js`** — boot trace/journals, RC runners, selftest, **`start(ctx)`**, REPL.
Future work may **concatenate** split sources into one deliverable; until then, keep this map updated when moving large blocks.
Staged paths: **`/lib/init/init-main.js`**, **`/lib/init/fragments/*`**, and bundled **`/boot/init.js`**.
| Concern | Responsibility | Primary source |
| --- | --- | --- |
| Boot policy & env gates | `applyBootPolicyFile`, skip sets, ABI checks | `fragments/20-init-boot-policy.js` |
| RC runners | `runRcLines`, `kernel.d`, `rc.d` | `init-main.js` |
| Extensions | `runKernelExtDropins`, topological ordering | `fragments/30-init-kernel-extensions.js` |
| Selftest | `kernel.d` / `selftest.d` harness | `init-main.js` |
| Interactive loop | readline / REPL after boot stages | `init-main.js` |
After editing any fragment or `init-main.js`, run `node scripts/bundle-kernel-init.mjs` and sync the seeder tree (`rsync -a --delete kernel/ packages/bare-os-seeder/kernel/`). CI: `verify-init-bundle-recipe.mjs`, `verify-kernel-seeder-parity.mjs`, `verify-runtime-no-incomplete-markers.mjs`.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,684 @@
/**
* Concatenated into /boot/init.js before init-main.js by scripts/bundle-kernel-init.mjs.
* kernel.ext.d: topological sort, signer pins, multisig gate, runKernelExtDropins.
* Depends on: BARE_OS_BOOT_TXN_STATE (boot preamble), bareOsPearMultisigShapeOk (00-pear-multisig-shape),
* semverGte from 20-init-boot-policy.js; bootStructuredLog/bootDryRun from init-main.js (same AsyncFunction body; hoisted).
* @see kernel/lib/init/STRUCTURE.md
*/
/**
* @param {{ file: string, extId: string, scripts: string[], dependsOn: string[], signaturePointer?: string }[]} entries
* @returns {{ ok: true, ordered: typeof entries } | { ok: false, cycleExtIds: string[] }}
*/
function topologicalOrderKernelExtEntries(entries) {
const sorted = [...entries].sort((a, b) => a.file.localeCompare(b.file))
const idToFile = new Map()
for (const e of sorted) {
if (!idToFile.has(e.extId)) idToFile.set(e.extId, e.file)
}
/** @type {Map<string, string[]>} */
const adj = new Map()
/** @type {Map<string, number>} */
const indeg = new Map()
for (const e of sorted) indeg.set(e.file, 0)
for (const e of sorted) {
for (const dep of e.dependsOn) {
const from = idToFile.get(dep)
if (!from || from === e.file) continue
if (!adj.has(from)) adj.set(from, [])
adj.get(from).push(e.file)
indeg.set(e.file, (indeg.get(e.file) || 0) + 1)
}
}
/** @type {string[]} */
const q = sorted
.map((e) => e.file)
.filter((f) => (indeg.get(f) || 0) === 0)
.sort()
/** @type {string[]} */
const out = []
while (q.length) {
const f = q.shift()
out.push(f)
for (const to of adj.get(f) || []) {
indeg.set(to, (indeg.get(to) || 0) - 1)
if (indeg.get(to) === 0) {
q.push(to)
q.sort()
}
}
}
if (out.length !== sorted.length) {
const stuck = sorted.filter((e) => !out.includes(e.file))
return { ok: false, cycleExtIds: stuck.map((e) => e.extId) }
}
const byFile = new Map(sorted.map((e) => [e.file, e]))
return {
ok: true,
ordered: out.map((f) => byFile.get(f)).filter(Boolean)
}
}
/**
* @param {{ extId: string, dependsOn: string[] }[]} entries
* @returns {number}
*/
function kernelExtDependencyDepth(entries) {
const idToEntry = new Map(entries.map((e) => [e.extId, e]))
const memo = new Map()
/**
* @param {string} id
* @param {Set<string>} stack
*/
function depth(id, stack) {
if (memo.has(id)) return memo.get(id)
if (stack.has(id)) return 99
const e = idToEntry.get(id)
if (!e) return 0
stack.add(id)
let d = 0
for (const dep of e.dependsOn) {
d = Math.max(d, depth(dep, stack) + 1)
}
stack.delete(id)
memo.set(id, d)
return d
}
let max = 0
for (const e of entries) {
max = Math.max(max, depth(e.extId, new Set()))
}
return max
}
/**
* Merge extension signer pin maps from boot policy env mirrors (V2V5; later JSON wins per key).
* @param {Record<string, unknown> | null | undefined} env
* @returns {Record<string, string | string[]>}
*/
function mergeExtensionSignerPinsFromEnv(env) {
if (!env || typeof env !== 'object') return {}
const keys = [
'BARE_OS_BOOT_POLICY_EXTENSION_SIGNER_PINS_V2_JSON',
'BARE_OS_BOOT_POLICY_EXTENSION_SIGNER_PINS_V3_JSON',
'BARE_OS_BOOT_POLICY_EXTENSION_SIGNER_PINS_V4_JSON',
'BARE_OS_BOOT_POLICY_EXTENSION_SIGNER_PINS_V5_JSON'
]
/** @type {Record<string, string | string[]>} */
const out = {}
for (const k of keys) {
const raw = String(env[k] ?? '').trim()
if (!raw) continue
try {
const o = JSON.parse(raw)
if (o && typeof o === 'object' && !Array.isArray(o)) {
for (const [ik, iv] of Object.entries(o)) {
out[String(ik)] = /** @type {string | string[]} */ (iv)
}
}
} catch {
/* ignore malformed JSON */
}
}
return out
}
/**
* When boot.policy pins an extension id to Ed25519 key(s), verify detached signature over script bytes.
* @param {Record<string, unknown>} ctx
* @param {{ extId: string, file: string, signaturePointer?: string }} ent
* @param {string} imgPath
* @param {Record<string, string | string[]>} pins
* @param {boolean} strictPol
* @returns {Promise<boolean>} true if the script may run
*/
async function verifyKernelExtSignerPinsForScript(
ctx,
ent,
imgPath,
pins,
strictPol
) {
const id = String(ent.extId || '').trim()
const need = pins[id]
if (need == null) return true
/** @type {string[]} */
const pubHexList = Array.isArray(need)
? need.map((x) =>
String(x)
.trim()
.toLowerCase()
.replace(/^0x/, '')
)
: [String(need).trim().toLowerCase().replace(/^0x/, '')]
const validKeys = pubHexList.filter(
(h) => h.length === 64 && /^[0-9a-f]+$/.test(h)
)
if (!validKeys.length) {
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinBadKey',
`[kernel.ext.d] extensionSignerPins for "${id}" must be 64-char hex pubkey(s)`
)
return !strictPol
}
const sigPtr = ent.signaturePointer
? String(ent.signaturePointer).trim()
: ''
if (!sigPtr.startsWith('/')) {
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinNoSigPath',
`[kernel.ext.d] "${id}": signaturePointer (absolute path to signature) required when extensionSignerPins lists this id`
)
return !strictPol
}
const { drive, b4a } = ctx
if (!drive || typeof drive.get !== 'function' || !b4a) {
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinNoDrive',
'[kernel.ext.d] signer pin verify requires ctx.drive.get and ctx.b4a'
)
return !strictPol
}
let scriptBuf
let sigBuf
try {
scriptBuf = await drive.get(imgPath)
sigBuf = await drive.get(sigPtr)
} catch (e) {
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinRead',
`[kernel.ext.d] signer pin read: ${(e && e.message) || String(e)}`
)
return !strictPol
}
if (!scriptBuf || !scriptBuf.byteLength || !sigBuf || !sigBuf.byteLength) {
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinMissingBytes',
`[kernel.ext.d] "${id}": script or signature file missing/empty for pin verify`
)
return !strictPol
}
const verifyFn = ctx.bareOsVerifyBootManifestSignature
if (typeof verifyFn !== 'function') {
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinNoVerify',
'[kernel.ext.d] ctx.bareOsVerifyBootManifestSignature unavailable; cannot enforce extensionSignerPins'
)
return !strictPol
}
for (const pk of validKeys) {
try {
if (verifyFn.call(ctx, scriptBuf, sigBuf, pk) === true) return true
} catch {
/* try next pubkey */
}
}
bootStructuredLog(
ctx,
'error',
'kernelExt.signerPinVerifyFailed',
`[kernel.ext.d] "${id}": Ed25519 verify failed for pinned key(s)`
)
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
* @param {{ incremental?: boolean, ranScripts?: string[] }} [opts]
* @returns {Promise<boolean>}
*/
async function runKernelExtDropins(ctx, opts = {}) {
const incremental = opts.incremental === true
const ranScripts = opts.ranScripts
const { drive } = ctx
const run = ctx.bareOsRunImageScript
if (typeof run !== 'function') return true
if (!ctx.bareOsLoadedKernelExtScripts) {
ctx.bareOsLoadedKernelExtScripts = new Set()
}
/** @type {Set<string>} */
const loadedSet = /** @type {Set<string>} */ (ctx.bareOsLoadedKernelExtScripts)
const denyRaw = String(
ctx.env?.BARE_OS_BOOT_POLICY_DENY_KERNEL_EXT_IDS || ''
).trim()
const deny = new Set(
denyRaw
.split(',')
.map((s) => s.trim())
.filter(Boolean)
)
const strictPol =
ctx.env?.BARE_OS_BOOT_POLICY_STRICT === '1' ||
ctx.env?.BARE_OS_BOOT_POLICY_STRICT === 'true'
const extSignerPins = mergeExtensionSignerPinsFromEnv(ctx.env)
const multisigExtGate =
ctx.env?.BARE_OS_EXTENSION_MULTISIG_VERIFY === '1' ||
ctx.env?.BARE_OS_EXTENSION_MULTISIG_VERIFY === 'true' ||
ctx.env?.BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG === '1' ||
ctx.env?.BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG === 'true'
if (multisigExtGate) {
const requireFile =
ctx.env?.BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG === '1' ||
ctx.env?.BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG === 'true'
try {
const mbuf = await drive.get('/etc/bare-os/pear.multisig.json')
if (!mbuf || mbuf.byteLength === 0) {
if (strictPol && requireFile) {
bootStructuredLog(
ctx,
'error',
'kernelExt.multisigMissing',
'[kernel.ext.d] strict boot requires /etc/bare-os/pear.multisig.json (BARE_OS_BOOT_POLICY_REQUIRE_PEAR_MULTISIG)'
)
if (typeof ctx.bareOsRequestBooterExit === 'function')
ctx.bareOsRequestBooterExit(1)
return false
}
} else {
const mj = JSON.parse(ctx.b4a.toString(mbuf))
if (!bareOsPearMultisigShapeOk(mj)) {
bootStructuredLog(
ctx,
'error',
'kernelExt.multisigInvalid',
'[kernel.ext.d] pear.multisig.json must be { signers: string[], quorum: number } with 1 ≤ quorum ≤ signers.length'
)
if (strictPol) {
if (typeof ctx.bareOsRequestBooterExit === 'function')
ctx.bareOsRequestBooterExit(1)
return false
}
}
}
} catch (e) {
bootStructuredLog(
ctx,
'warn',
'kernelExt.multisigRead',
'[kernel.ext.d] pear.multisig.json: ' + ((e && e.message) || String(e))
)
if (strictPol && requireFile) {
if (typeof ctx.bareOsRequestBooterExit === 'function')
ctx.bareOsRequestBooterExit(1)
return false
}
}
}
const maxDepthRaw = String(
ctx.env?.BARE_OS_BOOT_POLICY_MAX_KERNEL_EXT_DEPTH || ''
).trim()
const maxDepthCap =
maxDepthRaw && Number.parseInt(maxDepthRaw, 10) > 0
? Math.min(32, Number.parseInt(maxDepthRaw, 10))
: 0
/** @type {string[]} */
const names = []
try {
for await (const n of drive.readdir('/etc/bare-os/kernel.ext.d'))
names.push(n)
} catch {
return true
}
names.sort()
/** @type {{ file: string, extId: string, scripts: string[], dependsOn: string[], beforeIds: string[], conflictsWith: string[], signaturePointer?: string }[]} */
const collected = []
for (const name of names) {
if (!name.endsWith('.json')) continue
const p = `/etc/bare-os/kernel.ext.d/${name}`
try {
const buf = await drive.get(p)
if (!buf) continue
const pol = JSON.parse(ctx.b4a.toString(buf))
if (!pol || typeof pol !== 'object') continue
const extId =
pol.id != null
? String(pol.id).trim()
: name.replace(/\.json$/i, '')
if (deny.has(extId)) {
bootStructuredLog(
ctx,
'error',
'kernelExt.denyId',
`[kernel.ext.d] denied by policy id: ${extId}`
)
await appendKernelExtAuditNdjson(ctx, {
event: 'deny_id',
extId,
dropin: name
})
continue
}
const scripts = pol.scripts
if (!Array.isArray(scripts)) continue
/** @type {string[]} */
let dependsOn = Array.isArray(pol.dependsOn)
? pol.dependsOn.map((d) => String(d).trim()).filter(Boolean).slice(0, 16)
: []
if (Array.isArray(pol.requires)) {
dependsOn = dependsOn.concat(
pol.requires.map((d) => String(d).trim()).filter(Boolean).slice(0, 16)
)
}
if (Array.isArray(pol.after)) {
dependsOn = dependsOn.concat(
pol.after.map((d) => String(d).trim()).filter(Boolean).slice(0, 16)
)
}
const beforeIds = Array.isArray(pol.before)
? pol.before.map((d) => String(d).trim()).filter(Boolean).slice(0, 16)
: []
const sig =
typeof pol.signaturePointer === 'string'
? pol.signaturePointer.trim().slice(0, 512)
: undefined
const minExtCtx =
typeof pol.minCtxApiVersion === 'string'
? pol.minCtxApiVersion.trim()
: ''
if (minExtCtx) {
const haveS =
typeof ctx.bareOsCtxApiVersion === 'string'
? ctx.bareOsCtxApiVersion.trim()
: String(ctx.bareOsCtxApiVersion || '').trim()
if (!haveS || !semverGte(haveS, minExtCtx)) {
bootStructuredLog(
ctx,
'error',
'kernelExt.minCtxApiVersion',
`[kernel.ext.d] ${name}: minCtxApiVersion ${minExtCtx} not satisfied (have ${haveS || 'none'})`
)
if (strictPol) return false
continue
}
}
const conflictsWith = Array.isArray(pol.conflictsWith)
? pol.conflictsWith.map((d) => String(d).trim()).filter(Boolean).slice(0, 16)
: []
collected.push({
file: name,
extId,
scripts: scripts.map((s) => String(s).trim()).filter(Boolean),
dependsOn,
beforeIds,
conflictsWith,
signaturePointer: sig || undefined
})
} catch (e) {
bootStructuredLog(
ctx,
'error',
'kernelExt.dropinParse',
`kernel.ext.d/${name}: ` + ((e && e.message) || String(e))
)
}
}
const idToCollected = new Map(collected.map((e) => [e.extId, e]))
for (const e of collected) {
for (const bid of e.beforeIds) {
const target = idToCollected.get(bid)
if (target && target.extId !== e.extId) {
const next = new Set(target.dependsOn)
next.add(e.extId)
target.dependsOn = [...next].slice(0, 24)
}
}
}
for (const e of collected) {
e.dependsOn = [...new Set(e.dependsOn)]
}
const idSet = new Set(collected.map((e) => e.extId))
for (const e of collected) {
for (const c of e.conflictsWith) {
if (idSet.has(c)) {
bootStructuredLog(
ctx,
'error',
'kernelExt.conflict',
`[kernel.ext.d] conflict: extension "${e.extId}" conflictsWith "${c}"`
)
if (strictPol) {
await appendKernelExtAuditNdjson(ctx, {
event: 'conflict',
extId: e.extId,
conflictsWith: c
})
return false
}
}
}
}
if (maxDepthCap > 0) {
const d = kernelExtDependencyDepth(collected)
if (d > maxDepthCap) {
bootStructuredLog(
ctx,
'error',
'kernelExt.maxDepth',
`[kernel.ext.d] maxKernelExtensionDepth exceeded (${d} > ${maxDepthCap})`
)
if (strictPol) return false
}
}
const topo = topologicalOrderKernelExtEntries(collected)
/** @type {typeof collected} */
let ordered
if (!topo.ok) {
bootStructuredLog(
ctx,
'error',
'kernelExt.cycle',
'[kernel.ext.d] dependency cycle in extension drop-ins; ext ids: ' +
topo.cycleExtIds.join(', ')
)
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
}
const dry = bootDryRun(ctx)
const traceOn =
strictPol &&
(ctx.env?.BARE_OS_BOOT_EXT_RESOLUTION_TRACE === '1' ||
ctx.env?.BARE_OS_BOOT_EXT_RESOLUTION_TRACE === 'true')
const extResolutionFailure = strictPol && !topo.ok
if (
ctx.vfs &&
typeof ctx.vfs.writeFile === 'function' &&
ctx.b4a &&
(extResolutionFailure || traceOn)
) {
try {
const cycleSorted = topo.ok
? []
: [...topo.cycleExtIds].sort((a, b) => a.localeCompare(b))
const body =
JSON.stringify({
schema: 2,
atMs: Date.now(),
sessionId: String((ctx.env && ctx.env.BARE_OS_SESSION_ID) || ''),
bootPolicyStrict: !!strictPol,
failure: extResolutionFailure
? {
kind: 'dependency_cycle',
cycleExtIds: cycleSorted,
provenance: 'kernel.ext.d topological sort (init-main)'
}
: null,
ordered: ordered.map((e) => ({
extId: e.extId,
file: e.file,
dependsOn: e.dependsOn
})),
cycleExtIds: topo.ok ? [] : cycleSorted
}) + '\n'
await ctx.vfs.writeFile(
'/run/bare-os/kernel-ext-resolution.json',
ctx.b4a.from(body)
)
} catch {
/* ignore */
}
}
const extGraphOn =
ctx.env?.BARE_OS_KERNEL_EXT_GRAPH === '1' ||
ctx.env?.BARE_OS_KERNEL_EXT_GRAPH === 'true'
if (extGraphOn && ctx.vfs && typeof ctx.vfs.writeFile === 'function' && ctx.b4a) {
let bareModuleTraverse = 'unresolved'
try {
await import('bare-module-traverse')
bareModuleTraverse = 'import_ok'
} catch {
bareModuleTraverse = 'import_failed'
}
try {
const body =
JSON.stringify({
schema: 1,
atMs: Date.now(),
bareModuleTraverse,
note: 'Static drop-in DAG; deeper static edges require host tooling on extension sources.',
nodes: ordered.map((e) => ({
extId: e.extId,
file: e.file,
scripts: e.scripts,
dependsOn: e.dependsOn
}))
}) + '\n'
await ctx.vfs.writeFile(
'/run/bare-os/kernel-ext-graph.json',
ctx.b4a.from(body)
)
} catch {
/* ignore */
}
}
for (const ent of ordered) {
for (const sp of ent.scripts) {
const imgPath = String(sp).trim()
if (!imgPath.startsWith('/lib/bare-os/extensions/')) {
bootStructuredLog(
ctx,
'error',
'kernelExt.rejectedPath',
`[kernel.ext.d] rejected script path: ${imgPath}`
)
continue
}
if (incremental && loadedSet.has(imgPath)) {
continue
}
if (dry) {
bootStructuredLog(
ctx,
'error',
'bootDryRunKernelExt',
`[boot-dry-run] skip kernel.ext.d script: ${imgPath}`
)
continue
}
if (
!(await verifyKernelExtSignerPinsForScript(
ctx,
ent,
imgPath,
extSignerPins,
strictPol
))
) {
if (strictPol) {
if (typeof ctx.bareOsRequestBooterExit === 'function')
ctx.bareOsRequestBooterExit(1)
return false
}
continue
}
try {
const extT0 = Date.now()
await run(imgPath)
const loadMs = Date.now() - extT0
loadedSet.add(imgPath)
if (Array.isArray(ranScripts)) ranScripts.push(imgPath)
if (typeof ctx.bareOsRegisterKernelExtensionRecord === 'function') {
ctx.bareOsRegisterKernelExtensionRecord({
dropin: ent.file,
script: imgPath,
id: ent.extId,
dependsOn: ent.dependsOn,
signaturePointer: ent.signaturePointer,
loadMs
})
}
} catch (e) {
bootStructuredLog(
ctx,
'error',
'kernelExt.scriptThrown',
`[kernel.ext.d] ${ent.file}: ` + ((e && e.message) || String(e))
)
}
}
}
return true
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long