Skip to content

documenso#3

Merged
Connorbelez merged 10 commits intomainfrom
03-11-documenso
Mar 12, 2026
Merged

documenso#3
Connorbelez merged 10 commits intomainfrom
03-11-documenso

Conversation

@Connorbelez
Copy link
Copy Markdown
Owner

@Connorbelez Connorbelez commented Mar 12, 2026

documenso

Added document gen demo and audit trail demo

biome update

Summary by CodeRabbit

Release Notes

  • New Features

    • Document Engine: Design and generate templated PDFs with variable interpolation, signable fields, and batch group generation.
    • Audit & Traceability: Track entity changes with cryptographic hash chains, verify integrity, monitor outbox delivery, and generate compliance reports with PII redaction.
    • System Variables: Create and manage document variables with type-aware formatting (currency, dates, booleans).
  • Improvements

    • Enhanced form validation and submission handling across demos.
    • Theme detection now works reliably without localStorage dependencies.
    • Postal code validation now supports multiple countries.
  • Tests

    • Comprehensive end-to-end test coverage for Document Engine and Audit features.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Connorbelez, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9031485b-e32b-42b4-a5b9-4e9afc5c0a34

📥 Commits

Reviewing files that changed from the base of the PR and between 6ed9496 and 3504a0f.

⛔ Files ignored due to path filters (6)
  • bun.lock is excluded by !**/*.lock
  • convex/_generated/api.d.ts is excluded by !**/_generated/**
  • convex/components/auditTrail/_generated/api.ts is excluded by !**/_generated/**
  • convex/components/auditTrail/_generated/component.ts is excluded by !**/_generated/**
  • convex/components/auditTrail/_generated/dataModel.ts is excluded by !**/_generated/**
  • convex/components/auditTrail/_generated/server.ts is excluded by !**/_generated/**
📒 Files selected for processing (98)
  • .gitignore
  • AGENT_LESSONS.md
  • biome.json
  • convex/auditTrailClient.ts
  • convex/components/auditTrail/convex.config.ts
  • convex/components/auditTrail/crons.ts
  • convex/components/auditTrail/internal.ts
  • convex/components/auditTrail/lib.ts
  • convex/components/auditTrail/schema.ts
  • convex/convex.config.ts
  • convex/crons.ts
  • convex/demo/aggregate.ts
  • convex/demo/auditTraceability.ts
  • convex/demo/timeline.ts
  • convex/demo/triggers.ts
  • convex/documentEngine/basePdfs.ts
  • convex/documentEngine/dataModelEntities.ts
  • convex/documentEngine/generation.ts
  • convex/documentEngine/generationHelpers.ts
  • convex/documentEngine/systemVariables.ts
  • convex/documentEngine/templateGroups.ts
  • convex/documentEngine/templateTimeline.ts
  • convex/documentEngine/templateVersions.ts
  • convex/documentEngine/templates.ts
  • convex/documentEngine/validators.ts
  • convex/schema.ts
  • e2e/audit-traceability.spec.ts
  • e2e/auth/login.spec.ts
  • e2e/document-engine/designer.spec.ts
  • e2e/document-engine/generate.spec.ts
  • e2e/document-engine/groups.spec.ts
  • e2e/document-engine/library.spec.ts
  • e2e/document-engine/navigation.spec.ts
  • e2e/document-engine/templates.spec.ts
  • e2e/document-engine/variables.spec.ts
  • e2e/document-engine/workflow.spec.ts
  • e2e/helpers/document-engine.ts
  • package.json
  • scripts/code-review.sh
  • src/components/audit-traceability/access-log-content.stories.tsx
  • src/components/audit-traceability/alerts-card.stories.tsx
  • src/components/audit-traceability/control-card.stories.tsx
  • src/components/audit-traceability/page-badge.stories.tsx
  • src/components/audit-traceability/severity-badge.stories.tsx
  • src/components/audit-traceability/shared.stories.tsx
  • src/components/audit-traceability/shared.tsx
  • src/components/audit-traceability/summary-card.stories.tsx
  • src/components/document-engine/field-config-panel.tsx
  • src/components/document-engine/generation-results.tsx
  • src/components/document-engine/pdf-designer.tsx
  • src/components/document-engine/pdf-upload-dialog.tsx
  • src/components/document-engine/signatory-panel.tsx
  • src/components/document-engine/system-path-browser.tsx
  • src/components/document-engine/variable-picker.tsx
  • src/components/header.tsx
  • src/components/storybook/button.tsx
  • src/components/theme-toggle.tsx
  • src/components/ui/sonner.tsx
  • src/hooks/use-audit-access-log.ts
  • src/lib/document-engine/client-generation.ts
  • src/lib/document-engine/formatting.ts
  • src/lib/document-engine/hash.ts
  • src/lib/document-engine/pdfme-plugins/index.ts
  • src/lib/document-engine/pdfme-plugins/interpolable-field.ts
  • src/lib/document-engine/pdfme-plugins/signable-field.ts
  • src/lib/document-engine/pdfme-sync.ts
  • src/lib/document-engine/signatory-utils.ts
  • src/lib/document-engine/types.ts
  • src/routeTree.gen.ts
  • src/routes/__root.tsx
  • src/routes/demo/audit-traceability/access-log.tsx
  • src/routes/demo/audit-traceability/audit-trail.tsx
  • src/routes/demo/audit-traceability/hash-chain.tsx
  • src/routes/demo/audit-traceability/index.tsx
  • src/routes/demo/audit-traceability/pipeline.tsx
  • src/routes/demo/audit-traceability/report.tsx
  • src/routes/demo/audit-traceability/route.tsx
  • src/routes/demo/convex-crons.tsx
  • src/routes/demo/convex-workflow.tsx
  • src/routes/demo/document-engine/designer.$templateId.tsx
  • src/routes/demo/document-engine/generate.tsx
  • src/routes/demo/document-engine/groups.tsx
  • src/routes/demo/document-engine/index.tsx
  • src/routes/demo/document-engine/library.tsx
  • src/routes/demo/document-engine/route.tsx
  • src/routes/demo/document-engine/templates.tsx
  • src/routes/demo/document-engine/variables.tsx
  • src/routes/demo/form.address.tsx
  • src/routes/demo/storybook.tsx
  • src/routes/demo/table.tsx
  • src/routes/demo/workos.tsx
  • src/test/audit-traceability/shared.test.ts
  • src/test/convex/auditTrailClient.test.ts
  • src/test/convex/auth.test.ts
  • src/test/convex/components/auditTrail/crons.test.ts
  • src/test/convex/components/auditTrail/internal.test.ts
  • src/test/storybook/config.test.ts
  • vite.config.ts

📝 Walkthrough

Walkthrough

The PR introduces an audit trail system with append-only events, hash-chain integrity verification, and a document engine for template-based PDF generation. It includes demo pages showcasing audit traceability with mortgage lifecycle management, comprehensive end-to-end tests, UI components for audit visualization and document design, and supporting schema definitions, validators, and utilities.

Changes

Cohort / File(s) Summary
Audit Trail Component
convex/components/auditTrail/*, convex/auditTrailClient.ts
New audit trail Convex component with append-only event insertion, SHA-256 hash-chain verification, PII sanitization, outbox delivery pipeline, retention cleanup, and internal mutation/query operations.
Document Engine Core
convex/documentEngine/basePdfs.ts, convex/documentEngine/systemVariables.ts, convex/documentEngine/templates.ts, convex/documentEngine/templateVersions.ts, convex/documentEngine/templateGroups.ts
Full CRUD and management APIs for base PDFs, system variables, document templates, template versions, and template groups with validation, duplicate checking, and cross-entity consistency enforcement.
Document Generation
convex/documentEngine/generation.ts, convex/documentEngine/generationHelpers.ts, src/lib/document-engine/client-generation.ts, src/lib/document-engine/formatting.ts
Server-side and client-side PDF generation with variable validation, formatting, Documenso config building, and browser-based PDF hash verification and rendering via pdfme.
Audit Traceability Demo
convex/demo/auditTraceability.ts, src/routes/demo/audit-traceability/*
Comprehensive demo module and pages for mortgage management with audit event tracking, transfer lifecycle, compliance reporting, and access logging with layered audit infrastructure.
Document Engine UI & Pages
src/routes/demo/document-engine/*, src/components/document-engine/*
Designer and management pages for templates, variables, groups, and PDF library; UI components for field configuration, signatory management, PDF upload, and generation results.
Schema, Validators & Types
convex/schema.ts, convex/documentEngine/validators.ts, src/lib/document-engine/types.ts
New schema tables for audit mortgages, base PDFs, variables, templates, versions, entities, and groups; comprehensive validators and TypeScript type definitions for document-engine data structures.
PdfMe Integration
src/lib/document-engine/pdfme-plugins/*, src/lib/document-engine/pdfme-sync.ts
Custom pdfme plugins for interpolable and signable fields with property panels; bidirectional sync utilities between FieldConfig and pdfme Schema objects; template construction.
Audit UI Components
src/components/audit-traceability/shared.tsx, src/components/audit-traceability/*.stories.tsx
Shared audit visualization components (StatusIcon, ControlCard, AlertsCard, PageBadge, SeverityBadge, AccessLogContent) with Storybook stories.
Hooks & Utilities
src/hooks/use-audit-access-log.ts, src/lib/document-engine/hash.ts, src/lib/document-engine/signatory-utils.ts
Custom hook for audit access logging, SHA-256 browser hashing utility, and signatory color/label mappings for domain and custom roles.
End-to-End Tests
e2e/audit-traceability.spec.ts, e2e/document-engine/*, e2e/helpers/document-engine.ts
Comprehensive E2E test suites covering audit traceability workflows, document engine full lifecycle, and helper utilities for test automation.
Unit Tests
src/test/audit-traceability/shared.test.ts, src/test/convex/auditTrailClient.test.ts, src/test/convex/auth.test.ts, src/test/convex/components/auditTrail/*.test.ts, src/test/storybook/config.test.ts
Test suites for audit trail client, auth logic, cron jobs, internal mutations, and Storybook configuration.
Configuration & Infrastructure
convex/crons.ts, convex/convex.config.ts, convex/demo/timeline.ts, convex/demo/triggers.ts, vite.config.ts, biome.json, package.json, scripts/code-review.sh
Cron job setup, Convex component wiring, demo module updates, Vite pdfme-babel bypass plugin, Biome configuration, dependencies (pdfme, pdf-lib), and review script updates.
UI & Routing
src/routeTree.gen.ts, src/routes/__root.tsx, src/components/header.tsx, src/components/storybook/button.tsx, src/components/theme-toggle.tsx, src/components/ui/sonner.tsx, src/routes/demo/form.address.tsx, src/routes/demo/convex-crons.tsx, src/routes/demo/convex-workflow.tsx, src/routes/demo/storybook.tsx, src/routes/demo/table.tsx, src/routes/demo/workos.tsx
New route tree entries for document-engine and audit-traceability; Toaster integration; theme-toggle localStorage safety; header navigation updates; form validation enhancements; demo page refactoring and component extraction.
Documentation & Misc
.gitignore, AGENT_LESSONS.md
Added review.md to gitignore; added three new lessons (6–8) and enhanced lesson 5 with fixes and amendments regarding Playwright E2E testing, dotenv usage, and demo code hardening.

Sequence Diagram

sequenceDiagram
    participant Client as Client/Browser
    participant AppAPI as App API
    participant AuditComp as Audit Component
    participant DB as Database
    participant Crypto as Crypto/Hash

    Client->>AppAPI: insert(event: {...})
    AppAPI->>AuditComp: forward to component.lib.insert
    AuditComp->>Crypto: computeHash(prevHash, event)
    Crypto-->>AuditComp: hash
    AuditComp->>DB: store audit_events with hash chain
    AuditComp->>DB: create audit_outbox entry (pending)
    DB-->>AuditComp: success
    AuditComp-->>AppAPI: eventId
    AppAPI-->>Client: eventId

    Client->>AppAPI: verifyChain(entityId)
    AppAPI->>AuditComp: forward to component.lib.verifyChain
    AuditComp->>DB: fetch audit_events for entity
    loop For each event
        AuditComp->>Crypto: recompute hash
        Crypto-->>AuditComp: computed hash
        AuditComp->>AuditComp: compare with stored hash
    end
    AuditComp-->>AppAPI: { valid, brokenAt?, error? }
    AppAPI-->>Client: verification result

    Client->>AppAPI: emitPending()
    AppAPI->>AuditComp: forward to component.lib.emitPending
    AuditComp->>DB: query audit_outbox (status=pending, limit 100)
    loop For each pending entry
        AuditComp->>AuditComp: emit to external system
        AuditComp->>DB: patch entry (emitted=true, status=emitted)
    end
    AuditComp-->>AppAPI: { emittedCount, failedCount }
    AppAPI-->>Client: result
Loading
sequenceDiagram
    participant Client as Client/Browser
    participant Designer as PDF Designer Page
    participant PdfMe as PdfMe UI
    participant API as Document API
    participant Gen as Generation Service
    participant Storage as Storage

    Client->>Designer: navigate to template
    Designer->>API: fetch template, basePdf URL, variables
    API-->>Designer: template data
    Designer->>PdfMe: load pdfme Designer with fields
    PdfMe-->>Designer: ready

    Client->>Designer: add/edit field (drag on canvas)
    Designer->>PdfMe: onChangeTemplate event
    PdfMe-->>Designer: updated schemas
    Designer->>Designer: sync fields to local state
    Designer->>API: auto-save draft with fields

    Client->>Designer: publish template
    Designer->>API: publish(templateId)
    API->>API: validate fields, verify hash
    API->>Storage: check base PDF
    API->>API: create immutable version
    API-->>Designer: success
    Designer-->>Client: version badge

    Client->>Gen: select template on generate page
    Gen->>API: prepareGeneration(templateId, values)
    API->>API: validate variables, format values
    API-->>Gen: formatted values, fields, dimensions
    Gen->>Gen: client-side: generatePdfInBrowser
    Gen->>Storage: upload generated PDF
    Storage-->>Gen: pdfRef
    Gen-->>Client: success with download link
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐰 Hops with joy at cryptographic chains,
Templates dancing on PDF plains,
Hash by hash, event by event,
Audit trails where trust is spent!
From mortgages to documents true,
A full-stack feast for me and you! 🥕✨

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 03-11-documenso

@Connorbelez Connorbelez mentioned this pull request Mar 12, 2026
Merged
Copy link
Copy Markdown
Owner Author

Connorbelez commented Mar 12, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Connorbelez Connorbelez marked this pull request as ready for review March 12, 2026 15:52
Copilot AI review requested due to automatic review settings March 12, 2026 15:52
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces two new demo feature areas—Document Engine (PDF template authoring + generation) and Audit & Traceability (audit trail UI + Convex component outbox/retention)—and wires up supporting tooling (Vite/Vitest config, UI toasts, and Playwright E2E coverage).

Changes:

  • Add Document Engine routes/components, Convex backend tables/mutations, and pdfme-based designer/generation utilities.
  • Add Audit & Traceability demo UI plus an isolated Convex auditTrail component (schema, outbox processor, retention cron).
  • Expand tooling: Vite workaround for @pdfme/ui, add Playwright E2E suites/helpers, and adjust linting/review scripts.

Reviewed changes

Copilot reviewed 96 out of 99 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
vite.config.ts Adds pdfme/TanStack Start workaround plugin; adjusts Vitest excludes.
src/test/audit-traceability/shared.test.ts Unit tests for audit-traceability shared helpers.
src/routes/demo/workos.tsx Refactors repeated list rendering into components.
src/routes/demo/table.tsx Makes “Go to page” input controlled by pagination state.
src/routes/demo/storybook.tsx Connects submit button to a specific form via form attribute.
src/routes/demo/form.address.tsx Improves postal-code validation by country; auto-clears submit message.
src/routes/demo/document-engine/templates.tsx Adds templates management page for Document Engine demo.
src/routes/demo/document-engine/route.tsx Adds Document Engine layout + navigation.
src/routes/demo/document-engine/library.tsx Adds base PDF library page + upload entry point.
src/routes/demo/document-engine/index.tsx Adds Document Engine dashboard page.
src/routes/demo/convex-workflow.tsx Refactors status badge and step icon rendering.
src/routes/demo/convex-crons.tsx Tightens interval validation before registering cron job.
src/routes/demo/audit-traceability/route.tsx Adds Audit & Traceability layout + navigation.
src/routes/demo/audit-traceability/report.tsx Adds compliance report UI and JSON download.
src/routes/demo/audit-traceability/pipeline.tsx Adds outbox pipeline status/alerts UI with manual emission.
src/routes/demo/audit-traceability/audit-trail.tsx Adds audit trail query UI + critical events watcher.
src/routes/demo/audit-traceability/access-log.tsx Adds access log UI page.
src/routes/__root.tsx Mounts Sonner Toaster at app root.
src/lib/document-engine/types.ts Adds shared document-engine domain/type definitions.
src/lib/document-engine/signatory-utils.ts Adds signatory color/label helpers.
src/lib/document-engine/pdfme-sync.ts Adds conversions/merge logic between FieldConfig and pdfme schemas.
src/lib/document-engine/pdfme-plugins/signable-field.ts Adds custom pdfme “signable field” plugin (UI + prop panel).
src/lib/document-engine/pdfme-plugins/interpolable-field.ts Adds custom pdfme “interpolable field” plugin (pdf renderer + UI).
src/lib/document-engine/pdfme-plugins/index.ts Exposes designer/generator plugin sets.
src/lib/document-engine/hash.ts Adds browser SHA-256 helper.
src/lib/document-engine/formatting.ts Adds type-aware variable formatting for interpolation.
src/lib/document-engine/client-generation.ts Adds browser-side PDF generation + base-PDF hash verification.
src/hooks/use-audit-access-log.ts Adds hook to log audit page access with strict-mode guard.
src/components/ui/sonner.tsx Updates Toaster implementation and theme handling.
src/components/theme-toggle.tsx Hardens localStorage reads/writes with try/catch.
src/components/storybook/button.tsx Adds form prop passthrough to storybook Button.
src/components/header.tsx Adds “Platform” demo section links (Document Engine + Audit & Traceability).
src/components/document-engine/variable-picker.tsx Adds variable selector + inline create flow.
src/components/document-engine/signatory-panel.tsx Adds signatory list/editor UI for templates/groups.
src/components/document-engine/pdf-upload-dialog.tsx Adds base PDF upload dialog with server-side metadata extraction.
src/components/document-engine/pdf-designer.tsx Adds React wrapper around pdfme Designer with sync logic.
src/components/document-engine/generation-results.tsx Adds UI for generation outputs + PDF download links.
src/components/document-engine/field-config-panel.tsx Adds sidebar editor for selected field configuration.
src/components/audit-traceability/summary-card.stories.tsx Storybook stories for SummaryCard.
src/components/audit-traceability/shared.tsx Shared Audit & Traceability UI components/helpers.
src/components/audit-traceability/shared.stories.tsx Storybook stories for StatusIcon.
src/components/audit-traceability/severity-badge.stories.tsx Storybook stories for SeverityBadge.
src/components/audit-traceability/page-badge.stories.tsx Storybook stories for PageBadge.
src/components/audit-traceability/control-card.stories.tsx Storybook stories for ControlCard.
src/components/audit-traceability/alerts-card.stories.tsx Storybook stories for AlertsCard.
src/components/audit-traceability/access-log-content.stories.tsx Storybook stories for AccessLogContent.
scripts/code-review.sh Tweaks coderabbit invocation to review committed changes.
package.json Adds pdfme + pdf-lib dependencies.
e2e/helpers/document-engine.ts Adds shared Playwright helpers for Document Engine flows.
e2e/document-engine/variables.spec.ts Adds E2E coverage for system variables UI.
e2e/document-engine/templates.spec.ts Adds E2E coverage for templates UI and designer navigation.
e2e/document-engine/navigation.spec.ts Adds E2E coverage for Document Engine layout navigation.
e2e/document-engine/library.spec.ts Adds E2E coverage for base PDF upload/list/delete.
e2e/document-engine/groups.spec.ts Adds E2E coverage for template groups UI.
e2e/document-engine/generate.spec.ts Adds E2E coverage for generate page UI toggles/visibility.
e2e/document-engine/designer.spec.ts Adds E2E coverage for designer initialization and basic actions.
e2e/auth/login.spec.ts Adds required-env guard for WorkOS login E2E tests.
convex/schema.ts Adds Document Engine tables and demo audit mortgage table; imports shared validators.
convex/documentEngine/validators.ts Adds validators for document engine domain objects.
convex/documentEngine/templateVersions.ts Adds queries for template version retrieval.
convex/documentEngine/templateTimeline.ts Adds timeline-backed draft state history (undo/redo/checkpoints).
convex/documentEngine/templates.ts Adds template CRUD + draft validation + publish/versioning logic.
convex/documentEngine/templateGroups.ts Adds template group CRUD + signatory homogeneity enforcement.
convex/documentEngine/systemVariables.ts Adds system variable CRUD with snake_case enforcement.
convex/documentEngine/generationHelpers.ts Adds internal queries to prepare generation inputs and validate groups.
convex/documentEngine/dataModelEntities.ts Adds entity catalog seeding and custom entity management.
convex/documentEngine/basePdfs.ts Adds base PDF storage flows + server-side metadata/hash extraction.
convex/demo/triggers.ts Fixes inserted-contact summary to use first/last name fields.
convex/demo/timeline.ts Hardens undo/redo handling and ensures note upsert.
convex/demo/aggregate.ts Reorders aggregate deletion relative to doc deletion.
convex/crons.ts Adds host-app crons file (auditTrail handled by component).
convex/convex.config.ts Registers auditTrail component with Convex app.
convex/components/auditTrail/schema.ts Adds isolated audit trail component tables/indexes.
convex/components/auditTrail/internal.ts Adds outbox processor + retention cleanup internal mutations.
convex/components/auditTrail/crons.ts Adds component-owned cron schedule for outbox + retention.
convex/components/auditTrail/convex.config.ts Declares auditTrail Convex component.
convex/components/auditTrail/_generated/server.ts Generated component server helpers.
convex/components/auditTrail/_generated/dataModel.ts Generated component data model types.
convex/components/auditTrail/_generated/component.ts Generated component API typing.
convex/components/auditTrail/_generated/api.ts Generated component api/internal exports.
convex/auditTrailClient.ts Adds append-only client wrapper for interacting with auditTrail component.
convex/_generated/api.d.ts Updates generated API typings to include new modules/components.
biome.json Excludes e2e from Biome; disables filename convention rule.
AGENT_LESSONS.md Adds internal lessons about Playwright/env handling.
.gitignore Ignores generated review output file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +22
function AccessLogPage() {
useAuditAccessLog("audit-trail");
const accessLog = useQuery(api.demo.auditTraceability.getAccessLog, {});
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useAuditAccessLog("audit-trail") is logging this page view as audit.viewed.audit-trail, which will make the access-log page indistinguishable from the audit-trail page (and PageBadge will display the wrong page). Consider adding an explicit "access-log" member to the AuditPage union and logging that here so access-log views are tracked accurately.

Copilot uses AI. Check for mistakes.
Comment thread src/routes/demo/table.tsx
Comment on lines 260 to 269
| Go to page:
<input
className="w-16 rounded-md border border-gray-700 bg-gray-800 px-2 py-1 outline-none focus:border-transparent focus:ring-2 focus:ring-blue-500"
defaultValue={table.getState().pagination.pageIndex + 1}
onChange={(e) => {
const page = e.target.value ? Number(e.target.value) - 1 : 0;
table.setPageIndex(page);
}}
type="number"
value={table.getState().pagination.pageIndex + 1}
/>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pagination input is now fully controlled by table.getState().pagination.pageIndex + 1, but the onChange handler immediately forces empty input back to page 1 ("" -> pageIndex 0 -> value becomes 1). That makes it impossible to clear/edit the field naturally (e.g. select-all/delete, or temporarily type an out-of-range value). Consider keeping a local string state for the input and only committing to table.setPageIndex on blur/enter (or when the value parses cleanly).

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +34
function mergeFieldMeta(
pdfmeSchema: PdfmeFieldSchema,
existing?: FieldMeta
): FieldMeta | undefined {
const merged: FieldMeta = {
placeholder: pdfmeSchema.placeholder || existing?.placeholder || undefined,
helpText: pdfmeSchema.helpText || existing?.helpText || undefined,
readOnly: pdfmeSchema.fieldReadOnly ?? existing?.readOnly,
};
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mergeFieldMeta uses || when merging placeholder/helpText. Because empty string is falsy, clearing a value in the pdfme UI (""), or a plugin defaulting these fields to "", will cause the old existing value to be retained. This prevents users from actually clearing placeholder/help text once set. Use ?? / explicit undefined checks so empty strings can overwrite existing values (and optionally normalize "" -> undefined intentionally).

Copilot uses AI. Check for mistakes.
Comment on lines +153 to +165
if (existing.type === "interpolable") {
base.variableKey =
(pdfmeSchema as InterpolableSchema).variableKey || existing.variableKey;
}

if (existing.type === "signable") {
base.signableType =
((pdfmeSchema as SignableSchema).signableType as SignableType) ||
existing.signableType;
base.signatoryPlatformRole =
((pdfmeSchema as SignableSchema).platformRole || undefined) ??
existing.signatoryPlatformRole;
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mergeExistingField uses || / ?? in a way that makes it impossible to unset several string fields via the pdfme designer. For example, if an interpolable field previously had variableKey set, changing it to "(None)" in the designer will likely produce an empty string, but "" || existing.variableKey keeps the old key. Same issue for signatoryPlatformRole (empty string becomes undefined, then ?? falls back to existing). This will make the UI feel broken when trying to remove variable/signatory bindings.

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +61
.withIndex("by_entity")
.filter((q) => q.lt(q.field("timestamp"), cutoff))
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The retention query uses .withIndex("by_entity") (entityId, timestamp) but doesn't constrain entityId, and then filters by timestamp. This means cleanup will iterate in entityId order rather than oldest-first globally, and may never reach expired events for later entity IDs if there are always >100 expired rows earlier in the index. Consider adding an index that starts with timestamp (e.g. by_timestamp) and querying that for retention, or otherwise ensuring the scan order is based on timestamp.

Suggested change
.withIndex("by_entity")
.filter((q) => q.lt(q.field("timestamp"), cutoff))
.withIndex("by_timestamp", (q) => q.lt("timestamp", cutoff))

Copilot uses AI. Check for mistakes.
Comment on lines 21 to 31
style={
{
"--normal-bg": "var(--popover)",
"--normal-text": "var(--popover-foreground)",
"--normal-border": "var(--border)",
"--border-radius": "var(--radius)",
} as React.CSSProperties
}
theme={theme as ToasterProps["theme"]}
theme="dark"
{...props}
/>
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toaster is now hard-coded to theme="dark", but the app has a light/dark/auto theme toggle that updates the documentElement class. In light mode, toast styling will remain dark, which is inconsistent and may reduce readability. Consider deriving the Sonner theme from the current resolved theme (or omitting the prop and letting your CSS variables/theme classes drive colors) so toasts match the active UI theme.

Copilot uses AI. Check for mistakes.
@Connorbelez
Copy link
Copy Markdown
Owner Author

@greptile review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

✅ Unit tests committed locally. Commit: 703edc7833c262e9ee072cb91a5af6e3e268f24f

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Connorbelez, your pull request is larger than the review limit of 150000 diff characters

Copy link
Copy Markdown
Owner Author

Connorbelez commented Mar 12, 2026

Merge activity

  • Mar 12, 4:40 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Mar 12, 4:43 PM UTC: Graphite rebased this pull request as part of a merge.
  • Mar 12, 4:44 PM UTC: @Connorbelez merged this pull request with Graphite.

@Connorbelez Connorbelez changed the base branch from 03-11-fluent to graphite-base/3 March 12, 2026 16:41
@Connorbelez Connorbelez changed the base branch from graphite-base/3 to main March 12, 2026 16:42
Connorbelez and others added 10 commits March 12, 2026 16:43
…labels

- Add dataModelEntities table with schema introspection seed, custom entity
  CRUD, and browsable two-panel picker (SystemPathBrowser) for variable
  system path selection
- Replace inline error state with sonner toast notifications in groups and
  variables pages; mount Toaster in root layout
- Fix truncated pdfme designer sidebar labels by setting options.labels and
  options.icons for interpolableField/signableField plugins
- Refactor pdfme-sync.ts to reduce cognitive complexity by extracting
  shared helpers for schema conversion and field merging
- Fix nested ternaries in workos.tsx and convex-workflow.tsx
- Fix stray closing brace parse error in workos.tsx

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convex requires camelCase filenames for module path resolution, which
conflicts with biome's kebab-case default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Connorbelez Connorbelez merged commit c8fe340 into main Mar 12, 2026
0 of 2 checks passed
@Connorbelez Connorbelez mentioned this pull request Mar 13, 2026
Merged
@coderabbitai coderabbitai Bot mentioned this pull request Mar 15, 2026
Merged
Connorbelez added a commit that referenced this pull request Mar 16, 2026
SPEC 1.2 updates:
- §2 File Structure: corrected paths to convex/engine/ nesting
- §9 Developer Checklist: fixed all file paths
- §10 Open Questions: closed #1 (guard timing), #2 (confirmObligationPayment),
  #3 (generateObligations helper)
- Removed effects/mortgage.ts, added effects/workosProvisioning.ts

PRD 1.2 updates:
- GT DoD #3: marked deal machine as descoped to Project 4
- Renamed seedInvestor → seedLender (schema table is lenders)
- Marked seedDeal as descoped

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Connorbelez added a commit that referenced this pull request Mar 16, 2026
SPEC 1.2 updates:
- §2 File Structure: corrected paths to convex/engine/ nesting
- §9 Developer Checklist: fixed all file paths
- §10 Open Questions: closed #1 (guard timing), #2 (confirmObligationPayment),
  #3 (generateObligations helper)
- Removed effects/mortgage.ts, added effects/workosProvisioning.ts

PRD 1.2 updates:
- GT DoD #3: marked deal machine as descoped to Project 4
- Renamed seedInvestor → seedLender (schema table is lenders)
- Marked seedDeal as descoped

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Connorbelez added a commit that referenced this pull request Mar 16, 2026
#82)

ft. ENG-23: cross-entity effects, reconciliation, and engine hardening

- Replace obligation effect stubs with real cross-entity dispatch
  (emitObligationOverdue/Settled now read obligation → transition mortgage)
- Add transitionMortgageInternal for scheduler/effect use
- Add confirmObligationPayment (authedMutation + obligation:manage)
- Add notifyAdminNewRequest as entry action on pending_review state
- Filter assign-action warnings in effect scheduler (isBuiltInAction)
- Extend reconciliation to handle mortgage + obligation entity types
- Add machineContext explanatory comments to governed table schemas
- Fix reconciliation test to use non-governed entity type (deal)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

ft. ENG-23: seed mutations for all Phase 1 entities

- Create convex/seed/ directory with 8 files
- seedBroker: 2 brokers with FSRA license numbers, Ontario-based
- seedBorrower: 5 borrowers with Ontario addresses, verified IDV
- seedLender: 3 lenders with accreditation, broker-assigned
- seedMortgage: 5 mortgages with varied terms + auto-generated obligations
- generateObligations: interest-only bridge loan payment schedule
- seedObligationStates: transitions obligations to due/overdue/settled mix
- seedOnboardingRequest: 3 requests (pending_review, approved, rejected)
- seedAll: orchestrator in dependency order, idempotent

All seeds use executeTransition for non-initial states (proper journal entries).
Each entity gets a SEED_CREATED journal entry for audit trail continuity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

ft. ENG-23: reconciliation cron + internal query

- Add daily reconciliation cron (06:00 UTC) that runs Layer 1 check
- Create reconciliationAction.ts with internalQuery (no auth required)
  and internalAction for cron scheduling
- Discrepancies logged as P0 errors via console.error
- On-demand adminQuery reconciliation remains available

Resolves SPEC Open Question #5: daily cron + on-demand admin query.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

ft. ENG-23: integration tests — guard failure, missing effects, cross-entity

- Add guard failure test: mortgage DEFAULT_THRESHOLD_REACHED with 0 missed
  payments → rejected, status unchanged
- Add missing effect handler test: unknown action → warn + succeed
- Create crossEntity.test.ts with 4 tests proving full obligation→mortgage
  cascade: overdue dispatch, settlement cure, and journal chain consistency
- Fix pre-existing test: "throws when no machine is registered" assertion

Cross-entity tests manually invoke effects (convex-test doesn't auto-run
scheduled functions), verifying the complete chain:
  obligation due→overdue → mortgage active→delinquent
  obligation overdue→settled → mortgage delinquent→active (cure)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

docs: ENG-23 — update SPEC 1.2 and PRD 1.2 on Notion

SPEC 1.2 updates:
- §2 File Structure: corrected paths to convex/engine/ nesting
- §9 Developer Checklist: fixed all file paths
- §10 Open Questions: closed #1 (guard timing), #2 (confirmObligationPayment),
  #3 (generateObligations helper)
- Removed effects/mortgage.ts, added effects/workosProvisioning.ts

PRD 1.2 updates:
- GT DoD #3: marked deal machine as descoped to Project 4
- Renamed seedInvestor → seedLender (schema table is lenders)
- Marked seedDeal as descoped

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

fix: ENG-23 — type reconciliationAction entityType parameter

Use keyof typeof ENTITY_TABLE_MAP instead of string for type safety
in collectLatestEntries function parameter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

fix: ENG-23 — address code review findings in seed mutations

- Fix idempotency: reuse existing user when entity doesn't exist yet
  (seedBorrower, seedLender, seedOnboardingRequest, seedMortgage)
- Fix seedMortgage: reuse existing property instead of duplicating
- Fix generateObligations: clamp day to prevent setMonth date drift
- Note: seedLender entityType "borrower" is intentional — lenders are
  not yet a governed entity type in the GT engine

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

## Summary by Sourcery

Implement cross-entity coordination between obligations and mortgages, extend reconciliation and scheduling infrastructure, and add idempotent seed data plus tests and cron-based health checks.

New Features:
- Enable cross-entity effects so obligation state changes drive corresponding mortgage transitions.
- Introduce internal and admin-facing commands for mortgage transitions and confirming obligation payments.
- Add an internal reconciliation query and daily cron-driven reconciliation check across governed entities.
- Seed phase-1 entities (brokers, borrowers, lenders, mortgages, obligations, onboarding requests) with realistic, journal-backed demo data.
- Provide an orchestrated seedAll mutation to populate a complete demo dataset in dependency order.

Bug Fixes:
- Ensure reconciliation skips non-governed entity types while handling mortgages and obligations correctly.
- Prevent scheduling of XState built-in actions as effects and gracefully handle missing effect handlers.
- Fix reconciliation tests to use non-governed entities and relax an over-specific transition engine error assertion.
- Clamp generated obligation due dates to avoid calendar drift in monthly schedules.
- Improve seed mutations to be idempotent by reusing existing users, properties, and entities.

Enhancements:
- Document machineContext usage for governed tables and add notification entry actions to onboarding requests.
- Expand reconciliation utilities to support internal use and improve discrepancy reporting.
- Strengthen guard behavior for mortgage default thresholds via explicit tests.

Documentation:
- Clarify governed vs non-governed entities and machine context expectations in schema comments.

Tests:
- Add cross-entity integration tests covering obligation→mortgage cascades and journal chain consistency.
- Add tests for guard failures, missing effect handlers, and reconciliation behavior across entity types.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Release Notes

* **New Features**
  * Added automated daily health checks to verify system integrity.
  * Enabled obligation payment confirmation through the admin dashboard.
  * Added admin notifications for new onboarding requests.

* **Improvements**
  * Enhanced coordination between related financial entities to ensure consistent state transitions.
  * Strengthened validation to prevent invalid state changes.

* **Tests**
  * Added comprehensive test coverage for entity workflows and state validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@coderabbitai coderabbitai Bot mentioned this pull request Apr 18, 2026
Connorbelez added a commit that referenced this pull request Apr 20, 2026
documenso

Added document gen demo and audit trail demo

biome update
Connorbelez added a commit that referenced this pull request Apr 20, 2026
#82)

ft. ENG-23: cross-entity effects, reconciliation, and engine hardening

- Replace obligation effect stubs with real cross-entity dispatch
  (emitObligationOverdue/Settled now read obligation → transition mortgage)
- Add transitionMortgageInternal for scheduler/effect use
- Add confirmObligationPayment (authedMutation + obligation:manage)
- Add notifyAdminNewRequest as entry action on pending_review state
- Filter assign-action warnings in effect scheduler (isBuiltInAction)
- Extend reconciliation to handle mortgage + obligation entity types
- Add machineContext explanatory comments to governed table schemas
- Fix reconciliation test to use non-governed entity type (deal)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

ft. ENG-23: seed mutations for all Phase 1 entities

- Create convex/seed/ directory with 8 files
- seedBroker: 2 brokers with FSRA license numbers, Ontario-based
- seedBorrower: 5 borrowers with Ontario addresses, verified IDV
- seedLender: 3 lenders with accreditation, broker-assigned
- seedMortgage: 5 mortgages with varied terms + auto-generated obligations
- generateObligations: interest-only bridge loan payment schedule
- seedObligationStates: transitions obligations to due/overdue/settled mix
- seedOnboardingRequest: 3 requests (pending_review, approved, rejected)
- seedAll: orchestrator in dependency order, idempotent

All seeds use executeTransition for non-initial states (proper journal entries).
Each entity gets a SEED_CREATED journal entry for audit trail continuity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

ft. ENG-23: reconciliation cron + internal query

- Add daily reconciliation cron (06:00 UTC) that runs Layer 1 check
- Create reconciliationAction.ts with internalQuery (no auth required)
  and internalAction for cron scheduling
- Discrepancies logged as P0 errors via console.error
- On-demand adminQuery reconciliation remains available

Resolves SPEC Open Question #5: daily cron + on-demand admin query.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

ft. ENG-23: integration tests — guard failure, missing effects, cross-entity

- Add guard failure test: mortgage DEFAULT_THRESHOLD_REACHED with 0 missed
  payments → rejected, status unchanged
- Add missing effect handler test: unknown action → warn + succeed
- Create crossEntity.test.ts with 4 tests proving full obligation→mortgage
  cascade: overdue dispatch, settlement cure, and journal chain consistency
- Fix pre-existing test: "throws when no machine is registered" assertion

Cross-entity tests manually invoke effects (convex-test doesn't auto-run
scheduled functions), verifying the complete chain:
  obligation due→overdue → mortgage active→delinquent
  obligation overdue→settled → mortgage delinquent→active (cure)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

docs: ENG-23 — update SPEC 1.2 and PRD 1.2 on Notion

SPEC 1.2 updates:
- §2 File Structure: corrected paths to convex/engine/ nesting
- §9 Developer Checklist: fixed all file paths
- §10 Open Questions: closed #1 (guard timing), #2 (confirmObligationPayment),
  #3 (generateObligations helper)
- Removed effects/mortgage.ts, added effects/workosProvisioning.ts

PRD 1.2 updates:
- GT DoD #3: marked deal machine as descoped to Project 4
- Renamed seedInvestor → seedLender (schema table is lenders)
- Marked seedDeal as descoped

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

fix: ENG-23 — type reconciliationAction entityType parameter

Use keyof typeof ENTITY_TABLE_MAP instead of string for type safety
in collectLatestEntries function parameter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

fix: ENG-23 — address code review findings in seed mutations

- Fix idempotency: reuse existing user when entity doesn't exist yet
  (seedBorrower, seedLender, seedOnboardingRequest, seedMortgage)
- Fix seedMortgage: reuse existing property instead of duplicating
- Fix generateObligations: clamp day to prevent setMonth date drift
- Note: seedLender entityType "borrower" is intentional — lenders are
  not yet a governed entity type in the GT engine

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

## Summary by Sourcery

Implement cross-entity coordination between obligations and mortgages, extend reconciliation and scheduling infrastructure, and add idempotent seed data plus tests and cron-based health checks.

New Features:
- Enable cross-entity effects so obligation state changes drive corresponding mortgage transitions.
- Introduce internal and admin-facing commands for mortgage transitions and confirming obligation payments.
- Add an internal reconciliation query and daily cron-driven reconciliation check across governed entities.
- Seed phase-1 entities (brokers, borrowers, lenders, mortgages, obligations, onboarding requests) with realistic, journal-backed demo data.
- Provide an orchestrated seedAll mutation to populate a complete demo dataset in dependency order.

Bug Fixes:
- Ensure reconciliation skips non-governed entity types while handling mortgages and obligations correctly.
- Prevent scheduling of XState built-in actions as effects and gracefully handle missing effect handlers.
- Fix reconciliation tests to use non-governed entities and relax an over-specific transition engine error assertion.
- Clamp generated obligation due dates to avoid calendar drift in monthly schedules.
- Improve seed mutations to be idempotent by reusing existing users, properties, and entities.

Enhancements:
- Document machineContext usage for governed tables and add notification entry actions to onboarding requests.
- Expand reconciliation utilities to support internal use and improve discrepancy reporting.
- Strengthen guard behavior for mortgage default thresholds via explicit tests.

Documentation:
- Clarify governed vs non-governed entities and machine context expectations in schema comments.

Tests:
- Add cross-entity integration tests covering obligation→mortgage cascades and journal chain consistency.
- Add tests for guard failures, missing effect handlers, and reconciliation behavior across entity types.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Release Notes

* **New Features**
  * Added automated daily health checks to verify system integrity.
  * Enabled obligation payment confirmation through the admin dashboard.
  * Added admin notifications for new onboarding requests.

* **Improvements**
  * Enhanced coordination between related financial entities to ensure consistent state transitions.
  * Strengthened validation to prevent invalid state changes.

* **Tests**
  * Added comprehensive test coverage for entity workflows and state validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants