# What Changed — May 2026

**Audience**: Squire executive leadership and outside reviewers
**Last verified**: 2026-05-13 against the reviewer-mirror snapshot
**Vintage of the rest of this package**: April 28, 2026

---

## The one-line framing

**Task 17 turns NetSuite sync errors from "a backlog someone has to read" into "a queue someone has to approve."**

The rest of this document is the evidence behind that sentence.

---

## Context

The 28 documents in this executive package were assembled around an April 28, 2026 snapshot of the SuiteCentral 2.0 platform. They are accurate as of that date. Between April 28 and May 13, the platform shipped a governance wave that converted a number of "the code exists" claims into "an outside engineer can exercise the runtime path end to end." This document catalogs that wave so a reader doesn't have to reconcile what's in the package against what's in the repo.

An independent code review of the public reviewer-mirror snapshot, conducted in early May, characterized the result this way:

> "The platform now has an end-to-end production-credible feature (SyncErrorAssist) that demonstrates every governance claim — DLP before inference, reasoning trace persisted, cost recorded, audit logged, outbound write DLP-scanned, operator approval DB-durable, HMAC-authenticated ingest — and an ERP embedding contract with session infrastructure for seven modules."

That assessment is currently invisible to anyone reading the rest of this package. This document is the bridge.

---

## Why this matters specifically for Squire

The April 28 package made the case that SuiteCentral 2.0 is an enterprise-grade integration platform with governed AI workflows. The May 2026 wave makes a sharper case: there is now a concrete service Squire can run for a client in beta and charge for, today.

1. **Lower headcount on integration ops.** Most fixable sync errors don't need a human anymore. The ones that do are pre-diagnosed with a reasoning trace, so the operator's job is "approve this proposed fix" — not "figure out what failed."
2. **Faster recovery from data quality issues.** A bad sync that would historically have lived in an overnight queue is now triaged and ready to apply within seconds. NetSuite SuiteScript posts the error event to the platform's HMAC-authenticated ingest endpoint; the AI diagnoses it; the queue shows the operator what to approve.
3. **Better story than competitors.** Celigo, Boomi, and MuleSoft surface the error and walk away. This product explains *why* it failed, *how* to fix it, and shows the reasoning trace an auditor can inspect. That trace is persisted, not ephemeral.
4. **Production-grade safety.** HMAC-signed webhook ingest. DLP/PII redaction on what gets sent to the AI provider, before inference, mandatory at the boundary. Per-tenant opt-in via tenant configuration. Cost tracking per inference. Full audit log in a real database table with tenant attribution and DLP guard. Squire's compliance and security review will pass — the platform was built assuming it would have to.

---

## The eight evidence rows

Each row below is anchored to a proof card or source location so the claim is falsifiable. The proof cards live at `docs/review/proof-cards/` in the repo. CI enforces card structure (heading + six required `##` sections via `scripts/audit-proof-cards.mjs`) and source-status consistency (each connector card's `Status:` line must match the connector's `static readonly productionStatus`). Recipe executability is not auto-verified — that's still a human reviewer's job; the gate ensures the recipe is present and parseable, not that running it produces a specific output.

| # | Feature | Wave-2 PRs | Status | Anchor |
|---|---|---|---|---|
| 1 | SyncErrorAssist (webhook + AI diagnose + operator queue) | #762, #763, #769, #770, #777 | beta | `docs/review/proof-cards/sync-error-assist.md` |
| 2 | FinanceCentral operator promotion (durable two-stage lease) | #787 | beta | `docs/review/proof-cards/finance-central-operator.md` |
| 3 | Persistent SOC 2 audit log (tenant attribution + DLP guard) | #748 | beta | `docs/review/proof-cards/audit-service.md` |
| 4 | Outbound DLP at AI provider boundary (mandatory `scanBeforeSend`) | #743 | shipped | `docs/review/proof-cards/dlp-service.md` |
| 5 | Connector write DLP (5 production connectors guarded) | #747 | shipped | 5 connector proof cards |
| 6 | Identity context propagation through AI calls | #744 | shipped | `src/services/governance/identityContext.ts` |
| 7 | Canonical Connector Registry + wiring-drift CI gate | #755, #757 | shipped | `src/connectors/connectorRegistry.ts` + `npm run audit-status-claims --check-wired-connectors` |
| 8 | Embedded ERP Surface Contract (session infrastructure) | #754 | shipped | `src/routes/embedded/*` + `src/services/embedded/*` |

(The framing claim is "seven additions" — the four governance plumbing items (outbound DLP, connector write DLP, identity propagation, and registry+drift gate) are facets of one underlying claim: the governance surface is now CI-enforced, not aspirational. The table lists them as eight separate rows so a reviewer can verify each one independently.)

### 1. SyncErrorAssist

A NetSuite User Event SuiteScript posts sync-error records to `POST /api/sync-error-assist/ingest` with an HMAC-SHA256-signed body. The server returns `202 Accepted` after the synchronous claim row insert, then runs the AI suggestion pipeline in a `setImmediate` fire-and-forget worker. A 30-minute polling reconcile runs alongside as a backstop for missed webhooks. Per-tenant opt-in via two flags in `tenant_configurations`: `sync_error_assist.enabled='true'` AND `sync_error_assist.webhook_enabled='true'`.

The AI pipeline is governed end to end: the source payload is DLP-redacted via `sanitizeSourcePayloadForPrompt` before any provider sees it; the inference is wrapped in a reasoning trace persisted via `ReasoningTraceEngine`; the cost is recorded per call via `CostTrackingService.recordCost`; and the proposed fix is held in a `sync_error_assist_processed` row (the table created by migration 036, extended by 037 and 038) in `pending` status until an operator approves, rejects, or escalates it via the operator UI.

When an operator approves, the proposed fix is written back to NetSuite via the same `ConnectorManager.getConnector('netsuite', ...)` path the rest of the platform uses for production writes — and the outbound write is itself DLP-scanned by `OutboundGovernanceService.scanBeforeSend` before it reaches the wire.

**60-second verification recipe**: see `docs/review/proof-cards/sync-error-assist.md`. The proof card includes the curl invocation, expected status codes, and audit-log query.

### 2. FinanceCentral operator promotion

PR #787 promoted the FinanceCentral approval workflow from in-memory `Map` demo to a durable, audited state machine. Operators approve or reject `finance_central_approvals` rows via `POST /api/finance-central/approvals/:id/approve` and `.../reject`. The approve path is a two-stage durable lease (`pending → applying → accepted`) that wraps the NetSuite `update` write between `beginAccept` and `completeAccept`. Every failure mode — no `netsuite_id`, connector throw, connector returns null, completion lost-race — reverts the lease back to `pending` and stamps an `audit_logs` row keyed `finance_central.approve` with `result='failure'`. Reject is an atomic single-stage transition with no external write.

This is the same operator-approval shape as SyncErrorAssist, applied to a different upstream domain. The two features share the audit-log conventions and the outbound DLP guard.

**60-second verification recipe**: see `docs/review/proof-cards/finance-central-operator.md`. The card covers the two-stage lease implementation, 13 integration scenarios covering happy path plus 400/404/409/503/502-with-revert failure modes, and the six-section verification schema.

### 3. Persistent SOC 2 audit log

The audit service previously held audit records in process memory — adequate for tests, not for compliance. PR #748 promoted it to a persistent `audit_logs` table with tenant attribution and a DLP guard at the write boundary. Every governance-relevant action (DLP scan, AI inference, approval, rejection, outbound write) now lands in this table, queryable by tenant + time + action type, and the write itself is DLP-scanned to prevent secrets from leaking into the audit log.

**Anchor**: `docs/review/proof-cards/audit-service.md` and the `audit_logs` schema in `src/database/migrations/`.

### 4. Outbound DLP at the AI provider boundary

`OutboundGovernanceService.scanBeforeSend` is now a mandatory call site on every AI provider before any payload reaches a third-party LLM endpoint. This closed a silent exfiltration path that existed in earlier versions: DLP was applied at API ingress but not at AI egress. The DI binding now fails the smoke CI suite if `scanBeforeSend` is bypassed.

**Anchor**: `docs/review/proof-cards/dlp-service.md` and the inversify wiring at `src/inversify/inversify.config.ts`.

### 5. Connector write DLP

The same `scanBeforeSend` boundary now covers the five production connectors' write paths (NetSuite, Business Central, Salesforce, HubSpot, ShipStation). A reviewer can confirm by reading each connector's `write` / `update` / `create` method — `OutboundGovernanceService` is no longer optional.

**Anchor**: PR #747 and the five connector proof cards.

### 6. Identity context propagation

`AIProvider.chat`, `.suggest`, and `.assessQuality` now accept an optional `ctx?: IdentityContext` parameter. Routes call `extractIdentityContext(req)` using whole-source-first matching (`req.auth` → `req.user`, never splicing fields across sources). A drift gate at `scripts/check-system-identity-isolation.mjs` prevents hardcoded `'__system__'` literals outside the canonical `identityContext.ts` file. The practical effect: AI inferences and audit records are now attributable to a real tenant, not a system pseudo-identity.

**Anchor**: `src/services/governance/identityContext.ts` and `docs/adr/ADR-004-DUAL-AI-SYSTEM-DESIGN.md`.

### 7. Canonical Connector Registry + wiring-drift CI gate

`src/connectors/connectorRegistry.ts` is now the single source of truth for which connectors ship and how each one is wired. Per-entry `factory(systemId, deps)` closures encapsulate the five distinct constructor shapes. The CI gate `npm run audit-status-claims --check-wired-connectors` enforces both consistency (registry ↔ AST ↔ proof cards) and wiring drift — any `new <ClassName>(` outside the registry for a factory-wired class fails CI. Adding a new connector now has one canonical seam.

**Anchor**: `src/connectors/connectorRegistry.ts` and the AGENTS.md "How to add connector #19" section.

### 8. Embedded ERP Surface Contract

`src/routes/embedded/{contextBootstrapRouter,hostBootstrapRouter,sessionTeardownRouter}.ts` plus `src/services/embedded/{ActionIslandService,EmbeddedSessionRepository,EmbeddedServiceTokenRepository,EmbeddedRetentionJob}.ts` implement the session-token round-trip that backs the embedded ERP sidecar surface for seven modules. A host (NetSuite or Business Central) bootstraps a session, the platform issues a per-tenant service token, the sidecar uses that token for the session's lifetime, and the retention job reaps expired tokens.

**Anchor**: PR #754 and the source files listed above.

---

## What Squire can pilot today

SyncErrorAssist alone is a concrete service. The pilot shape:

1. Squire instruments a client's NetSuite instance with the User Event SuiteScript published in `docs/operations/SYNC-ERROR-ASSIST-WEBHOOK-SUITESCRIPT.md`.
2. The SuiteScript posts sync-error records to the platform's HMAC-authenticated ingest endpoint.
3. The platform diagnoses each error with the AI pipeline (DLP-redacted, cost-tracked, reasoning-traced).
4. A Squire consultant reviews each proposed fix in the operator UI and approves, rejects, or escalates.
5. Approved fixes write back to NetSuite via the platform's governed connector path.
6. Every action lands in the persistent audit log, queryable per client.

The pilot's contracted unit is the consultant-hours saved per resolved error, measured against a baseline of how long the same error took to resolve before the platform was in place. The four Squire-specific benefits at the top of this document are the marketing case; the audit log is the receipt that lets Squire bill against it.

---

## What's still beta. What's still roadmap.

**Beta** means the production-credibility evidence exists, but the feature has not been credentials-tested against a live Squire NetSuite sandbox under a real workload:

- SyncErrorAssist — operator UI is beta; webhook ingest is beta; the AI diagnosis path is functional.
- FinanceCentral operator service — the state machine is beta; the operator UI surface on `public/finance-central-dashboard.html` exercises the new API.

**Roadmap** items the package does not claim are shipped:

- A full operator cockpit UI (richer than the current narrow approve/reject surface). This is the human-approval queue called out in CLAUDE.md as Tier-3.
- Promotion of any of the 12 demo-mode / 1 stub connectors to production status. Each one requires a credentials test on file.
- Customer-facing pricing or contract templates for the SyncErrorAssist pilot. That's a Squire commercial conversation, not a platform deliverable.

---

## How to verify any claim in this document

Every feature row in the eight-row evidence table points at either a proof card (`docs/review/proof-cards/*.md`) or a source file. The proof cards have a fixed six-section schema:

1. Claim
2. Source
3. Tests
4. Live vs Fixture
5. Known Gaps
6. 60-second verification recipe

The 60-second recipe is meant to be copy-pasteable: clone the public reviewer-mirror, run the command, read the output. The CI gates that audit these cards run on every push to `main`, so a reader can trust the cards' status field over any prose claim in this document.

---

## Related artifacts

- The strategic narrative spine: [`docs/01_VISION_DOCUMENT.md`](../../docs/01_VISION_DOCUMENT.md) (Wave 2 section appended May 2026)
- The canonical wording rules: [`26-CANONICAL-METRICS-AND-WORDING.md`](./26-CANONICAL-METRICS-AND-WORDING.md) (Wave 2 approved-wording section appended May 2026)
- The proof-card index: [`docs/review/proof-cards/`](../../docs/review/proof-cards/) (15 cards on `main` as of May 2026, excluding `_template.md`)
- The NotebookLM source set: mirrored as Google Docs to a Drive folder and kept live in the NotebookLM notebook (auto-synced from Drive; no downloadable zip) — manifest at [`27-NOTEBOOKLM-SOURCE-MANIFEST.md`](./27-NOTEBOOKLM-SOURCE-MANIFEST.md)
- The reviewer-mirror public snapshot: `https://github.com/KStratMD/Preston-Test-reviewer-snapshot`
