Sprinter Docs

Tech Debt Pass 4

Close tool-layer tenant scoping gaps, collapse duplicate entity-tool mutations onto shared services, refresh backlog priorities, and restore local verification.

Problem

Recent dev work kept expanding the view/block/tool surface area while some of the most sensitive tool paths drifted away from the shared entity services. The result was two immediate platform risks:

  1. Entity and response tools were doing admin-client record access by ID without always enforcing tenant_id.
  2. Entity tools reimplemented entity CRUD and relation writes instead of reusing the tenant-scoped keyed entity services, which made behavior drift and increased bug surface.

The broader backlog had also gone stale: several old auth items were already fixed on current dev, while newer architecture debt around exploratory view/block growth and legacy extraction paths was underrepresented.

Goals

  • Fail closed on tenant scoping for agent-facing tools.
  • Reduce duplicate mutation logic in the tool layer.
  • Add regression coverage for the scoped paths.
  • Refresh the backlog so the next cleanup pass targets real current debt.
  • Restore local verification by fixing the localized code-side typecheck regression.

Scope

In scope

  • features/tools/entity-tools.ts
  • features/tools/response-tools.ts
  • features/tools/server/actions.ts
  • Focused regression tests for those paths
  • Backlog refresh notes
  • Local typecheck unblock for features/graph/hooks/use-graph-data.test.ts

Out of scope

  • Re-architecting the view/block system in this pass
  • Removing custom workspace views from record detail
  • Full extraction/runtime consolidation
  • Sweeping lint-warning cleanup across the repo

Changes

1. Tenant-scoped tool reads and writes

  • getEntity now resolves records through getEntityByIdKeyed(tenantId, id).
  • createEntity, updateEntity, deleteEntity, and createRelation now route through the keyed entity services instead of open-coding admin-client mutations.
  • submitResponse now resolves the entity type using tenant_id in addition to id.
  • getToolRunById now scopes by active tenant.

2. Shared mutation path

  • Entity tool CRUD now reuses the same keyed services used by API-key routes.
  • Activity logging for relation creation is handled through logTenantActivity rather than another inline insert path.
  • This narrows the number of places where entity-write behavior can diverge.

3. Regression coverage

  • Added tests that assert entity tools delegate to tenant-scoped keyed helpers.
  • Added test coverage for response-tool tenant scoping.
  • Added test coverage for tool-run tenant scoping.

4. Verification repair

  • Fixed the localized test typing issue in use-graph-data.test.ts so pnpm typecheck is no longer blocked on that code path.
  • The remaining lib/docs-source.ts failure is a generated-artifact issue and is handled by regenerating .source/ locally before verification.

5. Legacy extraction route consolidation

  • Extracted shared extraction submission/sync logic into features/entities/extraction/server/submissions.ts.
  • Updated run-extraction.ts and the deprecated external submit route to share the same response-sync path instead of maintaining separate promotion logic.
  • Reduced route-layer business logic in app/api/extraction/[entityId]/submit/route.ts so it is now primarily auth, validation, and response mapping.

6. Record detail default-path simplification

  • Extracted detail-view selection into a tested helper so the record page no longer decides view state ad hoc in the client.
  • Changed entity detail back to schema-first default behavior: custom workspace views now activate only when a specific ?view= is requested.
  • Reduced server work and bug surface by resolving blocks for only the selected custom detail view instead of resolving every workspace view on every record request.

7. Block/view canonical config cleanup

  • Moved legacy block-config migration to the parse/normalization boundary so older field-card.fieldName and stat-cards.stats shapes are standardized automatically on read and write.
  • Simplified resolveDetailViewBlocks() and editor previews to assume the canonical fields: string[] shape instead of carrying render-time compatibility branches.
  • Stopped the field-card config panel from writing legacy keys back into saved views.
  • Removed obsolete diagnostic warnings for legacy config shapes that are now auto-canonicalized.

8. Dead resolver-wrapper removal

  • Removed the unused collectViewBlocks() and resolveViewBlocks() exports from features/blocks/lib/from-entity-view.ts.
  • Tightened resolve-view.ts, architecture docs, and block-system docs so resolveView() is the documented entry point and the remaining helpers are clearly internal implementation details.

9. Unified entity-single resolution and flattened-view alignment

  • Folded the remaining entity-single resolver logic into resolveView() and deleted features/blocks/lib/from-entity-view.ts entirely.
  • Moved regression coverage onto resolve-view.test.ts so the supported contract is tested at the actual public entry point.
  • Updated the live docs to match the flattened views model already encoded in migrations: flat blocks, block_order, data_sources, and layout, without regions/tabs/presets in the runtime contract.

10. Extraction review and workflow-state cleanup

  • approveResult() and rejectResult() now synchronize linked entity_responses so extraction review cannot diverge from the canonical response runtime.
  • /api/workflows/[entityId] no longer fetches and returns legacy extraction rows that the workflow UI does not use.
  • Deleted the dead extraction-progress/history/result-row components that were no longer mounted anywhere in the app.
  • Updated the architecture docs to describe the workflow-first status UI and the extraction tables as compatibility/audit surfaces rather than the primary runtime.
  • Restored tenant scoping on the deprecated extraction-history path so getExtractionRunHistory() and /api/extraction/[entityId]/history no longer rely on entity_id alone.
  • Deleted the dead /api/enrich compatibility wrapper and the unused extraction barrel so fewer legacy workflow entry points remain available.

11. Canonical internal naming for server-resolved blocks

  • Renamed the remaining collection/aggregation helper from the deprecated resolve.ts path to resolve-server-blocks.ts.
  • Renamed the helper export to resolveServerBlocks() so resolveView() is the only documented/public block resolution entry point.
  • Updated tests and live docs to describe the helper as an internal implementation detail rather than another supported resolver API.

12. Dead compatibility-shim removal

  • Deleted the unused features/entities/components/registry.ts alias now that the codebase imports the canonical entity-card registry/types directly.
  • Removed stale docs references to /api/enrich so the documented manual workflow trigger path matches the actual runtime surface.

13. Workflow-route parity and non-mutating legacy view fallback

  • Added shared workflow API access resolution so /api/workflows/[entityId] and /api/workflows/[entityId]/history now support the same API-key tenant/scoping rules that the deprecated extraction trigger/history wrappers used.
  • Updated the single-field rerun dialog to call the canonical workflow trigger route directly with triggerType: "feedback_rejected" and field overrides.
  • Removed the deprecated extraction trigger/history/rerun wrappers once the workflow endpoints fully covered that functionality.
  • Replaced entity-type-page write-on-read migration with a deterministic synthetic legacy dashboard view so old config.dashboard.sections still render without creating DB rows during page load.
  • Stopped the record-detail client from recomputing detail-view selection; the server now passes one unified selection payload alongside resolved blocks.

Audit outcomes

Fixed in this pass

  • Tool-layer tenant scoping gaps for entity reads/writes
  • Duplicate entity tool mutation orchestration
  • Tool-run single-record scoping gap
  • Local graph hook test type regression
  • One legacy extraction-response duplication path in the external submit route
  • Extraction review no longer updates only legacy audit rows when a canonical response link exists
  • Extraction-history compatibility reads are tenant-scoped again instead of relying on entity ID alone
  • The dead /api/enrich workflow wrapper and unused extraction/entity-card compatibility barrels are removed
  • The default record-detail request path no longer resolves workspace views unless explicitly requested
  • Legacy field-card/stat-card config compatibility no longer leaks into the block render path
  • Dead wrapper exports around the old entity-view resolver path are removed
  • The old entity-detail resolver module is removed and entity-single resolution now lives behind resolveView() only
  • The deprecated features/blocks/server/resolve.ts entry point is gone; only resolveView() remains as the supported resolver contract
  • The record-detail client no longer runs a second custom-view selection pass on top of the server result
  • Workflow trigger/status/history routes now provide API-key parity, so the deprecated extraction trigger/history/rerun wrappers are removed
  • Legacy dashboard configs no longer create persisted views as a side effect of reading an entity-type page

Still high priority

  • Record detail still carries the workspace-view/editor system as optional page surface even though the default path is now schema-first again.
  • Extraction audit/result compatibility APIs and tables still coexist with workflow/response execution.
  • Some legacy dashboard/view schema compatibility code still exists even though the resolver stack is now standardized behind resolveView().
  • Some historical planning docs still reference removed compatibility surfaces and need occasional pruning as those surfaces are deleted.
  • Current backlog counts and some historical P0/P1 items needed rescoring against current dev.

Follow-up queue

  1. Continue narrowing record-detail customization so the optional workspace-view/editor surface stays aligned with the schema-first default.
  2. Retire or hard-freeze the remaining extraction audit compatibility surface behind the workflow/response runtime.
  3. Prune the remaining view/schema compatibility shims and historical docs that still imply write-on-read migration behavior.
  4. Keep route verification healthy by regenerating .source/ as part of environment setup or CI.

On this page