Keep sign-ups unlinkable on ActivityPods, and land the pending coherence-pass work
Participation privacy (decision_2026-10-29_participation-privacy-mechanism): a sign-up is a private Join naming the meeting point, addressed to nobody, handled by the backend on emission. Attendee lists hold member URNs hashed from (WebID, event, a secret kept in the participant's profile), so counts stay public and only contacts recognise anyone; the creator has no read right and is notified anonymously. Each person's participations collection, created by the backend at the first sign-up, is readable by their /contacts WAC group only, never world-readable. The member URN is sticky per (meeting point, participant) and every collection write is verified by reading back, so a refused write leaves the act unrecorded and retryable. The EventRef mechanism and its browser-side provisioning are gone. The backend now runs with WebACL on, as the reference apps do, on its own secure datasets festipod / settings-festipod instead of the pod provider's settings dataset; pod-notifications needs it. The compose header and the deployment leaf say how to reset a stack whose datasets predate this. The rights matrix covers the new mechanism live (148 hard lines), including a forged contact Accept between throwaway accounts: the stranger enters the contacts list (platform defect, reported upstream) but is refused the profile and the participations. Tests may attack as long as they never break the dev environment (rule_tests-never-break-the-dev-environment). Also lands the coherence-pass work that was still uncommitted: contacts as the Pod's social graph and invite links, image upload to the Pod, the meeting-point form, profile completion gate, and the doctrine for them. Superseded briefs and decisions are deleted rather than annotated.
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
// The backend's whole HTTP surface, as an allow-list checked in front of every route.
|
||||
//
|
||||
// WHY. The backend runs SemApps' CoreService with `webacl: false`, so nothing checks rights on the
|
||||
// resources it stores, and CoreService mounts routes Festipod never asked for — above all the LDP
|
||||
// catch-all (`@semapps/ldp` `getCatchAllRoute`: `GET|POST|PUT|PATCH|DELETE /<any path>`,
|
||||
// `authorization: false`), which served the backend's `settings` dataset to anyone: the app actor's
|
||||
// PRIVATE key (`GET /key`, observed 2026-10-13), the user registrations and grants the app holds
|
||||
// (`/interop/…`), the webhook listeners. A signed request is no better: any pod user can sign one.
|
||||
// Rather than chase each route (deny-list), the gateway serves ONLY what a caller legitimately needs
|
||||
// and refuses everything else with a 404 — for every caller, anonymous or signed, since none needs
|
||||
// more over HTTP: the backend's own services reach its data through internal calls, never through
|
||||
// these routes.
|
||||
// WHY. CoreService mounts routes Festipod never asked for — above all the LDP catch-all
|
||||
// (`@semapps/ldp` `getCatchAllRoute`: `GET|POST|PUT|PATCH|DELETE /<any path>`), over the dataset that
|
||||
// holds the app actor's PRIVATE key (`/key`), the user registrations and grants the app holds
|
||||
// (`/interop/…`), the catalog store and the ledgers. WebACL filters what those routes serve (the main
|
||||
// dataset is a secure one, see core.service.js), so each resource is only as private as the rights
|
||||
// its container gave it; this gate does not depend on those rights being right. A signed request is
|
||||
// no better than an anonymous one here: any pod user can sign one. Rather than chase each route
|
||||
// (deny-list), the gateway serves ONLY what a caller legitimately needs and refuses everything else
|
||||
// with a 404 — for every caller, anonymous or signed, since none needs more over HTTP: the backend's
|
||||
// own services reach its data through internal calls, never through these routes.
|
||||
//
|
||||
// WHAT IS PUBLIC, and who calls it (backend request log, 2026-10-09 → 2026-10-13, all e2e runs):
|
||||
// GET /app the app description — the Festipod front end and the pod (install)
|
||||
|
||||
Reference in New Issue
Block a user