The project licence governs this repository's code and says nothing about the application a role installs, which is where a restriction on commercial use usually sits: a deployment cleared to use Infinito.Nexus commercially is still barred from NLLB-200's CC BY-NC weights. Each invokable role names its licence in meta/<role>/license.yml with the url it was read from. The rights of a named licence live once in meta/licenses.yml, fifteen fields following the taxonomy choosealicense publishes. AND folds to the strictest combination, OR keeps the most favourable whole licence, and the seven contexts are derived from the rights rather than declared, so a heading cannot contradict the matrix under it. The generated page renders one matrix per context, a lint refuses a role that declares nothing, and a Playwright spec asserts the page against the deployed docs. 21 of 22 deprecated SPDX ids were resolved against the upstream text; EPSON's remains unread because its AUR page blocks automated access. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Postmarks
Description
Run Postmarks, a single-user ActivityPub bookmarking website for the Fediverse, via Docker Compose. The owner curates a public collection of bookmarks that federates to followers on Mastodon and other ActivityPub servers. Upstream project: ckolderup/postmarks.
Overview
This role builds Postmarks from source into a custom image, wires it to the standard reverse proxy, and persists its SQLite data. Postmarks is single-user: there are no accounts, only "the owner". The upstream login is a single shared-secret password form that flips one session boolean (req.session.loggedIn).
Features
- Containerized build: Clones the pinned upstream ref and runs
node server.jsbehind the front proxy. - Single-owner model: One privileged identity, gated by
req.session.loggedIn. - Trusted-header SSO bridge: Establishes the owner session from the oauth2-proxy identity (see below).
- Minimal footprint: Small Node.js/Express service that fits neatly into larger stacks.
Single sign-on
Postmarks has no native OIDC/SAML/LDAP/REMOTE_USER login — the only auth path is the ADMIN_KEY password form. Under the oauth2 SSO flavor this role adds a trusted-header SSO bridge:
- A sidecar
web-app-keycloakoauth2-proxy authenticates the visitor against Keycloak (OIDC, or LDAP federated through Keycloak) and nginx overwrites theX-Forwarded-*identity headers on every proxied request. - A small Express middleware (
files/sso/header_auth.js, mounted intoserver.jsat build time byfiles/sso/patch_server.js) reads only those nginx-overwrittenX-Forwarded-*headers and flipsreq.session.loggedIn = true, so the existingisAuthenticatedgate on/adminopens for the proxied owner. - The bridge activates only when
PROXY_HEADER_SSOis truthy (derived fromlookup('sso', application_id, 'is_proxy_gated')); otherwise the middleware is a transparent pass-through and the native password form still guards/admin. - An optional
PROXY_HEADER_SSO_ADMIN_GROUPcheck againstX-Forwarded-Groupsrestricts the owner session to members of the application's administrator RBAC group.
Security: the identity headers are trusted unconditionally, which is only safe because the app port is bound to 127.0.0.1 and every request traverses the oauth2-proxy that overwrites X-Forwarded-*. The X-Auth-Request-* / Remote-User variants are deliberately ignored so an already-authenticated client cannot inject a different identity. Logout must go through web-svc-logout / the oauth2-proxy sign-out, not Postmarks' own logout link, because the proxy header re-establishes the session on the next request.
RBAC is not feasible beyond the group gate: Postmarks has no in-app authorisation tier beyond "owner or not" and no per-user identity, so X-Forwarded-Email/X-Forwarded-Preferred-Username cannot scope anything inside the app. This RBAC exception is documented per lifecycle.md.
Further Resources
- Postmarks (GitHub)
- ActivityPub (W3C Recommendation)
- Corporate design review: screenshots in light, dark, desktop and mobile
Persona contract opt-outs
The persona flags are declared in templates/playwright.env.j2. administrator is blocked only in the sso: false variants: as described above, Postmarks' sole native credential is the single shared ADMIN_KEY password form, which is not the Keycloak administrator secret the persona types, so without the trusted-header bridge there is no admin login to drive. biber is blocked in every variant — the oauth2-proxy admits only the application's administrator RBAC group and the bridge re-checks X-Forwarded-Groups, so biber is denied before Postmarks is reached, and with SSO off the only credential left belongs to no user account.