# NexusCRM Code Map v5.7

> **Generated**: 2026-03-23
> **Methodology**: 8-Agent Parallel Deep Analysis + Cross-Validation + Adversarial Review
> **Status**: Architecture fully mapped. Development model identified.
> **Agents**: Architect / Pathfinder / Tester / Reviewer / Challenger / DataModel / APISurface / FeatureInteraction

---

## Development Model

> **This is the single most important section of the Code Map.**

### How This Project Is Built

```
                 Salesforce API (v63.0)
                 =====================
                 The "finished product"
                 The reference implementation
                        |
                        | Frontend built against real SF API
                        v
            +-------------------------+
            |   Frontend (React)      |  <-- SOURCE OF TRUTH for API contracts
            |   Every API call is a   |      Verified against working Salesforce
            |   SPECIFICATION of what |      DO NOT change unless SF API changes
            |   the backend must do   |
            +-------------------------+
                        |
                        | Backend implements the same surface
                        v
            +-------------------------+
            |   Backend (Go + TiDB)   |  <-- IMPLEMENTATION of the spec
            |   Goal: match what the  |      Missing routes = unfinished work
            |   frontend expects      |      NOT bugs or drift
            +-------------------------+
```

**Analogy**: Build the nut against a finished bolt (Salesforce), then build your own bolt (backend) to fit the nut (frontend).

### Development Constraints

1. **Frontend is the API contract specification.**
   Every endpoint in `ApiEndpoints.ts`, every call in `flows.ts`, `schemas.ts`, `data.ts`
   was built against a working Salesforce instance. These are not guesses — they are
   verified contracts.

2. **Frontend MUST NOT change unless verified against Salesforce API.**
   If a frontend API call follows Salesforce conventions, it is correct by definition.
   Changing it to match backend convenience breaks the contract and defeats the purpose.

3. **Backend changes must preserve frontend behavior.**
   The backend's job is to implement the surface the frontend expects. If the frontend
   calls `/tooling/query?q=SELECT...FROM FlowDefinition`, the backend must handle that
   exact URL with that exact SOQL — not offer a different endpoint and ask the frontend
   to change.

4. **Missing backend routes are unfinished features, not bugs.**
   When the frontend calls `/tooling/query` and gets 404, that means the backend hasn't
   implemented this Salesforce-compatible route yet. The frontend is correct.

### Backend Implementation Completeness

| API Surface | Frontend expects | Backend status |
|-------------|-----------------|----------------|
| SObject CRUD (`/sobjects/*`) | Yes | **Complete** |
| SOQL Query (`/query`) | Yes | **Complete** |
| Search (`/search`, `/parameterizedSearch`) | Yes | **Complete** |
| Composite API (`/composite/*`) | Yes | **Complete** |
| Bulk API v2 (`/jobs/*`) | Yes | **Complete** |
| Analytics (`/analytics/*`) | Yes | **Complete** (table name bugs fixed) |
| UI API (`/ui-api/*`) | Yes | **Complete** |
| OAuth (`/services/oauth2/*`) | Yes | **Complete** |
| CometD Streaming (`/cometd/*`) | Yes | **Complete** |
| Flow Typed CRUD (`/tooling/sobjects/FlowDefinition`, `Flow`) | Yes | **Complete** |
| Flow Execution (`/actions/custom/flow/*`) | Yes | **Complete** |
| Folders (`/folders/*`) | Yes | **Complete** |
| Quick Actions | Yes | **Complete** |
| Approvals | Yes | **Complete** |
| **Tooling Query** (`/tooling/query?q=`) | Yes | **Complete** |
| **Tooling sObject: ValidationRule** | Yes | **Complete** |
| **Tooling sObject: CustomObject** | Yes (update) | **Complete** |
| **Tooling sObject: CustomField** | Yes (create) | **Complete** |
| **Tooling sObject: ProfileLayout** | Yes | **Complete** |
| **Tooling sObject: FlowTestCoverage** | Yes (via query) | **NOT IMPLEMENTED** |

**Completion: ~80%.** Core CRUD, query, composite, analytics, streaming all work. The gap is Tooling API — metadata management operations that the frontend uses for schema/field/validation/layout/flow administration.

---

## Quick Navigation

| Category | Link | Status |
|----------|------|--------|
| Architecture Overview | [Architecture Analysis](#1-architecture-analysis) | Done |
| Core Modules | [Module Inventory](#2-core-module-inventory) | Done |
| Critical Paths | [Path Tracing](#3-critical-execution-paths) | Done |
| Test Coverage | [Coverage Report](#4-test-coverage) | Done |
| Code Quality | [Quality Report](#5-code-quality) | Done |
| Claim Verification | [Verification Report](#6-architecture-claim-verification) | Done |
| Priorities | [Priority List](#7-priority-list) | Done |
| Data Model | [Entity Relationships](#10-data-model--entity-relationships) | Done |
| API Surface | [Endpoint Map](#11-api-surface) | Done |
| Feature Interactions | [Service Wiring](#12-feature-interactions) | Done |

---

## 1. Architecture Analysis

### 1.1 System Architecture Diagram

```
+---------------------------------------------------------------------+
|                    Frontend (React + Vite + TanStack Query)          |
|                                                                     |
|  +----------+  +-----------+  +----------+  +------------------+   |
|  |  Pages   |->| Features  |->|  Core    |->| Infrastructure   |   |
|  | (31 files)|  |(259 files)|  |(58 files)|  |   /api (34)      |   |
|  +----------+  +-----------+  +----------+  +------------------+   |
|       |              |             |              |                  |
|  +----------+  +-----------+  +----------+  +------------------+   |
|  |Components|  | Registries|  | Contexts |  |     Types        |   |
|  | (36 files)|  | (10 files)|  | (6 files)|  |   (9 files)      |   |
|  +----------+  +-----------+  +----------+  +------------------+   |
+---------------------------------------------------------------------+
                            | HTTP/REST (fetch + React Query)
                            v
+---------------------------------------------------------------------+
|              Backend (Go 1.22 - Clean Architecture - Gin)           |
|                                                                     |
|  +-------------------------------------------------------------+   |
|  | Middleware (9 layers): RequestID -> Logger -> Tracing ->      |   |
|  |   Recovery -> ErrorHandler -> Security -> CORS -> Metrics ->  |   |
|  |   RateLimit(100rps) -> [per-route: RequireAuth]               |   |
|  +-------------------------------------------------------------+   |
|                                                                     |
|  +----------+  +--------------+  +-----------+  +-------------+    |
|  |interfaces |->|  features     |->|  domain   |<-|infrastructure|  |
|  |/rest (61) |  |(120 files)   |  |/ports (11)|  |/persistence |   |
|  |13,233 LOC |  |  analytics   |  |/schema (3)|  |  (63 files) |   |
|  |           |  |  auth        |  |  751 LOC  |  | 12,318 LOC  |   |
|  |           |  |  automation  |  |           |  |             |   |
|  |           |  |  metadata    |  |           |  |/database(1) |   |
|  |           |  |  records     |  |           |  |  154 LOC    |   |
|  |           |  |  permissions |  +-----------+  +-------------+   |
|  |           |  |  events      |                                    |
|  |           |  |  streaming   |  +---------------------------+    |
|  |           |  |  uiapi       |  | application/services (4)  |    |
|  |           |  |  ...         |  | ServiceManager (DI root)  |    |
|  +----------+  +--------------+  +---------------------------+    |
|                                                                     |
|  +-------------------------------------------------------------+   |
|  | pkg/: apierr(37 imp) query(35) utils(28) errors(28)         |   |
|  |       logging(23) formula(23) soql(2) auth(11)              |   |
|  +-------------------------------------------------------------+   |
+---------------------------------------------------------------------+
                            |
                            v
+---------------------------------------------------------------------+
|            Shared Kernel (SSoT Pipeline)                            |
|                                                                     |
|  system_tables.json (6,594L) -> cmd/codegen -> 7 generated files   |
|  +----------------+  +----------------+  +---------------------+   |
|  | pkg/models     |  | pkg/constants  |  | frontend/generated-* |  |
|  | (179 importers)|  |(153 importers) |  | (schema, api, errs)  |  |
|  +----------------+  +----------------+  +---------------------+   |
+---------------------------------------------------------------------+
                            |
                            v
                    +---------------+
                    |  TiDB Cloud   |
                    | (MySQL 8.0)   |
                    |   Port 4000   |
                    +---------------+
```

### 1.2 Codebase Size

| Layer | Files | Lines of Code | Share |
|-------|-------|---------------|-------|
| Backend (Go) | 274 source + 136 test | 66,240 (incl. 15,705 test) | 45% |
| Frontend (TS/TSX) | 400 source + 35 test | 73,756 | 50% |
| Shared (Go) | ~30 files | 7,319 | 5% |
| **Total** | **~915 files** | **~147,315** | 100% |

### 1.3 Frontend Provider Chain

```
ErrorBoundary
  +- QueryClientProvider (TanStack Query)
       +- NotificationProvider
            +- RuntimeProvider (auth, user, kernel boot)
                 +- BrowserRouter
                      +- [if authenticated]
                           +- AppProvider (apps, navigation)
                                +- UIProvider
                                     +- PermissionProvider
                                          +- Router + ToastContainer + VersionUpdater
```

---

## 2. Core Module Inventory

### 2.1 Ranked by Criticality (Fan-In x Risk)

| Rank | Module | Fan-In | Fan-Out | LOC | Risk | Rationale |
|------|--------|--------|---------|-----|------|-----------|
| 1 | `shared/pkg/models` | **179** | 0 | ~2,800 | Low | Most widely depended-on (generated code, stable) |
| 2 | `shared/pkg/constants` | **153** | 0 | ~4,000 | Low | Same as above + but has `manual_fields.go` bypass |
| 3 | `infrastructure/persistence` | 25 | 10 | **12,318** | **HIGH** | Largest package, all SQL concentrated here |
| 4 | `interfaces/rest` | 4 | **28** | **13,233** | **HIGH** | Highest coupling, second largest package |
| 5 | `features/metadata` | **32** | 15 | 4,563 | **HIGH** | Core of metadata-driven design |
| 6 | `features/records` | 15 | **21** | 4,688 | **HIGH** | Deep coupling + persistence bypass |
| 7 | `domain/ports` | **38** | 6 | 751 | Medium | Interface contract stability is critical |
| 8 | `features/permissions` | **21** | 14 | 2,178 | Medium | Security core + persistence bypass |
| 9 | `features/events` | **21** | 4 | 969 | Medium | Event backbone |
| 10 | `application/services` | 20 | 18 | 710 | Medium | DI root, architecture violation point |
| 11 | `frontend/core` | **371 imp** | -- | ~3,500 | Medium | Most critical frontend dependency |
| 12 | `frontend/infrastructure/api` | **130 imp** | -- | ~5,000 | Medium | All API communication |
| 13 | `frontend/features/flows` | -- | -- | ~6,000 | Medium | 39% of all frontend feature code |

### 2.2 Frontend Feature Modules

| Feature | Files | Test Files | Coverage | Complexity |
|---------|-------|------------|----------|------------|
| `flows` (visual flow builder) | 102 | 13 | Partial | Very High |
| `admin` (system management) | 32 | 0 | None | High |
| `analytics` (reports & dashboards) | 23 | 0 | None | Moderate |
| `record` (generic record CRUD) | 21 | 0 | None | Moderate |
| `studio` (layout editor) | 19 | 0 | None | Moderate |
| `approvals` (approval workflows) | 17 | 0 | None | Moderate |
| `dashboard` | 10 | 0 | None | Low |
| `auth` | 4 | 0 | None | Low |
| Other 10 features | 1-4 each | 0 | None | Minimal |

---

## 3. Critical Execution Paths

### 3.1 Backend CRUD Request Path (CreateRecord)

```
HTTP POST /services/data/v63.0/sobjects/{name}
  |
  +- [9 Middleware] RequestID -> Logger -> Tracing -> Recovery -> ErrorHandler
  |                 -> Security -> CORS -> Metrics -> RateLimit
  |
  +- [Auth] RequireAuth -> ValidateSession -> UserSession in context
  |
  +- [Handler] sobject_records.go:121 CreateRecord()
  |   +- Parse :sobject, bind JSON, extract UserSession
  |   +- svcMgr.Metadata.GetSchema() -- validate object exists
  |   +- validateInput() -- check field names against schema
  |
  +- [Service] persistence_insert.go:23 Insert()
  |   +- prepareOperation() -- permission check
  |   +- applyDefaults() -- default values from metadata
  |   +- generateSystemFields() -- Id, CreatedDate, etc.
  |   +- schemaValidator.ValidateSchemaCompliance()
  |   +- validateQueueAssignment()
  |   +- validatePolymorphicLookups() -- WARNING: per-field DB query
  |   +- RunInTransaction():
  |       +- generateAutoNumbers()
  |       +- publishRecordEvent(BeforeCreate) -- sync, can abort
  |       +- filterToLogicalFields()
  |       +- repo.Insert() -> [Repository]
  |       +- rollup.ProcessRollups() -- same TX
  |       +- outbox.EnqueueEvent(RecordCreated) -- async via outbox
  |
  +- [Repository] record_repository.go:174 Insert()
      +- Load schema for logical->physical aliasing
      +- Flatten JSON maps
      +- query.Insert() builder with column aliasing
      +- ExecContext() -> TiDB
```

**Total hops**: ~13 function calls | **Complexity**: Complex

### 3.2 Backend CRUD Request Path (GetRecord) -- N+1 Problem

```
HTTP GET /services/data/v63.0/sobjects/{name}/{id}
  |
  +- [Handler] sobject_records.go:17 GetRecord()
  |   +- svc.Persistence.Get()
  |
  +- [Service] persistence_get.go Get()
  |   +- repo.FindOne()
  |
  +- [Repository] record_repository.go FindOne()
  |   +- Single DB query
  |
  +- [Handler] sobject_records.go:72 hydrateLookups()
      +- WARNING: FOR EACH reference field with a value:
          +- svc.Persistence.Get() -- N+1 QUERY!
              +- 5 lookup fields = 5 additional DB queries
```

**Total hops**: ~8 + N | **Bottleneck**: `hydrateLookups()` N+1 queries

### 3.3 Frontend Request Path

```
User Click -> Page Component (ObjectView.tsx)
  |
  +- useObjectMetadata(objectApiName) -- React Query, 10min staleTime
  |   +- metadataAPI.getSchema() -> GET /sobjects/{name}/describe
  |
  +- useCreateRecord() -- useMutation wrapper
  |   +- dataAPI.createRecord(objectName, data)
  |   |   +- apiClient.post() -> POST /sobjects/{name}
  |   +- onSuccess: invalidate list cache, show toast
  |   +- onError: show error toast
  |
  +- APIClient.request() -- native fetch (NOT Axios)
      +- Inject: X-Request-ID (UUID), traceparent (W3C), Authorization
      +- Error: parse SF-format [{errorCode, message}]
      +- 401: dispatch auth:unauthorized event
```

**Total hops**: 5 | **Complexity**: Simple

### 3.4 Metadata Engine Path

```
[Build Time]
system_tables.json -> cmd/codegen -> 7 generated files (Go + TS)

[Boot Time]
//go:embed system_tables.json
  -> InitializeSchema() -- DDL reconciliation, 2-pass metadata registration
    -> MetadataService.RefreshCache()
      -> Load ALL schemas from _System_Object + _System_Field
      -> Build in-memory maps (schemaMap, fieldMap, validationRulesMap, ...)
      -> WARNING: Full write lock during refresh (blocks all reads)

[Runtime]
MetadataService.GetSchema(name) -> O(1) map lookup (RWMutex read lock)

[Frontend]
useObjectMetadata() -> React Query (10min staleTime)
  -> GET /sobjects/{name}/describe -> MetadataService.GetSchema()
    -> LayoutRenderer iterates layout.sections[].rows[].items[]
      -> InlineEditField per field with type/metadata
      -> WARNING: Case-insensitive Array.find() per field per render (O(n*m))
```

### 3.5 Code Generation Path

```
make generate
  +- cd backend && go run ./cmd/codegen
      +- Source: internal/bootstrap/system_tables.json (6,594 lines)
         + api_contracts.json
      +- Output (10 files, 7,203 generated lines):
          +- shared/pkg/constants/z_generated_tables.go  (173L)
          +- shared/pkg/constants/z_generated_fields.go  (2,076L)
          +- shared/pkg/constants/z_generated_columns.go (1,046L)
          +- shared/pkg/models/z_generated.go            (1,423L)
          +- frontend/src/generated-schema.ts            (2,353L)
          +- frontend/src/generated-api.ts               (105L)
          +- frontend/src/generated-error-codes.ts       (27L)
          +- shared/pkg/api/dtos.go
          +- docs/openapi.yaml
          +- backend/pkg/fieldtypes/fieldTypes.json

```

---

## 4. Test Coverage

### 4.1 Backend Coverage (Actual `go test -cover` Results)

| Package | Coverage | Rating | Notes |
|---------|----------|--------|-------|
| `features/auth` | **90.7%** | Good | Was 0% (PR #255) |
| `features/streaming` | **81.6%** | Good | |
| `pkg/soql` | **75.4%** | Good | |
| `pkg/flags` | **70.0%** | Good | |
| `features/events` | **95.5%** | Excellent | Was 70.3% (PR #280) |
| `interfaces/middleware` | **88.2%** | Good | Was 65.3% (PR #321) |
| `pkg/validation` | **45.9%** | Moderate | |
| `pkg/expression` | **41.5%** | Moderate | |
| `pkg/formula` | **34.9%** | Low | 23 importers, high blast radius |
| `features/mru` | **100%** | Excellent | Was 23.9% (PR #315) |
| `pkg/query` | **97.9%** | Excellent | Was 22.3% (PR #331). 35 importers, high blast radius |
| `pkg/fieldtypes` | **97.7%** | Excellent | Was 20.2% (PR #343) |
| `features/analytics` | **92.3%** | Excellent | Was 58.7% (PR #329), was 17.9% (PR #320) |
| `pkg/utils` | **97.4%** | Excellent | Was 15.4% (PR #342) |
| `interfaces/rest` | **46.4%** | Moderate | 13,233 LOC (was 37.4%, PR #332; was 26.9%, PR #327; was 16.6%, PR #324) |
| `features/records` | **70.3%** | Good | Core CRUD (was 42.6%, PR #323) |
| `features/permissions` | **74.1%** | Good | Security-critical (was 11.4%, PR #277) |
| `features/uiapi` | **78.5%** | Good | Was 8.2% (PR #313) |
| `features/metadata` | **78.1%** | Good | System core (was 59.4%, PR #328; was 5.4%, PR #259) |
| `infrastructure/persistence` | **18.3%** | Low | Largest package (was 12.0%, PR #333; was 3.6%, PR #264) |
| `features/automation` | **63.4%** | Adequate | Was 47.5% (PR #325). Composite: handler-layer tests added (PR #311) |
| `features/feed` | **92.9%** | Excellent | Was 0% (PR #316) |
| `features/notifications` | **60%** | Adequate | Was 0% (PR #317) |
| `pkg/auth` | **96.7%** | Excellent | Was 0% (PR #341) |

### 4.2 Zero-Test Packages (Backend)

| Package | Description | Risk |
|---------|-------------|------|
| `cmd/server` | Main entry point (build failure) | CRITICAL |
| `domain/ports` | Interface definitions | Low |
| `domain/schema` | Schema value objects | Medium |
| ~~`features/auth`~~ | ~~Authentication service~~ | **Fixed** — 90.7% coverage (PR #255) |
| ~~`features/feed`~~ | ~~Activity feed~~ | **Fixed** — 92.9% coverage (PR #316) |
| ~~`features/notifications`~~ | ~~Notification service~~ | **Fixed** — 60% coverage (PR #317) |
| `infrastructure/database` | DB connection layer | **HIGH** |
| `pkg/apierr` | API error types | Medium |
| ~~`pkg/auth`~~ | ~~Password hashing, JWT~~ | **Fixed** — 96.7% coverage (PR #341) |
| `pkg/errors` | Error types | Medium |
| `pkg/logging` | Logging infrastructure | Low |

### 4.3 Frontend Test Coverage

| Directory | Source Files | Test Files | Coverage |
|-----------|-------------|------------|----------|
| `infrastructure/` | 27 | 7 | **25.9%** Moderate |
| `registries/` | 8 | 2 | **25%** Moderate |
| `contexts/` | 5 | 1 | **20%** Low |
| `features/` | 240 | 19 | **7.9%** Very Low |
| `core/` | 54 | 4 | **7.4%** Very Low |
| `pages/` | 30 | 1 | **3.3%** Very Low |
| `components/` | 35 | 1 | **2.9%** Very Low |
| **Total** | **400** | **35** | **8.75%** Very Low |

### 4.4 Critical Test Gaps

- **No frontend tests in CI** -- GitHub Actions only runs backend tests
- ~~**Integration tests not isolated**~~ -- Fixed in PR #226: 12 test files now gated with `//go:build integration`
- **No coverage thresholds** -- CI does not enforce minimum coverage
- **No browser E2E tests** -- No Playwright/Cypress
- **Core frontend features have zero tests**: record (21 files), auth (4), dashboard (10), admin (32)

---

## 5. Code Quality

### 5.1 ~~CRITICAL: Backend Build Failure~~ (Fixed)

~~`registerRoutes()` undefined, backend could not compile.~~ Fixed in PR #226 — `routes.go` restored, build passes.

### 5.2 Dependency Vulnerabilities (Frontend)

~~9 vulnerabilities (4 High) — Fixed.~~ axios removed (dead dependency), flatted bumped to 3.4.2, dompurify bumped to 3.3.2.

| Package | Severity | Status |
|---------|----------|--------|
| ~~`axios 1.0.0-1.13.4`~~ | ~~High~~ | **Removed** (dead dependency) |
| ~~`flatted <=3.4.1`~~ | ~~High~~ | **Fixed** (bumped to 3.4.2) |
| ~~`minimatch`~~ | ~~High (x2)~~ | **Fixed** (resolved via dependency updates) |
| ~~`dompurify 3.1.3-3.3.1`~~ | ~~Moderate~~ | **Fixed** (bumped to 3.3.2) |
| ~~`ajv <6.14.0`~~ | ~~Moderate~~ | **Fixed** (resolved via dependency updates) |
| `esbuild <=0.24.2` | Moderate | Open (dev dependency only) |
| ~~`markdown-it`~~ | ~~Moderate~~ | **Fixed** (resolved via dependency updates) |

**Current state**: Only 2 moderate dev-dependency vulnerabilities remain (esbuild/vite).

### 5.3 Inconsistent Error Handling

| Issue | Data | Files |
|-------|------|-------|
| ~~`%v` instead of `%w` (breaks error chain)~~ | ~~10+ locations~~ | Fixed in PR #226 (analytics) |
| ~~Raw `errors.New()` share~~ | **COMPLETE** — Error handling is now unified. All production code uses typed errors from `pkg/errors/`. Two error packages still exist (`pkg/errors` and `pkg/apierr`) but all error creation uses `pkg/errors` constructors. Only ~1 `scripts/` test helper error remains (intentionally excluded). | **Fixed** |
| Two competing error packages | `pkg/errors` vs `pkg/apierr` | Overlapping responsibilities |
| OAuth handler uses `gin.H{}` non-standard format | 10 locations | `rest/oauth_handler.go` |
| Frontend ad-hoc catch blocks | Multiple locations | features/ |

### 5.4 Code Quality Metrics

~~**TypeScript `any` usage**: 48 occurrences (31 `: any` + 17 `as any`) across production code~~ **Fixed** — All 48 occurrences replaced with proper types. 0 remaining. PR #261.

**Oversized functions (>100 lines)**: 15 functions, largest is 406 lines (`testhelpers/schema.go`)

~~**Excessive useState**: CreateFieldWizard (19), ResourceModal (17), useDashboard (14), MetadataRecordList (14), MetadataRecordDetail (14), useReportBuilder (14)~~ **Fixed** — All 6 components refactored to useReducer: CreateFieldWizard (PR #267), ResourceModal (PR #279), useDashboard (PR #283), MetadataRecordList (PR #285), MetadataRecordDetail (PR #287), useReportBuilder (PR #289).

**Excessive Props (>15)**: RecordListHeader (23), RecordListTable (19), UIRegistry (18)

**Oversized files**:
| File | Lines |
|------|-------|
| `infrastructure/persistence/` (63 files) | 12,318 |
| `interfaces/rest/` (61 files) | 13,233 |
| ~~`infrastructure/api/flows.ts`~~ | ~~787~~ **Fixed** — split to 6 files, max 297L (PR #276) |
| ~~`infrastructure/api/data.ts`~~ | ~~782~~ **Fixed** — split to 8 files, max 183L (PR #281) |

### 5.5 Architecture Violations

| Violation | Evidence | Impact |
|-----------|----------|--------|
| `ServiceManager` imports infrastructure + interfaces | `service_manager_init.go` imports persistence + middleware | Composition root should be in main package |
| ~~features/ executes raw SQL (20 QueryRaw/ExecRaw calls in permissions/ + 18 query.Raw('NOW()') expressions)~~ | **Fixed** — permissions/ migrated to 14 typed repository methods (PR #265). records/ already had 0 raw SQL. 18 query.Raw('NOW()') expressions remain (non-bypass usage). | ~~Bypasses repository pattern~~ |
| `RecordRepository` bypasses `MetadataService` cache | `record_repository.go:41-57` builds its own sync.Map cache | Dual cache, potential inconsistency |
| `manual_fields.go` bypasses SSoT | 5+ manually defined constants | Schema drift risk |
| ~~Makefile verify-generated paths are wrong~~ | Fixed in PR #226 | ~~CI verification is ineffective~~ |

---

## 6. Architecture Claim Verification

> Independent verification of the project's 5 core architectural claims by the Challenger Agent (including counter-evidence)

| # | Claim | Verdict | Key Evidence |
|---|-------|---------|--------------|
| 1 | **SSoT (system_tables.json)** | **PARTIALLY TRUE** | Codegen pipeline is complete, verify_codegen.sh is rigorous. However, `manual_fields.go` and `tables.go` contain manually bypassed constants |
| 2 | **Clean Architecture** | **PARTIALLY TRUE** | Domain layer has zero external dependencies. However, `ServiceManager` directly imports infrastructure + interfaces |
| 3 | **Standardized Error Handling** | **PARTIALLY TRUE** | Two error packages + GlobalErrorHandler exist. However, ~75% of feature-layer errors use raw `errors.New()`, and the two packages have overlapping responsibilities |
| 4 | **End-to-End Request Tracing** | **PARTIALLY TRUE** | HTTP layer is complete: RequestID, logging, response headers, frontend capture. However, Request ID is **not propagated** into service/repository layers; deep errors cannot be correlated |
| 5 | **Salesforce v63.0 100% Compatibility** | **~80% IMPLEMENTED** | Backend implements ~80% of the Salesforce API surface the frontend requires. Remaining ~20% is Tooling API (query, sObject CRUD for metadata types). These are unfinished features, not architectural issues. See Issue #233 |

---

## 7. Priority List

### P0: Fix Immediately (Evidence-backed, Blocks Development/Deployment)

| # | Issue | Evidence | Impact | Estimated Fix Time |
|---|-------|----------|--------|--------------------|
| P0-1 | ~~`registerRoutes` undefined, backend cannot compile~~ | `main.go:218` calls non-existent function; `go build ./cmd/server` fails | Server cannot be built or deployed from main | **Fixed** |
| P0-2 | ~~Makefile verify-generated paths are wrong~~ | References `backend/pkg/constants/`, actual files are in `shared/pkg/constants/` | CI verification is ineffective, SSoT guarantee is broken | **Fixed** |
| P0-3 | ~~Integration tests not isolated, `go test ./...` always fails~~ | 4 tests connect to TiDB:4000 without build tags | Local development `make test-unit` always shows 4 red failures | **Fixed** |

### P1: High Priority (Significant Security/Quality Risk)

| # | Issue | Evidence | Impact | Estimated Fix Time |
|---|-------|----------|--------|--------------------|
| P1-1 | ~~**Frontend has 9 known vulnerabilities (4 High)**~~ | `npm audit`: axios DoS, flatted prototype pollution, dompurify XSS | Production security risk | **Fixed** -- axios removed (dead dependency), flatted bumped to 3.4.2, dompurify bumped to 3.3.2. Only 2 moderate dev-dependency vulnerabilities remain (esbuild/vite). |
| P1-2 | ~~**N+1 query: hydrateLookups()**~~ | `sobject_records.go:72-118`; one additional query per lookup field | 5 lookup fields = 6x DB queries; worse on list pages | **Fixed** -- hydrateLookups now batches lookup queries by target object type. PR #243. |
| P1-3 | ~~**features/ raw SQL bypass: 20 QueryRaw/ExecRaw calls in permissions/ (+ 18 query.Raw('NOW()') expressions)**~~ | records/ has 0 raw SQL bypass in production code. Original count of 63 included test files. | Architecture violation; schema migrations must audit call sites | **Fixed** — All 20 QueryRaw/ExecRaw calls in permissions/ migrated to 14 typed repository methods. 0 raw SQL remaining in permissions production code. PR #265. |
| P1-4 | ~~**CI has no frontend tests**~~ | `.github/workflows/ci.yml` has no frontend job | Frontend regressions are completely invisible | **Fixed** -- vitest job added to CI pipeline. PR #242. |
| P1-5 | **Core module test coverage is critically low** | **MILESTONE: ALL feature modules now above 40% coverage. 12 of 13 modules above 60% (all except composite which has no statements). Zero 0% packages remaining in pkg/ layer.** mru: **100%** (was 23.9%, PR #315), pkg/query: **97.9%** (was 22.3%, PR #331), pkg/fieldtypes: **97.7%** (was 20.2%, PR #343), pkg/utils: **97.4%** (was 15.4%, PR #342), pkg/auth: **96.7%** (was 0%, PR #341), events: **95.5%**, feed: **92.9%** (was 0%, PR #316), analytics: **92.3%** (was 58.7%, PR #329), auth: **90.7%**, middleware: **88.2%** (was 65.3%, PR #321), streaming: **81.6%**, uiapi: **78.5%** (was 8.2%, PR #313), metadata: **78.1%** (was 59.4%, PR #328), permissions: **74.1%**, records: **70.3%** (was 42.6%, PR #323), automation: **63.4%** (was 47.5%, PR #325), notifications: **60%** (was 0%, PR #317), REST: **46.4%** (was 37.4%, PR #332), persistence: **18.3%** (was 12.0%, PR #333). Composite: tests added for handler layer (PR #311). **~3,828 tests total, 0 failures.** PRs #255, #259, #260, #264, #277, #280, #293, #311, #312, #313, #315, #316, #317, #319, #320, #321, #323, #324, #325, #327, #328, #329, #331, #332, #333, #341, #342, #343. Coverage range: 18.3% (persistence) to 100% (mru). Only persistence (18.3%) and REST (46.4%) remain below 60%. | Substantially addressed — every module has meaningful tests | **Ongoing** -- raise coverage floors |
| P1-6 | ~~**ServiceManager architecture violation**~~ | `service_manager_init.go` imports persistence + middleware | Composition root is in the wrong layer, hinders testing and swapping | **Fixed** — ServiceManager composition root moved to cmd/server/wire.go. Application layer no longer imports infrastructure. PR #253. |
| P1-7 | ~~**Inconsistent error handling: two packages + 75% raw errors**~~ | **Fixed** — ALL raw errors across the entire backend migrated to typed errors from pkg/errors. Feature layer (13 modules), interfaces/rest, application/services, bootstrap, database, ALL pkg/ sub-packages (9), ALL persistence files (31), and ALL cmd/ tools (9 files) now use typed error constructors. Migration spanned rounds 5-16, PRs #263-#309. Only ~1 `scripts/` test helper error remains (intentionally excluded). | ~~Clients cannot reliably handle error types~~ | **Fixed** |
| P1-8 | ~~**Request ID not propagated to service/repo layer**~~ | Searching features/ and infrastructure/ for request_id returns zero results | Deep errors cannot be correlated to requests; production debugging is difficult | **Fixed** — Request ID propagated into service layer via context.WithValue. CRUD operations and analytics queries now log request ID. PR #251. |
| P1-9 | ~~**Analytics service layer uses wrong table names (4 production bugs)**~~ | `dashboard_service.go` and `report_service.go` hardcode incorrect table names; REST handlers are correct | Dashboard widget operations broken in production | **Fixed** -- all analytics table names use generated constants. PRs #240, #248. |
| P1-10 | ~~**Hardcoded table names audit needed**~~ | Analytics bug suggests other services may have same problem | Unknown scope of incorrect table references | **Fixed** -- audited all Go source files, replaced 22 hardcoded table names across 8 files with constants. PR #248. |
| P1-11 | ~~**Tooling API not yet implemented — metadata management UI returns 404**~~ | Frontend correctly calls SF Tooling endpoints; backend hasn't implemented them yet | Flow listing, validation rules, schema/field/layout admin all non-functional | **Fixed** -- /tooling/query route + sObject shims for ValidationRule, CustomObject, CustomField, ProfileLayout. PR #244. |

### P2: Medium-Term Optimization

| # | Issue | Evidence | Estimated Fix Time |
|---|-------|----------|--------------------|
| P2-1 | persistence package monolith (63 files, 12K LOC) | Largest package, no sub-package decomposition | 1-2 weeks |
| P2-2 | ~~Metadata cache full-lock refresh~~ | `sync.RWMutex` write lock blocks all reads | **Partially fixed** — Core schema/flow cache uses COW pattern via atomic.Pointer[metadataSnapshot]; readers are lock-free. However, 17 RLock calls remain in non-cache read paths (metadata_objects.go, metadata_apps.go, etc.). The COW pattern covers the core schema/flow cache but not all MetadataService read operations. PR #257. |
| P2-3 | ~~RecordRepository dual cache~~ | Bypasses MetadataService, builds its own sync.Map | **Fixed** — RecordRepository sync.Map removed, delegates to MetadataService via SchemaProvider interface. PR #256. |
| P2-4 | ~~TypeScript `any` (48 occurrences)~~ | ~~Production code in flows/registry/api~~ | **Fixed** -- All 48 TypeScript `any` occurrences replaced with proper types. 0 remaining. PR #261. |
| P2-5 | ~~Excessive useState (max 19)~~ | **Fixed** — All 6 excessive-useState components refactored to useReducer: CreateFieldWizard (PR #267), ResourceModal (PR #279), useDashboard (PR #283), MetadataRecordList (PR #285), MetadataRecordDetail (PR #287), useReportBuilder (PR #289). | **Fixed** |
| P2-6 | ~~`manual_fields.go` SSoT bypass~~ | 5+ manually defined constants | **Fixed** — All 13 manual constants migrated from manual_fields.go and tables.go into system_tables.json codegen pipeline. PR #252. |
| P2-7 | ~~Oversized frontend files (api/flows 787L, api/data 782L)~~ | **Fixed** — flows API split (PR #276): 787L → 6 files (max 297L). data.ts split (PR #281): 782L → 8 files (max 183L). Both oversized files resolved. | **Fixed** |

---

## 8. Code Map Evolution Strategy

### Stage 1 -- Architecture Discovery (Current Stage -- Complete)
- [x] Module identification and dependency analysis
- [x] Critical path tracing (13-hop Create, N+1 Read)
- [x] Test coverage measurement (backend 18/23 pass, frontend 8.75%)
- [x] Code quality static analysis (CRITICAL build failure + 9 vulnerabilities)
- [x] Independent verification of 5 architecture claims (all PARTIALLY TRUE)

### Stage 2: Fix Blockers -> Stabilize Architecture
**Goal**: Resolve all P0 + security-related P1; ensure main can compile and deploy
- [x] P0-1: Merge registerRoutes (Fixed)
- [x] P0-2: Fix Makefile paths (Fixed)
- [x] P0-3: Isolate integration tests (Fixed)
- [x] P1-1: npm audit fix (Fixed)
- [x] P1-4: Add frontend tests to CI (Fixed)

### Stage 3: Core Path Optimization
**Goal**: Resolve performance bottlenecks and architecture violations
- [x] P1-2: Fix N+1 query -- batch hydrateLookups (Fixed)
- [x] P1-3: Eliminate raw SQL bypass locations (Fixed — PR #265)
- [x] P1-6: Migrate ServiceManager to correct layer (Fixed)
- [x] P1-11: Tooling API shims (Fixed)
- [x] P1-8: Request ID propagation to service/repo layer (Fixed)
- [x] P2-2: Metadata cache COW optimization (Partially fixed — core cache is COW, 17 RLock calls remain in non-cache paths)
- [x] P2-3: Eliminate RecordRepository dual cache (Fixed)

### Stage 4: Test Coverage Improvement
**Goal**: Critical module coverage > 60%
- [ ] auth, records, persistence, metadata unit tests
- [ ] Frontend record, auth, dashboard component tests
- [ ] Establish coverage threshold CI gates

### Stage 5: Code Quality and Maintainability
**Goal**: Eliminate technical debt
- [ ] Unify error handling into a single package
- [ ] Request ID full-chain propagation
- [ ] Split persistence package into sub-packages
- [x] TypeScript `any` cleanup (Fixed, PR #261)
- [ ] Oversized component refactoring

---

## 9. Module Navigation Index

### Quick Jump by Purpose

| I want to... | Look here |
|--------------|-----------|
| Understand overall architecture | `docs/ARCHITECTURE.md` |
| Find API route definitions | `backend/internal/interfaces/rest/` (61 files) |
| Find CRUD for a specific object | `backend/internal/features/records/persistence_*.go` |
| Find permission check logic | `backend/internal/features/permissions/` |
| Find metadata loading/caching | `backend/internal/features/metadata/metadata_service.go` |
| Find DB query builder | `backend/pkg/query/` |
| Find SOQL parser | `backend/pkg/soql/parser.go` |
| Find formula engine | `backend/pkg/formula/` |
| Find frontend API calls | `frontend/src/infrastructure/api/` (34 files) |
| Find frontend page routes | `frontend/src/pages/` (31 files) |
| Find frontend hooks | `frontend/src/core/hooks/` |
| Find layout rendering | `frontend/src/components/runtime/LayoutRenderer.tsx` |
| Find flow builder | `frontend/src/features/flows/` (102 files) |
| Find code generator | `backend/cmd/codegen/` |
| Find SSoT source | `backend/internal/bootstrap/system_tables.json` |
| Find generated code (Go) | `shared/pkg/constants/z_generated_*.go`, `shared/pkg/models/z_generated.go` |
| Find generated code (TS) | `frontend/src/generated-*.ts` |
| Find middleware chain | `backend/cmd/server/main.go:153-175` |
| Find test files | `*_test.go` (136), `*.test.ts{x}` (35) |
| Find CI config | `.github/workflows/ci.yml` |

### Code Review Navigation

| When changes touch... | You must check... |
|-----------------------|-------------------|
| `system_tables.json` | Run `make generate`, verify all 7 generated files |
| `features/records/` | Check impact on permissions, events, analytics |
| `infrastructure/persistence/` | Check domain/ports interface consistency |
| `interfaces/rest/` | Check error format (SFErrorResponse vs gin.H) |
| `pkg/query/` | Check for SQL injection risk, run query tests |
| `frontend/infrastructure/api/` | Check error handling, type safety |
| `generated-*` files | **Never modify manually** -- run codegen |

---

## 10. Data Model & Entity Relationships

### 10.1 Table Inventory (80 tables)

| Category | Count | Key Tables |
|----------|-------|------------|
| **Metadata Engine Core** | 5 | `_System_Object`, `_System_Field`, `_System_Table`, `_System_Relationship`, `_System_FieldDependency` |
| **UI & Presentation** | 8 | `_System_App`, `_System_PageLayout`, `_System_ListView`, `_System_Action`, `ProfileLayout` |
| **Business Logic Rules** | 3 | `_System_ValidationRule`, `_System_RecordType`, `_System_AutoNumber` |
| **Auth & Identity** | 21 | `User`, `Profile`, `UserRole`, `PermissionSet`, `ObjectPermissions`, `FieldPermissions`, `Group`, `SharingRule`, `_System_RecordShare` |
| **Automation & Flows** | 9 | `FlowDefinition`, `Flow`, `FlowInterview`, `ProcessDefinition`, `ProcessInstance`, `ProcessInstanceWorkitem` |
| **Analytics & Reporting** | 5 | `Report`, `Dashboard`, `DashboardComponent`, `ReportFolder`, `FolderShare` |
| **Audit & Data Mgmt** | 4 | `_System_AuditLog`, `_System_RecycleBin`, `_System_Comment`, `_System_File` |
| **Total** | **80** | |

**Naming convention note:**
- 41 tables use the `_System_` prefix (internal infrastructure -- metadata engine, audit, sharing, etc.)
- 39 tables have no prefix (business/entity tables -- User, Report, Flow, etc.)
- Common mistake: adding `_System_` prefix to non-system tables. Only infrastructure tables owned by the platform kernel should carry this prefix.

### 10.2 Core ER Diagram

```
METADATA ENGINE (self-describing schema)
=========================================

_System_Object (ApiName, Label, SharingModel, ...)
    |
    |-- 1:N --> _System_Field (ObjectId FK, ApiName, Type, ReferenceTo, Formula, ...)
    |               |-- 1:N --> _System_FieldDependency (ControllingFieldId, DependentFieldId)
    |
    |-- 1:N --> _System_Relationship (ChildObjectApiName, ParentObjectApiName, RelationshipType)
    |-- 1:N --> _System_ValidationRule (ObjectApiName, Formula, ErrorMessage)
    |-- 1:N --> _System_RecordType (ObjectId FK, DeveloperName)
    |-- 1:N --> _System_AutoNumber (ObjectApiName, FieldApiName, CurrentValue)
    |-- 1:N --> _System_PageLayout (ObjectApiName, Config JSON)


AUTH & PERMISSION MODEL (Salesforce-compatible)
================================================

User (ProfileId FK, UserRoleId FK, ManagerId FK self-ref)
    |
    +-- Profile
    |     |-- 1:N --> ObjectPermissions (ParentId FK, SobjectType, CRUD flags)
    |     |-- 1:N --> FieldPermissions (ParentId FK, Field, Read/Edit flags)
    |     |-- 1:N --> ProfileLayout --> _System_PageLayout
    |     +-- 1:N --> ProfileTabSetting, ProfileAppVisibility
    |
    +-- UserRole (ParentRoleId FK self-ref = role hierarchy)
    |     +-- 1:N --> SharingRule (ShareWithRoleId FK)
    |
    +-- N:M --> PermissionSet (via PermissionSetAssignment)
    |     |-- 1:N --> ObjectPermissions
    |     |-- 1:N --> FieldPermissions
    |     +-- N:M --> PermissionSetGroup (via PermissionSetGroupComponent)
    |                   +-- MutingPermissionSet (revoke specific perms)
    |
    +-- N:M --> Group (via GroupMember)
          +-- QueueSobject (which objects a queue can own)
          +-- _System_RecordShare (manual record-level sharing)


AUTOMATION ENGINE
==================

FlowDefinition (DeveloperName, TriggerObjectOrEvent, ActiveVersionId)
    |-- 1:N --> Flow (versions, Metadata JSON = full canvas)
                  |-- 1:N --> FlowInterview (running/paused instances)

ProcessDefinition (approval processes)
    |-- 1:N --> ProcessNode (steps)
    |-- 1:N --> ProcessInstance (runtime, TargetObjectId)
                  |-- 1:N --> ProcessInstanceWorkitem (pending approvals)
                  |-- 1:N --> ProcessInstanceNode (step execution log)


ANALYTICS
==========

ReportFolder (ParentId FK self-ref = folder tree)
    |-- 1:N --> Report (SourceObject, Columns/Filters/Grouping as JSON)
    |-- 1:N --> Dashboard
    |             |-- 1:N --> DashboardComponent (ReportId FK = widget source)
    |-- 1:N --> FolderShare (access control)
```

### 10.3 Key Design Decision: SObject = map[string]interface{}

Business record data is **NOT** stored in typed Go structs. Instead:

```
type SObject = map[string]interface{}
```

All field validation, type coercion, and query building is driven dynamically by the metadata engine. This is the fundamental design choice enabling the metadata-driven architecture -- any object/field can be created at runtime without code changes.

Generated Go structs (`z_generated.go`) exist only for the 47 system tables. Custom/business objects use `SObject` exclusively.

### 10.4 Metadata Flow: Definition to Render

```
1. JSON Definition (system_tables.json or API call)
   |
2. DDL Execution (CREATE TABLE / ALTER TABLE on MySQL)
   |
3. Metadata Registration (_System_Object + _System_Field rows)
   |
4. MetadataService.RefreshCache() -- in-memory maps (sync.RWMutex)
   |  schemaMap:         map[lowercase_name] -> *ObjectMetadata
   |  fieldMap:          map[lowercase_name] -> []FieldMetadata
   |  validationRulesMap: map[lowercase_name] -> []*ValidationRule
   |  autoNumbersMap:    map[lowercase_name] -> []*AutoNumber
   |  flowDefinitionMap: map[name] -> *FlowDefinition
   |
5. API Response (GET /sobjects/{name}/describe -> ObjectMetadata as JSON)
   |
6. Frontend Cache (React Query, staleTime: 10min)
   |
7. Dynamic Render (LayoutRenderer -> InlineEditField per field type)
```

---

## 11. API Surface

### 11.1 Endpoint Summary: ~122 Endpoints (~108 SF-compatible + ~14 Custom)

| Category | Endpoints | Salesforce Parity |
|----------|-----------|-------------------|
| SObject CRUD | 11 | Full |
| Query/Search (SOQL, SOSL) | 8 | Full |
| Composite API | 8 | Full |
| Metadata API | 16 | Partial (REST instead of SOAP) |
| UI API | 7 | Full |
| Analytics (Reports + Dashboards) | 15 | Full |
| Folders + Shares | 12 | Full |
| Auth (OAuth) | 4 | Full |
| Bulk API v2 | 7 | Full |
| Streaming (CometD + WebSocket) | 5 | CometD=Full, WebSocket=Custom |
| Flows / Tooling | 17 | Mostly (activate/deactivate uses POST not PATCH) |
| Quick Actions + Approvals | 5 | Full |
| System / Limits / Identity | 4 | Full |
| Connect | 1 | Full |
| MRU / Relevant Items | 1 | Full |
| **Total** | **~122** | **~88% URL-pattern parity** |

### 11.2 Route Groups (from `routes.go`)

```
/services/oauth2/                    -- OAuth (mixed auth)
/services/data/                      -- API versions (no auth)
/services/data/:version/             -- All below require auth:
    +-- sobjects/                    -- SObject CRUD + describe
    +-- query, queryAll, query/:loc  -- SOQL
    +-- search, parameterizedSearch  -- SOSL
    +-- composite/                   -- Batch, collections, tree
    +-- metadata/                    -- Schema/field CRUD, deploy, validation rules
    +-- analytics/                   -- Reports + dashboards
    +-- jobs/                        -- Bulk API v2 (ingest + query)
    +-- folders/                     -- Folder tree + shares
    +-- connect/                     -- Notifications
    +-- actions/custom/flow/         -- Invocable flows
    +-- tooling/sobjects/            -- FlowDefinition, Flow, CustomApp CRUD
    +-- quickActions/                -- Quick action describe + execute
    +-- process/approvals            -- Approval processing
    +-- ui-api/                      -- Record UI, layouts, object info
/cometd/:version/                    -- CometD streaming (auth required)
/ws                                  -- WebSocket (auth required)
```

### 11.3 Salesforce Parity Gaps

| Feature | NexusCRM | Salesforce | Gap |
|---------|----------|------------|-----|
| Metadata API | REST CRUD at `/metadata/objects` | SOAP or `/services/metadata/` | Different protocol |
| Validation rules | REST at `/metadata/validation-rules` | Tooling API `ValidationRule` sObject | Custom REST path |
| Flow activate | `POST /Flow/:id/activate` | `PATCH` on Status field | Different verb |
| WebSocket | `GET /ws` | Not available (CometD or Pub/Sub gRPC) | Custom addition |
| Chatter | Not implemented | `/chatter/...` | Missing |
| Apex REST | Not implemented | `/services/apexrest/` | Missing |
| Pub/Sub gRPC | Not implemented | gRPC streaming | Missing |
| **Tooling Query** | **Complete** | `/tooling/query?q=` | Resolved (PR #244) |

### 11.5 Backend Implementation Gaps — Tooling API (Issue #233)

> These are not bugs or drift. The frontend is correct (built against Salesforce API).
> The backend has not yet implemented these Tooling API routes.

#### What works (backend routes exist):

| Feature | API Surface | Status |
|---------|-------------|--------|
| Record CRUD | `/sobjects/:name/:id` | Working |
| SOQL Query | `/query?q=` | Working |
| Search | `/search`, `/parameterizedSearch` | Working |
| Composite | `/composite/*` | Working |
| Bulk API | `/jobs/*` | Working |
| Analytics | `/analytics/*` | Working (table name bugs fixed) |
| UI API | `/ui-api/*` | Working |
| Flow CRUD (typed) | `/tooling/sobjects/FlowDefinition`, `/tooling/sobjects/Flow` | Working |
| Flow Execution | `/actions/custom/flow/:name` | Working |
| Streaming | `/cometd/*`, `/ws` | Working |

#### What is broken (frontend calls endpoints that don't exist):

| Feature | Frontend calls | Backend has | Impact |
|---------|---------------|-------------|--------|
| **Flow listing/search** | `/tooling/query?q=SELECT...FROM FlowDefinition` | No `/tooling/query` route | 404 — Flow list page broken |
| **Flow version lookup** | `/tooling/query?q=SELECT...FROM Flow WHERE DefinitionId=...` | No route | 404 |
| **Validation Rule read** | `/tooling/query?q=SELECT...FROM ValidationRule` | `/metadata/validation-rules` (different) | 404 |
| **Validation Rule create** | `POST /tooling/sobjects/ValidationRule` | `POST /metadata/validation-rules` (different) | 404 |
| **Validation Rule update** | `PATCH /tooling/sobjects/ValidationRule/:id` | `PATCH /metadata/validation-rules/:id` (different) | 404 |
| **Validation Rule delete** | `DELETE /tooling/sobjects/ValidationRule/:id` | `DELETE /metadata/validation-rules/:id` (different) | 404 |
| **Schema update** | `PATCH /tooling/sobjects/CustomObject/:id` | No route | 404 |
| **Field create** | `POST /tooling/sobjects/CustomField` | `POST /metadata/objects/:name/fields` (different) | 404 |
| **Layout assignment** | `POST /tooling/sobjects/ProfileLayout` | No route | 404 |
| **App resolution** | `/tooling/query?q=SELECT...FROM CustomApplication` | No route | 404 |

#### Why these routes don't exist yet

The backend team implemented some metadata capabilities via custom REST endpoints
(`/metadata/objects`, `/metadata/validation-rules`) rather than Salesforce Tooling API
conventions. The frontend was built against real Salesforce, so it calls Tooling endpoints.

Per the development model: **the frontend is correct**. The backend needs to implement
the Tooling API surface, or route Tooling URLs to the existing `/metadata/*` handlers.

#### Implementation path

1. **`/tooling/query`**: Route to existing QueryHandler. The SOQL engine already handles
   FlowDefinition and Flow tables. ValidationRule needs a table alias
   (`ValidationRule` -> `_System_ValidationRule`).
2. **Tooling sObject routes**: Add thin handler wrappers that accept Tooling-style
   requests and delegate to existing `/metadata/*` handlers.
3. **DO NOT change the frontend** to use `/metadata/*` endpoints. That breaks the
   Salesforce-compatible contract.

See Issue #233 for full analysis.

#### `schemas.ts` — Salesforce API Surface Reference

This file uses multiple Salesforce API families. **This is correct behavior** — Salesforce
itself uses different API surfaces for different metadata operations. The frontend faithfully
follows Salesforce conventions. Do not "simplify" this into a single surface.

| Function | SF API Surface | SF Convention? |
|----------|---------------|----------------|
| `getSchemas()`, `getSchema()` | Standard REST (`/sobjects`) | Yes |
| `createSchema()`, `deleteSchema()` | Metadata Deploy (`/metadata/deployRequest`) | Yes |
| `updateSchema()` | Tooling sObject (`/tooling/sobjects/CustomObject`) | Yes |
| `createField()` | Tooling sObject (`/tooling/sobjects/CustomField`) | Yes |
| `updateField()`, `deleteField()` | Standard REST (`/sobjects/:name/fields`) | Yes |
| `getLayout()`, `saveLayout()` | UI API (`/ui-api/layout`) | Yes |
| `assignLayoutToProfile()` | Tooling sObject (`/tooling/sobjects/ProfileLayout`) | Yes |
| `getValidationRules()` | Tooling Query (`/tooling/query?q=SELECT...`) | Yes |
| `createValidationRule()` | Tooling sObject (`/tooling/sobjects/ValidationRule`) | Yes |

Each function matches how a Salesforce client would perform the same operation.
The backend must implement all of these surfaces — the frontend should not be changed.

### 11.4 Backend Bug — Analytics Table Names

> Identified during adversarial review (2026-03-20). See Issue #227, Issue #229.

The analytics service layer has a **production bug** where service files reference incorrect table names:

| File | Problem | Status |
|------|---------|--------|
| `dashboard_service.go` | Uses wrong table names for dashboard/widget CRUD operations | Bug -- Issue #227 |
| `report_service.go` | Uses wrong table names for report query operations | Bug -- Issue #227 |
| REST handlers (analytics) | Use correct table names via constants | OK |

**Impact**: Dashboard widget operations were broken in production. The inconsistency is within the same feature boundary -- REST handlers reference the correct generated constants, but the service layer has hardcoded (incorrect) table name strings.

**Root cause**: Service files were written before the table naming convention was finalized and were never updated when the generated constants stabilized. The REST handlers were written later and correctly used the constants.

**Resolution**: Issue #227 (fix wrong names), Issue #229 (audit all hardcoded table names across the codebase).

---

## 12. Feature Interactions

### 12.1 Service Manager Boot Order

```
Phase 1: Infrastructure    -- TxManager, EventBus, ValidationService
Phase 2: Repositories      -- UserRepo, SystemRepo, BulkRepo
Phase 3: Core Domain       -- SchemaManager, MetadataService
Phase 4: Auth Stack        -- PermissionService, AuthService, OAuthService
Phase 5: Analytics Stack   -- QueryService, ReportService, DashboardService, RollupService
Phase 6: Automation Stack  -- OutboxService, PersistenceService(9 deps), FlowExecutor, ApprovalService
Phase 7: Business Services -- SystemManager, Feed, Notification, UIAPI, BulkService
```

### 12.2 Feature Interaction Diagram

```
                          +------------------+
                          | SERVICE MANAGER  |
                          | (DI & Boot)      |
                          +------------------+

  +------------+                                      +---------------+
  |  METADATA  |<---- cache read (O(1)) ------------- |   RECORDS     |
  |            |                                      | (Persistence) |
  | Schema     |--- direct call -->+------------+     |               |
  | Cache      |                   | PERMISSIONS|<----| 1. Obj perms  |
  | Flow Defs  |<-- direct call ---|            |     | 2. Field perms|
  | Validation |                   | Object     |     | 3. Record     |
  | Rules      |-- sync event -+   | Field      |     |    access     |
  +-----+------+  (schema chg) |   | Record     |     +--+--+--+-----+
        |                       |   | Sharing    |        |  |  |
        |                       |   +------------+        |  |  |
        |                       |                         |  |  |
   invalidate                   +--> FlowTriggerListener  |  |  |
   entire cache                                           |  |  |
   on any change                            sync Publish  |  |  |  Outbox
                                           (before-trig) -+  |  |  EnqueueEvent
                                                              |  |  (after-trig)
                                            rollup IN-TX -----+  |
                                                                  |
                                                  +---------------+
                                                  | EVENT BUS     |
                                                  |               |
                                                  | Sync: before- |
                                                  |  triggers     |
                                                  | (can abort TX)|
                                                  +-------+-------+
                                                          |
                                                          v
                            +-----------------+   +---------------+
                            | FLOW TRIGGER    |-->| FLOW EXECUTOR |
                            | LISTENER        |   |               |
                            |                 |   | Decisions     |
                            | Before-save:    |   | Record CRUD   |---> Persistence
                            |  mutates $Record|   | Actions       |---> QueryService
                            |  in-place       |   | Subflows      |
                            +-----------------+   +-------+-------+
                                                          |
                                          +---------------+---------------+
                                          v               v               v
                                   +----------+    +-----------+    +-----------+
                                   | APPROVAL |    | SCHEDULER |    | ANALYTICS |
                                   | SERVICE  |    | SERVICE   |    |           |
                                   +----------+    +-----------+    | Query     |
                                                                    | Report    |
                                   +--------------------------------| Dashboard |
                                   |  OUTBOX SERVICE                | Rollup    |
                                   |  Worker polls 500ms            +-----------+
                                   |  Retry <= 5x
                                   |  Own TX per event
                                   +-------------------------------+
```

### 12.3 Event System: Two Modes

| Mode | Mechanism | Timing | Can Abort TX? | Use Case |
|------|-----------|--------|---------------|----------|
| **Sync** | `EventBus.Publish()` | In caller's TX | Yes | Before-triggers (RecordBefore*), schema events |
| **Async** | Outbox table row + background worker | After TX commit | No | After-triggers (RecordCreated/Updated/Deleted) |

Event types: `record.{beforeCreate, created, beforeUpdate, updated, beforeDelete, deleted}`, `schema.{object,field}_{created,updated,deleted}`, `bulk.job.closed`

### 12.4 PersistenceService Pipeline (the hub)

Every CRUD operation follows this pipeline:

```
1. permissions.CheckPermissionOrError()     -- object-level (pre-TX)
2. metadata.GetSchemaOrError()              -- cache read
3. schemaValidator.ValidateSchemaCompliance() -- type/required checks
4. validator.ValidateRecord()               -- formula-based rules
5. BEGIN TX
   |-- permissions.CheckRecordAccess()      -- record-level (Update/Delete only)
   |-- permissions.CheckFieldEditability()  -- field-level (Update only)
   |-- eventBus.Publish(RecordBefore*)      -- sync, can abort
   |-- repo.Insert/Update/Delete()          -- actual DB write
   |-- rollup.ProcessRollups()              -- same TX
   |-- outbox.EnqueueEvent(Record*)         -- same TX
6. COMMIT TX
```

9 injected dependencies: `recordRepo`, `rollup`, `metadata`, `permissions`, `eventBus`, `validation`, `txManager`, `outbox`, `logger`

### 12.5 Permission Model: Three Layers

| Layer | Checked When | Source | Cached? |
|-------|-------------|--------|---------|
| Object-level | Pre-TX (`prepareOperation`) | Profile + PermissionSets -> ObjectPermissions | No (per-request DB query) |
| Field-level | In-TX (`filterEditableFields`) | Profile + PermissionSets -> FieldPermissions | No (per-request DB query) |
| Record-level | In-TX, after row lock | Owner -> Role hierarchy -> Sharing rules -> Manual shares -> Team members | Role hierarchy only |

### 12.6 Frontend State Management

| State | Source | Cache Strategy | Shared Via |
|-------|--------|---------------|------------|
| Auth / user session | Login API | None (ephemeral) | RuntimeContext (useState) |
| Permissions | `/ui-api/permissions` | React Query, 15min stale, prefetched on login | PermissionContext |
| App navigation | `/ui-api/apps` | React Query, 5min stale, prefetched on login | AppContext + localStorage |
| Schema metadata | `/sobjects/{name}/describe` | React Query, 10min stale, per-object | `useObjectMetadata()` hook |
| Page layouts | `/ui-api/layout/{name}` | React Query, 15min stale, per-object | `useLayout()` hook |
| Record data | `/sobjects/{name}/{id}` | React Query, 5min stale, per-record | `useRecord()` hook |
| UI preferences | Local | localStorage | UIContext (useState) |

Boot sequence: Login -> `prefetchBootData()` fires parallel React Query prefetches for permissions + apps -> downstream providers mount with warm caches.

---

## Version History

| Version | Date | Changes | Contributors |
|---------|------|---------|--------------|
| 0.1 | 2026-03-20 | Initial framework | -- |
| 1.0 | 2026-03-20 | 5-Agent full analysis: architecture + paths + tests + quality + verification | Architect, Pathfinder, Tester, Reviewer, Challenger |
| 2.0 | 2026-03-20 | Architecture deep-dive: 55-table data model, 105-endpoint API map, feature interaction diagram, event system, permission model, frontend state management | DataModel, APISurface, FeatureInteraction |
| 2.1 | 2026-03-20 | Adversarial review corrections: table naming, analytics drift, P0s fixed, P1-9/P1-10 added | Challenger (adversarial review) |
| 2.2 | 2026-03-20 | API contract analysis (Issue #233): Tooling API endpoints not yet implemented, metadata management UI returns 404. CI fixes reflected. | 4-agent verification |
| **3.0** | **2026-03-21** | **Development Model identified: frontend built against Salesforce API (spec), backend implements it (incomplete). Reframed all "drift" as "unfinished implementation." Added Backend Implementation Completeness table (~80%). Evo skill updated with development model constraints.** | **Architecture review** |
| **3.1** | **2026-03-21** | **Challenger verification: corrected 7 stale claims (npm vulns, raw SQL count, TypeScript any count, file count). Fixed P1-1 (npm vulns), P1-2 (N+1 query), P1-4 (CI frontend tests), P1-9 (analytics tables), P1-10 (table name audit), P1-11 (Tooling API). 6 of 11 P1 items now resolved.** | **Challenger (adversarial verification)** |
| **3.2** | **2026-03-21** | **Fixed P1-6 (ServiceManager architecture violation — composition root moved to cmd/server). Fixed P1-8 (Request ID propagation to service/repo layer via context). Fixed P2-6 (manual_fields.go SSoT bypass — all 13 constants migrated to codegen). Corrected Backend Implementation Completeness table (Tooling API now marked Complete). Challenger verification: P1-6 build failure was false positive (worktree artifact).** | **Evo round** |
| **3.3** | **2026-03-21** | **Fixed P2-2 (Metadata cache COW — lock-free reads via atomic.Pointer). Fixed P2-3 (RecordRepository dual cache removed — delegates to MetadataService). P1-5 partial: auth module coverage 0% → 90.7% (PR #255). 8/11 P1 items fixed, 3/7 P2 items fixed.** | **Evo round** |
| **3.4** | **2026-03-22** | **P1-5 progress: metadata coverage 5.4% → 59.4% (PR #259), records coverage 9.8% → 42.6% (PR #260). Fixed P2-4 (TypeScript any: 48 → 0 occurrences, PR #261). Challenger correction: P2-2 COW is partial — 17 RLock calls remain in non-cache read paths. 8/11 P1 items fixed, 4/7 P2 items fixed.** | **Evo round** |
| **3.5** | **2026-03-22** | **Fixed P1-3 (Raw SQL bypass: 20 QueryRaw/ExecRaw migrated to repository pattern, PR #265). P1-5 progress: persistence coverage 3.6% → 11.0% (PR #264). P1-7 progress: records/ raw errors migrated to typed errors (PR #263). Challenger correction: P1-7 error counts updated (was 280/91, actual 324/74 pre-migration). 9/11 P1 items fixed, 4/7 P2 items fixed.** | **Evo round** |
| **3.6** | **2026-03-22** | **P1-7 progress: metadata/ (PR #269) and permissions/ (PR #268) migrated to typed errors. 3 of ~10 feature modules now use typed errors. P2-5 partial: CreateFieldWizard 17 useState → 1 useReducer (PR #267). Challenger correction: persistence coverage 11.0% → 10.7%. 9/11 P1 items fixed, 4/7 P2 items fixed (P2-5 partial).** | **Evo round** |
| **3.7** | **2026-03-22** | **P1-7 progress: analytics/ (PR #272, 32 converted), automation/ (PR #273, 44 converted), events/ (PR #271, 7 converted) migrated to typed errors. 6/10 feature modules now use typed errors. Only uiapi/ (6) remains in feature layer. infrastructure/persistence/ has 265 raw errors (separate concern — repo layer). Challenger correction: raw error count was ~200 (wrong), actual pre-round was 338 (73 features + 265 persistence).** | **Evo round** |
| **3.8** | **2026-03-22** | **P1-7 MILESTONE: Feature-layer typed error migration COMPLETE (all 10 modules, 0 raw errors). P1-5 progress: permissions coverage → 74.1% (PR #277). P2-7 partial: flows API split 787L → 6 files, max 297L (PR #276). Challenger: total raw errors corrected to 323 (265 persistence + 58 other non-feature). 9/11 P1 fixed, 4/7 P2 fixed (P2-5, P2-7 partial).** | **Evo round** |
| **3.9** | **2026-03-22** | **P1-5 progress: events coverage 70.3% → 95.5% (PR #280). P2-5 progress: ResourceModal 17 useState → 1 useReducer (PR #279). P2-7 Fixed: both oversized API files split (flows PR #276, data PR #281). Challenger correction: total raw errors 323 → 441 (was missing cmd/29, pkg/88, scripts/1). Challenger note: features/auth/ has 17 raw errors not yet migrated. 9/11 P1 fixed, 5/7 P2 fixed (P2-5 partial).** | **Evo round** |
| **4.0** | **2026-03-22** | **P1-7 MILESTONE: ALL feature modules (including auth) now use typed errors — feature layer 100% complete. P2-5 progress: useDashboard (PR #283) and MetadataRecordList (PR #285) refactored. 4/6 components done. 10 rounds of automated evo loop: 49 PRs merged, 0 blocked, 100% /review pass rate.** | **Evo round (major version bump)** |
| **4.1** | **2026-03-22** | **P2-5 COMPLETE: All 6 excessive-useState components refactored (PRs #287, #289). P1-7 progress: interfaces/rest/ migrated (PR #288). Feature + REST layers complete. Challenger correction: total merged PRs is 49 (not 42). 9/11 P1 fixed, 6/7 P2 fixed.** | **Evo round** |
| **4.2** | **2026-03-22** | **P1-7: application/services (PR #292), bootstrap + database (PR #291) migrated to typed errors. P1-7 status: ALL internal/ layers except persistence/ now use typed errors. Remaining: persistence 265, pkg 88, cmd 29 = 382 total. P1-5: persistence coverage 10.7% → 12.0% (PR #293). 12 rounds: 56 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **4.3** | **2026-03-22** | **P1-7: pkg/validator (PR #297), pkg/auth (PR #295), pkg/formula+telemetry+utils+fieldtypes (PR #296) migrated. pkg/ layer: 6 of 9 sub-packages now use typed errors. Remaining: expression (35), soql (20), errors (7). 13 rounds: 60 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **4.4** | **2026-03-22** | **P1-7: pkg/ layer COMPLETE — expression (PR #300), soql (PR #301), errors (PR #299) migrated. All 9 pkg sub-packages done. CRITICAL Challenger correction: persistence raw errors were 62, NOT 265 (4.3x inflation). Total remaining: ~68 (persistence 62, cmd/installer 6). P1-7 is now 92% complete by error count (from original ~500+ to ~68 remaining). 14 rounds: 64 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **4.5** | **2026-03-22** | **P1-7: persistence/ batch 1 — 193 errors migrated across 17 files (PRs #303, #304, #305). Challenger re-measurement: persistence had 256 raw errors (not 62 — earlier measurement used narrower pattern). Remaining: ~63 in persistence + 29 in cmd/ = ~92 total. 15 rounds: 68 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **5.0** | **2026-03-22** | **P1-7 COMPLETE: ALL raw errors migrated to typed errors across entire backend. persistence/ batch 2 (PR #307, 45 errors) + batch 3 (PR #308, 27 errors) — persistence DONE. cmd/ all (PR #309, 29 errors) — cmd DONE. Total migrated across all P1-7 rounds: ~500+ raw errors → 0. P1 score: 10/11 fixed (only P1-5 test coverage remains). P2 score: 6/7 fixed (only P2-1 persistence monolith remains). 16 rounds: 72 PRs merged, 0 blocked, 100% /review pass rate.** | **Evo round (major version bump)** |
| **5.1** | **2026-03-22** | **P1-5: automation 2.2% → 47.5% (PR #312), uiapi 8.2% → 78.5% (PR #313), composite tests added (PR #311). +7,298 lines of test code in this round alone. Challenger confirms P1-7 is truly COMPLETE (0 real raw errors in production code). 17 rounds: 76 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **5.2** | **2026-03-22** | **P1-5 MILESTONE: ALL feature modules now have test coverage (0% modules eliminated). mru 23.9% → 100% (PR #315), feed 0% → 92.9% (PR #316), notifications 0% → 60% (PR #317). Coverage range: 12% (persistence) to 100% (mru) — no module at 0%. 18 rounds: 80 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **5.3** | **2026-03-22** | **P1-5: analytics 17.9% → 58.7% (PR #320), middleware 65.3% → 88.2% (PR #321), REST 10.8% → 16.6% (PR #319). Challenger comprehensive audit: 2,279 tests total, 0 failures, codebase now ~915 files. Fixed Section 11 internal inconsistency (Tooling Query status). 19 rounds: 84 PRs merged, 0 blocked, 100% review pass rate. EVO LOOP CONVERGENCE: All P0 fixed, 10/11 P1 fixed, 6/7 P2 fixed.** | **Evo round** |
| **5.4** | **2026-03-23** | **P1-5: records 42.6% → 70.3% (PR #323), automation 47.5% → 63.4% (PR #325), REST 16.6% → 26.9% (PR #324). All feature modules now above 40% coverage. 8 of 13 above 60%. Challenger: test failure was worktree artifact (false positive). Total tests ~2,500+. 20 rounds: 88 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **5.5** | **2026-03-23** | **P1-5: analytics 58.7% → 92.3% (PR #329), metadata 59.4% → 78.1% (PR #328), REST 26.9% → 37.4% (PR #327). 11 of 13 feature modules now above 60% coverage. ~2,739 tests total. Challenger correction: "8 of 13" was stale → actual is "11 of 13". 21 rounds: 92 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **5.6** | **2026-03-23** | **P1-5: pkg/query 22.3% → 97.9% (PR #331), REST 37.4% → 46.4% (PR #332), persistence 12.0% → 18.3% (PR #333). 12 of 13 feature modules above 60%. ~3,043 tests total. 22 rounds: 96 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
| **5.7** | **2026-03-23** | **P1-5: pkg/auth 0% → 96.7% (PR #341), pkg/fieldtypes 20.2% → 97.7% (PR #343), pkg/utils 15.4% → 97.4% (PR #342). All three utility packages now above 96% coverage. ~3,828 tests total, 0 failures. 23 rounds: 100 PRs merged, 0 blocked, 100% review pass rate.** | **Evo round** |
