@dwk/wac
v0.1.0-beta.2
Published
Web Access Control evaluation (effective-ACL walk, Append vs Write). Solid-specific helper.
Maintainers
Readme
@dwk/wac
Web Access Control (WAC) evaluation for Solid Pods. A pure, dependency-light
library consumed by @dwk/solid-pod: it takes ACL graphs (as
plain quads, compatible with @dwk/rdf terms) plus request facts and
returns an authorization decision. No Cloudflare bindings; unit-testable without
a Workers runtime.
See the spec for the authoritative requirements, and the Solid WAC specification for the model.
What it does
- Effective-ACL walk — resolves the nearest applicable
.acl, honoringacl:defaulton ancestor containers. A resource's ownacl:accessToACL takes precedence over inheritedacl:defaultACLs. - Modes —
acl:Read,acl:Write,acl:Append,acl:Control. - Subjects —
acl:agent,acl:agentGroup, andacl:agentClass(includingfoaf:Agentfor public access andacl:AuthenticatedAgent). - Origin —
acl:originacts as a per-authorization allow-list. - Append vs Write — an
appendrequest is satisfied byacl:Appendoracl:Write; a delete must be requested aswrite, whichacl:Appendalone never grants.
Decisions MUST NOT be memoized in eventually-consistent stores (e.g. KV); the walk is cheap and is meant to run against strongly-consistent ACL state.
Usage
import { evaluateAccess, type AclResource } from "@dwk/wac";
// Build the effective-ACL chain, nearest first. The requested resource's own
// ACL uses scope "accessTo"; ancestor container ACLs use scope "default".
const chain: AclResource[] = [
{ target: "https://alice.example/notes/secret.ttl", scope: "accessTo", quads: resourceAclQuads },
{ target: "https://alice.example/notes/", scope: "default", quads: containerAclQuads },
];
const decision = evaluateAccess(
{ mode: "write", agent: "https://bob.example/card#me", origin: "https://app.example" },
chain,
);
if (!decision.granted) {
// 401 if unauthenticated, otherwise 403.
}