PSA/ee/docs/plans/2026-03-14-n8n-contact-crud-design.md
Hermes 284313f908
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
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

8.2 KiB

N8n Contact CRUD Design

  • Date: 2026-03-14
  • Status: Approved
  • Scope: packages/n8n-nodes-alga-psa

Summary

Expand the Alga PSA n8n community node to support a first-class Contact resource with ticket-style ergonomics. The first pass should add contact Create, Get, List, Update, and Delete operations, align the editor experience with the existing ticket resource, and keep scope limited to core contact fields already exercised by the API and product UI.

This is an n8n package expansion, not a backend API invention. The server already exposes GET/POST /api/v1/contacts and GET/PUT/DELETE /api/v1/contacts/{id}.

Goals

  • Add Contact as a first-class n8n node resource.
  • Support contact CRUD with the same operational feel as ticket CRUD.
  • Reuse existing node conventions for validation, success normalization, and continue-on-fail behavior.
  • Keep first-pass field coverage focused on core contact fields.
  • Update package docs, examples, and tests so the new surface is shippable.

Non-goals

  • No contact Search operation in the first pass.
  • No attempt to expose the full contact schema on day one.
  • No backend API changes unless gaps are discovered during implementation.
  • No generic registry rewrite for all n8n resources in this pass.

Approaches Considered

  • Extend the current node with a Contact resource and contact-specific CRUD operations.
  • Extract or add shared helper logic where needed so ticket and contact behavior follow the same internal shape.

Why this approach:

  • Keeps the public node surface simple.
  • Avoids overloading the already-large node file with ad hoc one-off contact logic.
  • Delivers contact parity without taking on a full framework rewrite.

Alternative: Minimal inline extension in the existing node file

  • Add contact fields and execute branches directly into the current resource switch with minimal cleanup.

Why not recommended:

  • Fastest to start, but increases maintenance cost in an already dense file.
  • Makes future additions like contact search or more resources harder to reason about.

Alternative: Full resource-registry abstraction

  • Convert ticket, contact, and helper resources into a generic registry-driven architecture.

Why not recommended:

  • Too much surface area for a first contact pass.
  • Raises regression risk for existing ticket behavior.
  • Slows delivery of the actual user-facing capability.

User Experience

Contact should appear beside Ticket, Client, Board, Status, and Priority in the node resource selector.

When Contact is selected:

  • The node should expose a dedicated contactOperation selector.
  • Required create fields should be separated from optional additional fields, mirroring ticket create/update behavior.
  • client_id should use the same lookup-plus-manual-ID pattern already used by ticket references.
  • List output should preserve pagination metadata.
  • Success and error handling should match current ticket behavior, including continue-on-fail item wrapping.

Contact Scope

Operations

  • Create
  • Get
  • List
  • Update
  • Delete

Fields

Create required fields:

  • full_name

Create and update optional fields:

  • email
  • client_id
  • role
  • notes
  • is_inactive
  • phone_numbers

Field Shape Notes

  • client_id should be a resourceLocator with client lookup support and manual UUID fallback.
  • phone_numbers should be exposed as a JSON-authored field in the first pass rather than a complex nested n8n collection UI.
  • List should support practical filters that align with the API and current lookup usage:
    • page
    • limit
    • client_id
    • search_term
    • is_inactive if the API behavior is confirmed during implementation

Architecture

Node Description

Update packages/n8n-nodes-alga-psa/nodes/AlgaPsa/AlgaPsa.node.ts to:

  • add contact to the resource options
  • add contactOperation
  • define contact CRUD fields and additional-field collections
  • reuse existing client lookup load options for client_id
  • update the node subtitle so contact operations render cleanly

Payload and Query Helpers

Update packages/n8n-nodes-alga-psa/nodes/AlgaPsa/helpers.ts to add:

  • contact create payload builder
  • contact update payload builder
  • contact list query builder
  • phone_numbers parsing and validation helpers

The helper shape should stay close to the ticket helper conventions:

  • strip empty values
  • validate required strings and UUIDs before sending requests
  • normalize JSON-authored fields into the API payload shape

Execute Flow

Extend the execute logic in packages/n8n-nodes-alga-psa/nodes/AlgaPsa/AlgaPsa.node.ts to route:

  • POST /api/v1/contacts
  • GET /api/v1/contacts/{id}
  • GET /api/v1/contacts
  • PUT /api/v1/contacts/{id}
  • DELETE /api/v1/contacts/{id}

Use the same output conventions already established for tickets:

  • unwrap { data: ... } objects
  • preserve paginated list metadata
  • return non-empty normalized delete success objects
  • convert API errors into the current n8n error shape

Testing

Update the existing node tests rather than introducing a new testing style.

Description and Load Option Tests

Extend packages/n8n-nodes-alga-psa/tests/node-description-loadoptions.test.ts to cover:

  • Contact appearing in the resource selector
  • valid contact operation options
  • client lookup reuse in contact fields
  • separation of required create fields from optional update/create collections

Execute Tests

Extend packages/n8n-nodes-alga-psa/tests/node-execute.test.ts to cover:

  • create request payload mapping
  • get by ID
  • list query serialization and pagination output
  • update payload mapping
  • delete request shape and normalized success output
  • continue-on-fail behavior for contact operations

Helper Tests

Extend packages/n8n-nodes-alga-psa/tests/helpers.test.ts for:

  • phone_numbers parsing
  • malformed JSON handling
  • compact payload/query behavior for contact fields

Documentation Tests

Extend packages/n8n-nodes-alga-psa/tests/docs.test.ts so README examples and operation matrix stay in sync.

General Plan

  1. Extend the public node surface. Add Contact to the resource matrix, define contact CRUD operations, and expose ticket-style contact fields in the node description.

  2. Add contact helper builders and validation. Introduce contact payload/query helpers and validate JSON-authored phone_numbers before requests are sent.

  3. Implement execute paths. Wire the contact operations to the existing /api/v1/contacts endpoints using the same normalization and error-handling conventions as tickets.

  4. Expand package tests. Cover node description, request shapes, list behavior, validation failures, delete normalization, and continue-on-fail behavior.

  5. Update package documentation and examples. Refresh the README operation matrix and add at least one contact example workflow plus a release-note entry.

Risks and Open Questions

  • phone_numbers is the main shape risk because the API expects structured entries; the first pass should validate this aggressively and keep the authoring model simple.
  • The exact List filter set should be finalized against current contact API behavior during implementation, especially is_inactive.
  • If contact-specific label fields or response shapes differ from expectations, the node should follow actual API responses rather than forcing ticket-style naming.