Skip to Content

How to connect a QMS

Use this guide when the program’s controlled SOPs live in a QMS and Review should check work against the version in force. You start with a program and a read-only integration user in the QMS; you end with a connection in status connected, SOPs of source_kind = connector under Review › SOPs, and one sop_versions row per version the QMS holds. Creating the connection needs program.connections.manage; syncing needs program.connections.sync. The provider id is veeva_qualitydocs, category documents, write policy read_only, default API version v26.2.

The connector is designed until the R1 gates pass. Until the partner’s sandbox and integration user arrive it talks to the fake server api/scripts/fake_vault.py (port 8191), whose SOPs and versions are labelled “Illustrative”. The QMS stays the SOP record; Trovensa never approves or edits a connector SOP.

Prerequisites

  • A read-only integration user in the QMS whose profile covers the effective SOPs of the mapped document types and nothing else, plus its API credentials.
  • The document type (and, if used, subtype and classification) that identifies SOPs in that QMS, and the lifecycle labels the QMS uses (they are configured per tenant and per lifecycle).

Create the connection

Setup › Connections › Add connection, provider QMS/SOP connector (veeva_qualitydocs). Enter the tenant’s API host, keep api_version at v26.2 unless the partner says otherwise, set scope_rules.document_types to the SOP type, and map the lifecycle labels to Trovensa’s states (draft, in_review, effective, superseded, obsolete; anything else becomes unmapped). The record appears as pending with poll_interval_seconds = 900.

Store the integration user’s credentials

Configure credentials stores the user name and password or API token under <org_id>/connections/<connection_id>/<key>; the database holds references only. Every request carries the client id header trovensa-review-connector-client-vault so the tenant’s usage log names Trovensa.

Run the health check

Check health authenticates, verifies the returned tenant id, validates each field of the per-connection query template (SELECT id, name__v, document_number__v, major_version_number__v, minor_version_number__v, status__v, version_modified_date__v FROM ALLVERSIONS documents WHERE type__v = '<SOP type>'), checks that ALLVERSIONS is available and that every lifecycle label is mapped, and writes the result to connection.health. Gaps are listed before the first sync; this check is the exit gate of the connector’s release.

Run the first sync

Sync now runs the delta poll (version_modified_date__v > watermark). Each SOP becomes a sops row with source_kind = connector, document_number, owner_text and applicability tags from the type, subtype and classification; each version becomes a sop_versions row with major.minor, lifecycle_state, effective_at (from the effective-date field, else first observation with effective_on_observed = true), superseded_at, rendition_hash and external_version_label. The connection reads connected; afterwards the worker polls every 15 minutes (poll_qms) and reconciles nightly over ALLVERSIONS (reconcile_qms), throttled by the burst-limit and response-delay headers.

Check the versions page

Open Review › SOPs, choose an SOP and its Versions tab (GET .../review/sops/{sop_id}/versions, needs review.sops.read). Only versions in state effective can bind checks; each shows its requirement-set status (none until an extraction run proposes one) and, where the effective date was inferred, the note “inferred from first observation”.

What happens when a new version becomes effective

The poll sees the new version, the worker enqueues review_extract_requirements and then review_sop_impact, and holders of review.sops.manage receive a sop_changed notification. A system thread summarises the change; QA accepts the proposed requirement set with a signature (how-to) and approves the proposed re-check batch.

Troubleshooting

SymptomCauseFix
Health check lists an unmapped labelthe QMS uses a lifecycle label the map does not nameadd the mapping; versions in unmapped states stay ineligible and appear in health
A version shows no effective datethe tenant has no effective-date field on that typethe connector records first observation with effective_on_observed = true; bind checks manually with a reason when the work predates it
POST .../review/sops/{sop_id}/approve answers 409 sop_externalthe SOP comes from the connectorexpected: the QMS is authoritative; accept the requirement set instead
Sync stalls with rate_limitedburst limit reachedthe worker honours X-VaultAPI-ResponseDelay and resumes; nothing to fix
Last updated on