Skip to content

feat: emit relative acl:accessTo / acl:default in pod creation (#428)#429

Merged
melvincarvalho merged 1 commit into
gh-pagesfrom
issue-428-relative-accessto-default
May 14, 2026
Merged

feat: emit relative acl:accessTo / acl:default in pod creation (#428)#429
melvincarvalho merged 1 commit into
gh-pagesfrom
issue-428-relative-accessto-default

Conversation

@melvincarvalho
Copy link
Copy Markdown
Contributor

Summary

  • Fix host-locked pods: callers in createPodStructure (multi-user) and createRootPodStructure (single-user) now pass './' to the ACL generators instead of an absolute ${podUri}…. The on-disk .acl becomes portable across hostnames.
  • No generator behavior change required — they already copy resourceUrl verbatim. The parser at src/wac/parser.js:141 already calls resolveUri(uri, baseUrl) against the .acl's request URL.
  • WebID identifiers stay absolute (the profile document still publishes a global URI). acl:agent portability is Phase 2.

Why

jss start --single-user on the default 0.0.0.0 bind baked http://localhost:<port>/ into every .acl. Requests via 127.0.0.1, the LAN IP, or any public domain returned 401 even for foaf:Agent public-read rules — because checker.js:203 does strict string equality on the resolved accessTo vs. the request URL.

Same class of bug as previously fixed in #144, #250 (host/path/port mismatches). This phase fixes the public-read half by making the writer side match what the reader side has already supported since a736338.

Tests

  • 5 unit tests (one per generator) verify a relative './' is preserved verbatim.
  • 1 round-trip test parses the same on-wire ACL document under two different host URLs and asserts accessTo resolves to whichever host asked.
  • 1 integration test creates a pod and requests it with several Host: headers (localhost, 0.0.0.0, pod.example, pod.invalid) — all return 200 for a public-read resource.
  • All 787 existing tests still pass — existing on-disk pods with absolute-URI ACLs continue to authorize correctly because the parser handles both forms.

Reproduction (before this PR)

jss start --single-user --no-idp --port 4444
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:4444/   # 200
curl -s -o /dev/null -w "%{http_code}\n" http://0.0.0.0:4444/     # 401
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:4444/   # 401

After this PR all three return 200.

Test plan

  • npm test — 787/787 passing locally
  • New unit tests for each generator
  • New round-trip parser test
  • New cross-host integration test via Host: header rewriting

Out of scope (Phase 2+ of #427)

  • acl:agent portability (owner WebID currently still absolute). Tracked for Phase 2.
  • Cross-host owner write (token's webid claim vs. relative-resolved agent URI). Phase 4 — needs separate design.
  • Folding in feat: default landing page + ACL at server root (#276) #303's landing-page seeding. Phase 3.

Closes #428. Phase 1 of #427.

Pods are no longer locked to the hostname captured at first-start. The
ACL generators in `src/wac/parser.js` already copy `resourceUrl` into
the JSON-LD verbatim; the bug was on the caller side, where
`createPodStructure` (multi-user) and `createRootPodStructure`
(single-user) both passed the absolute `${podUri}…`. With `--single-user`
on `0.0.0.0` (the default bind), this baked `http://localhost:<port>/`
into every .acl, so requests via 127.0.0.1, the LAN IP, or any public
domain returned 401 even for `foaf:Agent` public-read rules.

Fix: callers now pass './' (or a relative basename for resource ACLs
like publicTypeIndex.jsonld.acl). The parser at parser.js:141 already
calls `resolveUri(uri, baseUrl)` against the .acl's request URL, so the
public-read rule now matches whichever host the request comes in on.

Tests:
- 5 unit tests (one per generator) verify relative input is preserved.
- 1 round-trip test parses the same ACL document under two different
  host URLs and asserts accessTo resolves to whichever host asked.
- 1 integration test creates a pod and requests it with several Host:
  headers (localhost, 0.0.0.0, pod.example, pod.invalid) — all return
  200 for a public-read resource.

No regression: existing on-disk pods with absolute-URI ACLs still
authorize correctly; the parser handles both forms.

Phase 1 of #427. Refs #428.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 14, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes newly created pod ACLs portable across hostnames by writing relative acl:accessTo / acl:default values where appropriate, relying on existing parser-side relative URI resolution.

Changes:

  • Updated pod creation paths to pass relative resource references (./, ./publicTypeIndex.jsonld) into ACL generators.
  • Clarified parser generator docs to state relative resource URLs are supported.
  • Added unit, round-trip parser, and cross-host integration coverage for relative ACL portability.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/handlers/container.js Emits relative ACL resource references during multi-user pod creation.
src/server.js Emits relative ACL resource references during single-user root pod creation.
src/wac/parser.js Documents relative resourceUrl support for ACL generators.
test/wac.test.js Adds generator, parser round-trip, and cross-host authorization tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@melvincarvalho melvincarvalho merged commit 8dd60c1 into gh-pages May 14, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phase 1: emit relative acl:accessTo / acl:default in ACL generators (#427)

3 participants