Commit Graph
46 Commits
Author SHA1 Message Date
patrickandClaude Sonnet 5 b2d9bf5f15 feat: admin can set a member's password directly, no email required
PUT /api/members/:memberId/password — admin-only, hashes and sets the
password immediately instead of going through the email reset-link
flow. Useful in this deployment where SMTP isn't configured yet, and
more generally whenever the member needs to log in right away.

Frontend: "Passwort direkt setzen" dialog in the members list dropdown,
alongside the existing "Passwort-Mail senden" (renamed for clarity now
that there are two options).

Verified end-to-end: new password logs in, old password is rejected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-12 00:16:19 +02:00
patrickandClaude Sonnet 5 f9451881c4 fix: invitation accept sent empty password string for existing users
AcceptInvitationPage's form always initializes password to "" via
react-hook-form defaultValues, even when the invited email already has
an account and the password field is hidden (requiresPassword=false).
The empty string was sent as-is instead of omitted, tripping the
backend's password.min(8).optional() — which only treats an absent key
as optional, not an empty string — and surfacing Zod's raw untranslated
message ("Too small: expected string to have >=8 characters") instead
of a friendly one.

Frontend: omit the password key entirely from the payload when
requiresPassword is false. Backend: defense in depth — treat an empty
string the same as omitted via a transform, and give the min(8) check
an actual German message for if this path is ever hit another way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-12 00:10:45 +02:00
patrickandClaude Sonnet 5 ad6efc4afa fix(PROJ-11): BUG-26 (session persist), BUG-27 (org-scoped chat token), BUG-28 (composer off-screen)
BUG-27: POST /api/chat/token required no organizationId and just took
whichever provisioned membership row the DB returned first — a user in
more than one org (multi-tenant is explicitly in scope per PRD) could
get a Matrix token for the wrong org's identity. organizationId is now
required, threaded through fetchChatCredentials/useTeamChat/
useTeamUnreadCounts, and the frontend credential cache is now keyed
per-org so switching orgs doesn't reuse a stale token. Same ambiguity
fixed in GET /api/teams' BUG-13 membership lookup. Verified: token
request without organizationId now 400s.

BUG-26: the JWT lived only in useState, so every reload or deep link
threw the user back to /login. auth-context.tsx now persists it to
localStorage and restores/validates it on mount (via /api/auth/me);
ProtectedRoute waits on a new `initializing` flag instead of redirecting
before the restore attempt resolves.

BUG-28: TeamChat's fixed vh-fraction height could never guarantee the
composer stayed on screen — page header, the create-team card and the
team-tile grid all sit above it, so total content exceeds 100vh
regardless of the chat box's own height. Switched vh to dvh (mobile
keyboard/chrome resize) and added a scrollIntoView on mount, which
fires reliably since Radix Tabs only mounts the active tab's content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-12 00:05:49 +02:00
patrickandClaude Sonnet 5 94b25bcc36 fix(PROJ-11): BUG-24 — duplicate team-member add returned 500, not 409
First attempt checked err.code, which is undefined — drizzle-orm wraps
the raw pg error (the one that actually has .code = '23505' for a
unique violation) in .cause. Live-tested and caught before assuming
the fix worked from code review alone. Now checks err.cause?.code
first, falls back to err.code.

Verified: first add 201, duplicate add 409 "Member is already on this
team" instead of 500.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 23:55:29 +02:00
patrickandClaude Sonnet 5 5c2e09b36d feat: admin-triggered password reset for members
Org admins can now trigger a password reset for a member from the
members list dropdown, without ever seeing or setting the password
themselves — POST /api/members/:memberId/reset-password sends the
same reset-link email the self-service /forgot-password flow uses.

Extracted the shared token-generation + email logic into
lib/password-reset.ts so both flows use one implementation. Returns
409 member_has_no_account for members who never accepted their
invitation (no linked login account to reset).

Verified end-to-end on talkhub: admin trigger sends the mail (SMTP
not configured in this test env, confirmed via the mail service's
own log fallback), non-admin gets 403.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 23:52:17 +02:00
patrickandClaude Sonnet 5 dc1ba9ae27 fix(PROJ-11): BUG-23 (real fix, second attempt) and BUG-25 — QA round 4 gate
BUG-25: DashboardPage header ran ~200px past the viewport at 375px,
"Abmelden" unreachable without horizontal scroll. flex-col/flex-wrap
so it stacks on narrow screens instead of overflowing.

BUG-23: the previous fix (logout_all admin endpoint) never worked —
that route doesn't exist on Synapse (404, swallowed by try/catch).
A second attempt (list + bulk-delete devices) also did nothing,
because loginAsUser()'s admin puppet-login issues a deviceless token
that never appears in the devices list. Live-tested both failures via
account/whoami with the "revoked" token still returning 200.

Actual fix: revokeAccessToken() calls the plain Client-Server /logout
endpoint authenticated as the token being revoked, not as the backend's
admin token — the only mechanism that invalidates a deviceless token.
invalidateMatrixAccessToken() now returns the token it removed so the
route can pass it along. Verified: whoami returns 200 before logout,
401 M_UNKNOWN_TOKEN with the same token right after.

QA round 4 (first with real cross-browser access — Chromium/Firefox/
WebKit at 375/768/1440px) found no remaining Critical or functional
High findings once these two land: production-ready.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 23:38:33 +02:00
patrickandClaude Sonnet 5 edc05d4d1e fix(PROJ-11): clear the remaining QA backlog (BUG-5/6/9/10/13/14/15/16/17/21/22)
Every previously-reported bug from the three QA rounds is now addressed
(BUG-11 and BUG-15 mitigated rather than fully solved — see spec for
why). Verified end-to-end on talkhub/matrix after each change.

Security:
- BUG-21: @fastify/helmet registered, CORS origin allowlist (APP_BASE_URL
  + localhost:5173) replaces `origin: true`. Verified: own origin gets
  CORS + HSTS/nosniff/X-Frame-Options headers, foreign origins get none.
- BUG-13: GET /api/teams only returns matrixRoomId for teams the
  requester actually belongs to (was leaking every team's room id to
  any org member). Verified with/without team membership.
- BUG-14: leftJoin now filters scope='team'; new partial unique index
  chat_rooms_team_id_team_scope_unique enforces one room per team at
  the DB level, not just in the query (migration 0002).

Reliability:
- BUG-5: use-team-chat.ts's setup poll now backs off exponentially
  (5s->60s) instead of a fixed 15s; SyncState.Error stops the client
  and reconnects with backoff instead of letting matrix-js-sdk retry
  against Synapse forever.
- BUG-6: one-off backfill script (src/scripts/backfill-history-visibility.ts)
  sets history_visibility=shared on rooms created before that fix;
  run against talkhub/matrix.
- BUG-9: route rate limit on GET /api/chat/room, unified 404 for
  nonexistent-team vs not-a-member (was a cross-org existence oracle),
  LRU-correct eviction order in matrix-token-cache.ts, scroll position
  preserved on "load older messages", and eslint.config.js added (lint
  never ran on this feature before — flat config was simply missing).
- BUG-15 (mitigated): a small module-level credential cache in
  lib/matrix.ts lets useTeamChat and useTeamUnreadCounts share one
  fetched token instead of each hitting POST /api/chat/token
  independently. Reduces but doesn't eliminate rate-limit risk under
  rapid team switching (no in-flight dedup between the two hooks).
- BUG-16: refreshCounts() checks `cancelled` before setCounts.
- BUG-17: use-team-chat.ts uses getRoomUnreadNotificationCount()
  instead of the deprecated getUnreadNotificationCount(); left
  unchanged in use-team-unread-counts.ts on purpose, since importing
  NotificationCountType there would undo BUG-11's bundle-splitting fix.

Cleanup:
- BUG-10: new POST /api/chat/logout invalidates the cached token and
  calls Synapse's logout_all admin endpoint; frontend calls it
  best-effort on logout and clears its own credential cache.
- BUG-22: trim() on displayName construction (trailing space with an
  empty last name); the reported trailing-dot localpart is moot after
  BUG-20 since localparts are random now, not name-derived.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 23:10:37 +02:00
patrickandClaude Sonnet 5 f3361d695e fix(PROJ-11): BUG-20 — stop generating guessable Matrix localparts
toLocalpart() built vorname.nachname from real names, so anyone could
construct another org's Matrix ID and DM them directly — completely
sidestepping the user_directory.enabled=false mitigation from BUG-2,
which only blocks *searching*, not addressing a known ID. Live-exploited
during QA round 3 (cross-club DM succeeded).

Now generates a random `u<16 hex chars>` localpart with no relation to
the member's name. Display name (passed separately to createUser) still
shows the real name in room member lists.

sync-worker.ts and invitations.ts both used to retry on collision by
appending a numeric suffix to the name-derived base; since there's no
name relation left, collision retry now just draws a fresh random id.

Verified end-to-end on talkhub/matrix: new org creator got
@u747fcd631af6db20:matrix.perlbach24.de instead of a name-derived id.
Test data cleaned up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 22:55:50 +02:00
patrickandClaude Sonnet 5 121d80e707 fix(PROJ-11): address QA round-3 findings — BUG-18/19 fixed, BUG-11/12 improved
BUG-18 (Critical) — invitations.ts never joined the Matrix room for
members invited with a teamId (only teams.ts's add-member path did).
Standard onboarding flow left every invited team member stuck on
"Raum wird eingerichtet" forever, with no self-healing (reconciliation
only checks user provisioning, never room membership) and no repair
path (blocked by BUG-19). Now mirrors teams.ts: inline addUserToRoom
with an enqueueSyncJob("join_team_room") fallback.

BUG-19 (High) — no global Fastify error handler meant an uncaught
error (e.g. a duplicate-key insert) echoed back the raw Drizzle error,
including the full SQL statement and bound parameters, to the client.
Added app.setErrorHandler(): 5xx is logged server-side and replaced
with a generic message, 4xx keeps its already-safe original message.

BUG-12 (High) — use-team-unread-counts.ts had no SyncState.Error
handling, so an expired token meant matrix-js-sdk retried /sync
against Synapse forever with a dead token while badges silently
froze. Now stops the client and reconnects with a fresh token,
capped exponential backoff.

BUG-11 (High, partially mitigated) — deferred the app-level unread
client's start to requestIdleCallback instead of firing synchronously
on TeamsPage mount, taking it off the critical path. Does NOT fix the
underlying complaint (SDK still loads for anyone who visits the team
list, whether or not they open chat) — documented as an open
architecture question rather than declared fixed.

All four fixes verified end-to-end against the live talkhub/matrix
TLS deployment (invitation accept -> joined_rooms; duplicate insert ->
generic 500). Test data from QA round 3 and this verification pass
cleaned up (orgs, users, Matrix accounts erased, rooms purged).

Not addressed: BUG-20 (predictable Matrix IDs undermine the BUG-2
user_directory mitigation), BUG-5/6/7/9/10/13/14/15/16/17/21/22.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 22:51:42 +02:00
patrickandClaude Sonnet 5 c200fafd03 docs(PROJ-11): TLS infra done, end-to-end verified over public domains
Nginx Proxy Manager now terminates TLS for matrix.perlbach24.de and
talkhub.perlbach24.de with real Let's Encrypt certs. talkhub's backend
.env updated (SYNAPSE_PUBLIC_BASE_URL, APP_BASE_URL). Full chat flow
re-verified end-to-end against the public HTTPS domains: login, token
mint, room resolve, message send — all 200s, event id returned.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 22:28:33 +02:00
patrickandClaude Sonnet 5 8f6e05481b fix(PROJ-11): address QA BUG-2/3/4, partially mitigate BUG-1
BUG-4 (High, failed acceptance criterion) — per-tile unread badges:
new use-team-unread-counts.ts runs one app-level Matrix client (separate
from useTeamChat's detail-view client) that syncs every room GET /api/teams
now resolves (matrixRoomId added via leftJoin on chat_rooms) and reports
unread counts per team. TeamsPage tiles show the badge without the chat
tab being open. Side fix: createMatrixClient() now dynamic-imports
matrix-js-sdk instead of a static import, so the new always-mounted hook
doesn't drag the SDK (and its 7.8MB crypto WASM) back into TeamsPage's
main bundle — verified via build output (TeamDetail chunk 853KB -> 27KB,
SDK now in its own on-demand chunk).

BUG-3 (High) — kick-while-open: use-team-chat.ts now listens for
RoomEvent.MyMembership; leaving/removal flips status to a new "removed"
state instead of leaving history and the composer usable.

BUG-2 (High, partially mitigated) — minted tokens are unscoped Matrix
credentials by nature (Matrix has no token scoping). Disabled
user_directory search on Synapse (config + live matrix.perlbach24.de
instance), verified empty results instead of cross-club user listing.
Direct addressing by known Matrix ID is still possible — full tenant
isolation needs an explicit decision (one Synapse per club vs. an
isolation module on a shared homeserver), documented as an open item
in the spec rather than silently declared fixed.

BUG-1 (Critical, not fixed) — backend/.env.example is outside my
permission sandbox (can't read or write .env* files). Documented the
required block in the spec for manual addition; talkhub's real .env
already has the values.

Verified end-to-end on talkhub/matrix test LXCs. Not addressed in this
pass (lower priority per QA): BUG-5/6/7/8/9/10.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 20:21:07 +02:00
patrickandClaude Sonnet 5 7fa658b4ff feat(PROJ-11): build team chat via direct browser-to-Synapse connection
Frontend: matrix-js-sdk client per opened team, /sync against Synapse
directly (no chat traffic proxied through the backend), timeline with
day-grouping and read receipts, history backfill, lazy-loaded chat tab
in TeamsPage's team detail view (keeps matrix-js-sdk out of the initial
bundle).

Backend: POST /api/chat/token mints/caches a short-lived per-member
Matrix access token via Synapse's admin puppet-login (1h TTL, in-memory
cache with 5min pre-expiry refresh, concurrent-request dedup, audited
on real mints only); GET /api/chat/room resolves a team's Matrix room.
Cached tokens are invalidated immediately on member suspend/leave.

Fixes found while wiring this up:
- createRoom() now explicitly sets history_visibility=shared (PROJ-9)
  instead of relying on the private_chat preset's implicit default.
- POST /api/organizations never provisioned a Matrix account for the
  org creator (only the invitation-accept path did) — they'd have
  seen "Chat wird eingerichtet" forever. Now enqueues the same
  provision_matrix_user job invitations use.

Open: SYNAPSE_PUBLIC_BASE_URL needs documenting in backend/.env.example
(blocked by local permission rules on that file — added manually on
the talkhub test host instead), per-tile unread counts need an
app-level Matrix client instead of one per opened team, and Synapse
needs TLS + public reachability before this works outside a LAN.

Verified end-to-end on the talkhub/matrix test LXCs: registered a
throwaway account, created org → department → season → team, joined
the team, minted a token, sent a message directly to Synapse, read it
back from room history.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 19:09:24 +02:00
patrickandClaude Sonnet 5 8b6114c3e8 docs(PROJ-11): add technical design for chat feature
Direct browser-to-Synapse connection via matrix-js-sdk, backend only
mints a short-lived per-member access token (no chat proxy, no new
WebSocket server, no new DB table). Status set to In Progress.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:52:39 +02:00
patrickandClaude Sonnet 5 4cb2284ad9 docs: spec PROJ-12 — automatic retention-based deletion for left members (GDPR)
Configurable per-organization retention period, daily job, reuses the
existing hard-delete path from PROJ-3 instead of introducing a new one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:47:59 +02:00
patrickandClaude Sonnet 5 ffe2d450eb fix: revoke org API access immediately on member suspend/leave, not just Matrix
findMembership() and GET /api/organizations/mine ignored members.status —
a suspended or left member kept full API access to the organization (member
list, teams, roles, audit log) and still saw it in the org switcher, even
though only their Matrix account was deactivated. Both now require
status = "active".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:46:34 +02:00
patrickandClaude Sonnet 5 956cb6147b docs: cover member leave/suspend status explicitly in PROJ-3 acceptance criteria
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:44:40 +02:00
patrickandClaude Sonnet 5 568c56a4a7 docs: document password reset and member delete as additions to PROJ-1/PROJ-3
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:43:47 +02:00
patrickandClaude Sonnet 5 bc4d74995f feat: add member hard-delete and password reset flow
- DELETE /api/members/:memberId — admin-only, erases the Matrix account,
  audit-logs before deleting (audit_logs.targetId is unconstrained text so
  the entry survives), relies on existing cascade FKs for team/role cleanup.
  Frontend: confirm dialog in the members table dropdown.
- POST /api/auth/forgot-password + /api/auth/reset-password/:token —
  token-based reset via the existing mail.ts SMTP client, generic response
  regardless of whether the email is registered (no enumeration leak),
  60min token TTL, single-use. Frontend: forgot/reset password pages,
  link added to the login form.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:42:47 +02:00
patrickandClaude Sonnet 5 1c013b301c feat: generalize UI wording — Verein→Organisation, Mannschaft→Team
Makes the German UI labels domain-neutral (Verein/Firma both fit "Organisation"),
Mannschaft was pure sports vocabulary and is replaced with Team.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 18:35:54 +02:00
patrickandClaude Sonnet 5 597f7a8135 chore: import matching subagents for TalkTime stack
Add fastify-expert, postgres-pro, websocket-engineer, backend-security-coder,
react-specialist, tailwind-expert, gdpr-ccpa-compliance, frontend-security-coder
from https://gitea.perlbach24.de/scripte/claude-subagents

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 17:18:27 +02:00
patrickandClaude Sonnet 5 b1d662fa5b feat: rename CLAUDE.md to TalkTime, retro-document features, add PROJ-11 chat spec
- CLAUDE.md header/description now match actual project (TalkTime), not starter-kit template
- Retro-documented already-built MVP features as PROJ-1..PROJ-10 in features/INDEX.md
- Corrected PROJ-9: Matrix User Provisioning, room sync and reconciliation were already implemented, not just health-check
- Added PROJ-11 requirements spec for basic chat (Matrix Client-Server API, team scope, text-only MVP)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
2026-09-11 17:18:22 +02:00
patrickandClaude Sonnet 5 90669b4568 feat: add universal Synapse install.sh for bare-metal/Proxmox-LXC
Own installer instead of relying only on the external bashclub script:
builds homeserver.yaml straight from our homeserver.yaml.sample (so it
inherits TalkTime's security defaults — no federation, no public
registration — automatically), sets up Postgres, a systemd service, and
prints the admin token ready to paste into backend/.env. Works identically
in a Proxmox LXC and on bare metal (both are just a Debian userland).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBf3yfnnHzMQ5qhLV2285A
2026-09-11 15:38:07 +02:00
patrickandClaude Sonnet 5 51426a944c fix: finish VereinsChat->TalkTime rename in synapse docs, harden defaults
- Fixed leftover chat.vereinschat.local defaults in docker-compose.yml and
  homeserver.yaml.sample that the earlier bulk rename missed (placeholders
  weren't plain "VereinsChat" text)
- Generalized example prod domain from chat.verein.de to chat.example.org
- Disabled federation by default in homeserver.yaml.sample (client-only
  resources, empty federation_domain_whitelist) since TalkTime runs a
  private homeserver per deployment, not a public Matrix participant
- Added concrete nginx TLS reverse-proxy config and a federation-enable
  note to the Synapse README instead of a stale "see deployment.md" pointer

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBf3yfnnHzMQ5qhLV2285A
2026-09-11 15:34:25 +02:00
patrickandClaude Sonnet 5 b5ac041c32 feat: add Docker Compose deployment for backend/frontend/postgres
Backend Dockerfile runs drizzle-kit migrate on start, frontend serves the
built Vite app via nginx and proxies /api to the backend container.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBf3yfnnHzMQ5qhLV2285A
2026-09-11 15:28:01 +02:00
patrickandClaude Sonnet 5 b38a5a4a57 feat: member status actions, roles/audit-log UI, member deactivation sync
- PATCH /api/members/:id/status (suspend/reactivate/leave) with Matrix deactivation
- Reconciliation worker comparing local member status against Synapse state
- Roles page (assign/revoke) and audit log page on the frontend
- Dashboard tiles for departments/teams now link to their pages
- Reference bashclub/zamba-lxc-toolbox as a Proxmox-LXC autoinstaller option in Synapse docs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBf3yfnnHzMQ5qhLV2285A
2026-09-11 15:13:23 +02:00
patrickandClaude Sonnet 5 5e6ee2c456 feat: build TalkTime MVP backend/frontend, rename from VereinsChat
- Generic org/team/member data model (renamed from club-specific naming)
- Auth, organizations, invitations with mail + Matrix provisioning
- Teams with automatic Matrix room creation, sync-job retry, reconciliation
- Departments, seasons, roles (RBAC with privilege-escalation guard), audit log
- Dashboard, members list, org switcher on the frontend
- Synapse setup docs (Docker + bare-metal) and generalized PRD/architecture docs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TBf3yfnnHzMQ5qhLV2285A
2026-09-11 15:07:47 +02:00
patrickandClaude Sonnet 5 58a56439a0 docs: echte Gitea-Clone-URL in README ergänzen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMdBJfD9TT6XUU2NqGG1PN
2026-09-08 21:24:23 +02:00
patrickandClaude Sonnet 5 4a19335a1e feat: rework starter kit for self-hosted deploy (Vite/React + Fastify/Drizzle/Postgres)
Replace Next.js/Supabase/Vercel stack with a self-hostable setup: Vite+React
frontend, Fastify+Drizzle+PostgreSQL backend with own JWT auth, deploy via
git pull + rsync + systemd (checkout/service separated, updates pulled from
Gitea). Adds a reference auth route (register/login/me) as the canonical
pattern for new routes. Updates all skills/rules/agents/docs to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMdBJfD9TT6XUU2NqGG1PN
2026-09-08 11:42:47 +02:00
“alexvisualmakers”andClaude Opus 4.6 a893084a88 feat: Add path scoping to rules and enforce project init workflow
- Add paths frontmatter to frontend, backend, and security rules so
  they only load when editing relevant files
- Add mandatory new-project detection to general rules that redirects
  to /requirements before any implementation
- Add write-then-verify protocol for feature tracking updates to
  prevent hallucinated file edits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:11:43 +01:00
“alexvisualmakers”andClaude Opus 4.6 7c8a2c3622 chore: Use Opus 4.6 for all skills and sub-agents
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:57:44 +01:00
“alexvisualmakers”andClaude Opus 4.6 600552c858 feat: Migrate from agent markdown files to Skills, Rules, and Sub-Agents
Replace the manual "read .claude/agents/*.md" workflow with native
Claude Code features for a more efficient, scalable development experience:

- **Skills** (.claude/skills/): 7 auto-discovered slash commands
  (/requirements, /architecture, /frontend, /backend, /qa, /deploy, /help)
  with forked sub-agents for heavy tasks and inline execution for interactive ones
- **Rules** (.claude/rules/): 4 modular rule files (general, frontend, backend,
  security) auto-applied based on file context
- **Sub-Agents** (.claude/agents/): Lightweight configs for frontend-dev,
  backend-dev, and qa-engineer with model, tool, and turn limit settings
- **Context Engineering**: Layered context loading, context isolation via
  forked skills, built-in context recovery after compaction, and
  "always read, never guess" rules to prevent hallucinated code references
- **CLAUDE.md**: Auto-loaded project context replacing PROJECT_CONTEXT.md
- **Feature tracking**: features/INDEX.md as persistent state across sessions
- **Production guides**: docs/production/ for error tracking, security,
  performance, database optimization, and rate limiting
- **Init Mode**: /requirements detects empty PRD and bootstraps full project
  setup (PRD + all feature specs) from a single project description

Removed: 6 monolithic agent files, PROJECT_CONTEXT.md, HOW_TO_USE_AGENTS.md,
TEMPLATE_CHANGELOG.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 10:15:27 +01:00
“alexvisualmakers”andClaude Opus 4.5 d7abbc3f8c fix: Add complete shadcn/ui CSS variables and Tailwind config
globals.css:
- Add all shadcn/ui CSS variables in HSL format (without hsl() wrapper)
- Include: card, popover, primary, secondary, muted, accent, destructive
- Include: input, ring, radius, chart colors
- Complete light and dark mode definitions

tailwind.config.ts:
- Map all CSS variables with hsl(var(--...)) wrapper
- Add borderRadius config for --radius variable
- Add chart colors mapping

This ensures all shadcn/ui components render correctly out of the box.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 15:28:09 +01:00
“alexvisualmakers”andClaude Opus 4.5 cec3890c6f fix: Resolve build errors with border color and import paths
- Add missing --border CSS variable for light and dark mode
- Add border color to Tailwind config using hsl(var(--border))
- Fix import paths in sidebar.tsx (@/hooks/ instead of @/components/hooks/)
- Fix import path in toaster.tsx (@/hooks/ instead of @/components/hooks/)

These fixes ensure npm run dev / npm run build work out of the box.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 12:53:56 +01:00
“alexvisualmakers”andClaude Opus 4.5 2f47d526ff feat: Enforce mandatory shadcn/ui component usage in Frontend Dev
- Add critical section: always check shadcn/ui before creating components
- List all 35 installed shadcn components with categories
- Add VERBOTEN section: never create own versions of shadcn components
- Update example component to use shadcn Card/Button/Badge
- Add shadcn checklist items before marking work as done

This ensures Claude Code always uses shadcn/ui instead of building
custom implementations of standard UI elements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 10:23:25 +01:00
“alexvisualmakers”andClaude Opus 4.5 3aa2072cca feat: Add comprehensive shadcn/ui component library
Install 35 shadcn components for standard business application:

Base: Button, Input, Label, Card
Forms: Form, Select, Checkbox, Radio, Switch, Textarea
Auth/Feedback: Dialog, Alert, AlertDialog, Toast, Sonner
Dashboard: Table, Tabs, Avatar, Badge, Dropdown, Popover, Tooltip
Navigation: NavigationMenu, Sidebar, Breadcrumb, Sheet, Command
Data Display: Skeleton, Progress, Separator, ScrollArea, Collapsible,
              Accordion, Pagination

Includes hooks (use-toast, use-mobile) and updated Tailwind config.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 10:20:39 +01:00
“alexvisualmakers”andClaude Opus 4.5 13cda026ba fix: Restore design guidelines in Frontend Dev workflow
Revert accidental removal of design-vorgaben section while keeping
the new Supabase auth best practices.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 09:56:01 +01:00
“alexvisualmakers”andClaude Opus 4.5 13c086275c feat: Add Supabase auth best practices to Frontend Dev
- Simplify workflow section structure
- Add Auth/Login Best Practices for Supabase + Next.js
  - Hard redirect after login (window.location.href)
  - Session validation before redirect
  - Proper loading state handling
  - Debugging tips for auth issues
- Remove redundant design-vorgaben checkpoint

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 09:54:41 +01:00
“alexvisualmakers”andClaude Opus 4.5 b957bca346 feat: Add security testing focus to QA Engineer role
Extend QA Engineer responsibilities to include security analysis
and permission checks with a Red Team pentester approach.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 09:52:33 +01:00
“alexvisualmakers”andClaude Opus 4.5 5c55902b6e feat: Requirements Engineer updates PROJECT_CONTEXT.md after writing specs
- New Phase 5: Update PROJECT_CONTEXT.md with current status and roadmap
- Updates "Aktueller Status", "Features Roadmap", optionally "Vision"
- New checklist item ensures PROJECT_CONTEXT.md stays current

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 11:27:48 +01:00
“alexvisualmakers”andClaude Opus 4.5 84f177872b feat: Frontend Dev asks for design input when no mockups exist
- New workflow step: Check for design files before implementing
- Interactive questions for style, colors, inspiration
- Uses AskUserQuestion for structured input
- New checklist item for design clarification

Also: Refactored TEMPLATE_CHANGELOG to compact bullet-point format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 11:18:21 +01:00
“alexvisualmakers”andClaude Opus 4.5 c87a360f2e feat: Add feature granularity guidelines to Requirements Engineer
Enforce Single Responsibility Principle for feature specifications:
- Each feature file should be one testable, deployable unit
- Clear rules on what NOT to combine in one file
- 5 decision criteria for splitting features
- Dependency documentation between features

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 11:04:27 +01:00
“alexvisualmakers”andClaude Sonnet 4.5 1c3a81156a refactor: Migrate to Git-based workflow (v1.4.0)
BREAKING CHANGE: Removed FEATURE_CHANGELOG.md and test-reports/

**What changed:**
- All 6 agents now use Git commands to check existing features/components
- Feature specs include test results and deployment status (no separate files)
- Git commits are the single source of truth for implementation details
- Git tags for deployment versioning (e.g., v1.0.0-PROJ-1)

**Why:**
- Prevents context bloat (no growing FEATURE_CHANGELOG.md)
- Scales better (Git is built for large projects)
- No manual changelog maintenance
- Better developer experience (native Git workflow)

**Migration:**
- Requirements Engineer: Uses `ls features/` and `git ls-files` instead of FEATURE_CHANGELOG
- Solution Architect: Uses `git ls-files src/components/` to check existing code
- Frontend/Backend Devs: Use `git log --grep="PROJ-X"` to see feature history
- QA Engineer: Adds test results directly to feature spec
- DevOps: Updates feature spec with deployment status + creates Git tags

**Files changed:**
- Updated all 6 agent instructions (.claude/agents/*.md)
- Deleted FEATURE_CHANGELOG.md
- Deleted test-reports/ folder
- Updated PROJECT_CONTEXT.md (removed references)
- Updated README.md (v1.4.0, updated workflow)
- Updated features/README.md (new format with QA + Deployment sections)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 14:57:19 +01:00
“alexvisualmakers” f035934f42 fix: Add missing SVG assets for Next.js starter page 2026-01-12 09:00:44 +01:00
“alexvisualmakers” a73df5ea26 docs: Remove redundant TEMPLATE_OVERVIEW.md (duplicates README.md content) 2026-01-12 08:46:25 +01:00
“alexvisualmakers” b4da197850 docs: Remove unnecessary CHECKLIST.md file 2026-01-12 08:45:05 +01:00
“alexvisualmakers”andClaude Sonnet 4.5 9195df186c Initial commit: AI Coding Starter Kit v1.3.0 (Production-Ready)
Features:
- Next.js 16 + TypeScript + Tailwind CSS
- 6 Production-Ready AI Agents (Requirements → Deployment)
- Production Guides (Error Tracking, Security, Performance, Scaling)
- Feature Changelog System (Code Reuse)
- PM-Friendly Documentation
- Supabase-Ready (optional)
- shadcn/ui-Ready
- Vercel Deployment-Ready

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 08:41:31 +01:00