diff --git a/docs/FEATURE_MAP.md b/docs/FEATURE_MAP.md
index a434916ce..4aee6aba1 100644
--- a/docs/FEATURE_MAP.md
+++ b/docs/FEATURE_MAP.md
@@ -12,10 +12,11 @@ an interactive page (open it in a browser), and
[the test and fix plan](plans/2026-10-25-feature-and-dialect-test-plan.md) sets
the order every feature and dialect is tested in.
-Measured on `main` at `100fb679` (2026-10-26): 17 server feature modules,
-155 HTTP routes (pinned by `packages/server/src/api/http-contract.test.ts`),
-14 frontend features, 16 database engines, 28 metadata tables (31 migrations),
-56 e2e specs, ~600 unit-test files. Re-measure with the commands in
+Measured on `main` at `b12bcd5607` (2026-10-31): 34 features, 18 server
+feature modules, 158 HTTP routes (pinned by
+`packages/server/src/api/http-contract.test.ts`), 14 frontend features,
+16 database engines, 28 metadata tables (31 migrations), 57 e2e specs in 35
+groups, ~550 unit-test files. Re-measure with the commands in
[Keeping this page true](#keeping-this-page-true).
- [System](#system)
@@ -37,7 +38,7 @@ flowchart LR
end
subgraph server["Fox server — packages/server (Fastify)"]
PLAT["platform
identity · RBAC · workspaces
connections · guards"]
- FEAT["17 feature modules
153 routes"]
+ FEAT["18 feature modules
158 routes"]
end
WFS["Workflow server :8081
apps/workflow-server
+ packages/workflow-engine"]
META[("Metadata store
SQLite · 28 tables")]
@@ -625,7 +626,9 @@ tables in the schema diagram.
The interactive page, [feature-map.html](feature-map.html), is generated. Edit
its inventory in `docs/feature-map/data.js` (its layout in `template.html`, its
-script in `app.js`; the diagrams come from this page), then rebuild it:
+script in `app.js`; the diagrams come from this page), then rebuild it. Never
+edit the page itself: `feature-map-build.test.ts` fails while it differs from
+the build.
```bash
npm run docs:feature-map
diff --git a/docs/feature-map.html b/docs/feature-map.html
index f2c9f608d..1219927b7 100644
--- a/docs/feature-map.html
+++ b/docs/feature-map.html
@@ -238,17 +238,17 @@
main · 100fb679 · 2026-10-26 · mirrors docs/FEATURE_MAP.mdmain · b12bcd5607 · 2026-10-31 · mirrors docs/FEATURE_MAP.mdflowchart LR
- R[Request] --> O["Origin policy<br/>+ rate limit"] --> S["Session guard<br/>(auth.guard)"] --> W["Workspace scope<br/>(resolveWorkspace)"]
+ R[Request] --> O["Origin policy<br/>+ rate limit"] --> S["Session guard<br/>(auth.guard)"] --> RO["app.write or GET / reads"]
+ RO --> W["Workspace scope<br/>(resolveWorkspace)"]
W --> P["Permission guard<br/>requirePermissions()"] --> H["Feature route<br/>→ service"]
H --> C["Connection resolver<br/>(decrypts the saved connection)"] --> D["Driver<br/>packages/db"]
H --> M[("Metadata store")]Every request passes origin, session, workspace and permission checks before a feature runs.
flowchart LR
A[Same SELECT on ≥2 destinations] --> B[Side by side + Compare data]
- B --> C[align rows by key columns]
- C --> D[add / edit / delete per target<br/>Sync column picks rows]
+ B --> W["Compare 2,000 rows<br/>both sides in key order"]
+ B --> C[or align the pages already loaded]
+ W --> D[add / edit / delete per target<br/>Sync column picks rows]
+ C --> D
D --> E[Preview SQL]
E --> F{Safe mode}
F -- confirm --> G[POST /api/data-migrations/start]
G --> H[backup snapshot of affected rows]
- H --> I[POST /api/data-migrate/execute<br/>Transaction only where it can roll back<br/>stop or continue on error]
+ H --> I["POST /api/data-migrate/execute<br/>≤ 2,000 ops, one shared cap<br/>Transaction only where it can roll back"]
I --> J[POST /api/data-migrations/:id/finish<br/>data_migrate_runs]
J --> K[History: restore from snapshot]flowchart LR @@ -650,7 +653,7 @@Coverage
56 Playwright specs in 37 groups, run with npm run test:e2e:all. Dialect suites need their Docker container and a fresh seed.
57 Playwright specs in 35 groups, run with npm run test:e2e:all. Dialect suites need their Docker container and a fresh seed.