Skip to main content

Internal Ticketing Runtime

Status​

Implemented

  • Client response references: Phase 1 canonical OneProtect internal ticketing; Jira/ServiceNow/Freshdesk/Zendesk/HaloPSA remain Phase 2 integrations.
  • ADR references: docs/adr/ADR-0010-internal-ticketing-contracts.md.
  • Task board references: OP-033 and OP-033R.

Problem Statement​

OneProtect needs a canonical tenant-scoped investigation record. Generic webhook delivery exists, but outbound delivery is not the same as an internal ticket store.

Architectural Intent​

Tickets link alerts, assets, evidence, delivery attempts, audit records, and operator comments into one tenant-owned work item. External ticketing products can mirror or receive data later through adapters, but they do not own OneProtect's lifecycle state.

What Was Implemented​

  • ADR-0010 accepted the internal ticket/work-item model.
  • Postgres/RLS and SQLite local tables for tickets, ticket events, comments, and links.
  • FastAPI ticket routes for manual creation, alert-to-ticket creation, list, detail, status/assignment updates, comments, and links.
  • Idempotent alert-to-ticket creation.
  • Event publication for ticket.created, ticket.status_changed, ticket.assigned, ticket.comment_added, and ticket.linked.
  • Worker handling for ticket.created.
  • Basic API-backed Tickets console page.
  • Contract validation continues to cover ticket event payloads.

Components Involved​

  • OpenAPI: specs/openapi.yaml
  • AsyncAPI: specs/asyncapi.yaml
  • Event schemas: specs/events/ticket.*.v1.schema.json
  • Architecture docs: docs/architecture/internal-ticketing-contracts.md
  • ADRs: docs/adr/ADR-0010-internal-ticketing-contracts.md
  • Runtime migration: db/postgres/007_internal_ticketing_runtime.sql
  • Runtime service: poc/ingest_api/ticket_service.py
  • UI: frontend/src/app/console/tickets/page.tsx

APIs / Events / Schemas​

  • API: POST /api/v1/alerts/{alert_id}/ticket
  • API: GET /api/v1/tickets
  • API: POST /api/v1/tickets
  • API: PATCH /api/v1/tickets/{ticket_id}
  • Event: ticket.created
  • Event: ticket.status_changed
  • Event: ticket.assigned
  • Event: ticket.comment_added
  • Event: ticket.linked

Deployment Notes​

No new pods or infrastructure. Existing migration paths apply db/postgres/007_internal_ticketing_runtime.sql through local Compose and the application migration runner. External ticketing adapters remain future work.

Security / Tenant Isolation​

All tickets, events, comments, links, and audit records are tenant-scoped. Comments use internal or auditor_visible visibility. Auditor reads are read-only and redacted.

Validation Steps​

UI Validation​

cd frontend && npm test -- --run

API Validation​

make validate-contracts
ONEPROTECT_DB_BACKEND=sqlite ONEPROTECT_WEBHOOK_ADAPTER_MODE=mock .venv/bin/python -m unittest tests.test_internal_ticketing

Smoke Validation​

make test-sqlite

Known Limitations​

  • External Jira/ServiceNow/Freshdesk/Zendesk/HaloPSA adapters are not implemented.
  • The Tickets page now has OP-066a mutation controls for create, status/priority/assignee updates, comments, and links. Alert triage, bulk actions, and external adapter mirroring UI remain separately scoped.
  • Exports follow ADR-0014 and are not part of this runtime slice.

Follow-Up Work​

  • Keep external ticketing adapters behind integration seams.
  • Add scoped alert triage, bulk action, and external adapter UI only after backend APIs are stable and tested.
  • Mirror OneProtect tickets to external systems only through future adapters.

Acceptance Criteria Mapping​

Acceptance criterionEvidence
Canonical ticket/work-item model is accepteddocs/architecture/internal-ticketing-contracts.md, ADR-0010
Alert-to-ticket flow is idempotent and implementedpoc/ingest_api/ticket_service.py, tests/test_internal_ticketing.py
Status lifecycle and role rules are enforcedpoc/ingest_api/ticket_service.py, tests/test_internal_ticketing.py
Audit and event contracts are emittedspecs/asyncapi.yaml, scripts/validate_contracts.py, tests/test_internal_ticketing.py
Basic UI reads and OP-066a mutations use APIsfrontend/src/app/console/tickets/page.tsx, frontend/src/app/console-api/oneprotect/tickets/, frontend/src/test/oneprotect-ui.test.tsx