Skip to content

Authorization.accessTo / .default are single-valued but acl:accessTo / acl:default are multi-valued #33

Description

@jeswr

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.subjectPredicateSet<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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions