Commit Graph

5 Commits

Author SHA1 Message Date
simone 64030afef3 feat: sidebar CTA removal, delete phase/task, public dashboard UX, chat panel
1. AdminSidebar: removed yellow "Genera preventivo" CTA (duplicated Preventivi tab nav item)
2. Delete phase/task: new deletePhase/deleteTask server actions with FK cascade and phase-status recompute; DeletePhaseTaskButton client component with window.confirm; trash icons in PhasesTab per phase and per task
3. Public dashboard: extend activeOffers query with offer_macros join (offer_name, offer_type); reorder sidebar 1°Offerte 2°Pagamenti 3°Documenti; OffersSection shows macro public_name as heading (never tier letter/internal_name); PaymentStatus gains totalLabel/overrideAmount/hideRows props — retainer=monthly label + no Acconto/Saldo rows
4. Offer editor: Descrizione textarea (nota interna) and Modalità toggle moved directly under title; Tags section now contains only Categoria/Ticket/Tipo/Obiettivo
5. Basecamp chat: API route supports entity_type="phase" with authorization scoping; comments scope in client-view broadened to include phaseIds and client_id (general); CommentsTab updated with phase/general entities; ChatProvider React context; ChatPanel fixed slide-in panel with FAB (bottom-right) and composer tag selector (Generale + phases); PhaseCard gets chat-bubble icon pre-tagging that phase; inline ChatSection block removed from dashboard main column

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:11:55 +02:00
simone a478462aa4 security: full hardening pass — auth guards, rate limiting, headers, internal secret
- Add requireAdmin() to all unprotected admin server actions
  (clients/new, clients/[id], timer-actions — 17 functions total)
- Protect /api/internal/* endpoints with X-Internal-Secret header
  (proxy.ts sends it; routes reject requests without it)
- Randomize auto-generated client slugs with 4-char suffix
  to prevent enumeration via predictable name-based slugs
- Add in-memory rate limiting to /api/client/approve (20/min)
  and /api/client/comment (10/min) per IP
- Add security headers: X-Frame-Options, X-Content-Type-Options,
  Referrer-Policy, Permissions-Policy, X-DNS-Prefetch-Control
- Reduce JWT session from 30 days to 7 days with daily rotation
- Remove hardcoded NEXTAUTH_URL from Dockerfile (pass via Coolify env)
- Genericize client API error messages to not leak data structure
- Update .env.example with all required variables including INTERNAL_SECRET

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 14:36:16 +02:00
simone 63c9f750df feat(04-01): multi-project schema migration — projects, settings, FK pivot
- schema.ts: add projects table, settings kv table, slug on clients;
  migrate 6 FK from client_id to project_id (phases, payments, documents, notes,
  time_entries, quote_items); update all relations and TypeScript types
- admin-queries.ts: fix getAllClientsWithPayments + getClientFullDetail to aggregate
  through projects; add getAllProjectsWithPayments, getProjectFullDetail,
  getClientWithProjects, ClientWithProjects type
- settings.ts: new file — getSetting, updateSetting, getTargetHourlyRate, SETTINGS_KEYS
- Fix all downstream files: actions.ts, quote-actions.ts, new/actions.ts,
  timer-actions.ts, approve/route.ts, comment/route.ts, TimerCell.tsx,
  analytics-queries.ts, client-view.ts, seed.ts
- DB migration applied to Coolify Postgres (all test data cleared, schema rebuilt)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 21:58:15 +02:00
Simone Cavalli 549cf0b592 feat: unify client messaging into ChatSection + add general comment type
Removed per-task/deliverable CommentList/CommentForm from PhaseTimeline and
ClientKanban. Replaced with a single ChatSection at the bottom of the dashboard
that handles general, task, and deliverable messages in a unified chat UI.
Added "general" entity_type to the comment API (entity_id = client UUID).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:49:14 +02:00
Simone Cavalli c24bdde603 feat(02-04): add POST /api/client/approve and POST /api/client/comment API routes
- approve: validates token, checks deliverable ownership via phase→client join, sets status=approved + approved_at=now() only if approved_at is currently null (CLAUDE.md immutability rule enforced)
- comment: validates token, checks entity ownership (task or deliverable) via phase→client chain, inserts comment with author='client'
- both routes return 404 on invalid token or unknown entity
- neither route references quote_items (CLAUDE.md constraint enforced)
- Zod validation on comment body: min 1 char, max 2000 chars (T-02-20 DoS mitigation)
2026-05-15 21:39:32 +02:00