--- id: SEED-002 status: dormant planted: 2026-07-10 planted_during: v1.0 milestone (Pulse Mobile Shell Redesign), Phase 9.1 in flight trigger_when: Whenever the developer is ready to start this as its own milestone — surface during the next /gsd-new-milestone scan scope: 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 2–4 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/-client.ts` + `-factory.ts` (`isConfigured()`) — 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.