- Guest-safe legacy personal-root migration with state file and env gates - VFS guest deny for sensitive /.bare paths; warm-cache clear on identity switch - Optional acct/<hash>/ personal layout, guest scrub, vault exclude alignment - Shell session reset + errexit; fish history reload hook; replication metric - Audit NDJSON for migration/scrub; structured booter logging paths - Bump POSIX profile; getconf keys; syscall/socket contract + handbook/docs pass - Booter tests (Bare vs Node split for identity-session); release-checklist audit hook
68 lines
2.5 KiB
JavaScript
68 lines
2.5 KiB
JavaScript
/**
|
|
* Persist an operator-facing snapshot of HDMS mounts.
|
|
* Writes `/.bare/os/mounts_last.json` on the personal drive first, then best-effort
|
|
* `/etc/bare-os/mounts.json` when the system image is writable (often not for guest sessions).
|
|
* Source of truth remains `/.bare/hdms/registry.json` on the personal drive.
|
|
*/
|
|
|
|
import b4a from 'b4a'
|
|
|
|
/**
|
|
* @param {{ writeFile?: Function, mkdir?: Function } | null | undefined} vfs
|
|
* @param {import('./hdms-manager.js').HdmsController | null | undefined} hdms
|
|
* @param {{ console?: { warn?: (msg: string) => void } }} [opts] Guest session console; omit to stay silent on failure (tests / minimal VFS).
|
|
*/
|
|
export async function persistBareOsMountsSnapshot(vfs, hdms, opts = {}) {
|
|
if (!vfs || typeof vfs.writeFile !== 'function') return
|
|
if (!hdms?.active || !hdms.registry) return
|
|
|
|
/** @type {{ label: string, target: string, mode: string, readOnly: boolean, key?: string, ns?: string }[]} */
|
|
const mounts = []
|
|
for (const d of hdms.registry.drives) {
|
|
mounts.push({
|
|
label: d.label,
|
|
target: `/mnt/${d.label}`,
|
|
mode: d.mode,
|
|
readOnly: d.mode === 'readonly',
|
|
...(d.key ? { key: d.key } : {}),
|
|
...(d.ns ? { ns: d.ns } : {})
|
|
})
|
|
}
|
|
|
|
const doc = {
|
|
schemaVersion: 1,
|
|
updatedAt: new Date().toISOString(),
|
|
note: 'Snapshot for operators; authoritative registry is /.bare/hdms/registry.json on the personal drive. When writable, the same JSON is mirrored at /.bare/os/mounts_last.json for multi-drive tooling.',
|
|
mounts
|
|
}
|
|
const body = JSON.stringify(doc, null, 2) + '\n'
|
|
const buf = b4a.from(body, 'utf8')
|
|
|
|
/** Personal-drive mirror (always preferred; VFS allows writes here for normal sessions). */
|
|
let personalOk = false
|
|
try {
|
|
await vfs.mkdir('/.bare/os', { recursive: true })
|
|
await vfs.writeFile('/.bare/os/mounts_last.json', buf)
|
|
personalOk = true
|
|
} catch {
|
|
/* personal tree may be unavailable in minimal tests */
|
|
}
|
|
|
|
/** Optional system-drive copy for operators when the system image is writable. */
|
|
let systemOk = false
|
|
try {
|
|
await vfs.mkdir('/etc/bare-os', { recursive: true })
|
|
await vfs.writeFile('/etc/bare-os/mounts.json', buf)
|
|
systemOk = true
|
|
} catch {
|
|
/* expected for guests: /etc is on the system drive and not under $HOME */
|
|
}
|
|
|
|
if (!personalOk && !systemOk) {
|
|
const msg =
|
|
'[bare-os] mounts snapshot persist failed: could not write /.bare/os/mounts_last.json or /etc/bare-os/mounts.json'
|
|
const w = opts.console && typeof opts.console.warn === 'function'
|
|
if (w) opts.console.warn(msg)
|
|
}
|
|
}
|