Files
bare-operating-system/packages/bare-os-booter/lib/bare-os-acl-eval.js
T
Raven Scott 8f2e3cceb0 Move editable kernel bulk from kernel/init-main.js to kernel/lib/init/
(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).
2026-04-04 17:51:47 -04:00

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()
}
}