feat: ConnectWise PSA integration (#106)

PSA abstraction layer with provider pattern, ConnectWise integration (connection management, ticket linking, note posting, status updates, member mapping), Integrations page UI, Fernet credential encryption, in-memory TTL cache, 6 DB migrations, ConnectWise API reference docs.
This commit was merged in pull request #106.
This commit is contained in:
chihlasm
2026-03-15 01:45:35 -04:00
committed by GitHub
parent 80e094215f
commit 46865882c6
60 changed files with 726716 additions and 11 deletions

View File

@@ -89,3 +89,4 @@ export type {
} from './kbAccelerator'
export * from './scripts'
export * from './integrations'

View File

@@ -0,0 +1,123 @@
export interface PsaConnectionResponse {
id: string
account_id: string
provider: string
display_name: string
site_url: string
company_id: string
is_active: boolean
last_validated_at: string | null
created_at: string
updated_at: string
public_key_hint: string
private_key_hint: string
}
export interface PsaConnectionCreate {
provider: string
display_name: string
site_url: string
company_id: string
public_key: string
private_key: string
}
export interface PsaConnectionUpdate {
display_name?: string
site_url?: string
company_id?: string
public_key?: string
private_key?: string
}
export interface PsaConnectionTestResponse {
success: boolean
message: string
server_version: string | null
}
export interface PSATicketInfo {
id: string
summary: string
company_name: string | null
board_name: string | null
status_name: string | null
priority_name: string | null
}
export interface TicketLinkResponse {
session_id: string
psa_ticket_id: string | null
ticket: PSATicketInfo | null
}
export interface PSATicketSearchResult {
id: string
summary: string
company_name: string | null
board_name: string | null
status_name: string | null
priority_name: string | null
closed: boolean
}
export interface PSATicketStatusItem {
id: number
name: string
is_closed: boolean
}
export interface PsaPreviewResponse {
content: string
ticket: PSATicketSearchResult
available_statuses: PSATicketStatusItem[]
character_count: number
previous_posts: number
}
export interface PsaPostResponse {
id: string
session_id: string
ticket_id: string
note_type: string
status: string
external_note_id: string | null
error_message: string | null
status_changed_from: string | null
status_changed_to: string | null
posted_at: string
}
export interface PsaPostLogEntry {
id: string
ticket_id: string
note_type: string
status: string
error_message: string | null
status_changed_from: string | null
status_changed_to: string | null
posted_at: string
content_preview: string
}
export interface PsaMemberResponse {
id: string
identifier: string
name: string
email: string | null
}
export interface PsaMemberMappingResponse {
id: string
user_id: string
user_email: string
user_name: string
external_member_id: string
external_member_name: string
matched_by: string
}
export interface AutoMatchResult {
matched: PsaMemberMappingResponse[]
unmatched_users: number
}

View File

@@ -64,6 +64,8 @@ export interface Session {
assigned_to_id?: string | null
batch_id?: string
target_label?: string
psa_ticket_id?: string | null
psa_connection_id?: string | null
}
export interface SessionCreate {