10 KiB
Znuny and OTRS-compatible service-desk connector
Boundary
Connectors owns the governed endpoint profile, GenericInterface REST transport, credential hand-off, provider discovery, bounded synchronization, external references, mapping diagnostics, health, and recovery evidence. It does not own ticket, helpdesk, or case semantics. A synchronized provider ticket remains an external service-desk ticket; creating or relating a GovOPlaN Ticket, Helpdesk item, or Case is the responsibility of the corresponding optional module.
The provider interface is connectors.external_service_desk@1.0.0, and the
target-tested provider declaration is connectors.znuny.tickets.
Governed configuration and routes
Create an active connector definition/configuration with:
provider:znuny,otrs, orznuny_otrs;protocol:generic_interface_rest(the aliasesrestandotrs_generic_interface_restare accepted);- an HTTP(S) endpoint that passes the central outbound-request policy; and
- an optional scoped Core credential-envelope reference.
Znuny GenericInterface routes are configured by each deployment rather than
being one universal product API. The profile therefore governs relative search,
ticket-read, and optional update paths and their supported
methods. Ticket and update paths must contain {ticket_id}. An optional
absolute HTTP(S) browser URL template may contain {ticket_id} or
{ticket_number}. search_filters carries up to 100 deployment-supported,
secret-free GenericTicket search criteria such as queue identifiers. It cannot
override synchronization bounds, ordering, change cursors, or authentication.
Routes cannot change authority or contain credentials.
Header authentication is the recommended default. The adapter supports the
documented X-OTRS-Header-UserLogin, X-OTRS-Header-Password,
X-OTRS-Header-SessionID, and customer-login headers. A legacy credential may
declare auth_mode: body, but then every affected route must use POST. Secret
fields are never placed in a GET URL, persisted projection, diagnostic, or API
response. Core also treats these provider headers as redirect-sensitive and
removes them before following any cross-origin redirect.
Reference configuration examples:
- Znuny GenericTicketConnectorREST example
- Znuny provider and header authentication
- Znuny web-service configuration
Profile policy
The integration and authority choices are intentionally separate but bounded:
| Integration mode | Allowed authority | Maturity |
|---|---|---|
link |
linked_reference |
link through search |
import |
external_authoritative, external_mirror |
exactly read |
synchronize |
external_authoritative, governed_sync |
exactly synchronize |
link retains stable identity and routing facts and asks the provider not to
return articles, attachments, or dynamic fields; any unexpectedly returned
content is still discarded. import is a deliberate bounded full snapshot and
never silently changes to delta synchronization.
synchronize completes a full reconciliation and then advances to overlap-safe
change-time deltas.
Queue mappings govern inclusion, an optional opaque target queue reference, and
tenant or restricted visibility with ACL tokens. A restricted default requires
at least one ACL token. Provider-supplied GovOPlaNVisibility and
GovOPlaNACL fields win when valid. Otherwise a reviewed queue mapping wins,
then the profile default. Standard GenericInterface installations do not expose
a portable ticket-ACL contract, so every fallback is visible as a diagnostic.
Dynamic-field mappings govern source name, optional target name, inclusion, and
string, number, boolean, date, or json conversion. Conversion loss,
unreturned configured fields, provider-specific ticket fields, synthesized
identities, and truncation are structured diagnostics rather than silent loss.
Discovery and synchronization
Discovery performs a bounded ticket search and records health, API family,
route hash, the exact governed configuration revision/hash, product/version
evidence, capabilities, maturity, and diagnostics. A changed endpoint,
configuration revision, or route map invalidates that evidence: synchronization,
and updates fail closed until discovery is repeated, while prior projections are
invalidated and Search stays closed until a new full reconciliation verifies
them. Integration, route, queue, or dynamic-field mapping changes also reset the
cursor and require a full reconciliation. Recognized Znuny or OTRS major
versions 6 and later can reach synchronization maturity. An unverified
product/version stays at read maturity. An update route adds the technical
publish capability, but does not override profile authority.
Full synchronization first obtains a stable ordered identity set, then reads at
most 500 tickets per call. A continued full run stores its offset, identity-set
fingerprint, and cumulative high-watermark. If the provider identity set changes
mid-run, the cursor is rejected and the operator must restart the full run. A
completed full run reconciles local removals and, for synchronize mode,
transitions to an overlap-safe delta cursor.
An explicit full request always restarts at the beginning; auto continues a
committed full cursor or advances a completed delta cursor. A caller-supplied
cursor must exactly match the profile's committed cursor, and delta mode cannot
bootstrap a profile that has not completed its full synchronization.
Delta synchronization reads the bounded candidate set, orders changes by provider change time and ticket id, and suppresses only the exact ticket revisions already observed at the current timestamp boundary. A previously seen ticket that has changed again is therefore not lost. Every run requires a profile-wide idempotency key. An exact replay returns the committed run without contacting the provider; reuse for a different request or changed profile policy is rejected.
Operational bounds:
- at most 10,000 ticket identities per profile search;
- at most 500 ticket reads per API call;
- at most 10 MB per provider response;
- a 20-second outbound timeout; and
- a 4,000-character cursor, including timestamp-boundary identities.
Partition larger or unusually bursty providers into queue-scoped profiles by
combining provider-side queue search_filters with matching queue mappings. A
full-run fingerprint conflict requires a restart. A timestamp-boundary overflow
requires a narrower partition. These are explicit safety stops, not partial
success claims.
Mapping and attachment policy
Each ticket projection retains stable ticket id/number, title, type, queue, target queue reference, state, priority, owner, responsible user, customer user, organization, service, SLA, creation/change times, mapped dynamic fields, articles, attachment metadata, permission source, ACLs, canonical URL, content hash, provider revision, cursor, observation time, and source provenance.
Article and attachment references use Core ExternalObjectReference values.
Article bodies are capped at 200,000 characters. Attachment content is never
retained; only stable identity, filename, media type, size, disposition, content
id, article/ticket relationship, version, and provenance are mapped. Returned
bytes produce an attachment_content_omitted diagnostic.
Search authorization
When Search is installed and both desired and discovered maturity permit it, active non-deleted ticket projections are indexed. Search documents carry the current visibility, ACL tokens, external reference, source revision, routing metadata, article text, and bounded dynamic-field keywords.
Authorization always fails closed unless all of these remain true:
- the requesting principal belongs to the exact tenant;
- the principal has
connectors:service_desk:read; - the profile remains active and search-capable;
- the ticket remains active; and
- tenant visibility applies or a current account, membership, identity, group, role, function, or scope ACL token intersects.
Pausing a profile or changing fallback/queue ACLs updates or removes Search projections immediately. Search also rechecks the current database state for every result, so a delayed index update does not grant access.
Governed external updates and recovery
An external update is allowed only when the profile is active, authority is
governed_sync, discovery recorded the publish capability, and the caller has
connectors:service_desk:update. The request must include the synchronized
provider revision and a new idempotency key. Supported governed fields are
title, queue, state, priority, owner, responsible user, and explicitly mapped
dynamic fields.
Before dispatch, the adapter refetches the ticket and rejects a stale revision.
After dispatch, it refetches again and verifies both the changed revision and
every requested field value. A transport failure before a conclusive provider
response, an unchanged revision, or a requested value that cannot be confirmed
becomes outcome_unknown. Do not retry with another key. Inspect the provider
ticket and reconcile its accepted revision through the Core recovery evidence
first. Local database rollback cannot undo a remote provider mutation.
Administrator verification
- Create the governed definition/configuration and scoped credential envelope.
- Create a restricted profile with reviewed routes, queue partitions, dynamic fields, authority, and fallback ACLs.
- Discover and confirm product/version, maturity, capabilities, and diagnostics.
- Finish a keyed full run; continue while its cursor kind is
full. - Run a new keyed automatic delta and inspect effects, losses, and health.
- Verify one allowed and one denied Search principal against a restricted ticket.
- If governed writes are enabled, update a non-production ticket with its current revision, then verify provider and recovery evidence.
- Reconcile every
outcome_unknownrun before any retry.