Member invites, gallery resync, content and operator docs

- Invite flow: admin issue/revoke on join requests, public single-use
  claim links (hash-only tokens, 7-day expiry, no state reveal), claim
  creates the Member account and marks the request accepted
- Gallery: admin status page plus resync endpoint; sync refreshes
  thumbnails whose content changed; tools/gallery contract and checker
- Docs: public content page, admin-only operator runbook, api.md
  invite/gallery sections, all routes in the live API docs, docs
  reachability gate test
- Screenshots cover the new pages; version 1.0.18
This commit is contained in:
2026-10-06 02:56:08 +02:00
parent e512556703
commit 9fb4d65787
36 changed files with 1147 additions and 19 deletions
+8
View File
@@ -23,6 +23,14 @@ curl -H 'Accept: application/json' https://molodetz.nl/roll
Errors have the shape `{"error": {"status": 404, "message": "..."}}`. Validation errors return `422` with `{"error": "validation", "fields": [...], "messages": [...]}`.
## Invites
Membership starts from a join request plus an admin-issued invite. Admins call `POST /admin/joins/{uid}/invite` (returns `claim_url` and `expires_at` in `data`) and `POST /admin/joins/{uid}/invite/revoke`. The public claim is `GET` and `POST /invite/{token}` with `username`, `email`, `password`, `password_confirm` and `terms`. Claim links are single use and every dead link answers 404 with the same message.
## Gallery
`GET /admin/gallery` reports live flyer and meme counts plus catalogued source files missing from disk. `POST /admin/gallery/resync` re-reads the sources and retires removed entries. See [Galleries and content](/docs/content) for how publishing works.
## Old paths
The Dutch paths from before (`/rol`, `/standaard`, `/mensen`, `/binnen`, `/voorwaarden`) answer with a 301 to their English replacement. Query strings are kept.