Commit graph

17 commits

Author SHA1 Message Date
f1cbe941e9 feat(CC-066): add journal entry for migration 0012 2026-08-02 12:09:01 +00:00
641c68ed91 feat(CC-066): add action_plans and scenarios tables (migration 0012) 2026-08-02 12:09:00 +00:00
035b71108b feat(CC-064): add contracts, obligations, pipeline_deals migration 2026-08-01 21:24:19 +00:00
e2756ffe79 chore(CC-064): add 0011_contracts_pipeline to migration journal 2026-08-01 21:24:18 +00:00
da8ac3359a feat(CC-063): add contacts, risks, projects tables migration 2026-08-01 21:20:49 +00:00
080769998a chore(CC-063): add 0010_ceo_os_features to migration journal 2026-08-01 21:20:48 +00:00
46a152dd13 feat(cc-052): add 0009_financial_intelligence to drizzle journal 2026-08-01 10:32:00 +00:00
ae7be88829 feat(cc-052): migration 0009 — financial_signals table 2026-08-01 10:31:59 +00:00
c3b0005e19 feat(db): versioned Drizzle migration for workspace_id columns (CC-044 backfill) 2026-07-31 14:39:24 +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
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
42cefaddb2 feat: Platform Kernel v1 -- workspaces, ExecutionContext, /v1/navigation, event envelope
Specul de arhitectura cere Platform Kernel INAINTEA modulelor de domeniu.
Modulele A1/A2 au fost construite peste un kernel caruia ii lipseau exact
piesele astea. Le adaug acum, aditiv, fara sa rup ce merge.

- workspaces: tenant != workspace. Workspace-ul e contextul de lucru DIN
  tenant. Backfill: fiecare tenant existent primeste workspace implicit,
  altfel SessionGuard i-ar respinge toate requesturile.
- memberships.workspace_id + valid_from/valid_until: rol per workspace si
  acces delegat cu expirare (contabil pana la o data). SessionGuard respinge
  membership expirat si membership legat de alt workspace.
- ExecutionContext inlocuieste sesiunea subtire (userId+tenantId+role):
  requestId, correlationId, workspaceId, membershipId, roles, permissions,
  purpose, timezone, source. Tipul vechi ramane exportat sub acelasi nume,
  ca sa nu ating ~15 module de domeniu doar pentru o redenumire.
- GET /v1/navigation: menu registry mutat in backend. Filtreaza pe rol, tip
  de workspace, permisiuni si feature flags; intoarce doar itemii autorizati.
  Ramane UX, nu securitate -- fiecare endpoint verifica din nou.
- event envelope: workspace_id, occurred_at, actor_id, aggregate_type,
  causation_id, classification, provenance
- audit envelope: workspace_id, actor_type, purpose, changed_fields,
  before/after hash, session_id
2026-07-29 11:46:20 +02:00
3bc0d65c46 feat: AI Gateway -- Context Manifest, model routing, cost audit, guardrails
- AiGatewayService: punct unic de acces la modele (LiteLLM -> OpenRouter).
  Clasele de actiuni din blueprint 14.3 sunt aplicate hard: high_risk blocat
  permanent, material blocat pana exista coada de aprobare + idempotency;
  doar read_only si draft ruleaza.
- Spotlighting (design doc Strat 1): continutul untrusted (date Apollo) e
  impachetat in <untrusted-data> cu instructiune de sistem ca e DATE, nu
  comenzi -- plus redactie PII deterministica (email/telefon/CNP) inainte
  sa plece catre provider extern.
- ai_requests: adaugat action_class + context_manifest complet (nu doar
  hash) pentru audit; cost_usd_minor_units (integer) inlocuit cu
  cost_usd numeric(12,6) -- costurile reale sunt fractiuni de cent.
- research-briefs: POST /draft genereaza un rezumat AI din datele Apollo
  fara sa salveze nimic (clasa draft -- userul revizuieste, apoi salveaza).
- briefing: aiExplanation devine narativ real peste prioritizarea
  determinista; esecul AI intoarce null, nu strica briefingul.
- teste: clase de actiuni blocate, spotlighting, redactie PII.
2026-07-28 22:34:36 +02:00
0f8390f31b feat: Faza A2 -- intelligence proxy, saved segments, research briefs, briefing
- IntelligenceModule: proxy tenant-scoped catre intelligence-api
  (/companies/search, /companies/{id}); ceo-web nu vorbeste niciodata
  direct cu intelligence-api (blueprint 10.3/16).
- SavedSegments: salveaza o cautare Apollo si o ruleaza din nou oricand.
- ResearchBriefs: dovezi curatate manual per companie, cu sursa Apollo
  implicita plus surse suplimentare -- explicit fara rezumat generat de
  AI (AI Gateway inca neconstruit, blueprint 14).
- BriefingService: /v1/briefing/today, agregare deterministica de
  taskuri restante/viitoare + activitate saptamanala; campul
  aiExplanation ramane null si vizibil in raspuns, nu simulat.
2026-07-28 22:01:17 +02:00
0ea8e69233 feat: multi-tenant core -- session auth, RBAC, organizations, tasks, audit
- SessionGuard resolves Supabase JWT (local HS256 verify, GoTrue fallback)
  and loads the tenant membership from x-tenant-id; TenantGuard keeps
  deny-by-default and rejects client-supplied tenant_id (blueprint 11.3).
- New bootstrap routes: GET /v1/me, POST/GET /v1/tenants, tenant member
  management (list/add/remove) with owner/admin RBAC.
- Organizations and Tasks modules: full CRUD scoped to session.tenantId,
  soft delete, audit log + outbox events on every write.
- AuditService (global) for blueprint 3.4 "100% audit on material ops".
- jest + tenant.guard.spec covering deny-by-default and anti-IDOR cases.
2026-07-28 21:15:43 +02:00
5656f1cc1c feat: scaffold Business/Life/Intelligence/Trust Engine tables
Per Blueprint v4.0 §12 canonical data models:
- Business Engine: organizations extended (legal_name, country, registry_id,
  domain, external_ids), transactions (minor-unit amounts, evidence_status),
  documents (metadata only -- binary/OCR stays in Paperless via paperless_id)
- Life Engine: goals (horizon/metric/target/milestones)
- Intelligence Engine: decisions (context/options/assumptions/evidence),
  opportunities, ai_requests (context_manifest_hash for audit without
  storing sensitive payload content in Postgres)
- Trust Engine: observations (generic subject_type/subject_id so any
  entity -- user, org, device -- can feed reputation/trust scores)

Applied directly to Supabase staging Postgres (14 tables total now).
This is also the first drizzle/ migration actually committed -- the
earlier one from the Identity Engine work never made it into git.
2026-07-21 19:44:45 +02:00