Commit graph

65 commits

Author SHA1 Message Date
020b0c21da fix(test): mock db+supabase at module level so SessionGuard loads without real DB in TST-012 2026-07-31 15:03:40 +00:00
694ba7a5a6 fix(test): default import for supertest (esModuleInterop), add CASL member high-risk denial test 2026-07-31 15:01:46 +00:00
e3b5cca72c chore: regenerate lockfile after supertest devDep addition 2026-07-31 15:00:09 +00:00
4f801d6964 fix(deps): add supertest + @types/supertest devDeps for TST-012 security tests 2026-07-31 15:00:08 +00:00
b9f9c970b7 fix(ts): cast SupabaseClient through unknown in Proxy get trap (TS2352) 2026-07-31 15:00:07 +00:00
ebbac2dc58 docs(privacy): PRV-005 GDPR Legal Basis Registry — CC-046 securizare 2026-07-31 14:58:03 +00:00
e22215ab64 test(security): TST-012 HTTP-level security test suite (auth, headers, CORS, CASL, route enum) 2026-07-31 14:57:03 +00:00
1c784b654f feat(security): Goal/Decision/Observation/Opportunity as explicit CASL subjects for member role (SEC-004/F4) 2026-07-31 14:57:02 +00:00
ace0000349 fix(security): startup env validation + CORS origin filter (SEC-012/F6) 2026-07-31 14:57:01 +00:00
7d43bc6b70 fix(security): USER node + HEALTHCHECK in production stage (SEC-013/F9/F11) 2026-07-31 14:57:01 +00:00
97c32222ce fix(supabase): lazy client init — validates env vars at first use, not at import time 2026-07-31 14:44:00 +00:00
c7e09ed647 test(integration): audit log, outbox atomicity and transaction minor units tests 2026-07-31 14:40:30 +00:00
458217a0ec test(integration): tenant isolation tests for goals and organizations 2026-07-31 14:40:29 +00:00
c3b0005e19 feat(db): versioned Drizzle migration for workspace_id columns (CC-044 backfill) 2026-07-31 14:39:24 +00:00
21c6ff2fde feat(schema): add workspaceId to 11 tables missing from Drizzle ORM (organizations, tasks, goals, decisions, transactions, documents, opportunities, observations, ai_requests, research_briefs, saved_segments) 2026-07-31 14:39:23 +00:00
f5ac5f11f1 chore: regenerate package-lock.json after dependency version fixes 2026-07-31 14:36:21 +00:00
94506c8f80 fix(deps): @nestjs/schedule ^5.0.0 + @nestjs/testing devDep for NestJS 11 compatibility 2026-07-31 14:36:19 +00:00
0e016edec2 fix(opportunities): enforce @IsInt() on valueRangeMin/Max to prevent float input 2026-07-31 10:48:40 +00:00
6c44c327cf fix(transactions): remove ad-hoc UUID regex, use ParseUUIDPipe for path params 2026-07-31 10:48:38 +00:00
3b1b14e380 fix(decisions): wrap mutations in db.transaction() for audit atomicity 2026-07-31 10:48:37 +00:00
880c2a7018 test(transactions): add unit tests for TransactionsService 2026-07-31 10:47:16 +00:00
19fd999441 test(goals): add unit tests for GoalsService 2026-07-31 10:47:15 +00:00
281fb9e780 feat(projection): wire transactionsUnclassifiedCount to executive dashboard 2026-07-31 10:46:11 +00:00
bdcf63e2a6 feat: register Goals, Decisions, Transactions, Observations, Opportunities modules 2026-07-31 10:45:07 +00:00
7569d7ee87 feat(opportunities): add opportunities.module 2026-07-31 10:45:06 +00:00
5caa233bea feat(opportunities): add opportunities.controller 2026-07-31 10:45:05 +00:00
80fd3e0b4e feat(opportunities): add opportunities.service 2026-07-31 10:45:04 +00:00
0243e78fea feat(opportunities): add dto 2026-07-31 10:45:03 +00:00
0105bf1f73 feat(observations): add observations.module 2026-07-31 10:45:02 +00:00
8db3ccf300 feat(observations): add observations.controller 2026-07-31 10:45:01 +00:00
f2733c6e72 feat(observations): add observations.service 2026-07-31 10:45:01 +00:00
3cd2bdc82b feat(observations): add dto 2026-07-31 10:45:00 +00:00
4315e7f31f feat(transactions): add transactions.module 2026-07-31 10:44:59 +00:00
78d60c69ab feat(transactions): add transactions.controller 2026-07-31 10:44:58 +00:00
a80bd5080b feat(transactions): add transactions.service 2026-07-31 10:44:57 +00:00
844dd81af2 feat(transactions): add dto 2026-07-31 10:44:56 +00:00
00b0c843f9 feat(decisions): add decisions.module 2026-07-31 10:44:56 +00:00
e1fc7eb0b7 feat(decisions): add decisions.controller 2026-07-31 10:44:55 +00:00
b60c255080 feat(decisions): add decisions.service 2026-07-31 10:44:54 +00:00
df054750f2 feat(decisions): add dto 2026-07-31 10:44:53 +00:00
284fba0d3a feat(goals): add goals.module 2026-07-31 10:44:52 +00:00
90c4932227 feat(goals): add goals.controller 2026-07-31 10:44:51 +00:00
160daab7c9 feat(goals): add goals.service 2026-07-31 10:44:51 +00:00
9d9870877e feat(goals): add dto 2026-07-31 10:44:50 +00:00
a3b29e6cc2 fix: guard Swagger /docs behind SWAGGER_ENABLED env var 2026-07-31 10:32:52 +00:00
10fe16a7f5 fix: guard Swagger /docs behind SWAGGER_ENABLED env var 2026-07-31 10:30:29 +00:00
765ec37c3a feat: Saga Manager (Sprint 4-6)
Motor generic pentru procese cu mai multi pasi care nu incap intr-o
tranzactie. Garantia nu e atomicitatea, ci compensarea in ordine inversa.

- saga-registry: definitii versionate in cod, backoff exponential plafonat
- saga-runner: corelator outbox->instanta, step runner, timeout, retry,
  compensare; revendicare cu FOR UPDATE SKIP LOCKED ca doua procese sa nu
  avanseze aceeasi saga simultan
- idempotenta la pornire prin index unic (saga, versiune, trigger_event),
  nu prin SELECT-apoi-INSERT care ar avea race
- compensarea are propriul retry: o compensare esuata lasa sistemul mai rau
  decat esecul original
- monitor /v1/sagas cu instante blocate si retry manual care NU sare pasi
- prima saga reala: imbogatire research brief, fara pas AI (un apel AI
  automat per brief ar schimba profilul de cost)
2026-07-29 15:02:56 +02:00
c8b9be585e refactor: extrage quiet hours in functie pura si o acopera cu teste
Aritmetica ferestrei care traverseaza miezul noptii era netestata si prinsa
intr-o metoda privata. Extrasa in quiet-hours.ts cu 10 teste care acopera
fereastra simpla, traversarea miezului noptii si politica de bypass CRITICAL.

Documenteaza explicit ca agregarea nu reevalueaza quiet hours: incrementarea
unui contor pe o notificare deja vizibila nu e o intrerupere noua.
2026-07-29 14:48:04 +02:00
80e9ede875 feat: Sprint 2-3 -- Notifications Engine
Motorul NU trimite o notificare per eveniment. Decide daca merita notificat,
cui, ce severitate, daca se agrega, ce canal si cand.

- notifications / notification_preferences / notification_processed_events.
  Ultimul da idempotency: aceeasi regula nu proceseaza acelasi eveniment de
  doua ori (unique rule_id + event_id).
- Reguli in COD, nu in DB cu condition_expression evaluat dinamic. Un
  evaluator de expresii e o suprafata de atac si un limbaj in plus, fara ca
  nimeni sa administreze inca reguli per tenant. Contractul ramane acelasi
  cand vor migra in DB.
- Destinatarii se rezolva server-side din memberships, niciodata din payload.
  Implicit nu notificam actorul despre propria actiune.
- Deduplicare pe cheia tenant+recipient+categorie+entitate+versiune regula.
- Agregare: 47 de taskuri intr-o ora devin o notificare cu aggregated_count,
  nu 47 de notificari. Testul verifica invariantul ca fereastra de agregare
  <= fereastra de dedup, altfel s-ar crea una noua inainte sa se agrege.
- Quiet hours cu fereastra care poate traversa miezul noptii. CRITICAL le
  depaseste DOAR daca politica userului permite, nu implicit.
- Inbox: filtre (unread/action_required/critical/intelligence/system),
  mark-read, acknowledge (opreste escaladarea), dismiss, snooze.
- Preferinte per user+tenant cu UPSERT (NULLS NOT DISTINCT pe category, ca
  randul implicit "toate categoriile" sa fie unic).
2026-07-29 14:36:29 +02:00
eb652446f6 feat: Sprint 1 -- Projection Kernel (read models pentru dashboard)
Repara criteriul de acceptare "dashboardurile citesc read models, nu
interogheaza haotic toate modulele".

- projection_processed_events (unique: name+version+event_id) = garantia de
  idempotency. Checkpointul e doar optimizare de scanare, nu corectitudine:
  rescanam cu un safety lag de 60s si sarim ce s-a aplicat deja, ca sa nu
  pierdem evenimente comise dupa unul cu created_at mai mare.
- ProjectionRegistry cu ProjectionDefinition (name, version, subscribedEvents,
  rebuildStrategy, apply, rebuildTenant).
- executive_dashboard foloseste rebuildStrategy 'canonical-tables':
  recalculeaza contorii din tabelele canonice, nu incrementeaza. Contorii
  incrementali pot deriva daca un eveniment se pierde sau se dubleaza;
  recalcularea e corecta prin constructie si idempotenta natural. Costul e o
  interogare per eveniment relevant -- ok la volumul actual.
- GET /v1/dashboard/executive citeste proiectia. Cand proiectia inca n-a rulat
  pentru workspace, intoarce status 'building' explicit, NU zerouri care ar
  parea date reale.
- POST /v1/dashboard/executive/rebuild -- owner/admin, auditat.
- Serviciile de taskuri/organizatii/segmente emit acum evenimente in outbox
  (in aceeasi tranzactie cu scrierea). Fara ele proiectia era cod mort.
- Campurile din spec care depind de module neconstruite (documents,
  transactions, approvals) raman 0 explicit, nu inventate.
2026-07-29 12:03:34 +02:00