Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
8.5 KiB
PRD — Invoice Template Execution Abstraction Cutover (JSON AST + Shared React Renderer)
- Slug:
invoice-template-json-ast-renderer-cutover - Date:
2026-02-12 - Status: Draft
- Supersedes:
ee/docs/plans/2026-02-09-invoice-template-designer-preview-workspace/
Summary
Replace the current invoice template execution pipeline (GUI IR -> AssemblyScript generation -> Wasm compile -> Wasm/QuickJS execution) with a declarative JSON AST and one shared React/TypeScript renderer.
The template is data, not executable code. The Designer should output a versioned JSON AST. Rendering should run through one shared renderer in both:
- interactive preview in the app, and
- backend PDF generation via headless browser.
The system must still support future customization of invoice line-item calculations and groupings by expressing those behaviors declaratively (and optionally via whitelisted strategy hooks), not by embedding arbitrary per-template code.
Problem
Current architecture requires maintaining multiple custom layers for one invoice output path:
- GUI state compiler IR
- AssemblyScript source generation
- AssemblyScript compilation orchestration
- runtime module loading/execution (Wasm/QuickJS)
- host function glue and compile artifact caching
This increases complexity, testing surface, runtime failure modes, and maintenance burden. It also creates a conceptual mismatch: an invoice layout definition is fundamentally declarative data.
Insight
An invoice template is a declarative UI/data-shaping structure, not a program.
Goals
- Make Designer the source of truth for a versioned JSON AST.
- Implement one generic invoice renderer in React/TS that consumes AST + invoice data.
- Use identical render logic for preview and PDF generation.
- Preserve extensibility for future custom line-item calculations/groupings through declarative transform specs and optional whitelisted strategy hooks.
- Remove compiler/executor layers and their operational burden.
- Eliminate generated Wasm artifact management and cache concerns.
Non-goals
- Supporting arbitrary user-authored executable code in templates.
- Full migration tooling for tenant custom templates (none exist yet).
- Replatforming invoice data sources or billing domain logic.
- Reworking unrelated billing UI flows outside template render/edit/preview/PDF paths.
Users and Primary Flows
Primary personas:
- Billing admins designing invoice templates.
- Implementers maintaining template rendering reliability.
Primary flows:
-
Design -> Preview
- User edits template in visual designer.
- Designer emits AST snapshot.
- Shared data-shaping evaluator + renderer produces preview output.
-
Save -> Reopen
- User saves template AST.
- Reopening editor hydrates from persisted AST.
-
Invoice PDF generation
- Invoice generation selects template AST.
- Same renderer path generates HTML/CSS in headless browser.
- PDF output matches preview behavior.
-
Future customization (calculation/grouping)
- Template AST declares group/filter/sort/aggregate/computed-field rules.
- Evaluator applies them consistently in preview and PDF.
- Optional
strategyIdcan route to vetted server-side functions for advanced behavior.
UX / UI Notes
- Keep top-level editor tabs (
Visual,Code) unless product decides otherwise. - In
Visual -> Preview, retain source selection UX (Sample/Existing) and status surface. - Preview status terminology should reflect new phases (
shape,render,verify) instead of compile. - If
Codetab remains for GUI templates, show generated/read-only AST JSON (or remove tab in a follow-up).
Requirements
Functional Requirements
- Define a versioned
InvoiceTemplateAstschema with runtime validation. - AST must represent layout tree, style tokens, bindings, and repeatable item regions.
- AST must support declarative data-shaping blocks for:
- filtering,
- sorting,
- grouping,
- aggregations,
- computed fields,
- totals composition.
- Add optional
strategyIdhooks that resolve only to whitelisted server-side implementations. - Implement a shared evaluator that transforms invoice view-model data according to AST shape rules.
- Evaluator output must be deterministic for equivalent inputs.
- Implement one shared React renderer that consumes evaluated AST context and renders invoice HTML/CSS.
DesignerVisualWorkspaceexport path must persist AST directly (no IR->AssemblyScript generation).- Template save/get actions must use AST as canonical template payload.
- Preview action must run evaluator + shared renderer (no Wasm compile/execute).
- Preview must continue supporting sample and existing-invoice sources.
- Backend PDF generation must use the same renderer output path in headless browser.
- Remove compile-cache behavior tied to generated Wasm artifacts.
- Remove runtime dependency on custom compiler/executor modules listed in this PRD.
- Preserve clear, structured errors for schema, evaluator, strategy, and rendering failures.
Non-functional Requirements
- Preview and PDF rendering should remain functionally consistent for the same template + invoice data.
- Rendering path should be fast enough for iterative design/preview usage.
- Renderer/evaluator modules must be unit-testable without external compiler toolchains.
- Architecture should reduce moving parts versus current compiler + runtime stack.
Data / API / Integrations
- Update invoice template type contracts to include canonical AST payload.
- Keep invoice data retrieval and mapping (
fetchInvoicesPaginated,getInvoiceForRendering, adapter mapping) intact. - Introduce shared modules for:
- AST schema,
- evaluator,
- React invoice renderer,
- server-side render-to-html wrapper for PDF.
- Update save/load/query paths in billing actions/models to use AST as primary source.
- Standard templates should be represented in AST form for this cutover path.
Security / Permissions
- No template execution of arbitrary code.
strategyIdresolution must be allowlisted, tenant-safe, and auditable.- Existing tenant isolation requirements for invoice/template access remain unchanged.
- Preview and PDF rendering must remain read-only relative to invoice mutation.
Deleted / Eliminated Layers
Delete these modules and remove call paths:
packages/billing/src/components/invoice-designer/compiler/guiIr.tspackages/billing/src/components/invoice-designer/compiler/assemblyScriptGenerator.tspackages/billing/src/components/invoice-designer/compiler/diagnostics.tspackages/billing/src/lib/invoice-template-compiler/assemblyScriptCompile.tspackages/billing/src/lib/invoice-renderer/wasm-executor.tspackages/billing/src/lib/invoice-renderer/quickjs-executor.tspackages/billing/src/lib/invoice-renderer/host-functions.ts
And eliminate generated Wasm module caching/management (including preview compile cache concerns).
Rollout / Migration
- No tenant custom templates currently exist, so no backfill migration is required for custom template payloads.
- Implement as a forward cutover for template authoring/rendering pipeline.
- Keep legacy columns/artifacts only as temporary compatibility scaffolding if needed during implementation; prioritize runtime cutover first.
Risks
- Functional parity drift between old and new rendering semantics.
- Ambiguity in declarative transform expressiveness for advanced grouping/calc scenarios.
- Under-specified strategy hook boundaries could reintroduce ad hoc execution behavior.
Open Questions
- Should
Codetab for GUI templates become read-only AST JSON immediately, or be hidden in this cutover? - Which initial strategy hooks are required in MVP (
none,custom-group-key,custom-aggregate, etc.)? - Do we keep layout verification in MVP, and if yes, does it compare AST-intended constraints to rendered DOM geometry?
Acceptance Criteria (Definition of Done)
- Designer persists a validated JSON AST as canonical template representation.
- Preview pipeline uses shared evaluator + React renderer (no compiler/Wasm executor path).
- PDF generation uses same renderer path in headless browser and matches preview semantics.
- Declarative grouping/calculation rules are supported in AST evaluator.
- Optional whitelisted
strategyIdhooks are supported without arbitrary code execution. - Legacy compiler/executor modules listed above are deleted and no longer referenced.
- No generated Wasm compile cache/module lifecycle remains in invoice template pipeline.
- Automated tests cover AST validation, evaluator behavior, preview/PDF parity, and error handling.