feat(backend): Phase 4a PR1 — user status/roles + admin approval queue #4

Open
vikingowl wants to merge 8 commits from feat/burgund-backend into main

8 Commits

Author SHA1 Message Date
vikingowl 808f07800e feat(backend): Phase 4a PR4 — lagerleben articles + camps API; wire frontend loaders
ci/someci/push/web Pipeline was successful
ci/someci/pr/web Pipeline was successful
ci/someci/push/backend Pipeline was successful
ci/someci/pr/backend Pipeline was successful
2026-05-10 17:54:19 +02:00
vikingowl b62271eeb6 feat(backend): Phase 4a PR3 — applications + application_status_log
ci/someci/pr/web Pipeline was successful
ci/someci/push/backend Pipeline was successful
ci/someci/pr/backend Pipeline was successful
2026-05-10 17:42:26 +02:00
vikingowl a37e79ec16 feat(backend): Phase 4a PR2 — groups, group_members, group_profiles
ci/someci/pr/web Pipeline was successful
ci/someci/push/backend Pipeline was successful
ci/someci/pr/backend Pipeline was successful
- Migration 000035: three new tables.
  groups: id, name, kind (haendler|kuenstler|lager), created_by.
  group_members: id, group_id, user_id, role (admin|member) + UNIQUE
  constraint; indexed on user_id and group_id for fast membership lookup.
  group_profiles: one-to-one with groups — description, categories (TEXT[]),
  avatar_url, website_url; upserted so the profile always exists after group
  creation.

- internal/domain/group package: model, repository (pgx), service, handler,
  routes. Public routes: GET /groups/:id, GET /groups/:id/members.
  Auth-gated routes: POST /groups, PATCH /groups/:id/profile,
  POST /groups/:id/members, DELETE /groups/:id/members/:userId,
  GET /users/me/groups.

- Authorization is group-scoped (not platform-role): UpdateProfile and
  AddMember require group admin role; RemoveMember allows self-remove or
  admin. Removing the last admin is blocked (ErrCannotRemoveLastAdmin).
  Creator is automatically added as admin on group creation.

- Security tests (Iron Law): 8 PoC tests covering 401 for unauthenticated
  requests on all auth-gated endpoints, 403 for non-admin on profile/member
  write endpoints, self-remove happy path, last-admin guard, create happy
  path (creator becomes admin), and public endpoint accessibility.
2026-05-10 17:32:15 +02:00
vikingowl b5748121dd feat(backend): Phase 4a PR1 — user status/roles + admin approval queue
ci/someci/pr/web Pipeline was successful
ci/someci/push/backend Pipeline was successful
ci/someci/pr/backend Pipeline was successful
- Migration 000034: add users.status (pending|active|suspended) with
  CHECK, users.approved_at, and users.role CHECK constraint covering
  all 6 planned roles (gast, user, veranstalter, haendler, lager, admin).
  Existing rows default to status='active' to preserve behaviour.

- Role and status constants in user/roles.go (single source of truth).

- User model extended with Status and ApprovedAt; all repository
  RETURNING/Scan clauses updated accordingly.

- Repository interface extended with ListByStatus and SetStatus.

- Admin approval queue: GET /admin/users/pending, POST /admin/users/:id/approve,
  POST /admin/users/:id/reject. Guarded by RequireAuth + RequireRole("admin").
  Approve/reject revokes all target user sessions before updating status
  (session cache carries stale role data; revocation forces re-login).

- SessionRevoker interface defined in user package to avoid import cycle
  with auth package. auth.Repository satisfies it at the wiring layer.

- Login now gates suspended accounts (returns "account suspended" error
  so new sessions cannot be created after rejection).

- Security tests (Iron Law): failing PoC tests written for all three
  admin endpoints verifying 401 for unauthenticated, 403 for non-admin,
  and correct status transitions + session revocation for admin.
2026-05-10 17:24:03 +02:00
vikingowl 911439ebd8 feat(web): implement Burgund Phase 3 — profile, security, auth component cleanup
ci/someci/push/web Pipeline was successful
ci/someci/pr/web Pipeline was successful
ci/someci/pr/backend Pipeline was successful
2026-05-10 16:23:17 +02:00
vikingowl 5e24be03af feat(web): implement Burgund Phase 2 — public surfaces
ci/someci/pr/web Pipeline was successful
ci/someci/push/web Pipeline was successful
ci/someci/push/backend Pipeline was successful
ci/someci/pr/backend Pipeline was successful
2026-05-10 14:54:27 +02:00
vikingowl 00d43675ff fix(web): replace old signet with Burgund shield-M favicon across all sizes
Updates static/favicon.svg (was the old forest-green MedievalSharp signet),
regenerates favicon.ico, favicon-32.png, apple-touch-icon.png. Fixes
site.webmanifest theme_color and background_color to Burgund parchment.
Swaps app.html font preloads to EB Garamond + Cormorant Garamond and
theme-color meta tags to Burgund bg values.
2026-05-10 13:14:46 +02:00
vikingowl 418a4411f3 feat(web): implement Burgund design system foundation (Phase 1)
Establishes the Burgund visual identity system: 11-token color palette
(sealing-wax burgundy #9a1e2c light / halbton rosé #d86268 dark), editorial
typography (Cormorant Garamond display, EB Garamond serif, JetBrains Mono
caps), and all atoms (MarktvogtMark, Caps, Tag, Rule, Heraldry). Rewrites
Header, Footer, MobileNav, all ui/ components, and MarketCard to Burgund
tokens. Self-hosts 12 woff2 variable font subsets. Adds design-system.md
reference doc. Also switches pre-commit hook prettier step to --write.
2026-05-10 12:56:51 +02:00