(staged as /lib/init/init-main.js); point bundle-kernel-init and verify scripts at the new path. Wire curl, wget, openssl, ssh-keygen, and tar through coreutils and booter host delegates with booter-side CLI helpers; refresh related bins, bare manifest, shell completion, and man DB (kernel + seeder). Add booter support modules for ACL evaluation, audit chain, secret handles, peer admission, replication priority, process table, swarm lifecycle, boot-graph proc, metrics, monotonic time, protomux alias registry, and swarm peer policy; extend extension resolver, VFS, swarm connection managers, IPC, identity-account, and initd. Harden bare-os-bare-libs build on esbuild failure; add verify scripts for extension manifest schema and runtime incomplete markers; extend ctx API typings, gen-ctx-client-stub, and verify-ctx-dts. Update boot hook fragment, bundled init.js, handbook and reference docs (incl. kernel security and VFS path classes).
66 lines
2.0 KiB
JavaScript
66 lines
2.0 KiB
JavaScript
/**
|
|
* Capability-oriented ACL evaluation (advisory; callers enforce verdict).
|
|
* @param {{ user?: string, groups?: string[], caps?: string[] }} subject
|
|
* @param {{ path?: string, pathClass?: string }} resource
|
|
* @param {{ id?: string, effect: 'allow' | 'deny', users?: string[], groups?: string[], caps?: string[], pathPrefix?: string, pathClass?: string }[]} rules
|
|
*/
|
|
export function evaluateBareOsAcl(subject, resource, rules = []) {
|
|
const u = String(subject?.user || '').trim()
|
|
const groups = new Set(
|
|
Array.isArray(subject?.groups)
|
|
? subject.groups.map((g) => String(g).trim()).filter(Boolean)
|
|
: []
|
|
)
|
|
const caps = new Set(
|
|
Array.isArray(subject?.caps)
|
|
? subject.caps.map((c) => String(c).trim()).filter(Boolean)
|
|
: []
|
|
)
|
|
const path = String(resource?.path || '').replace(/\\/g, '/')
|
|
const pClass = String(resource?.pathClass || '').trim()
|
|
|
|
/** @type {{ id?: string, effect: 'allow' | 'deny' }[]} */
|
|
const matched = []
|
|
let verdict = 'neutral'
|
|
|
|
for (const r of rules) {
|
|
if (!r || (r.effect !== 'allow' && r.effect !== 'deny')) continue
|
|
if (r.pathClass && r.pathClass !== pClass) continue
|
|
if (r.pathPrefix && !path.startsWith(String(r.pathPrefix))) continue
|
|
|
|
let hit = false
|
|
if (r.users && r.users.length) {
|
|
if (u && r.users.includes(u)) hit = true
|
|
}
|
|
if (!hit && r.groups && r.groups.length) {
|
|
for (const g of r.groups) {
|
|
if (groups.has(g)) {
|
|
hit = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (!hit && r.caps && r.caps.length) {
|
|
for (const c of r.caps) {
|
|
if (caps.has(c)) {
|
|
hit = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (!hit && !r.users && !r.groups && !r.caps) hit = true
|
|
if (!hit) continue
|
|
|
|
matched.push({ id: r.id, effect: r.effect })
|
|
verdict = r.effect
|
|
}
|
|
|
|
return {
|
|
subject: { user: u, groupCount: groups.size, capCount: caps.size },
|
|
resource: { path, pathClass: pClass },
|
|
matched,
|
|
verdict,
|
|
atMs: Date.now()
|
|
}
|
|
}
|