908f7ea973
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.
106 lines
5.2 KiB
YAML
106 lines
5.2 KiB
YAML
# Docker Compose definition used by Coolify to build and run Festipod straight from the
|
|
# git repository: one stack for the branch it follows (the test environment). The images
|
|
# are built on the Coolify server from the two Dockerfiles of this repository (the app at
|
|
# the root, the backend in /backend); nothing is pulled from a registry.
|
|
#
|
|
# Before `docker compose build` and `up`, Coolify writes a .env file next to this file
|
|
# with the variables defined in its UI plus generated ones. The generated ones used here:
|
|
# SERVICE_FQDN_BACKEND / SERVICE_FQDN_FRONTEND host of each service, as set in its
|
|
# Domains field
|
|
# SERVICE_NAME_BACKEND / SERVICE_NAME_FESTIPOD_REDIS service names (Coolify suffixes
|
|
# them with "-pr-<n>" in a preview)
|
|
# A value starting with `${` becomes an editable variable in Coolify (with its default);
|
|
# the other `${...}` references are only interpolated by docker compose.
|
|
#
|
|
# One base URL per environment, as for the other ActivityPods apps on this Coolify (it is
|
|
# what lets a pull request preview live on a single host): the frontend's domain serves the
|
|
# app, and the backend is served on the same host under `/api` and `/.well-known` — its
|
|
# Domains field is `https://<host>/api,https://<host>/.well-known`. The proxy must pass those
|
|
# paths through unchanged — Coolify's "Strip Prefixes" OFF, as on the other apps: the backend
|
|
# mounts its routes under `/api` itself, from its base URL, and keeps its `/.well-known` ones
|
|
# at the origin root (backend/services/base-path.js). With the prefixes stripped, every
|
|
# backend request would be refused (404).
|
|
#
|
|
# The backend registers its app actor in its main dataset on the first boot, with the
|
|
# domain it had at that time: set the domains in Coolify BEFORE the first deployment. The
|
|
# main dataset must be a SECURE one (WebACL is on): the backend creates it so when it does
|
|
# not exist, and refuses to start on an existing one that is not secure. To start again from
|
|
# nothing (the domains changed, or the main dataset was created before WebACL was on):
|
|
# 1. delete the two datasets in Fuseki. Fuseki's delete leaves a secure dataset's files on
|
|
# disk — remove `databases/<main>`, `databases/<main>Acl`, `databases/<main>Mirror` and
|
|
# `configuration/<main>.ttl` under the Fuseki base too, or a dataset created again under
|
|
# the same name reopens the old data;
|
|
# 2. empty this stack's Redis (the `redis-data` volume): its cache outlives the datasets and
|
|
# would keep serving the old app actor, keys and access needs;
|
|
# 3. redeploy.
|
|
#
|
|
# Fuseki is the one shared with the other apps (shared-infra, in the "infra" project): the
|
|
# backend joins the "coolify" network to reach it, with its own pair of datasets. Redis
|
|
# runs inside the stack (on the stack's private network only, under a name that cannot be
|
|
# confused with the shared one).
|
|
|
|
services:
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
restart: always
|
|
depends_on:
|
|
- festipod-redis
|
|
expose:
|
|
- '3003'
|
|
# Coolify adds the stack's own network to every service; only the backend also needs
|
|
# the shared one, where Fuseki lives.
|
|
networks:
|
|
- coolify
|
|
environment:
|
|
SEMAPPS_APP_NAME: ${APP_NAME:-Festipod}
|
|
SEMAPPS_APP_DESCRIPTION: ${APP_DESCRIPTION:-Points de rencontre sur les événements publics}
|
|
SEMAPPS_APP_LANG: ${APP_LANG:-en,fr}
|
|
SEMAPPS_HOME_URL: https://${SERVICE_FQDN_BACKEND}/api/
|
|
SEMAPPS_FRONT_URL: https://${SERVICE_FQDN_FRONTEND}
|
|
SEMAPPS_PORT: '3003'
|
|
SEMAPPS_SHAPE_REPOSITORY_URL: ${SHAPE_REPOSITORY_URL:-https://shapes.activitypods.org/}
|
|
SEMAPPS_SPARQL_ENDPOINT: ${SPARQL_ENDPOINT}
|
|
SEMAPPS_JENA_USER: ${JENA_USER:-admin}
|
|
SEMAPPS_JENA_PASSWORD: ${JENA_PASSWORD}
|
|
# A pair of datasets named after DATASET_PREFIX and the backend's service name, e.g.
|
|
# festipod-backend / settings-festipod-backend (…-backend-pr-<n> in a preview). Two
|
|
# non-preview stacks on the same Fuseki would share them: give the second its own
|
|
# DATASET_PREFIX (or MAIN_DATASET / SETTINGS_DATASET).
|
|
SEMAPPS_MAIN_DATASET: ${MAIN_DATASET:-${DATASET_PREFIX:-festipod}-${SERVICE_NAME_BACKEND}}
|
|
SEMAPPS_AUTH_ACCOUNTS_DATASET_NAME: ${SETTINGS_DATASET:-settings-${DATASET_PREFIX:-festipod}-${SERVICE_NAME_BACKEND}}
|
|
SEMAPPS_REDIS_CACHE_URL: redis://${SERVICE_NAME_FESTIPOD_REDIS}:6379/0
|
|
SEMAPPS_QUEUE_SERVICE_URL: redis://${SERVICE_NAME_FESTIPOD_REDIS}:6379/1
|
|
|
|
frontend:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
restart: always
|
|
depends_on:
|
|
- backend
|
|
expose:
|
|
- '3000'
|
|
# Read by the server on every request to /festipod-config.json, not inlined at build
|
|
# time: changing one needs a restart, not a rebuild.
|
|
environment:
|
|
PORT: '3000'
|
|
VITE_BACKEND_URL: https://${SERVICE_FQDN_BACKEND}/api
|
|
# The Pod provider the login screen offers in one click; any other can be typed in.
|
|
VITE_POD_PROVIDER_URL: ${POD_PROVIDER_URL:-https://mypod.store}
|
|
|
|
festipod-redis:
|
|
image: redis:7-alpine
|
|
restart: always
|
|
command: ['redis-server', '--appendonly', 'yes']
|
|
volumes:
|
|
- redis-data:/data
|
|
|
|
volumes:
|
|
redis-data:
|
|
|
|
networks:
|
|
coolify:
|
|
external: true
|