Updates
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
async function readUtf8(ctx, path) {
|
||||
const vfs = ctx.vfs
|
||||
if (!vfs || typeof vfs.readFile !== 'function') {
|
||||
throw new Error('kernel-boot-diff: vfs.readFile unavailable')
|
||||
}
|
||||
const buf = await vfs.readFile(path)
|
||||
return ctx.b4a ? ctx.b4a.toString(buf) : String(buf)
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
const a = argv[2]
|
||||
const b = argv[3]
|
||||
if (!a || !b) {
|
||||
ctx.console.error('Usage: kernel-boot-diff FILE1 FILE2')
|
||||
ctx.console.error('Compares NDJSON or line-oriented boot checkpoint dumps.')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
let t1 = ''
|
||||
let t2 = ''
|
||||
try {
|
||||
;[t1, t2] = await Promise.all([readUtf8(ctx, a), readUtf8(ctx, b)])
|
||||
} catch (e) {
|
||||
ctx.console.error(
|
||||
'kernel-boot-diff: ' + ((e && e.message) || String(e))
|
||||
)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
const lines1 = t1.split(/\r?\n/).filter((x) => x.trim())
|
||||
const lines2 = t2.split(/\r?\n/).filter((x) => x.trim())
|
||||
const s1 = new Set(lines1)
|
||||
const s2 = new Set(lines2)
|
||||
for (const x of lines2) {
|
||||
if (!s1.has(x)) ctx.console.log('+ ' + x.slice(0, 800))
|
||||
}
|
||||
for (const x of lines1) {
|
||||
if (!s2.has(x)) ctx.console.log('- ' + x.slice(0, 800))
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,38 @@ async function run(ctx, argv) {
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
if (argv[i] === '--json') json = true
|
||||
}
|
||||
const caps = ctx.bareOsRuntimeCaps
|
||||
const out = {
|
||||
note: 'kernel-doctor — guest snapshot (non-secret). See developer-guide/giant-phase-kernel-program.md',
|
||||
note: 'kernel-doctor — guest snapshot (non-secret). See developer-guide/kernel-program.md',
|
||||
ctxApiVersion: String(ctx.bareOsCtxApiVersion || ''),
|
||||
giantPhase: await readProcJson(ctx, '/proc/bare_os/giant_phase_program.json'),
|
||||
programProc: await readProcJson(ctx, '/proc/bare_os/kernel_program.json'),
|
||||
resources: await readProcJson(ctx, '/proc/bare_os/resources'),
|
||||
bootReady: await readProcJson(ctx, '/run/bare-os/boot.json'),
|
||||
initdDag: await readProcJson(ctx, '/proc/bare_os/initd_dag.json'),
|
||||
servicesRegistry: await readProcJson(ctx, '/run/bare-os/services.json'),
|
||||
moduleResolution: await readProcJson(
|
||||
ctx,
|
||||
'/proc/bare_os/bare_module_resolution.json'
|
||||
),
|
||||
delegateFairness:
|
||||
typeof ctx.bareOsReadDelegateFairnessSnapshot === 'function'
|
||||
? ctx.bareOsReadDelegateFairnessSnapshot()
|
||||
: null,
|
||||
runtimeCapsSubset: caps
|
||||
? {
|
||||
kernelEventSubscribe: /** @type {any} */ (caps).kernelEventSubscribe,
|
||||
keyBrokerHandleSketch: /** @type {any} */ (caps).keyBrokerHandleSketch,
|
||||
bootEventSubscribe: /** @type {any} */ (caps).bootEventSubscribe
|
||||
}
|
||||
: null,
|
||||
envHints: {
|
||||
bootSafeMode: ctx.env?.BARE_OS_BOOT_SAFE_MODE,
|
||||
bootTransactionJournal: ctx.env?.BARE_OS_BOOT_TRANSACTION_JOURNAL,
|
||||
bootCheckpoint: ctx.env?.BARE_OS_BOOT_CHECKPOINT
|
||||
bootCheckpoint: ctx.env?.BARE_OS_BOOT_CHECKPOINT,
|
||||
bootDryRun: ctx.env?.BARE_OS_BOOT_DRY_RUN,
|
||||
bootPolicyPath: ctx.env?.BARE_OS_BOOT_POLICY_PATH,
|
||||
dnsProfile: ctx.env?.BARE_OS_DNS_PROFILE,
|
||||
delegateTrace: ctx.env?.BARE_OS_DELEGATE_TRACE
|
||||
}
|
||||
}
|
||||
if (json) {
|
||||
@@ -33,8 +55,8 @@ async function run(ctx, argv) {
|
||||
} else {
|
||||
ctx.console.log('ctx API: ' + out.ctxApiVersion)
|
||||
ctx.console.log(
|
||||
'giant phase program: ' +
|
||||
(out.giantPhase ? 'see /proc/bare_os/giant_phase_program.json' : '(unavailable)')
|
||||
'kernel program proc: ' +
|
||||
(out.programProc ? 'see /proc/bare_os/kernel_program.json' : '(unavailable)')
|
||||
)
|
||||
ctx.console.log('run: kernel-doctor --json | jq .')
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
/** Map common failure tokens to documentation anchors (offline-friendly). */
|
||||
var KERNEL_EXPLAIN_MAP = {
|
||||
boot_policy: 'docs/reference/kernel-extensions.md — BARE_OS_BOOT_POLICY',
|
||||
safe_mode: 'BARE_OS_BOOT_SAFE_MODE — skips rc.d, kernel.ext.d, onboot (developer-guide/giant-phase-kernel-program.md)',
|
||||
safe_mode: 'BARE_OS_BOOT_SAFE_MODE — skips rc.d, kernel.ext.d, onboot (developer-guide/kernel-program.md)',
|
||||
boot_journal:
|
||||
'BARE_OS_BOOT_TRANSACTION_JOURNAL — /run/bare-os/boot-transaction.ndjson',
|
||||
boot_checkpoint: 'BARE_OS_BOOT_CHECKPOINT — /run/bare-os/boot-checkpoint.json',
|
||||
kernel_ext:
|
||||
'kernel.ext.d — dependsOn, requires, after, before (stock kernel/init.js header)',
|
||||
giant_phase:
|
||||
'/proc/bare_os/giant_phase_program.json — giant-phase program snapshot',
|
||||
kernel_program:
|
||||
'/proc/bare_os/kernel_program.json — operator program snapshot (schema 2; legacy path giant_phase_program.json)',
|
||||
operator_sketches:
|
||||
'operatorSketches in kernel_program.json — env-driven JSON hints; see developer-guide/kernel-program.md',
|
||||
boot_policy_fail:
|
||||
'Strict boot policy exit — check boot.policy.json vs caps; use kernel-preflight; docs/reference/kernel-extensions.md',
|
||||
cap_mismatch:
|
||||
'minKernelCapabilitiesPrimary / requireSeedCaps vs advertised words — compatibility-matrix.md; kernel-explain boot_policy_fail',
|
||||
bare_module:
|
||||
'Use bare-module / bare-node mapping (Holepunch); never node:module in guest',
|
||||
bare_crypto:
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
async function run(ctx, argv) {
|
||||
const vfs = ctx.vfs
|
||||
if (!vfs || typeof vfs.readdir !== 'function') {
|
||||
ctx.console.error('kernel-fsck: vfs.readdir unavailable')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
let json = false
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
if (argv[i] === '--json') json = true
|
||||
}
|
||||
/** @type {string[]} */
|
||||
const names = []
|
||||
try {
|
||||
for await (const n of vfs.readdir('/bin')) names.push(n)
|
||||
} catch (e) {
|
||||
ctx.console.error(
|
||||
'kernel-fsck: ' + ((e && e.message) || String(e))
|
||||
)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
names.sort()
|
||||
const out = {
|
||||
schema: 1,
|
||||
ok: true,
|
||||
binCount: names.length,
|
||||
sample: names.slice(0, 32),
|
||||
note: 'Integrity walk stub — lists /bin; extend with checksum pass when policy requires.'
|
||||
}
|
||||
if (json) {
|
||||
ctx.console.log(JSON.stringify(out, null, 2))
|
||||
} else {
|
||||
ctx.console.log('kernel-fsck: /bin entries ' + names.length)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
async function run(ctx, argv) {
|
||||
let json = false
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
if (argv[i] === '--json') json = true
|
||||
}
|
||||
const out = {
|
||||
schema: 1,
|
||||
ok: false,
|
||||
note:
|
||||
'Home snapshot placeholder — stream tar-like archives from personal drive in a future slice; see handbook VFS.',
|
||||
argv: argv.slice(1)
|
||||
}
|
||||
if (json) {
|
||||
ctx.console.log(JSON.stringify(out, null, 2))
|
||||
} else {
|
||||
ctx.console.error(
|
||||
'kernel-home-snapshot: not implemented — use host backup tools for now'
|
||||
)
|
||||
}
|
||||
ctx.exitCode = 1
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
async function run(ctx, argv) {
|
||||
const { drive, b4a, console } = ctx
|
||||
if (!drive || typeof drive.get !== 'function' || !b4a) {
|
||||
console.error('kernel-manifest-validate: drive / b4a required')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
let path = '/lib/bare/manifest.json'
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
if (argv[i] === '--path' && argv[i + 1]) {
|
||||
path = String(argv[++i]).trim()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!path.startsWith('/lib/bare/')) {
|
||||
console.error('kernel-manifest-validate: only /lib/bare/* paths allowed')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
let buf
|
||||
try {
|
||||
buf = await drive.get(path)
|
||||
} catch (e) {
|
||||
console.error(
|
||||
'kernel-manifest-validate: ' + ((e && e.message) || String(e))
|
||||
)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
if (!buf) {
|
||||
console.error('kernel-manifest-validate: missing ' + path)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
let m
|
||||
try {
|
||||
m = JSON.parse(b4a.toString(buf))
|
||||
} catch (e) {
|
||||
console.error(
|
||||
'kernel-manifest-validate: JSON: ' + ((e && e.message) || String(e))
|
||||
)
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
if (!m || typeof m !== 'object' || !Array.isArray(m.bundles)) {
|
||||
console.error('kernel-manifest-validate: invalid manifest shape')
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
let missing = 0
|
||||
for (const b of m.bundles) {
|
||||
const p = b && typeof b.path === 'string' ? b.path.trim() : ''
|
||||
if (!p.startsWith('/lib/bare/')) continue
|
||||
try {
|
||||
const chunk = await drive.get(p)
|
||||
if (!chunk) {
|
||||
missing++
|
||||
console.error('kernel-manifest-validate: missing bundle ' + p)
|
||||
}
|
||||
} catch {
|
||||
missing++
|
||||
console.error('kernel-manifest-validate: error reading ' + p)
|
||||
}
|
||||
}
|
||||
if (missing) {
|
||||
ctx.exitCode = 1
|
||||
return
|
||||
}
|
||||
console.log('kernel-manifest-validate: ok (' + m.bundles.length + ' bundles)')
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
async function readProcJson(ctx, p) {
|
||||
const vfs = ctx.vfs
|
||||
if (!vfs || typeof vfs.readFile !== 'function') return null
|
||||
try {
|
||||
const buf = await vfs.readFile(p)
|
||||
const t = ctx.b4a ? ctx.b4a.toString(buf) : String(buf)
|
||||
const j = JSON.parse(t.trim())
|
||||
return j && typeof j === 'object' ? j : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function run(ctx, argv) {
|
||||
let json = false
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
if (argv[i] === '--json') json = true
|
||||
}
|
||||
const features = await readProcJson(ctx, '/proc/bare_os/features')
|
||||
const caps = await readProcJson(ctx, '/proc/bare_os/capabilities.json')
|
||||
const program = await readProcJson(ctx, '/proc/bare_os/kernel_program.json')
|
||||
const polOn =
|
||||
ctx.env?.BARE_OS_BOOT_POLICY === '1' ||
|
||||
ctx.env?.BARE_OS_BOOT_POLICY === 'true'
|
||||
const ok = !!(features && caps && program)
|
||||
const out = {
|
||||
schema: 1,
|
||||
ok,
|
||||
bootPolicyEnabled: polOn,
|
||||
ctxApiVersion: String(ctx.bareOsCtxApiVersion || ''),
|
||||
programProcSchema:
|
||||
program && typeof program.schema === 'number' ? program.schema : null,
|
||||
note: 'kernel-preflight: non-secret proc presence only; extend with policy file checks on trusted images.'
|
||||
}
|
||||
if (json) {
|
||||
ctx.console.log(JSON.stringify(out, null, 2))
|
||||
} else {
|
||||
ctx.console.log(ok ? 'kernel-preflight: ok' : 'kernel-preflight: missing proc nodes')
|
||||
}
|
||||
if (!ok) ctx.exitCode = 1
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
async function run(ctx, argv) {
|
||||
let json = false
|
||||
for (let i = 1; i < argv.length; i++) {
|
||||
if (argv[i] === '--json') json = true
|
||||
}
|
||||
const paths = [
|
||||
'/proc/bare_os/kernel_program.json',
|
||||
'/proc/bare_os/giant_phase_program.json',
|
||||
'/proc/bare_os/resources',
|
||||
'/proc/bare_os/features',
|
||||
'/proc/bare_os/capabilities.json',
|
||||
'/proc/bare_os/metrics_live.json',
|
||||
'/run/bare-os/boot.json',
|
||||
'/run/bare-os/boot-checkpoint.json',
|
||||
'/run/bare-os/boot-transaction.ndjson',
|
||||
'/run/bare-os/services.json',
|
||||
'/run/bare-os/loader-audit.ndjson',
|
||||
'/var/log/bare-os/kernel.log'
|
||||
]
|
||||
const manifest = {
|
||||
schema: 1,
|
||||
note: 'Support bundle manifest — collect these paths (non-secret).',
|
||||
paths,
|
||||
sessionId: String(ctx.env?.BARE_OS_SESSION_ID || '')
|
||||
}
|
||||
if (json) {
|
||||
ctx.console.log(JSON.stringify(manifest, null, 2))
|
||||
} else {
|
||||
ctx.console.log('kernel-triage — include in support bundle:')
|
||||
for (const p of paths) ctx.console.log(' ' + p)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user