Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
2.8 KiB
2.8 KiB
Scratchpad — Extension Invoicing (Manual Invoice MVP)
- Plan slug:
extension-invoicing-manual-invoices - Created:
2026-01-14
What This Is
Rolling notes for implementing an invoicing host API capability for extensions (MVP: create draft manual invoices).
Starting Context / Relevant Existing Code
- Capability registry:
ee/server/src/lib/extensions/providers.ts - Install config + provider grants:
ee/server/src/lib/extensions/installConfig.ts - Gateway passes install + providers + user info to Runner:
server/src/app/api/ext/[extensionId]/[[...path]]/route.ts
- Existing internal host API pattern (scheduler):
- Server host API:
ee/server/src/lib/extensions/schedulerHostApi.ts - Internal route:
ee/server/src/app/api/internal/ext-scheduler/install/[installId]/route.ts - Runner calls internal route:
ee/runner/src/engine/host_api.rs(scheduler_request) - Runner capability constants:
ee/runner/src/providers/mod.rs - WIT:
ee/runner/wit/extension-runner.wit - JS SDK types:
sdk/extension-runtime/src/index.ts
- Server host API:
Invoice Domain Touchpoints
- Manual invoice API route (user-authenticated):
server/src/app/api/v1/invoices/manual/route.tsserver/src/lib/api/controllers/ApiInvoiceController.ts→invoiceService.generateManualInvoice(...)
- Core manual invoice creation expects permissions + user attribution:
server/src/lib/api/services/InvoiceService.ts(generateManualInvoiceusescontext.userId)
- Manual invoice schemas (for input shape parity):
server/src/lib/api/schemas/invoiceSchemas.ts(manualInvoiceRequestSchema,manualInvoiceItemSchema)
Open Decisions
- Capability naming: decided
cap:invoice.manual.create - Authorization model: decided capability-only (no user required)
- Output shape: decided minimal
{ invoiceId, invoiceNumber, totals } - Inputs: decided include invoice header fields (
invoiceDate,dueDate,poNumber) - Prepayments: deferred (no
isPrepayment/expirationDatein MVP) - Invoice attribution (MVP): implemented using a tenant user id fallback (first
users.user_idfor tenant) to satisfy requiredcreated_byfields when persisting invoice charges. This is a stopgap until we add a dedicated “extension/system principal” strategy.
Commands / Runbooks
- Validate plan folder:
python3 scripts/validate_plan.py ee/docs/plans/2026-01-14-extension-invoicing-manual-invoices
Implementation Notes
server/src/lib/services/invoiceService.tsnow usesimport type { Session } from 'next-auth'and a dynamic import forgetSession()so the shared invoice helpers can be imported from non-Next contexts (e.g., EE server tests / host APIs) without pulling innext-authat module load time.- SDK sample extension:
sdk/samples/component/invoicing-demo/demonstrateshost.invoicing.createManualInvoicefrom an iframe UI.