wulf-pulse/.planning/seeds/SEED-002-pax8-integration.md
lorentz 4f7e9be059 docs: capture exploration — PAX8 integration scope
Plant two seeds (PAX8 sync + Autotask mapping, general Pulse data
assistant) and one research question (PAX8 company identifier
alternatives to fuzzy name matching), surfaced while scoping a
future PAX8 integration.
2026-07-10 11:45:11 -04:00

4.4 KiB
Raw Permalink Blame History

id status planted planted_during trigger_when scope
SEED-002 dormant 2026-07-10 v1.0 milestone (Pulse Mobile Shell Redesign), Phase 9.1 in flight Whenever the developer is ready to start this as its own milestone — surface during the next /gsd-new-milestone scan Medium

SEED-002: PAX8 Integration

A read-only integration syncing PAX8 (vendor licensing/distribution marketplace) data into Pulse — companies, subscriptions, product catalog, and orders/invoices — mapped to existing Autotask companies, surfaced on a new /pax8 page.

Why This Matters

Three overlapping needs, all satisfied by the same underlying data sync:

  1. Cost reconciliation — compare what PAX8 bills per client/subscription against what's actually provisioned or invoiced.
  2. License visibility — see subscription/seat counts per company alongside other Pulse company data.
  3. Autotask cost mapping — tie PAX8 companies and subscription costs to Autotask companies/contracts for margin/profitability reporting.

The developer already has a PAX8 client ID + client secret provisioned, so auth setup is not a blocker — this seed is purely about scope/sequencing, not credential access.

When to Surface

Trigger: Whenever the developer wants to start this — not gated on any other milestone closing, but naturally lands after the current Mobile Shell Redesign wraps. Also surface if a future milestone's scope mentions: "PAX8", "license reconciliation", "vendor subscription costs", "seat count audit", or "Autotask contract margin".

Scope Estimate

Medium — roughly 24 phases. New external client integration (auth, 4 entities), a sync service, a new migration, a company-matching pass with manual review for exceptions, and one new UI page. Follows an existing, well-worn pattern in this codebase (autotask-factory, veeam-sync-service, etc.) — no new architectural concepts, just new surface area.

Breadcrumbs

  • Auth: PAX8 REST API at https://api.pax8.com/v1, OAuth2 client-credentials. Client ID + secret already provisioned by the developer.
  • Pattern to follow: lib/services/<name>-client.ts + <name>-factory.ts (is<Name>Configured()) — see lib/services/veeam-client.ts / veeam-factory.ts or lib/services/msgraph-client.ts / msgraph-factory.ts for the shape.
  • Sync pattern: lib/services/entity-sync.ts (Autotask) and lib/services/engagement-sync-service.ts — incremental-if-supported, else full upsert via postgresClient.bulkUpsert().
  • Env vars: PAX8_* (add to the integrations table in CLAUDE.md / INTEGRATIONS.md once built).
  • Scheduler: new pax8-daily schedule via lib/services/sync-scheduler.ts, matching cadence of other integrations (see engagement-daily).
  • Admin disable: wire into /admin/integrations (integration_settings table, migration 081) like other integrations, so it can be toggled without a container restart.
  • UI: new top-level page (like /engagement) — company list, subscriptions, cost breakdown. Not folded into the existing company detail modal.
  • This is explicitly the first planned data source for SEED-003 (General Pulse Data Assistant) — build the Postgres schema with that eventual consumer in mind (clean, well-typed tables; avoid PAX8-API-shaped blobs).

Notes

Entities in scope (v1)

  • Companies (join key to Autotask companies)
  • Subscriptions (product, seat count, billing term — current state)
  • Products/Catalog (SKUs, categories — needed to make subscriptions readable)
  • Orders/Invoices (historical line items — needed for actual cost reconciliation, not just current-state seats)

Key design forks (decided during exploration)

  • Read-only — no write-back to PAX8 (no seat adjustments, no orders) in v1.
  • Company matching: fuzzy name match at sync time — auto-match by name similarity, flag unmatched/ambiguous companies for manual review. See RESEARCH-pax8-company-identifiers — worth checking whether PAX8 exposes a more stable identifier (domain, external ID) before committing to fuzzy matching as the permanent strategy.
  • New dedicated /pax8 page, not folded into company detail — daily sync via the scheduler, not on-demand-only.

Anti-goals

  • Not building write access (seat changes, placing orders) in v1.
  • Not building the chatbot/NL query layer here — that's SEED-003, a separate initiative that consumes this data once it exists.