Operational Qualification — QMS Nordic
| Document ID | QMSN-OQ-001 |
| Applies to | QMS Nordic v1.5.0 |
| Generated | from the source of truth, not written by hand |
Generated from the platform's requirement register, not written by hand, and regenerated on every change. A build check fails if this document falls out of step with the code it describes, so it cannot quietly stop being true — which is what happens to a hand-maintained matrix within two releases.
Operational qualification asks whether each specified function works as specified. For this platform the specification is the 26 requirements of the URS, and the qualification is executed by us, automatically, on every change: the evidence beside each requirement below is a test that runs before any release can deploy, on a database rebuilt from empty. This is the same evidence the traceability matrix cites, arranged for execution.
What you add is confirmation in your own tenant — that the function behaves the same way with your configuration, your roles and your data. Each requirement carries a plain-language way to do that; none needs knowledge of our code, and several need only that you read our evidence and decide it is sufficient, which is a legitimate outcome under §4.1.6 and GAMP 5's supplier-leverage principle. Record what you did in T4.
Requirements marked customer testing required carry no evidence from us; the confirmation step is then the whole of the qualification for that requirement. The Performance Qualification (QMSN-PQ-001) covers the process modules — CAPA, complaints and the rest — which are not requirements here and are evidenced in the Module Evidence Annex.
Document control
URS-DOC-01 — Controlled documents are created, reviewed and approved in the system, with a defined lifecycle
Risk High · ISO 13485 §4.2.4, FDA QMSR §820.10 · Coverage: Full
Our evidence, executed on every change:
- Test: 1. the author creates a draft: version 1, one snapshot, on the trail
- Test: 4. the author submits it for review
- Test: 5. the author cannot approve their own document, even with re-authentication
- Test: 6. in production the reviewer cannot sign without a passkey assertion
- Test: 8. the reviewer signs: approved, and the signature names signer, version, meaning and reason
- Test: 9. the author makes it effective
- Test: a rejection returns the document to draft, and the rejection is a signature too
- Test: a colleague verifies every section, and the document moves to Under Review by itself
- Test: IVDR PerformanceEvaluation report approval gate
- Test: IEC 62366-1 UsabilityFile approval gate
Confirm in your tenant: Create a document, submit it for review, approve it and make it effective. Open its history: the four states appear in that order, each with a person and a time.
The general lifecycle — draft, revision, review, a second person's signature, effective, and back to draft on the next revision — is run in order through the real actions on a rebuilt database (added 2026-09-07). The reviewer's identity in that suite is proven by the demo-mode confirmation; the passkey assertion itself is URS-SIG-01. Your own approval route, with your own people and passkeys, is T4.
URS-DOC-02 — Each document carries a unique identifier and a version; superseded versions remain retrievable
Risk High · ISO 13485 §4.2.4, FDA QMSR §820.10 · Coverage: Full
Our evidence, executed on every change:
- Test: 2. the author revises it: version 2, both snapshots kept, still a draft
- Test: 10. revising an effective document returns it to draft at version 3; the old approval does not carry
- Test: 12. every version is still retrievable, with its own content
- Test: keeps every version's content after a revision
- Test: numbering — formatRef / parseRef round trip
- Test: derives a tenant prefix from a manufacturer name
Confirm in your tenant: Open any document with more than one version. The identifier is unchanged across versions, the version number increments, and an earlier version opens read-only with its own content.
Reference formatting, the version increment on revision, and the retention of every superseded version's content are covered by automated tests on a rebuilt database (retention evidence added 2026-09-07). Confirm your own documents' identifiers and version history in T4.
URS-DOC-03 — Only approved, current versions are presented to users as effective
Risk High · ISO 13485 §4.2.4(d) · Coverage: Full
Our evidence, executed on every change:
- Test: accepts an approved document
- Test: refuses a draft
- Test: refuses a document still in review
- Test: refuses a document marked approved that carries no approval record
- Test: refuses when the approval on file is for an earlier version
Confirm in your tenant: As an ordinary user, open the document list. Only effective versions are offered; a document in draft or review shows its state and is not presented as current.
Enforced in the action from v1.3.0, and tested. Before that release the rule lived only in the interface — the button is rendered for approved documents, but the action behind it accepted any status — so a form post could take a draft straight to effective. If you validated a release before v1.3.0 and relied on this behaviour, see the release record.
URS-DOC-04 — Obsolete documents are prevented from unintended use
Risk High · ISO 13485 §4.2.4(f) · Coverage: Full
Our evidence, executed on every change:
- Test: cannot return an obsolete document to effective
- Test: retires the prior effective policy when a new one is released
- Test: records the retirement in the audit trail
Confirm in your tenant: Supersede an effective document with a new version. The old version is marked superseded, is no longer offered as current, and cannot be attached as the effective procedure to a new record.
A superseded document is marked obsolete, linked to what replaced it, and cannot return to effective. Note the scope: automatic retirement applies to single-instance types — quality policy and quality manual — where one effective document per scope is the rule. For SOPs and the rest, retiring the predecessor is a step in your own process, and it is what T4 should exercise.
URS-DOC-05 — Periodic review dates are tracked and surfaced before they lapse
Risk Medium · ISO 13485 §4.2.4(b) · Coverage: Partial
Our evidence, executed on every change:
- Test: opens thirty days before the due date and never closes
- Test: does not repeat itself within a week, and does after
- Test: warns before the date and is urgent after it
- Test: tells the owner and the QA administrator about the due and the overdue document, and nobody about the paused one
- Test: says nothing the second time the same week
Confirm in your tenant: Set a review cadence on a document with a next-due date within 30 days. The owner and a quality administrator receive a reminder; set the date in the past and the reminder is marked urgent.
A document with a review schedule is surfaced to its owner and to the QA administrators from 30 days before the review date, daily thereafter but not more than once a week, and as urgent once the date has passed. The rules are tested without a database; the daily job that applies them is exercised end to end on the CI database. Until 2026-09-05 this requirement carried no evidence — the behaviour had existed since the data model, the tests had not.
Record integrity
URS-AUD-01 — Every create, change and delete of a quality record is recorded with actor, timestamp and previous value
Risk High · ISO 13485 §4.2.5, 21 CFR Part 11 §11.10(e) · Coverage: Partial
Our evidence, executed on every change:
- Test: creates an AiGeneration row + AI_DRAFT_GENERATED audit event with matching hashes
- DB: audit_event table with actor, timestamp, payload and prior value
Confirm in your tenant: Change any field on a quality record. The audit trail shows who, when, the field, the previous value and the new one.
Audit writing is covered for the AI drafting path. Coverage across all modules is not automated — spot-check the modules you rely on.
URS-AUD-02 — The audit trail cannot be altered or deleted by users, including administrators
Risk High · ISO 13485 §4.2.5, 21 CFR Part 11 §11.10(e) · Coverage: Full
Our evidence, executed on every change:
- Test: blocks UPDATE and DELETE for the application role
- DB: audit_event_no_update and audit_event_no_delete triggers
- CI: Security DDL survived the rebuild — asserts 3 triggers exist
- Test: no email address and no live credential is written into the trail by any audit call in the application
- Test: the recorder itself refuses an address or a credential a moment before the row is written
Confirm in your tenant: As an administrator, attempt to edit or delete an audit entry through any screen. There is no such control; the entry is unchanged.
Exercised, not merely asserted to exist: the test runs as the application's own database role and confirms both an UPDATE and a DELETE are refused. A role carrying BYPASSRLS — the migration owner — is outside what a trigger can stop; that case is covered by URS-AUD-03, which detects rather than prevents. A trail that cannot be altered also cannot be redacted, so what goes into it is a decision that cannot be revisited: every audit call in the application is scanned, and one writing an email address fails the build. Each such case found was redundant — the row already names the invitation, ticket, user or grant whose own record holds the address and can be redacted — and the domain is kept where it was useful, because it identifies nobody. The scan reads the values rather than the field names, having missed half the cases when it read the names, and expands shorthand properties, having walked past one written that way. The same scan refuses a live credential: the access token for a technical documentation pack was hashed in its own table and the original kept in the audit row beside it, which is the hashing undone — that row outlives the token's revocation, ignores the expiry date printed next to it, and leaves in every CSV export of the trail. Nothing in the trail is now a key to anything. Reading the source can only ever catch what the source says, so the recorder checks the values themselves a moment before writing: an address typed into a reviewer's rationale or a comment reaches the trail at run time, in a string no parser could look inside. Outside production that write is refused outright; in production it is written with the offending value replaced and the incident reported, because a missing audit row is a gap in evidence that no later fix can fill and is worse than an imperfect one.
URS-AUD-03 — Alteration of an audit record is detectable
Risk High · 21 CFR Part 11 §11.10(e) · Coverage: Full
Our evidence, executed on every change:
- Test: recomputing the hash exposes a tampered row
- Test: links each row to the one before it
- DB: audit_event_hash_chain trigger; prevHash/hash columns
Confirm in your tenant: Export the audit trail and verify the hash chain with the exported verifier, or ask us for a verification run. Any altered entry breaks every entry after it.
The test alters an audit row as the owner role — the one party a trigger cannot stop — and confirms an independent recomputation of the hash no longer matches. The claim is not that a record cannot be changed, but that a change cannot be hidden.
URS-AUD-04 — The audit trail is readable and exportable for review
Risk High · 21 CFR Part 11 §11.10(b), §11.10(e) · Coverage: Partial
Our evidence, executed on every change:
- Test: exports the audit trail as CSV, with the hash chain intact
- Test: records the export itself in the trail
- Test: refuses the export to a role that may not take records out
Confirm in your tenant: Open the audit log for one record and export it. The export is readable without our help and contains every entry the screen shows.
The trail exports as CSV carrying every field including hash and prevHash, so the chain can be verified outside the platform. Two limits worth knowing: the export is capped at 50,000 events, which is above any current tenant but is a ceiling rather than a guarantee of completeness under Part 11 §11.10(b); and it is a whole-trail export, not a filtered one, so producing the events for a single record means filtering the file yourself.
Electronic signature
URS-SIG-01 — Signing requires the signer to re-authenticate at the moment of signing
Risk High · 21 CFR Part 11 §11.10(g), §11.200 · Coverage: Partial
Our evidence, executed on every change:
- Test: refuses when no challenge has been issued
- Test: refuses a challenge that has expired
- Test: refuses a challenge issued for registration, not signing
- Test: refuses to sign without an assertion once a passkey is enrolled
- Test: refuses a signature whose re-authentication does not match the signer
Confirm in your tenant: Sign a document. The platform asks you to authenticate again at the moment of signing; cancelling the authentication leaves the document unsigned.
Covered as a gate, on both ways of signing a document — direct approval and each step of an approval route: a signature cannot be produced without a live SIGN challenge issued to this user, and the action refuses to sign at all once a passkey is enrolled. The cryptographic verification itself is @simplewebauthn's, and we do not re-test it — forging a valid assertion to prove the happy path would only prove we can forge one. Note also that §11.200(a) sets a two-component test for non-biometric signatures and §11.200(b) a different bar for biometric ones; a passkey with user verification is not squarely either, and FDA has published no position. Decide which limb you are relying on and record the reasoning.
URS-SIG-02 — The signature records signer, date, time and the meaning of the signature
Risk High · 21 CFR Part 11 §11.50 · Coverage: Full
Our evidence, executed on every change:
- Test: records signer, time and meaning when a signature is accepted
- Test: cannot record a signature with no meaning
- Test: signs the named step and writes the signature against the document
- Test: refuses a signature with no reason — the meaning of the signature
- DB: document_approval stores signer, timestamp, meaning and credential id
Confirm in your tenant: Open a signed document. The signature shows the signer's name, the date and time, and the meaning of the signature (approved, reviewed).
URS-SIG-03 — A signature is bound to the specific record signed and cannot be transferred to another
Risk High · 21 CFR Part 11 §11.70 · Coverage: Full
Our evidence, executed on every change:
- Test: refuses a live challenge issued for a different document
- Test: refuses a credential belonging to another user
- DB: webauthn_challenge.documentId binds a SIGN challenge to its document
Confirm in your tenant: Note the signature on one document version. It does not appear on any other document or version; a new version of the same document is unsigned until signed again.
URS-SIG-04 — Signed records cannot be modified without invalidating the signature
Risk High · 21 CFR Part 11 §11.70, §11.10(e) · Coverage: Full
Our evidence, executed on every change:
- Test: editing an effective document returns it to draft and versions the content
- Test: does not require a join to the audit trail to establish what was signed
- Test: keeps null distinguishable from a version, for signatures predating the column
- DB: document_approval.documentVersion records the version signed; document_snapshot retains it; appendVersion drops an EFFECTIVE document back to DRAFT
Confirm in your tenant: Attempt to edit the content of a signed, effective document. The edit produces a new, unsigned version; the signed version is unchanged and still carries its signature.
An edit produces a new version and returns the document to draft, so a signature cannot carry silently onto text it did not approve; the version that was signed stays retrievable; and from v1.2.0 the signature itself records which version it released, so the link can be read without joining to the audit trail. Signatures recorded before v1.2.0 carry no version where the audit trail did not supply one — that is shown as absent rather than filled in, because inventing a version number on a signature record would be worse than declaring the gap.
Access control
URS-ACC-01 — Access requires authentication; permissions are assigned by role
Risk High · ISO 13485 §4.1.6, 21 CFR Part 11 §11.10(d) · Coverage: Full
Our evidence, executed on every change:
- Test: grants each permission to exactly the roles it is meant for
- Test: refuses an unknown or absent role everything
- Test: enforces it in the action, not only in the check
- Test: records the refusal, so a denied attempt is not invisible
- Test: lets R&D sign the first step of a design plan, and Quality release it
- Test: refuses Regulatory Affairs approving the last step of a route made before the rule
- Test: refuses a route whose last step is not Quality's
- Test: lets a Manufacturing engineer sign that step, and Quality release the SOP
- Test: refuses a change while an approval route is open
Confirm in your tenant: Sign out and open any record's address directly. You are sent to sign in. As a user with the auditor role, attempt to change a record: the controls are absent or refused.
The permission matrix is asserted role by role, the action is shown to consult it rather than merely the interface, and a refused attempt is shown to be audited. What remains yours: which of your people hold which role.
URS-ACC-02 — Users see only records belonging to our organisation
Risk High · ISO 13485 §4.2.5, GDPR Art. 32 · Coverage: Full
Our evidence, executed on every change:
- Test: cross-tenant retrieval — query from tenant A returns no tenant B rows
- Test: submitForReview cannot read tenant B's document
- Test: refuses to sign a document belonging to another organisation
- DB: row-level security enabled and forced on every table carrying tenantId
- CI: Tenant isolation is enforced on the rebuilt database — inserts two tenants and asserts a scoped read returns only its own row
Confirm in your tenant: If you have two organisations, sign in to one and open a record address from the other. It is not found. If you have one organisation, rely on our evidence: the isolation is enforced in the database and proven on every change.
URS-ACC-03 — Separation of duties can be enforced where our processes require it
Risk High · ISO 13485 §4.2.4(a), §5.5.1 · Coverage: Full
Our evidence, executed on every change:
- Test: refuses to let the author approve their own document
- Test: refuses the author approving their own document
- Test: refuses one person approving two steps of the same route
- Test: refuses a Super Admin signing a step assigned by name to someone else
- Test: refuses the same Super Admin signing a second approval
- Test: becomes APPROVED when three different people have signed, and records the role each holds
- Test: enforces segregation of duties between plan and report approver
- Test: approves a complete PER from a different approver
Confirm in your tenant: As the author of a document, attempt to approve it yourself. The approval is refused; a second person approves it.
URS-ACC-04 — Access is removed promptly when a user leaves
Risk High · ISO 13485 §4.1.6, 21 CFR Part 11 §11.10(d) · Coverage: None
Our evidence, executed on every change:
- None — customer testing required.
Confirm in your tenant: Deactivate a user. That user can no longer sign in, and their records remain, attributed to them.
This is a customer process requirement, not a platform one. The platform removes access when told to; knowing when to tell it is your joiner/leaver process. Most commonly found gap under this clause — test it.
Retention and availability
URS-RET-01 — Records remain legible and retrievable for our retention period
Risk High · ISO 13485 §4.2.5, 21 CFR Part 11 §11.10(c) · Coverage: Partial
Our evidence, executed on every change:
- Test: keeps every version's content after a revision
- Test: does not delete anything when a document is retired
Confirm in your tenant: Set your retention period in settings. Open a record older than any purge you might expect: it is intact and legible. Nothing is deleted automatically.
Every version's content stays retrievable, and retiring a document deletes neither its versions nor the signatures on it. What is still absent is a retention period: the platform does not delete records, but neither does it enforce or track how long you have undertaken to keep them. That undertaking, and evidence that nothing in your own configuration removes records before it expires, remains yours.
URS-RET-02 — Records can be exported in a usable format without vendor assistance
Risk High · ISO 13485 §4.2.5, 21 CFR Part 11 §11.10(b) · Coverage: Partial
Our evidence, executed on every change:
- Test: exports documents without vendor assistance
- Test: exports the audit trail as CSV, with the hash chain intact
- Test: refuses the export to a role that may not take records out
Confirm in your tenant: Run the export for your organisation. The archive opens without our software and contains your documents, records and audit trail in readable formats.
Documents and the audit trail export to CSV without our involvement, and each export is itself audited. Not covered: there is no single whole-tenant export — you export per entity — and document content leaves as Word or Markdown from the document itself rather than in the CSV. Export what you would actually need in an inspection and confirm it is complete and readable outside the platform.
URS-RET-03 — Data is backed up and restorable
Risk High · ISO 13485 §4.2.5, EU GMP Annex 11 §7.2 · Coverage: Partial
Our evidence, executed on every change:
- Report: Witnessed restore of production, 2026-08-28 — 45 minutes measured
Confirm in your tenant: Rely on our evidence: a restore of production was rehearsed and witnessed, with the measured recovery time recorded in this pack. Ask us for the next rehearsal date.
Witnessed restore, 2026-08-28. A point-in-time copy of production was restored to a separate branch and verified: all 4,006 audit records rehashed to their contents, all reachable from the start of their chain, and row-level security and tenant isolation present on the copy — a scoped read returned 31 of 547 documents. The application was then run against the restored copy and signed into. Measured recovery time 45 minutes, from deciding to restore to the system being usable, against our stated four-hour recovery commitment. One finding is recorded in the report rather than omitted: 67 places where two audit rows share a predecessor, from batched writes between 23 May and 22 June 2026 — records unaltered and none missing, but at those points the chain alone does not prove nothing was removed. That finding stood against data which no longer exists: on 2026-09-09, before the first customer, the audit chain was restarted from empty and every tenant on the platform was demo or test data. The advisory lock that caused those shared predecessors was fixed in migration 20260427300000; the rows that predated the fix are gone, and the chain running today began after it. The rehearsal itself is unaffected — it evidenced a restore capability on a day, and that day happened. Rehearsed annually; next due 2026-08-28 + 12 months. The restore window itself was confirmed on 2026-09-09 and is 7 days: the platform moved off the provider's free tier, whose 6-hour history could not have supported the recovery the published security overview describes. Beyond seven days there is no restore point, which bounds what this requirement can claim — a fault introduced more than a week before it is noticed is not recoverable by this route.
AI-assisted drafting
URS-AI-01 — AI-generated content is identifiable as such, with recorded provenance
Risk Medium · ISO 13485 §4.2.5, EU AI Act Art. 50 (where applicable) · Coverage: Full
Our evidence, executed on every change:
- Test: creates an AiGeneration row + AI_DRAFT_GENERATED audit event with matching hashes
Confirm in your tenant: Generate a draft with the assistant. The document is marked as AI-generated and its provenance shows the model and the generation.
Art. 50 addresses disclosure of AI-generated content to people who encounter it; an internal SOP draft reviewed and approved by your own staff may fall outside it. Cited because provenance is recorded either way.
URS-AI-02 — No AI-generated document becomes effective without human review and approval
Risk High · ISO 13485 §4.2.4 · Coverage: Full
Our evidence, executed on every change:
- Test: refuses an AI draft that has not been approved
- Test: clears the AI badge only when a human signs the approval
- Test: refuses a draft
Confirm in your tenant: Attempt to make an AI-generated draft effective without review. It is refused until a person has reviewed and approved it.
The platform now refuses to make any document effective without an approval record, so an unreviewed AI draft cannot reach effective status. Stated plainly, because this file said otherwise until v1.3.0: that guarantee did not previously exist. The claim was that approval was required; the check was in the interface only. Whether your own process then permits an approver to sign an AI draft without reading it is still yours to control, and AI output remains non-deterministic and unvalidated — so this is still worth testing in your context.
URS-AI-03 — An incomplete generation is flagged rather than presented as complete
Risk High · ISO 13485 §4.2.4 · Coverage: Full
Our evidence, executed on every change:
- Test: continues when the model runs out of room, and finishes without warning
- Test: continues when the model stops early WITHOUT the completion marker
- Test: gives up after the continuation limit and says so
Confirm in your tenant: Ask the assistant for a document it lacks material for, or interrupt a generation. The result is flagged as incomplete, not presented as finished.
Fixed in v1.0.0. Documents drafted before that release may be incomplete — see the platform release record (QMSN-CL-001).
URS-AI-04 — A failure of the AI provider does not produce a document
Risk High · ISO 13485 §4.2.4 · Coverage: Full
Our evidence, executed on every change:
- Test: reports a rate limit as transient and produces no document
- Test: reports a non-transient failure plainly, and still produces no document
Confirm in your tenant: Rely on our evidence, or ask us to demonstrate: when the AI provider is unavailable the platform reports the failure and produces no document.
Fixed in v1.0.0. Before that release a busy provider silently substituted a template.
Change control
URS-CHG-01 — Changes to the platform are recorded, reviewed and traceable to a released version
Risk High · ISO 13485 §4.1.6 · Coverage: Full
Our evidence, executed on every change:
- CI: Verify — test and build on every change, blocking
- CI: Verify — type checking and linting on every change, blocking
- CI: Migration history rebuilds the database — blocking
- DB: schema changes applied only via reviewed migrations (prisma migrate deploy)
Confirm in your tenant: Open the release record. Every release lists what changed and its class; the version you are running appears on the pack page and in the release record.
Type checking and linting block on every change, in CI and in the build itself. Until 2026-09-09 the build suppressed both, to live with 145 type errors across 39 files that the release record disclosed; those errors are gone and the suppressions with them, so a deploy that skipped the pipeline can no longer ship a type error either. Code-owner review is configured but branch protection is not enforced — that needs a paid GitHub plan on a private repository, and the rule is published as procedural rather than technical until it is.
URS-CHG-02 — The recorded change history reproduces the validated system
Risk High · ISO 13485 §4.1.6 · Coverage: Full
Our evidence, executed on every change:
- CI: Migration history rebuilds the database — rebuilds from empty, diffs against the shipped schema, asserts 185 policies, 636 grants and 3 triggers survive
Confirm in your tenant: Rely on our evidence: on every change the database is rebuilt from the recorded migration history and verified against the shipped schema and security configuration.
Concluding
The OQ passes for a release when every requirement's evidence ran and passed on that release — which is what the build gate enforces — and your confirmations in T4 are recorded. A confirmation that fails is a deviation against the platform: tell us, and record it in T4 pending our response.
QMSN-OQ-001 · v1.5.0 · pack rev. J (2026-09-07)
Published at qmsnordic.com/legal/validation/operational-qualification. Cite the version above in your validation record — a pack is evidence, and evidence has to stay retrievable at the version you validated against.
