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
+15
View File
@@ -90,6 +90,21 @@ class JoinStatusForm(FormModel):
return value
class InviteClaimForm(FormModel):
username: str = Field(min_length=3, max_length=32)
email: str = Field(min_length=3, max_length=255)
password: str = Field(min_length=6, max_length=128)
password_confirm: str = Field(min_length=6, max_length=128)
terms: bool = False
@field_validator("username")
@classmethod
def check_username(cls, value):
if not re.fullmatch(r"[A-Za-z0-9_-]{3,32}", value or ""):
raise ValueError("Use 3 to 32 letters, digits, _ or -")
return value
class RoleForm(FormModel):
role: str