Scope
The “Enterprise Enrichment Plan” carried out in three labelled phases over two days, 2026-03-24 → 2026-03-25.
Plan document referenced: plans/ENTERPRISE_ENRICHMENT_PLAN.md (in repo, not in vault).
Commits
2f1119d — 2026-03-24 — Phase 1
“feat: Phase 1 critical fixes — reklamspärr gate, real validation layers, Art.14 at collection, email confidence”
Co-author: Claude Sonnet 4.6.
What changed:
src/compliance/reklamsparre.ts— new Gate 0.isScbAdvertisingBlocked()checks the SCBadvertising_blockcolumn (Reklam=2). See Reklamspärr.src/queues/workers.ts— replaced brokenisOptedOut(orgNr)with the new gate. Triggered Article 14 inupdateWorker.src/api/export.ts— removed Article 14 trigger from the export handler. GDPR Art.14(3)(b) requires notification at collection time, not at export. See Article 14.src/workers/art14Worker.ts— new BullMQArt14_Jobworker for async notification.src/fetchers/bolagsverket/openApi.ts— real BV Öppen API client with OAuth2 token caching (replaced mock).src/validation/layers/registryLayer.ts— real Layer 1, BV active-status check (replacedhash(orgNr) % 2mock).src/validation/layers/newsLayer.ts— real Layer 4, Serper news check (replacedrandom < 0.2mock).enrichmentEngine.v7.ts:286—generateEmailGuesses()confidence demotedmedium→low, source set togenerated_guess.enrichmentEngine.v7.ts:765— fixed LinkedIn regex: escaped special chars and a\bat\bbackspace bug.
Before this commit, two of the four validation layers returned random or hash-based mock data. Lead scores from before 2026-03-24 are not comparable to scores after.
714a500 — 2026-03-24 — Phase 2
“feat: Phase 2 — decompose enrichmentEngine.v7.ts god file into modules”
Broke the 1176-line monolith into single-responsibility modules:
src/enrichment/
types.ts — EnrichmentInput, EnrichedContact, EnrichmentResult, RoleType, SearchResult
config.ts — INVALID_DOMAINS, INVALID_NAME_WORDS, INVALID_SUFFIXES
processors/
nameUtils.ts — inferRoleType, isValidPersonName, normalizeCompanyName (pure)
emailUtils.ts — normSe, extractEmails, generateEmailGuesses, detectEmailPattern (pure)
phoneUtils.ts — extractPhones (pure)
scoring.ts — calculateLeadScore (pure)
sources/
serper.ts — serperSearch() — replaced axios with native fetch
domain.ts — findCompanyDomain(), validateCompanyDomain()
maps.ts — queryGoogleMaps()The current layout in Repository Layout descends from this commit. The pure annotation indicates processors/ modules have no I/O and are unit-testable.
c006048 — 2026-03-25 — Phase 3
“feat: Phase 3 — scale infrastructure for 1.4M enrichment runs/year”
Infrastructure for scale, not worker isolation. What landed:
migrations/002_enrichment_scale.sql— promoted JSONB fields (domain,lead_score,contacts_count,has_vd_contact,last_enriched_at) to real columns. Indexedlead_score DESC,has_vd_contact,domain,last_enriched_at. Addedidx_companies_needs_refresh(partial index, stale > 6 months).idx_art14_email_orgfor Art.14 dedup. AddedRoPA_Log.month_bucketcolumn + index. Addedenrichment_queue_statetable.src/lib/redisClients.ts— six named Redis logical DBs (BullMQ, enrich-cache, rate-limit, bv-token, domain-cache, serper-cache).src/workers/enrichDispatcher.ts— rolling refresh at ~160 companies/hour (13 per batch every 5 min).
This commit does NOT decouple Playwright from the enrich worker. Memory
MEMORY.mdflags this as a still-open critical blocker before raising concurrency above 40. Phase 3 closed the data-layer scaling gap; the runtime-layer isolation work has not landed.
95694e5 — 2026-03-25 — Phase 3 follow-up
“fix: migration 002 — remove partial index with NOW(), move Art14 index to runtime, fix GENERATED column”
Fix-up to the migration. Postgres rejects NOW() inside a partial index predicate (the index would freeze at create time). Patch moved the timestamp comparison out of the index WHERE clause and into runtime queries.
Significance
The refactor era is the single biggest architectural pivot in the visible history. The current shape of src/enrichment/ and the migrations/ numbering scheme both originate here.
See also
EnrichV7, Lead Scoring, Reklamspärr, Article 14, Database Schema, History Overview.