Files
govoplan-connectors/docs/ZNUNY_OTRS_CONNECTOR.md
zemion b277e8d7ac
Module Package Release / publish-packages (push) Successful in 12s
Release Connectors v0.1.22 with service-desk federation
2026-08-22 16:11:07 +02:00

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, or znuny_otrs;
  • protocol: generic_interface_rest (the aliases rest and otrs_generic_interface_rest are 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:

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

  1. Create the governed definition/configuration and scoped credential envelope.
  2. Create a restricted profile with reviewed routes, queue partitions, dynamic fields, authority, and fallback ACLs.
  3. Discover and confirm product/version, maturity, capabilities, and diagnostics.
  4. Finish a keyed full run; continue while its cursor kind is full.
  5. Run a new keyed automatic delta and inspect effects, losses, and health.
  6. Verify one allowed and one denied Search principal against a restricted ticket.
  7. If governed writes are enabled, update a non-production ticket with its current revision, then verify provider and recovery evidence.
  8. Reconcile every outcome_unknown run before any retry.