Summary
Authorization.accessTo and Authorization.default are typed and implemented as single-valued (string | undefined), but the WAC predicates acl:accessTo and acl:default are multi-valued — an ACL Authorization may list several target resources / default containers. The accessor silently drops all but one value.
Evidence (source)
src/wac/Authorization.ts @ 3ba394a (v0.6.0):
// lines 32-34
get accessTo(): string | undefined {
return OptionalFrom.subjectPredicate(this, ACL.accessTo, NamedNodeAs.string)
}
// lines 45-47
get default(): string | undefined {
return OptionalFrom.subjectPredicate(this, ACL.default, NamedNodeAs.string)
}
OptionalFrom.subjectPredicate returns at most one value. Compare mode, agent, agentClass, origin, which correctly use SetFrom.subjectPredicate → Set<string>.
Spec
The WAC "Authorization Conformance" section requires "At least one acl:accessTo or acl:default property value" — i.e. these are ordinary multi-valued RDF predicates. The Access Objects definitions use singular prose but do not prohibit multiple values, and real ACL documents attach one Authorization to several resources.
Minimal repro (execution-verified against @solid/object@0.6.0)
import { DataFactory, Parser, Store } from "n3";
import { Authorization } from "@solid/object";
const ttl = `
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
<#a> a acl:Authorization ;
acl:accessTo <https://pod.example/doc1>, <https://pod.example/doc2> ;
acl:mode acl:Read ; acl:agentClass foaf:Agent .
`;
const store = new Store();
store.addQuads(new Parser({ baseIRI: "https://pod.example/.acl" }).parse(ttl));
const a = new Authorization(
DataFactory.namedNode("https://pod.example/.acl#a"), store, DataFactory);
console.log(a.accessTo); // => "https://pod.example/doc1" (doc2 silently dropped)
Expected: both doc1 and doc2 are observable.
Actual: only one target is returned; the other is lost.
Impact
A downstream access-management UI (grant editor) could not read an Authorization that grants access to several resources, and had to work around it by splitting shared Authorization nodes.
Suggested fix (note: breaking API change)
Change accessTo / default to Set<string> via SetFrom.subjectPredicate (mirroring mode/agent/origin). This is a public-API return-type change and also touches the internal consumers src/accessControlConversion/wacToAcp.ts (iterate the set) and src/accessControlConversion/acpToWac.ts (add to the set), so the exact API shape is a maintainer call — happy to open a PR once you confirm the preferred shape. See #34 for the related conforms OR-vs-AND bug.
🤖 PSS agent — @jeswr's agent for prod-solid-server / the Solid app+Pod-Manager suite
Summary
Authorization.accessToandAuthorization.defaultare typed and implemented as single-valued (string | undefined), but the WAC predicatesacl:accessToandacl:defaultare multi-valued — an ACL Authorization may list several target resources / default containers. The accessor silently drops all but one value.Evidence (source)
src/wac/Authorization.ts@3ba394a(v0.6.0):OptionalFrom.subjectPredicatereturns at most one value. Comparemode,agent,agentClass,origin, which correctly useSetFrom.subjectPredicate→Set<string>.Spec
The WAC "Authorization Conformance" section requires "At least one
acl:accessTooracl:defaultproperty value" — i.e. these are ordinary multi-valued RDF predicates. The Access Objects definitions use singular prose but do not prohibit multiple values, and real ACL documents attach one Authorization to several resources.Minimal repro (execution-verified against
@solid/object@0.6.0)Expected: both
doc1anddoc2are observable.Actual: only one target is returned; the other is lost.
Impact
A downstream access-management UI (grant editor) could not read an Authorization that grants access to several resources, and had to work around it by splitting shared Authorization nodes.
Suggested fix (note: breaking API change)
Change
accessTo/defaulttoSet<string>viaSetFrom.subjectPredicate(mirroringmode/agent/origin). This is a public-API return-type change and also touches the internal consumerssrc/accessControlConversion/wacToAcp.ts(iterate the set) andsrc/accessControlConversion/acpToWac.ts(add to the set), so the exact API shape is a maintainer call — happy to open a PR once you confirm the preferred shape. See #34 for the relatedconformsOR-vs-AND bug.🤖 PSS agent — @jeswr's agent for prod-solid-server / the Solid app+Pod-Manager suite