feat: user invite flow, deactivate/delete, favicon, dashboard loading fix, admin full-width

- Invite flow: admin can invite users by email with role selection; accept-invite page
  sets password and creates the account; 72-hour token expiry; E2E tests
- User deactivate/reactivate/delete: new tRPC procedures + UI buttons; deactivation
  revokes all active sessions immediately; delete cascades vacation/broadcast records;
  isActive field added via migration 20260402000000_user_isactive
- Auth: block login for inactive users with audit entry
- Favicon: SVG favicon + ICO/PNG fallbacks (16, 32, 180, 192, 512px); manifest updated
- Dashboard: GridLayout dynamic-import loading skeleton prevents blank dark area
  on first login before react-grid-layout chunk is cached
- Admin users: remove max-w-5xl constraint so table uses full page width
- Dev: docker container restart workflow documented in LEARNINGS.md; Prisma generate
  must run inside the container after schema changes (named node_modules volume)

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-04-02 20:19:26 +02:00
parent dc5bbdc47d
commit 41eb722369
33 changed files with 6755 additions and 169 deletions
+62
View File
@@ -0,0 +1,62 @@
name: Docker Deploy Test
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: deploy-test-${{ github.ref }}
cancel-in-progress: true
jobs:
docker-deploy-test:
name: Fresh-Linux Docker Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create minimal .env
run: |
cat <<'EOF' > .env
NEXTAUTH_URL=http://localhost:3100
NEXTAUTH_SECRET=ci-test-secret-minimum-32-chars-xx
PGADMIN_PASSWORD=ci-pgadmin
EOF
- name: Start infrastructure (postgres + redis)
run: docker compose up -d postgres redis
- name: Wait for postgres
run: |
for i in $(seq 1 20); do
docker compose exec -T postgres pg_isready -U capakraken -d capakraken && break
sleep 3
done
- name: Build and start app (full profile)
run: docker compose --profile full up -d --build app
- name: Wait for /api/health (up to 3 minutes)
run: |
for i in $(seq 1 36); do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3100/api/health || echo "000")
echo "Attempt $i: HTTP $STATUS"
if [ "$STATUS" = "200" ]; then exit 0; fi
sleep 5
done
echo "Health check timed out"
docker compose logs app --tail=50
exit 1
- name: Verify health response contains status ok
run: |
BODY=$(curl -sf http://localhost:3100/api/health)
echo "$BODY"
echo "$BODY" | grep '"status":"ok"'
- name: Show logs on failure
if: failure()
run: docker compose logs --tail=100