Commit graph

491 commits

Author SHA1 Message Date
b168d44585 feat(appgate): add AppGate SDP integration health check and sync service
Registers AppGate as a checkConfigOnly integration-health row and public
sync route, matching the existing factory + is<Name>Configured() pattern.
Committed now so Phase 13's worktree-isolated executors fork from a HEAD
that includes this integration-health.ts entry, since Plan 13-02 inserts
the PAX8 row immediately after it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHRgZqkzBHBbAbc3KHneuR
2026-07-11 09:43:48 -04:00
f70a4a36ed docs(13): create phase plan 2026-07-11 09:27:09 -04:00
424c7c85fb docs(13): create phase plan 2026-07-11 09:21:54 -04:00
c4f825bac4 docs(state): record phase 13 context session 2026-07-11 08:20:39 -04:00
e6802d549a docs(13): capture phase context 2026-07-11 08:20:30 -04:00
4b34109a65 docs(milestone-v2.0): add milestone audit report 2026-07-11 07:56:22 -04:00
8ba10d96ef docs(phase-12): audit validation strategy — nyquist compliant, 0 gaps 2026-07-11 07:45:14 -04:00
ff55ff75c2 docs(phase-12): add security threat verification 2026-07-11 07:41:57 -04:00
80897c62df test(12): complete UAT - 7 passed, 0 issues 2026-07-11 07:36:13 -04:00
e92268f38c docs(12): add code review fix report 2026-07-11 07:25:58 -04:00
be6f07b8c9 fix(12): WR-03 follow-up - fix TS type narrowing on token return 2026-07-11 07:24:15 -04:00
1bb2b8b0a2 fix(12): WR-03 validate PAX8 token response shape in Pax8Client.getToken() 2026-07-11 07:22:59 -04:00
76a652ddfd fix(12): WR-02 rotate matchPax8Companies eligibility ordering and raise the limit to prevent starvation 2026-07-11 07:22:25 -04:00
cb8ae85737 fix(12): WR-01 isolate per-row failures in pax8 sync loops so one bad record can't abort the batch 2026-07-11 07:20:54 -04:00
bddf612c7b fix(12): CR-02 stop folding company-match review counts into sync_history.records_deleted 2026-07-11 07:18:27 -04:00
591fc5cf10 fix(12): CR-01 widen partner_cost/partner_cost_total to NUMERIC(14,4) to stop silent precision loss 2026-07-11 07:16:38 -04:00
dbc0d5a703 docs(phase-12): evolve PROJECT.md after phase completion 2026-07-11 07:12:34 -04:00
8a55eb3f2a docs(phase-12): complete phase execution 2026-07-11 07:12:01 -04:00
f9646c6480 docs(12): add code review report 2026-07-11 07:11:50 -04:00
2a4a27f1e0 docs(phase-12): update tracking after wave 4 2026-07-11 07:04:06 -04:00
247d016fcf chore: merge executor worktree (worktree-agent-ab3956ccfacb0f828) 2026-07-11 07:03:50 -04:00
dd01e9a892 docs(12-05): complete plan — live verification approved
Developer reviewed the SC#1-SC#4 verdict block and the auto-match sample
and responded "approved" — all four success criteria pass, auto-matches
are correct, no threshold/mapping changes needed. Marks PAX8-06, PAX8-10,
PAX8-11 complete in REQUIREMENTS.md.
2026-07-11 07:03:24 -04:00
0e8504c1c1 feat(12-05): live PAX8 orders/matching verification script + quantity fix
- scripts/verify-pax8-orders-matching.ts: runs a real Pax8SyncService.fullSync()
  twice, then asserts all four Phase 12 success criteria (order items
  populated with company id + billing period, confident auto-matches exist,
  no-match/ambiguous companies flagged for review, auto-match set stable
  across two syncs). Never logs secrets/tokens.
- migrations/094_pax8_order_items_quantity_numeric.sql (Rule 1 auto-fix):
  pax8_order_items.quantity was INTEGER but real PAX8 usage-based invoice
  items (e.g. Azure per-unit bandwidth overage) report fractional
  quantities, which aborted the entire orders/order_items sync loop on the
  first such row and silently truncated SC#1's item coverage to ~123 rows
  instead of the full ~56k-row history. Widened to NUMERIC(14,4); applied
  directly to the dev DB (existing volume, not a fresh init).
- deferred-items.md: logged pre-existing out-of-scope failures (appgate
  TS2307 type errors, itglue-search.test.ts) confirmed unchanged by this
  plan's files.
2026-07-10 23:10:44 -04:00
f75409448c docs(phase-12): update tracking after wave 3 2026-07-10 22:56:07 -04:00
f8841ebd14 chore: merge executor worktree (worktree-agent-a878e4ba8fa21ac68) 2026-07-10 22:55:49 -04:00
d78aa60a6c docs(12-04): add self-check verification section to SUMMARY
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 22:55:33 -04:00
6c7b70dfc3 docs(12-04): complete sync service wiring plan
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 22:55:25 -04:00
59294cee5e test(12-04): add pax8-sync-service.test.ts for syncOrders + syncCompanyMatches
- First unit tests for Pax8SyncService, mocking postgresClient.query and
  pax8-company-matcher's matchPax8Companies (following
  pax8-company-matcher.test.ts's mocking discipline)
- Asserts INSERT INTO pax8_orders / pax8_order_items with companyId bound
  into pax8_company_id and amountDue into line_total
- Asserts resolveCostColumns' default (CONFIRM) mapping for both observed
  item types (subscription, one-time) per 12-02-SUMMARY.md
- Asserts child-then-parent tombstone ordering (pax8_order_items before
  pax8_orders)
- Asserts fullSync's entities include 'orders' and 'company_matches'

No TDD gate — plan is autonomous without a plan-level `type: tdd`
frontmatter; the implementation already existed from Tasks 1-2, so this
follows the same single-commit test-addition pattern established by
12-02-SUMMARY.md's Task 2.
2026-07-10 22:54:18 -04:00
5f960601e3 feat(12-04): wire syncOrders + syncCompanyMatches into fullSync
- syncCompanyMatches() delegates to matchPax8Companies() (Plan 03),
  shaping its result into the standard Pax8EntitySyncResult
- fullSync() now pushes ordersResult then matchResult after products,
  so pax8_companies is fully populated before matching runs
- Both steps roll up into the existing success/status/totals reducer
  and sync_history record unchanged
2026-07-10 22:52:30 -04:00
a06c1d314b feat(12-04): add syncOrders nested invoice->item upsert + tombstone
- Adds Pax8SyncService.syncOrders(): pages all invoice headers, then
  per-header pages its items (12-RESEARCH.md Pattern 1 nested fetch)
- resolveCostColumns() branches on item.type per 12-02-SUMMARY.md's
  live spot-check verdicts (all types CONFIRM -> single default branch,
  kept as a named seam for future divergence)
- pax8_orders.pax8_company_id stays NULL (Pitfall 1); per-company data
  lives on pax8_order_items.pax8_company_id
- Tombstones child (pax8_order_items) before parent (pax8_orders) to
  respect the FK, using the existing id <> ALL($1::uuid[]) pattern
2026-07-10 22:52:03 -04:00
a8bb55e394 docs(phase-12): update tracking after wave 2 2026-07-10 22:49:31 -04:00
fe7860760b chore: merge executor worktree (worktree-agent-a0da7e5b2254b56f8) 2026-07-10 22:48:53 -04:00
3e2dd6c99a chore: merge executor worktree (worktree-agent-a5f863a8e23f3aa61) 2026-07-10 22:48:53 -04:00
8868f2c9bd docs(12-03): complete pax8 company matcher plan
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 22:48:32 -04:00
7d934f6bb3 docs(12-02): append self-check result to SUMMARY.md 2026-07-10 22:48:17 -04:00
f2538ffb02 docs(12-02): complete PAX8 invoice client methods plan
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHRgZqkzBHBbAbc3KHneuR
2026-07-10 22:48:00 -04:00
ae44669b9e test(12-03): add pax8-company-matcher unit tests
- Mocks postgresClient.query (default export) per pax8-client.test.ts
  discipline, adapted from fetch mocking
- Covers all five decision branches: auto-link, review (below
  threshold), review (near-tie, D-02), empty candidates (D-03), and
  the idempotency guard (D-05/SC#4)
- Covers dryRun: asserts zero UPDATE/INSERT/DELETE calls issued
- npx vitest run lib/services/pax8-company-matcher.test.ts: 6/6 passed
2026-07-10 22:47:43 -04:00
691bb47a91 feat(12-03): create pax8-company-matcher.ts
- Ports device-link-reconciler.ts's findBy*/applyLink/recordConflict/
  pickBestCandidate shape to a single pg_trgm similarity() score
- AUTO_LINK_THRESHOLD=0.90 (D-01), TIE_MARGIN=0.05 (D-02),
  CANDIDATE_FLOOR=0.3, exported and tunable
- decide() implements D-01..D-04: auto-link only on unambiguous
  high-confidence match, review with top-3 candidates (or empty array
  when none clear the floor)
- applyLink()/recordConflict() guard resolved_at IS NOT NULL and
  match_method IS DISTINCT FROM 'manual' (D-05/SC#4 idempotency)
- matchPax8Companies() scans the re-scoring-eligible subset of
  pax8_companies and reports scanned/autoLinked/flaggedAmbiguous/
  flaggedNoCandidate/durationMs
2026-07-10 22:47:33 -04:00
232b642197 feat(12-02): add live field-mapping spot-check script for invoice items
- Fetches the first invoice + its items, inspects one item of each
  observed type (subscription, prorate, one-time), prints raw cost
  fields, and emits a CONFIRM/DIVERGENCE verdict for the Plan 04 mapping:
  unit_price<-price, line_total<-amountDue, partner_cost<-cost,
  partner_cost_total<-costTotal
- Read-only (listAllInvoices/listAllInvoiceItems only); never prints the
  client secret or access token
- Live run against the real PAX8 API confirms the mapping across all
  three observed item types — resolves 12-RESEARCH.md Open Question 1
2026-07-10 22:47:09 -04:00
5cfbd13bcb test(12-02): add pagination + GET-only tests for listAllInvoices/listAllInvoiceItems
- listAllInvoices() concatenates pages in order, size=200 on each request
- listAllInvoiceItems(invoiceId) requests the nested /invoices/{id}/items
  path and concatenates its pages
- Extends the existing GET-only / Authorization-header assertion to both
  new methods (PAX8-08)
2026-07-10 22:46:12 -04:00
0920ef8e43 feat(12-02): add listAllInvoices and listAllInvoiceItems to Pax8Client
- listAllInvoices() pages the flat /invoices header list via paginateAll
- listAllInvoiceItems(invoiceId) pages the nested per-invoice
  /invoices/{id}/items child resource
- Both GET-only, reusing the existing paginateAll helper (PAX8-08)
- Note: no /orders call added (12-RESEARCH.md Pitfall 3 — unreliable/504s)
- Log pre-existing unrelated sync-scheduler.ts TS2307 errors to
  deferred-items.md (appgate-factory/appgate-sync-service not in this
  worktree's git history)
2026-07-10 22:45:40 -04:00
acf01de133 chore: merge executor worktree (worktree-agent-a8887844e4db2658d) 2026-07-10 22:43:17 -04:00
94f02e6e1c docs(12-01): complete schema + type foundation plan
- Add SUMMARY.md documenting migration 093 and Pax8Invoice/Pax8InvoiceItem types
- Log pre-existing, out-of-scope tsc failure (appgate-factory/appgate-sync-service missing) to deferred-items.md
2026-07-10 22:42:00 -04:00
5197cbebf1 feat(12-01): add Pax8Invoice/Pax8InvoiceItem types
- Replace stale unused Pax8Order/Pax8OrderItem stubs with live-verified
  Pax8Invoice (header) and Pax8InvoiceItem (per-company line item) types
- Field shapes sourced from 12-RESEARCH.md live PAX8 API verification
2026-07-10 22:41:20 -04:00
111ef56e45 feat(12-01): add migration 093 for pax8 orders + company matching schema
- Enable pg_trgm extension for fuzzy company-name matching
- Add per-company id, billing period, and dual-cost columns to pax8_order_items
- Add auto-match columns (autotask_company_id, match_confidence, match_method, matched_at) to pax8_companies
- Applied to dev DB and verified idempotent
2026-07-10 22:40:03 -04:00
f68e1c50b6 docs(12): create phase plan 2026-07-10 22:27:17 -04:00
fcc93b38f4 docs(12): tag D-01/D-02/D-04 citations in must_haves 2026-07-10 22:26:33 -04:00
1a9c491b03 docs(12): create phase plan
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHRgZqkzBHBbAbc3KHneuR
2026-07-10 22:15:05 -04:00
6d8b2610bb docs(phase-12): add validation strategy 2026-07-10 22:00:08 -04:00
b99f84ffa0 docs(12): research phase domain 2026-07-10 21:59:05 -04:00