d804a436d7
Polyfill capabilities landed for Festipod's T02 features (all generic,
zero-domain — the consumer injects the domain).
- inbox: implement the previously-stubbed namespace. post(target,{from?,
payload,ts?}) deposits {from,payload,ts} as RDF via docs.sparqlUpdate (the
real injected ng, never makeNg); read/materialize + watch emulate the curator
in-lib (deposits read via docs.sparqlQuery). `from` optional = anonymity.
- write-guard: caps.hasWritePolicy() + ng-proxy.sparql_update rejects when the
target doc is under a write policy and the current user lacks its write cap;
passthrough otherwise (no regression). Read-cap registry unchanged.
- sparql.ts (new): escapeLiteral / escapeIri / assertNuri, exported from index.
store-registry now escapes every literal and validates/encodes every IRI-
position value — closes a SPARQL-injection hole where an untrusted username
could inject triples into the shim (the account→doc-NURI trust root).
Tests: inbox, sparql (incl. injection), ng-proxy write-guard, isolation-active.
68 tests pass; tsc --noEmit rc=0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
65 lines
2.8 KiB
TypeScript
65 lines
2.8 KiB
TypeScript
import { test, expect } from "bun:test";
|
|
import { CapRegistry } from "../src/caps";
|
|
|
|
test("public documents are readable by anyone, even anonymous", () => {
|
|
const caps = new CapRegistry();
|
|
caps.open("did:ng:o:pub", "public", "alice");
|
|
expect(caps.canRead("did:ng:o:pub", null)).toBe(true);
|
|
expect(caps.canRead("did:ng:o:pub", "bob")).toBe(true);
|
|
});
|
|
|
|
test("protected documents: owner + explicitly granted principals only", () => {
|
|
const caps = new CapRegistry();
|
|
caps.open("did:ng:o:prot", "protected", "alice");
|
|
expect(caps.canRead("did:ng:o:prot", "alice")).toBe(true);
|
|
expect(caps.canRead("did:ng:o:prot", "bob")).toBe(false);
|
|
caps.grantRead("did:ng:o:prot", "bob"); // bob becomes a connection of alice
|
|
expect(caps.canRead("did:ng:o:prot", "bob")).toBe(true);
|
|
});
|
|
|
|
test("private documents: owner only", () => {
|
|
const caps = new CapRegistry();
|
|
caps.open("did:ng:o:priv", "private", "alice");
|
|
expect(caps.canRead("did:ng:o:priv", "alice")).toBe(true);
|
|
expect(caps.canRead("did:ng:o:priv", "bob")).toBe(false);
|
|
expect(caps.canRead("did:ng:o:priv", null)).toBe(false);
|
|
});
|
|
|
|
test("write is restricted to write-cap holders; the creator always holds it", () => {
|
|
const caps = new CapRegistry();
|
|
caps.open("did:ng:o:pub", "public", "alice");
|
|
expect(caps.canWrite("did:ng:o:pub", "alice")).toBe(true);
|
|
expect(caps.canWrite("did:ng:o:pub", "bob")).toBe(false);
|
|
expect(caps.canWrite("did:ng:o:pub", null)).toBe(false);
|
|
});
|
|
|
|
test("holding a document's cap does NOT grant another document (no inheritance)", () => {
|
|
const caps = new CapRegistry();
|
|
caps.grantRead("did:ng:o:doc1", "alice");
|
|
expect(caps.canRead("did:ng:o:doc1", "alice")).toBe(true);
|
|
expect(caps.canRead("did:ng:o:doc2", "alice")).toBe(false); // separate repo, separate cap
|
|
});
|
|
|
|
test("governsRead / hasReadPolicy distinguish governed from ungoverned documents", () => {
|
|
const caps = new CapRegistry();
|
|
expect(caps.hasReadPolicy()).toBe(false);
|
|
caps.grantRead("did:ng:o:doc1", "alice");
|
|
expect(caps.hasReadPolicy()).toBe(true);
|
|
expect(caps.governsRead("did:ng:o:doc1")).toBe(true);
|
|
expect(caps.governsRead("did:ng:o:unknown")).toBe(false); // not declared → not enforced
|
|
});
|
|
|
|
test("governsWrite / hasWritePolicy distinguish governed from ungoverned documents", () => {
|
|
const caps = new CapRegistry();
|
|
expect(caps.hasWritePolicy()).toBe(false);
|
|
caps.open("did:ng:o:doc1", "private", "alice"); // owner gets the write cap
|
|
expect(caps.hasWritePolicy()).toBe(true);
|
|
expect(caps.governsWrite("did:ng:o:doc1")).toBe(true);
|
|
expect(caps.governsWrite("did:ng:o:unknown")).toBe(false); // not declared → not enforced
|
|
// A public doc grants read to all but its write cap is still owner-only.
|
|
const pub = new CapRegistry();
|
|
pub.open("did:ng:o:pub", "public", "alice");
|
|
expect(pub.hasWritePolicy()).toBe(true);
|
|
expect(pub.governsWrite("did:ng:o:pub")).toBe(true);
|
|
});
|