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