Commit Graph

7 Commits

Author SHA1 Message Date
Michael Chihlas
88495b10f0 feat(psa): add in-memory TTL cache for board statuses
Add PSACache class with get/set/invalidate/clear operations and TTL expiry.
Board statuses are cached for 1 hour in the provider.
Cache is cleared when a PSA connection is re-tested.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 23:07:08 -04:00
Michael Chihlas
5a35c933e0 feat(psa): implement search_tickets, get_ticket_statuses, list_companies in CW provider
Implement all remaining NotImplementedError stubs in ConnectWiseProvider:
- search_tickets: query by summary with board_id, status_id, include_closed filters
- get_ticket_statuses: fetch statuses for a service board
- list_companies: list companies with optional status filter
- get_company: fetch a single company by ID
- get_ticket_configurations: fetch configs attached to a ticket
- Extract shared _map_ticket helper to reduce duplication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 23:06:57 -04:00
Michael Chihlas
2a53f48d69 feat(psa): implement get_ticket in ConnectWise provider
Replace NotImplementedError stub with real implementation that fetches
a ticket by ID via CW REST API and maps it to PSATicket.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:44:58 -04:00
Michael Chihlas
2086ecb5ea feat(psa): add ConnectWiseProvider with test_connection + provider registry
ConnectWiseProvider implements PSAProvider with test_connection() that
calls GET /system/info to verify credentials and connectivity. All other
methods raise NotImplementedError with slice references for future work.

Provider registry (get_provider_for_account) looks up the account's
PsaConnection, decrypts stored credentials, and instantiates the
correct provider. Currently supports connectwise only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 21:52:23 -04:00
Michael Chihlas
fdaea49d3b feat(psa): add ConnectWise HTTP client with auth, URL resolution, pagination, retry
Implements ConnectWiseClient in services/psa/connectwise/client.py with:
- API key auth (Base64 companyId+publicKey:privateKey) + clientId header
- Accept header pinned to CW API version 2025.16
- Dynamic base URL resolution via /login/companyinfo (cloud vs on-premise)
- SSRF prevention: validates against known CW domains, rejects private IPs
- Retry with exponential backoff for timeouts and 5xx errors
- 429 rate limit handling with Retry-After header respect
- Error mapping: 401/403/404/429/5xx to typed PSA exceptions
- Paginated GET with while-loop pattern (max 1000 per page)
- JSON Patch array format for PATCH requests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 21:51:49 -04:00
Michael Chihlas
086e4c6d59 feat(psa): add Fernet credential encryption with HKDF key derivation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 21:48:09 -04:00
Michael Chihlas
d2edb9e3ce feat(psa): add PSA abstraction layer — base types, exceptions, abstract interface
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 21:46:12 -04:00