QMS Nordic
PrivacyTermsSecuritySub-processorsAI ActValidation

← Software validation pack

Module Evidence Annex — QMS Nordic

Module Evidence Annex — QMS Nordic
Document IDQMSN-MEA-001
Applies toQMS Nordic v1.5.0
Generatedfrom 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.


The requirement register behind the URS and the traceability matrix is deliberately narrow: the 26 properties a regulator holds any electronic quality-record system to, whatever a customer runs in it. A customer who also runs CAPA, complaints, training or suppliers in the platform must validate those for their intended use (ISO 13485 §4.1.6) — and may lean on the supplier's testing to do less of their own.

This annex is that testing, module by module, held to the same discipline as the register: which suites, what they establish, and, at more length, what they leave to you. The test names are read from the suites themselves when this document is generated, so a renamed test appears here and a deleted suite fails the build. The Performance Qualification (QMSN-PQ-001) cites these sections so your own steps stop where ours end.

These are not requirements and do not appear in the matrix. A requirement is a promise held to full evidence on every release. Module evidence is a description of what we test, allowed to be partial because it says where it is partial.

Module Evidence Annex — QMS Nordic
ModuleIdSuitesTests
Product classificationM-CLSclassifier, rules-engine20
Corrective and preventive actionM-CAPAcapa-gates, complaint-capa-link, complaint-capa-link42
Complaints and vigilanceM-CMPcomplaint-gates, reportability, regulatory-citations, reportability-determination, reportability-determination, survey-intake, complaint-vocabulary, ticket-complaint, trend-detection107
Management reviewM-MRmanagement-review-gates4
Post-market surveillance — proactive feedbackM-PMSpms-feedback-selection, pms-feedback-screen, pms-feedback-unsubscribe, pms-feedback-escalation, pms-feedback-delivery, pms-feedback-psur, pms-feedback-plan-text, pms-feedback-gates, pms-feedback-i18n, pms-feedback-customisation, pms-feedback-retention, pms-report-due, pms-feedback-reply, pms-feedback-closure, pms-feedback-end-users, sending-domain285
Servicing — analysed for complaintsM-SVCservicing-complaint, servicing-gates30
Supplier controlM-SUPsupplier-gates6
Training and competenceM-TRNtraining-gates4
Equipment and calibrationM-EQPequipment-gates, calibration-gates7
Software lifecycle (IEC 62304)M-SWsoftware-gates4
Usability engineering (IEC 62366-1)M-USElifecycle-gates4
Performance evaluation (IVDR)M-PElifecycle-gates6
Process and software validation runsM-VALsoftware-validation, lifecycle-gates, revalidation-drift30
Regulatory submissionsM-SUBsubmission-gates4
Traceability of units leaving the buildingM-TRACEtraceability-rules, recall-chain38
Product register and market releaseM-PRODproduct-udi, product-release-gates13

M-CLS — Product classification

Your obligation: EU MDR Annex VIII · EU MDR Article 51 · ISO 13485 §7.1

What our tests establish. For known inputs the classifier returns the expected class under the EU MDR and FDA rules, cites the rule it fired, and the rule pack derives the obligations that follow from a class.

classifier.test.ts:

  • non-invasive → Class I baseline
  • implantable in contact with heart → Class III
  • SaMD with life-impacting decisions → Class III
  • measuring function lifts Class I → IIa
  • non-invasive non-software → Class I
  • software-driven → Class II
  • implantable → Class III
  • raises a long-term surgically invasive device in contact with the CNS to Class III
  • treats an implantable the same way, because Rule 8 does
  • says which exceptions it did not evaluate, rather than presenting a floor as an answer
  • claims nothing it evaluated when the exception is settled
  • does not put a short-term surgically invasive device under Rule 8
  • is honest that an FDA result is not a classification
  • stores the unevaluated rules beside the class they qualify
  • shows them on the product, where the class is read

rules-engine.test.ts:

  • regulator predicate matches when classification is present
  • classMin enforces ordering
  • all/any/not compose correctly
  • EU MDR Class IIb implantable triggers SSCP and Implant Card
  • FDA-only context does not pull MDR-only obligations

What they do not cover — and so what your PQ must. Whether your device's inputs are the right inputs is a regulatory judgement the platform records but does not make. The pack pins the rule version used; it does not validate your rationale, and it does not replace the classification in your technical documentation.


M-CAPA — Corrective and preventive action

Your obligation: ISO 13485 §8.5.2 · ISO 13485 §8.5.3

What our tests establish. Walking one case through the real server actions on a real database: it cannot move to implementation until both a corrective and a preventive action are written; effectiveness cannot be verified before implementation; it cannot be closed without a verified effectiveness check, and the refusal names §8.5.2(f); every transition is on the audit trail with the previous state. A case can address several complaints and a complaint can lead to several cases, and every link states which cause it addresses — a link without a reason is refused. A closed case refuses a new cause: when a cause recurs after its effectiveness was verified, a new case is opened that follows it and must state what it will do differently, while the closed case is left unmodified and shows the recurrence through a marker derived from the case that followed. A complaint about a unit made before the fix may be attached to the closed case, and is recorded as not counting against its effectiveness. A link cannot be removed from a closed case, and a removal from an open one keeps the link's content on the audit trail. A case opened from a complaint is linked to it in the same transaction, so a case can never exist without its record of what caused it. Links do not cross organisations.

capa-gates.integration.test.ts (against a real database, as a signed-in user):

  • opens a case with a number and an audit record, then shows it
  • will not move to implementation until both actions are written
  • refuses the outcome of a monitoring period that has not run out
  • cannot be closed without a verified effectiveness check, and says which clause
  • closes once effectiveness is verified, and the trail shows the path
  • does not verify effectiveness on a case that is not being implemented

complaint-capa-link.test.ts:

  • allows a reasoned link to an open case
  • requires a reason, because a link without one is just a list
  • does not count whitespace as a reason
  • refuses a duplicate, naming both records
  • refuses an unknown kind
  • never lets a person record a link as carried over
  • refuses to attach a cause to a closed case
  • tells the user both honest alternatives
  • allows a pre-fix unit to attach to the closed case
  • allows a pre-fix unit while the case is verifying
  • refuses 'pre-dates the fix' when there is no fix yet
  • is allowed on an open case, with a reason
  • is refused on a closed case, because it closed on that evidence
  • requires a reason, which is recorded with the removal
  • is allowed against a closed case, with a real rationale
  • is refused against an open case — that is just more evidence for it
  • requires saying what will be different
  • is absent when nothing followed
  • names the case that followed
  • says the closed case itself is unchanged
  • lists several in the order they were opened
  • counts causes and carried-over links
  • does not count a unit that pre-dates the fix

complaint-capa-link.integration.test.ts (against a real database, as a signed-in user):

  • links several complaints to one case, each with its reason
  • links one complaint to several cases — one investigation, two causes
  • refuses a link without a reason
  • refuses a duplicate link
  • never lets a person record a link as carried over
  • refuses a new cause on a closed case
  • accepts a pre-fix unit on the closed case
  • refuses to remove a link from a closed case
  • removes a link from an open case and keeps what it said in the trail
  • does not link to another organisation's case
  • refuses without saying what will be different
  • refuses to follow a case that is still open
  • opens the follow-up, linked to its complaint in the same transaction, and leaves the closed case alone

What they do not cover — and so what your PQ must. Root-cause method, the adequacy of the actions, your escalation and due-date rules, and what counts as an effective outcome are yours. The platform enforces that the steps happen in order and are recorded; it cannot judge that they were done well. Whether several complaints genuinely share a cause is your investigator's judgement: the platform requires that the cause be stated for each link, not that the statement is right. Whether a unit pre-dates a fix is established from your own production and traceability records; the platform records the classification you make and what it means for the case, but does not check it against them.


M-CMP — Complaints and vigilance

Your obligation: ISO 13485 §8.2.2 · EU MDR Article 87 · EU MDR Article 88 · 21 CFR Part 803

What our tests establish. A complaint flagged as reportable under the EU MDR or to the FDA cannot be closed until the report is recorded with its reference, or a determination is recorded that it is not reportable after all; a report cannot be recorded against a complaint that is not flagged. The reporting clocks — 2, 10 and 15 days under Article 87, 5 and 30 days under Part 803 — run from the awareness date, not from the day the complaint was entered. Harm reported without an explicit serious-injury or malfunction flag is presumed reportable pending a qualified assessment, rather than excused by default. The FDA clock is not applied to a device that is not placed on the US market. Each deadline is stated with the sub-paragraph that sets it, and the citations themselves are held to the regulation by test. A report is stood down only by a recorded determination — the regime, the ground from a fixed vocabulary, the reasoning, the decider and their qualification, with the platform's own suggestion of that moment kept beside it — never by editing the triage answers, which stay as the complainant gave them; a flagged complaint closes on a filed report or such a determination. A customer's survey answer, its feedback record and its audit entry are written in one transaction, so an answer describing harm cannot be thanked for and lost, and the respondent's address never enters the hash-chained trail. A customer message that reaches the helpdesk and alleges anything wrong with a device is put to a person as a possible complaint, on the customer's own words as well as on how it was triaged, and never on our own replies; recording it carries the customer's account and the moment the message arrived — which is when awareness began — into the complaint file rather than leaving either to be retyped; and deciding it is not a complaint takes a written reason and its author, as FDA QMSR §820.10 (ISO 13485:2016 §8.2.2) requires of a complaint that is not investigated. Complaints that were found not to be serious incidents are counted each night against the observation period, baseline and significance threshold recorded in that product's PMS plan, as EU MDR Article 88(2) requires the manufacturer to specify them, and a rise that meets the plan's threshold is raised as a signal with every number a reviewer needs to recompute it. Serious incidents are excluded from that count, since they are reported individually under Article 87. No signal is raised while the records do not yet cover the whole baseline, nor below the plan's floor of events, so a newly entered product and a rise from one event to two are both left alone.

complaint-gates.integration.test.ts (against a real database, as a signed-in user):

  • will not close an EU-reportable complaint while the report is outstanding
  • will not close an FDA-reportable complaint while the MDR is outstanding
  • will not record a report against a complaint that is not flagged
  • closes once the EU report is recorded with its reference, and the trail shows both
  • closes an unflagged complaint without a report

reportability.test.ts:

  • runs from the awareness date, not from now
  • gives 2 days for a serious public health threat, whatever else is true
  • gives 10 days for death or unanticipated serious deterioration
  • gives 15 days for harm or a malfunction
  • is not reportable when nothing happened, and says so without a date
  • gives 5 days for a public health threat
  • gives 30 days for death or serious injury, and for a malfunction
  • presumes harm without a serious-injury or malfunction flag is reportable, pending a qualified assessment
  • marks the clear cases as decided, not presumed
  • does not apply to a device that is not on the US market, and says why
  • assesses normally when the market is unknown
  • names the right Article 87 sub-paragraph for each deadline
  • never cites 87(6) or 87(7), which are not the reporting deadlines
  • reads the product's markets first, then the organisation's
  • counts MDSAP, which includes the FDA as a participating regulator
  • is unknown when nothing is recorded, so the assessment stays conservative
  • counts down and goes negative once missed

regulatory-citations.test.ts:

  • pairs each EU deadline with the sub-paragraph that sets it
  • does not offer an EU deadline of 30 days anywhere
  • cites no MDCG 2022-21 for a PMS-plan section — that guidance is about the PSUR
  • does not invent a 30-day EU vigilance deadline
  • describes Article 88 trend reporting as triggered by a signal, not by the calendar
  • still names the deadlines it does give, correctly

reportability-determination.test.ts:

  • accepts a decision with a ground that belongs to it and reasoning of substance
  • refuses a ground borrowed from the other decision
  • refuses a ground that belongs to the other regime
  • refuses a shrug, and says what the ground wants answered
  • refuses an unknown regime, decision or ground rather than storing it
  • offers each regime a way to say yes and several ways to say no
  • gives every ground a clause and a prompt, so the form can explain itself
  • has a ground for triage answers entered in error, in both regimes
  • closes when nothing was reportable
  • refuses while a flagged report is unfiled, naming the way out
  • closes once the report is filed
  • closes on a determination that it is not reportable after all
  • is not satisfied by a determination that it IS reportable
  • checks both regimes, and the EU one first

reportability-determination.integration.test.ts (against a real database, as a signed-in user):

  • keeps the decision, the ground, the reasoning, the decider and the suggestion it was made against
  • refuses a shrug for reasoning, and refuses a ground from another regime
  • supersedes the previous determination for the regime and keeps it readable
  • will not un-file a report that has already been filed
  • holds one live determination per regime, per complaint
  • refuses closure while a flagged report is unfiled, and names the way out
  • closes once the determination stands the report down
  • refuses to clear a reportable flag by unticking a box, and points at the determination
  • allows the edit once a determination has stood the report down
  • still allows an edit that adds a flag
  • is given no FDA deadline, so its complaint is not held open by one

survey-intake.integration.test.ts (against a real database, as a signed-in user):

  • writes the answer, the feedback record and the audit entry together, linked
  • keeps the respondent's address out of the audit trail
  • refuses a second submission, an expired link and an unknown token, without half-writing
  • refuses a missing required answer before anything is written
  • has no silent catch on the writes
  • writes the three rows in one transaction

complaint-vocabulary.test.ts:

  • can say a post-market survey brought it
  • keeps the values the existing records already carry
  • separates the roles the regulation separates
  • keeps a distributor distinguishable from a user in the label, not only the code
  • gives every value a label, in both vocabularies
  • offers every country, not a shortlist
  • names them, and sorts by the name
  • names them in the reader's language where the platform has one
  • holds no OTHER, because that is not a country
  • accepts a real code in either case and refuses a made-up one

ticket-complaint.test.ts:

  • asks about the message that started all this
  • asks when triage called it a product problem
  • asks when triage raised the priority
  • asks on the customer's own words alone
  • does not ask about an ordinary question
  • reads only what the customer wrote, not what we replied
  • is when the customer's first message arrived
  • takes the earliest customer message, whatever order they are given in
  • falls back to when the ticket was opened if no customer wrote
  • carries the customer's own words, not a summary of them
  • says which ticket it came from
  • keeps only what the customer wrote
  • sets the awareness date to the day the message arrived
  • carries the contact details already recorded
  • maps how it reached us into the complaint module's words
  • guesses nothing that decides a reporting deadline
  • stays inside the field limits the intake form enforces
  • refuses an empty reason
  • refuses whitespace dressed up as a reason
  • accepts a reason that says something
  • asks for at least a sentence

trend-detection.test.ts:

  • puts the baseline immediately behind the current period, newest first
  • counts a boundary event once
  • raises one when the period stands well above a steady baseline
  • raises one when events appear where there were none
  • stays quiet below the floor of events the plan sets
  • stays quiet when the rise is within ordinary variation
  • refuses to compare against a baseline that predates the records
  • compares normally once the records cover the whole baseline
  • reaches a different answer under a stricter threshold
  • reaches a different answer under a longer observation period
  • ships defaults that are a starting point, not a rule
  • shows every number a reviewer would need to recompute it
  • states a signal and refuses to state a conclusion
  • does not invent a standard deviation it could not compute
  • does not raise again while one is still open
  • raises again once the open one has been dealt with
  • raises again when the last one is older than the observation period

What they do not cover — and so what your PQ must. The reportability decision itself — whether an event is a serious incident, whether a malfunction would be likely to cause harm if it recurred — is made by your vigilance officer on the facts. The platform computes the deadline from the flags you set, presumes reportability where the flags are ambiguous, and records the decision your officer makes against it, with the ground and the reasoning; it does not make that decision. The content of the manufacturer incident report and its submission to the competent authority or the FDA happen outside the platform. For trends, the platform detects a rise against the numbers you set and raises it; whether that increase could significantly change the benefit-risk determination — the question Article 88(1) actually asks — is your vigilance officer's to decide and record, as is whether to open a CAPA. Trending is over frequency only: severity trending would need a graded severity on every complaint, which the platform does not yet capture.


M-MR — Management review

Your obligation: ISO 13485 §5.6

What our tests establish. A review is conducted only from the planned state and closed only from the conducted state; it cannot be closed until the §5.6.3 outputs — improvement, resources, product — are recorded; a closed review can no longer be edited; only quality administrators may run one; each transition is on the trail.

management-review-gates.integration.test.ts (against a real database, as a signed-in user):

  • is not something an RA user can open
  • is planned, then conducted — and cannot be closed straight from planned
  • cannot be closed until the §5.6.3 outputs are recorded
  • is frozen once closed, and the trail shows each transition with its previous state

What they do not cover — and so what your PQ must. Whether the §5.6.2 inputs presented were complete and current, and whether the decisions taken were the right ones, is the review's own business. The platform assembles inputs from its records and holds the outputs; it does not assess them.


M-PMS — Post-market surveillance — proactive feedback

Your obligation: EU MDR Article 84 · EU MDR Annex III §1.1 · EU MDR Article 86 · EU MDR Article 87(1) · ISO 13485 §8.2.1

What our tests establish. A shipment becomes eligible for a feedback survey only after the delay its PMS plan sets, and only if it was recorded after the programme was switched on — enabling a programme does not survey the organisation's history. A shipment under recall or under review is never surveyed, and that check comes before every other; an address that has objected, hard-bounced or been erased is never written to; the same contact is not asked again inside the plan's interval; and a shipment with no usable feedback address is recorded as skipped with its reason rather than passed over in silence. The address is matched by a per-tenant salted hash, so the rule survives anonymisation and does not correlate a person across organisations. One reminder is sent, never two, and never after the link has expired. A send that was claimed and not confirmed is marked failed for a person, never re-sent by a machine. In the survey instrument the safety questions are required, carry no branching condition, and precede every satisfaction question; they ask about plain events rather than categories, and carry no Net Promoter question. Any answer other than "No" flags the response by rule at receipt, "I am not sure" exactly like "Yes", and confusing labelling that led to a mistake screens as a product problem because the instructions are part of the device. Every reason that applies is recorded, not only the most serious. The triage suggested to the complaint form is a malfunction and a harm and nothing else — never seriousness, never a public-health threat. The email itself names the manufacturer as controller and states the surveillance purpose, offers a way out in the RFC 8058 headers as well as the body, shows the survey link as an address and not only as a button, always gives a way to report a problem that does not depend on the link, and sells nothing — one promotional sentence would turn a surveillance message into marketing, which needs a consent nobody obtained. Its display name cannot be made to forge a second address. The opt-out token is a keyed hash of the tenant and the address hash: it cannot be forged, it identifies nobody who intercepts it, and it keeps working after the address itself has been erased, because the suppression list has to outlive the data it protects. A flagged response that nobody has determined escalates to the back-up reviewer at 24 hours and to the person responsible for regulatory compliance at 48, driven by the scheduled job rather than by somebody opening the queue, and never repeating a step it has already taken; something already two days old goes straight to the second step rather than climbing one a day. Escalation stops the moment a determination is recorded. A message the provider reports as permanently rejected, and a recipient who marks one as spam, both suppress the address by hash; a temporary failure — a full mailbox, a server down for an hour — never does, because suppressing on it would silently stop writing to a customer who never asked for that and cost the manufacturer a channel it is obliged to run. The periodic safety report carries what the programme did: what was surveyed, what came back, what was flagged, what became a complaint, and how quickly somebody looked — every rate stated with its denominator, and the shipments that were not surveyed reported with their reasons rather than hidden, since a response rate over the shipments that could be asked is not a response rate over the distribution. The plan's own paragraph describing the programme is generated from the settings that run it — the delay, the reminder, the expiry, the cap, the approval mode and the escalation chain — in roles rather than names, so a document and a scheduled job cannot drift apart and a plan does not name somebody who left. That paragraph always states that consignee answers are distributor and importer feedback and not user feedback, that awareness is receipt rather than reading, that shipments under recall are never surveyed and are contacted through the field safety process instead, and that every response ends in a recorded determination. The survey and its email exist in all 23 languages the application routes; no language is missing a string, no placeholder was lost in translation, the stored answer values are identical across languages so an answer given in Greek counts as the same answer as one given in English, the safety questions remain required and unconditional in every language, and none of them has drifted into the clinical register. A manufacturer may replace the wording of any question in any language and add up to three questions of its own; what it cannot do is remove a safety question, make one optional or conditional, move one after the satisfaction questions, change what an answer is stored as, or rewrite a safety question as a statement that gives the reader nothing to answer. Wording of its own is warned about, never refused, when it asks the reader to classify rather than to describe. Each language is edited separately, English is the fallback for any language left unwritten, and every change is recorded with the text before and after — on an active plan with a reason as well. Contact details of somebody surveyed are cleared once their cycle has closed, nobody still owes it a determination and the tenant's retention period has run, with a floor of one year that a lower setting cannot go under; what they said, the determination recorded about it and the audit trail are never scrubbed, because they are the quality record. Clearing the contact data changes nothing the periodic report says, which is asserted by summarising the same cycles either side of the scrub rather than assumed. An erasure request clears every copy of the name and address at once regardless of the clock, cancels anything queued to that address, records the objection as a hash so it goes on being honoured, and produces a reply stating what was removed, what was kept and under which exemption. The periodic report an active plan owes under EU MDR Article 86 is reminded about two months out, a fortnight out, on the day and weekly once late, counted from the date on the plan or — where none was set — a cadence after the plan was signed; a month-end due date does not roll into the following month; and approving the report moves the next due date on by a cadence, so a plan is never reminded about a report that has been filed. A customer who answers by replying to the email rather than clicking the link is matched to their own survey by the Message-Id we generated for it, not by a subject line or an address, and their reply becomes a response on that cycle with a review row like any other. Keywords in the recipient's language and in English can raise a flag on such a reply; nothing clears one — a reply with no keyword hit is put to a person, because the phrases 'nothing to report' and 'nothing worked' share a word and no list can establish the absence of a problem. A reviewer may flag a response the rules let through and may lift a flag the rules got wrong; both take a written reason and their author, both are recorded beside what the rules found rather than over it, and neither is possible once the response has been determined. Lifting a flag does not determine anything — it takes the response out of the queue and leaves it to the closure rule. A response that no rule and no reviewer flagged is closed after five working days by a versioned rule that records itself, so the promise of a determination on every response holds for the quiet ones too; a flagged response is never closed that way however long it waits, because that one escalates and is a person's to answer — the phrase "adverse event" and its equivalents are held out by test, because a question in that register collects fewer reports than one about plain events. The people who actually used a device are reached in one of two ways, and the difference is what the platform ends up holding. A forwardable link is issued once per shipment, travels inside the consignee's own survey email, and is answered by whoever it reaches: no name, no address and no identifier of a respondent is collected, and the database refuses to store one — a cycle that arrived through a link cannot carry a recipient name, a recipient address or a send time, and cannot be queued, sent or reminded, whatever code attempts it. The link expires, stops at a cap that is enforced as a constraint rather than a convention so two simultaneous answers cannot both pass it, is never issued for a shipment under recall, is refused at submission if a recall began after it went out, and can be withdrawn by the manufacturer with what it already collected left intact. Because no one is addressed, no response rate can be computed from it: those answers are counted on their own line of the periodic report, with the reason stated, and they never move the rate for the shipments that were addressed. Everything downstream is identical to an emailed answer — the same screening rules, the same review row, the same queue, the same awareness date at receipt — because the route an answer took must never change what happens when somebody reports harm. The alternative, holding contact details supplied on the shipment, cannot be switched on without a recorded attestation: five statements confirmed, a lawful basis written in the manufacturer's own words rather than chosen from a list, the person's name and role and the date, and the wording stored as displayed so that improving the screen later cannot change what was agreed. The database refuses that mode without it, and refuses a basis too short to be one. Patients are excluded by that attestation rather than by a check no schema could make, and the first message to a supplied contact carries what Article 14 requires, including which organisation provided the details. A programme that would ask nobody at all is refused.

pms-feedback-selection.test.ts:

  • is the same for the same address however it was typed
  • differs between tenants for the same address
  • rejects what is not an address
  • is the delay after it shipped, not before
  • ignores shipments from before the programme was switched on
  • never surveys a shipment under recall
  • never surveys a shipment under review either
  • checks the recall before anything else
  • does not write to an address that has objected, bounced or been erased
  • does not ask the same person again inside the cap
  • asks again once the cap has passed
  • honours a cap of zero as no cap at all
  • records a shipment with no usable address rather than passing over it
  • stops when the programme is paused
  • sends when nothing stands in the way
  • reminds once, after the interval the plan sets
  • never reminds twice
  • does not remind somebody to click a link that has already died
  • does not remind at all when the plan asks for no reminder
  • expires a link that was never answered
  • is picked up for a person to look at, not re-sent
  • leaves a send that is still in flight alone

pms-feedback-screen.test.ts:

  • never hides a safety question behind another answer
  • requires an answer to each of them
  • asks about safety before it asks about satisfaction
  • carries no Net Promoter question
  • asks about plain events, not categories
  • opens the detail and consent questions only when something is reported
  • lets a clean set of answers through
  • flags reported harm above everything else
  • flags a reported product problem
  • flags both together when both are reported
  • treats confusing labelling that led to a mistake as a product problem
  • routes 'I am not sure' to a person, exactly like a yes
  • keeps every reason, not only the most serious one
  • flags somebody who asked to be contacted, even with nothing else
  • flags a shipment that never arrived
  • survives a response with nothing in it
  • names every flag in words a reviewer can act on
  • suggests the two triage answers the survey can actually support
  • suggests nothing about seriousness or public health
  • suggests nothing at all from an unsure answer

pms-feedback-unsubscribe.test.ts:

  • verifies the one it produced
  • refuses a token for another address
  • refuses a token from another organisation
  • refuses a guess, whatever its length
  • does not contain the address it protects
  • names the controller and the purpose
  • offers a way out in the headers as well as the body
  • shows the link as an address, not only as a button
  • gives a way to report a problem that does not depend on the survey
  • says when the link stops working
  • sells nothing
  • identifies the shipment the recipient actually received
  • replies go somewhere a person reads
  • keeps the way out and the way to report

pms-feedback-escalation.test.ts:

  • leaves it alone inside the target
  • goes to the back-up at 24 hours
  • goes to the person responsible for regulatory compliance at 48
  • never repeats a step it has already taken
  • goes straight to the second step when it is already that late
  • stops once somebody has determined it
  • ignores a response that was never flagged
  • keeps the two thresholds a day apart
  • names the flag, the hours and the clock that is running
  • says awareness began when the answer arrived

pms-feedback-delivery.test.ts:

  • suppresses when the address rejected it for good
  • does not suppress a temporary failure
  • treats an unrecognised bounce type as temporary
  • treats a bounce with no type at all as temporary
  • suppresses at once
  • records a delivery
  • leaves a delayed message alone
  • ignores an event about nothing

pms-feedback-psur.test.ts:

  • counts anything that went out as sent, answered or not
  • states the rate over what was actually asked
  • reports the skips with their reasons rather than hiding them
  • says plainly when the rate does not describe the whole distribution
  • gives no rate at all when nothing was sent
  • separates what became a complaint from what did not
  • does not count a clean response as awaiting a determination
  • measures how quickly the organisation looked
  • says so plainly when nothing was reported
  • never move the response rate
  • are counted on their own line, with the reason there is no rate
  • are not counted among the shipments considered for a survey
  • say nothing at all when none arrived
  • treat a row with no origin as an ordinary addressed send
  • are reviewed exactly like an emailed one

pms-feedback-plan-text.test.ts:

  • states the delay, the reminder, the expiry and the cap as configured
  • says so when no reminder is configured
  • says so when there is no frequency cap
  • describes the approval mode that is actually in force
  • refuses to call consignee feedback user feedback
  • states that awareness is receipt, not reading
  • states the recall exclusion and where those customers are contacted instead
  • states that the skips are reported with the response rate
  • states the escalation chain and the review target
  • promises a determination on every response, not only the flagged ones
  • uses roles rather than names
  • falls back to a role that always exists when nobody is named
  • describes the link, and that nothing about a user is collected
  • says answers through a link are counted and never rated
  • keeps the recall exclusion, which applies to a link as much as an email
  • states the Article 14 duty and the basis when addresses are held
  • says patients are not contacted
  • does not claim a consignee was surveyed when none was
  • still names the consignee's answers as economic-operator feedback when it does ask them
  • connects the two sections so they read as one process

pms-feedback-gates.integration.test.ts (against a real database, as a signed-in user):

  • refuses a second cycle for the same shipment, audience and person
  • allows a cycle for a different address on the same shipment
  • refuses a skip with no reason
  • refuses a survey that claims to have been sent with no send time or link
  • refuses a determination of not-a-complaint with no rationale
  • refuses a determination of complaint with no complaint to point at
  • refuses a rationale too short to be a reason
  • records the determination with its reason, its author and the moment
  • will not determine the same response twice
  • takes its awareness date from when the answer arrived, not from today
  • carries the shipment across so nobody retypes it
  • quotes the respondent's own words rather than a summary of them
  • takes the triage the answers actually support
  • suggests nothing about seriousness or public health
  • links the feedback to the complaint in both directions
  • puts the raising on the audit trail with where it came from
  • is stored without a send time, which an addressed one could not be
  • cannot be given an address, however it is written
  • cannot be queued, sent, or reminded
  • still cannot be answered without the distribution holding the answers
  • stops accepting answers at its cap
  • is issued once per shipment
  • refuses a programme that holds end-user addresses with no attestation
  • refuses a programme that asks nobody at all

pms-feedback-i18n.test.ts:

  • carries every language the application routes
  • leaves no string missing in any language
  • keeps every placeholder the English has
  • does not leave an untranslated language silently blank
  • asks about plain events, not clinical categories
  • offers an unsure answer distinct from yes and no in every language
  • keeps the line that comes before the survey's own interests
  • translates the questions while keeping their ids
  • keeps the stored answer values identical across languages
  • still requires the safety questions in every language
  • prefers what the shipment recorded
  • falls to the consignee's country
  • then to the organisation's own language, then to English
  • reports whether the wording has been reviewed by a speaker
  • replaces what it knows and leaves what it does not
  • handles a translation that moved the placeholders around

pms-feedback-customisation.test.ts:

  • replaces a question with the tenant's own words
  • keeps each language's wording separate
  • falls back to the platform's wording where the tenant wrote none
  • treats an emptied field as reverting to the platform's wording
  • refuses wording for a question that does not exist
  • refuses to let a safety question stop being a question
  • allows a reworded safety question that is still a question
  • refuses wording longer than the field can carry
  • cannot change what an answer is stored as
  • cannot make a safety question optional or conditional
  • appends them after the fixed set
  • never makes one required
  • shows them in the reader's language, falling back to English
  • caps how many there can be
  • needs English as the fallback every language can reach
  • needs at least two answers when it is a choice
  • keeps their ids out of the fixed set's namespace
  • warns when a safety question asks the reader to classify
  • warns in the language the wording was written in
  • says nothing about wording that describes an event
  • ignores anything that is not wording
  • ignores a stored question that could shadow a fixed one
  • never reads back more than the cap

pms-feedback-retention.test.ts:

  • clears it once the period has run
  • leaves it while the period is still running
  • leaves a cycle that has not closed
  • leaves a response still awaiting a determination, however old
  • does not clear twice
  • has nothing to clear when no address was ever held
  • will not go below a year, whatever is configured
  • honours a longer period
  • defaults to a year when nothing is configured
  • applies the floor to the decision, not only to the number
  • produces the same figures before and after the scrub
  • reads no field that the scrub clears
  • says what was removed
  • says what was cancelled
  • says what was kept and under which exemption
  • says the complaint keeps its contact details, and why
  • explains the fingerprint that has to stay
  • leaves out the complaint paragraph when there is no complaint

pms-report-due.test.ts:

  • uses the date on the plan
  • counts from the signature when no date was set
  • has no clock for a plan nobody signed
  • does not roll a month-end into the next month
  • advances a cadence from the period that was approved
  • says nothing two months and a day out
  • speaks up two months out, when there is still time to gather the data
  • speaks up again a fortnight out
  • speaks on the day
  • keeps speaking once it is late, with the count
  • does not repeat a milestone it has already given
  • repeats weekly once it is late, and not more often
  • says nothing about a plan that is not active
  • says nothing when there is no clock to run
  • names the device and the date
  • calls a two-yearly report biennial
  • says what a missing report means at audit
  • says why two months is the moment to start

pms-feedback-reply.test.ts:

  • picks up the id we generated, from either header
  • puts the message being answered first
  • ignores somebody else's thread
  • flags a reply that reports somebody hurt
  • flags a reply that reports something broken
  • flags both when both are described
  • reads the recipient's language and English together
  • does not clear a reply just because no keyword matched
  • reads every language the survey goes out in
  • still puts a pleasant reply in front of a person, in any language
  • does not clear an empty reply
  • keeps what the customer actually wrote

pms-feedback-closure.test.ts:

  • puts a rule-flagged response in front of a person
  • leaves a clean one out of it
  • lets a reviewer put one in that the rules let through
  • lets a reviewer take out one the rules got wrong
  • skips the weekend
  • counts nothing across a weekend alone
  • counts nothing backwards or for the same day
  • closes it after five working days
  • leaves it alone before then
  • never closes a flagged response, however long it waits
  • never closes one a reviewer flagged by hand
  • closes one whose flag a reviewer removed
  • does not determine the same response twice
  • stamps the rule's version on what it closed
  • asks for a reason worth reading
  • accepts one that says something

pms-feedback-end-users.test.ts:

  • is usable while it is live, unspent and unrevoked
  • stops at the cap
  • stops when it expires
  • says revoked rather than expired when both are true
  • lives longer than the personal link it travels with
  • mints a token nobody is going to guess
  • is keyed by an opaque value, one per answer
  • does not collide with a real recipient's hash
  • carries no name and no address
  • is refused if anybody tries to put an address on it
  • was never sent, so it cannot claim a send time
  • is born answered
  • leaves an ordinary emailed cycle alone
  • reads the mode
  • treats anything it does not recognise as reaching nobody
  • accepts a complete one
  • refuses until every statement is confirmed
  • refuses a basis too short to be one
  • reports every problem at once rather than one at a time
  • is recorded against a person
  • contains every statement, so the stored record is the whole undertaking
  • leaves our commentary out
  • says patients are excluded, in the statement rather than a footnote
  • is versioned, so a reworded screen does not rewrite what was agreed
  • names who supplied the details
  • names the manufacturer, states the purpose, and offers the way out

sending-domain.test.ts:

  • is read as the domain they meant
  • accepts a subdomain
  • refuses the root domain, and says what to use instead
  • counts a multi-part public suffix as the root it is
  • refuses our own domain, since that is what it already uses
  • refuses what is not a domain, without saying merely 'invalid'
  • stays on ours until theirs is verified
  • moves to theirs once it is
  • drops the 'via' only when the domain itself says who sent it
  • cannot be made to forge a second address
  • falls back to a name when the manufacturer has not set one
  • stays on ours when the status says verified but no domain was stored
  • is read into our own vocabulary
  • does not read a temporary failure as a failure
  • treats a part-way domain as not ready, in either direction
  • keeps a verified domain verified through a check that did not complete
  • keeps what a DNS entry needs and drops the rest
  • drops anything incomplete rather than rendering a half record
  • survives a provider that returns nothing at all
  • is read out of either form somebody configured
  • never nests one header inside another
  • uses what the deployment configured rather than a hardcoded domain
  • is ignored once the tenant has a domain of their own

What they do not cover — and so what your PQ must. Whether a response is a complaint is decided by your reviewer and recorded with a rationale; the platform flags and refuses to close a determination without one, but it does not decide. The delay, reminder, validity and frequency numbers are the plan's, as EU MDR Article 88(2) and Annex III intend, and choosing them is your judgement about your device. Deliverability is not something the platform can promise. Mail goes out from the platform's own domain by default, whose reputation is the operator's responsibility; a manufacturer may instead send from a subdomain of their own, and from that point its reputation, its DNS records and anything that damages them are theirs. The platform refuses a root domain, keeps sending from its own until the records verify, and will not move mail onto a part-verified domain — but whether a given mailbox accepts a message is the recipient's provider's decision, and no configuration here makes it otherwise. Consignee answers are distributor, importer or procurement feedback and must never be presented as user feedback; that distinction is stated in the generated plan paragraph and is not one the platform can enforce for you. Where end users are reached by a forwarded link, the platform cannot know who answered, cannot tell whether one person answered twice, and cannot say how many people the link reached — so it reports those answers as a count and refuses to state a rate, and any statement in your own documents about user coverage is yours to justify. Whether the people you reach that way are the people who used the device depends on the consignee forwarding it, which is outside the platform entirely. Where you instead record end-user contact details, whether you may hold them is your determination: the platform captures the attestation, the lawful basis you state and who made it, and refuses the mode without them, but it does not assess the basis, cannot detect a patient behind an address, and does not carry out your balancing test or impact assessment. Keeping that list accurate, and passing objections into the platform so they are honoured, is the undertaking you sign. The survey and its email exist in all 23 languages the application routes, but Danish was reviewed by the operator on 2026-09-09 — the safety questions and their answers, and again for the wording the forwarded link added — and is marked as such; the remaining 21 non-English translations were produced by the platform's author and have NOT been reviewed by a speaker — the operator decided to ship them on that basis on 2026-09-08. What can be checked mechanically is checked by test: no missing string, no lost placeholder, identical stored answer values, the safety questions still required and unconditional, and no drift into the clinical register. What cannot be checked that way is whether the safety questions read plainly in each language rather than sounding clinical or accusatory, and that is a judgement only a speaker can make. Every send records which language it went out in and whether that wording had been reviewed, so the gap sits on the record rather than being assumed away; a language moves into the reviewed list in one line once somebody has checked it. The same caveat covers the word lists that read an emailed reply: they are the author's, unchecked by speakers, and their failure mode is one-sided by design — a missing word means the reply is put to a person rather than cleared.


M-SVC — Servicing — analysed for complaints

Your obligation: ISO 13485 §7.5.4 · ISO 13485 §8.2.2 · FDA QMSR §820.10 · EU MDR Article 87(1)

What our tests establish. Every servicing record is analysed for a complaint when it is created, and every record ends in one of three recorded states — raised as a complaint, determined not to be one, or owing that determination and listed as owing it. The distinction the analysis turns on is not whether a repair happened but whether somebody told the manufacturer something was wrong: scheduled maintenance with nothing reported is not a complaint, and the same visit made because a customer reported a fault is, because the customer's report is the communication ISO 13485 §8.2.2 describes and the visit is only how its meaning was established. Corrective servicing, a customer report recorded against the visit, and words in the engineer's own narrative describing the device not performing are three independent signals, any one of which puts the record to a person; every reason that applied is recorded rather than the strongest one. Wording that describes somebody being hurt or nearly hurt is flagged as harm and can never be closed by rule, whatever category the service was logged under, because the reporting clock is already running by the time an engineer writes it down — the database refuses that combination rather than trusting the application to remember it. The screening rule may close only the quiet case, and records its own version on the row it closed, so a decision taken by machine can be explained years later by the rule that took it. A person deciding a service was not a complaint gives a written reason of at least twenty characters and is named; a record said to be a complaint names the complaint it became; a determination without a moment or without an author cannot be stored at all. The awareness date is held in its own column and is the day the customer reported the problem, not the day the engineer arrived and not the day the paperwork was filed — EU MDR Article 87(1) and 21 CFR §803.50 run from awareness, and where no report date was recorded the complaint form says the date was inferred rather than presenting the service date as though somebody had checked it. The complaint raised from a servicing record carries the engineer's own words, the device's serial or lot, and that awareness date, and leaves the malfunction, harm and complainant-type answers blank, because those three set the reporting deadlines.

servicing-complaint.test.ts:

  • is not a complaint, and the rules may say so themselves
  • still records why it reached that conclusion
  • covers the other planned activities too
  • is presumed a complaint when the service was corrective
  • is presumed a complaint when the customer reported it, whatever the category says
  • reads the engineer's plain words, not a clinical vocabulary
  • gives every reason that applies, not the strongest one
  • is flagged as harm and never closed by rule
  • outranks the servicing category it was logged under
  • says harm rather than merely deficiency when both appear
  • catches a near miss, which matters as much as an injury
  • is when the customer reported it, not when the engineer arrived
  • falls back to the service date, and says that it did
  • carries the engineer's own words and the device it was about
  • carries the awareness date the customer's report sets
  • leaves malfunction, harm and complainant type to the person filling it in
  • marks an inferred awareness date so the reviewer can correct it
  • takes a sentence, not a word
  • names the clause an auditor will ask about

servicing-gates.integration.test.ts (against a real database, as a signed-in user):

  • starts as owing one — never as an answer nobody gave
  • is a moment when it is made, and nothing when it is not
  • has an author — a person, or the rule that made it
  • takes a written reason from a person who says it is not a complaint
  • lets the screening rule close the quiet case, under its own version
  • names the complaint when it says there is one
  • is never closed by a rule
  • can still be determined by a person, with their reason
  • comes from a vocabulary rather than free text
  • keeps 'nobody asked' distinct from 'they said no'
  • is stored apart from the service date, and can precede it

What they do not cover — and so what your PQ must. Whether a serviced device's record is a complaint is your determination; the platform screens, refuses to leave the question unanswered, and refuses a determination without a reason and an author, but it does not decide. The word lists that read an engineer's narrative are English, and they are a net rather than a classifier: a record whose wording they do not match still reaches a person as PENDING, so their failure mode is a needless prompt rather than a missed complaint, but a service report written in another language will not be screened by them. Whether the report date entered against a visit is the date the customer actually told you is a matter of your own records — the platform stores what is entered and says when nothing was, and cannot detect a date that is simply wrong. Servicing records created before this analysis existed are listed as owing a determination rather than being decided retrospectively; working through them is yours. The platform does not schedule servicing, does not track engineer competence or the calibration state of their tools, and does not verify that the work described was actually performed.


M-SUP — Supplier control

Your obligation: ISO 13485 §7.4.1 · ISO 13485 §7.4.2

What our tests establish. A supplier code is unique in your organisation; qualification moves through pending, under review, approved, conditional and disqualified; approval stamps the date; a status the register does not have is refused; every change is on the trail with the previous status; an auditor can read the register but not change it.

supplier-gates.integration.test.ts (against a real database, as a signed-in user):

  • refuses a second supplier with the same code
  • starts unqualified
  • is approved with a dated stamp, and the trail records the previous status
  • can be disqualified, and the register says so
  • rejects a status the register does not have
  • is not something an auditor can change

What they do not cover — and so what your PQ must. Your evaluation criteria, the supplier audits and questionnaires behind a status, quality agreements and their content, and the re-evaluation interval are yours. The platform records the outcome of your evaluation; it does not perform it.


M-TRN — Training and competence

Your obligation: ISO 13485 §6.2

What our tests establish. Training is assigned to a named person for a named topic; the trainee completes it, and a colleague of ordinary rights cannot complete it for them; it cannot be verified before completion; the verifier must be a different person from the trainee, by identity rather than by role; the record says who verified and when.

training-gates.integration.test.ts (against a real database, as a signed-in user):

  • assigns training to a named person for a named topic
  • cannot be verified before it is completed
  • is completed by the trainee, not by a colleague of ordinary rights
  • is verified by someone other than the trainee, and the record says who and when

What they do not cover — and so what your PQ must. Whether the person is competent — the assessment behind the verification — and the content and effectiveness of the training are yours. The platform records that training was assigned, completed and verified by separate people; it does not examine anyone.


M-EQP — Equipment and calibration

Your obligation: ISO 13485 §7.6 · ISO 13485 §6.3

What our tests establish. An asset code is unique; a status change is recorded with its reason and previous state; only quality or manufacturing roles may record a calibration certificate; a certificate's due date must fall after the date performed; recording one moves the equipment's next-due date; only quality administrators may delete a certificate.

equipment-gates.integration.test.ts (against a real database, as a signed-in user):

  • refuses a second asset with the same code
  • records a status change with its reason and the previous state
  • is not something an auditor can change

calibration-gates.integration.test.ts (against a real database, as a signed-in user):

  • refuses a certificate from a role that is not QA Admin or Manufacturing
  • refuses a due date that is not after the performed date
  • records a certificate from Manufacturing and moves the equipment's next-due date
  • refuses to let anyone but QA Admin delete a certificate

What they do not cover — and so what your PQ must. The validity of a certificate, its traceability to national standards, and the impact assessment when an instrument is found out of tolerance are yours. The platform keeps the dates and the documents; it does not calibrate anything.


M-SW — Software lifecycle (IEC 62304)

Your obligation: IEC 62304 §9

What our tests establish. A problem report is numbered against its software item; it cannot be closed until a root cause and a resolution are recorded and verified; an engineer can report and resolve but not close; the trail shows the path.

software-gates.integration.test.ts (against a real database, as a signed-in user):

  • an engineer reports a problem, and it is numbered against its item
  • cannot be closed before a resolution is recorded and verified
  • is resolved with a root cause and a resolution, which marks it verified
  • is closed only by someone with approval rights, and the trail shows the path

What they do not cover — and so what your PQ must. Only problem resolution (§9) is covered. Safety classification, the development and maintenance processes (§5–§8), SOUP evaluation and verification are the software team's, and the platform's records of them are not tested here.


M-USE — Usability engineering (IEC 62366-1)

Your obligation: IEC 62366-1 §5.9

What our tests establish. A usability file cannot be approved until the summative evaluation is completed and the residual risk is marked acceptable with a recorded rationale.

lifecycle-gates.test.ts › IEC 62366-1 UsabilityFile approval gate:

  • approves when all conditions met
  • blocks approval when summative not completed
  • blocks approval when residual risk not marked acceptable
  • blocks approval when residual rationale missing

What they do not cover — and so what your PQ must. The evaluation itself — its protocol, participants and findings — is yours. The gate checks that it was recorded as done and concluded; it cannot check that it was done well.


M-PE — Performance evaluation (IVDR)

Your obligation: EU IVDR Annex XIII

What our tests establish. A performance evaluation report cannot be approved until each pillar — scientific validity, analytical performance, clinical performance — carries a recorded conclusion, together with the benefit-risk assessment and an overall conclusion; the approver must differ from the plan approver.

lifecycle-gates.test.ts › IVDR PerformanceEvaluation report approval gate:

  • approves a complete PER from a different approver
  • rejects approval from a state other than REPORT_DRAFT
  • requires all three pillar conclusions
  • requires benefit-risk + overall conclusion
  • requires a PER document reference
  • enforces segregation of duties between plan and report approver

What they do not cover — and so what your PQ must. The scientific content of each pillar is yours. The platform holds the structure and enforces that nothing is left blank before approval.


M-VAL — Process and software validation runs

Your obligation: ISO 13485 §7.5.6 · ISO 13485 §4.1.6

What our tests establish. A validation run must have a recorded result before approval; the approver must differ from the executor; a software validation cannot pass with deliverables outstanding but may fail at any point; a run that names an older platform version is reported as drifted, one that names no version as unknown rather than stale; and drift raises a task for your administrators once per version.

software-validation.test.ts:

  • are T1 through T5, in the order they have to be done
  • start out none done
  • survives null, which is what a run from before this feature holds
  • survives values that are not step state at all
  • keeps what was stored
  • drops a deliverable the pack no longer has
  • defaults a deliverable the pack has gained, rather than stranding the run
  • treats a truthy-but-not-true done as not done
  • is false while any is outstanding
  • is true only when all five are done
  • is false for a run with no step state, not vacuously true
  • says nothing while the run is still open
  • flags a concluded run pinned to an older version
  • does not flag a concluded run pinned to the current version
  • does not claim drift for a run that never named a version
  • flags a passed-but-not-yet-closed run too
  • counts planned and in-progress, and nothing else

lifecycle-gates.test.ts › Validation run closure gate:

  • closes a PASSED run that's been approved
  • blocks a FAILED run without a linked CAPA
  • allows a FAILED run with a linked CAPA
  • blocks any run that hasn't been approved

revalidation-drift.test.ts:

  • raises for a tenant whose latest concluded run names an older version
  • is silent when the validated version is the current one
  • does not claim drift for a run that never named a version
  • ignores equipment and process validations
  • lets the latest concluded run speak for the tenant
  • stays quiet for a tenant already revalidating against the current version
  • does not treat a FAILED run as a validation to measure drift from
  • keys the task to the current version, so a daily run raises it once
  • handles several tenants independently

What they do not cover — and so what your PQ must. Your protocols' content and acceptance criteria are yours — the platform is the record of the run, not its author. The IQ, this OQ and the PQ are our validation of the platform; a process you validate in it (a steriliser, a line) is validated by your protocol.


M-SUB — Regulatory submissions

Your obligation: EU MDR Annex II · EU MDR Annex III · 21 CFR 807 (510(k))

What our tests establish. Evidence is pinned to a named section of a submission and records what it points at; external evidence with neither a title nor a URL is refused; a pin can be removed and the removal is on the trail; a role without document rights cannot pin.

submission-gates.integration.test.ts (against a real database, as a signed-in user):

  • refuses external evidence with neither a title nor a URL
  • pins external evidence to a section and records what it points at
  • is not something an auditor can pin
  • removes a pin, and the removal is on the trail

What they do not cover — and so what your PQ must. Whether the dossier is complete and whether the regulator accepts it are questions the platform cannot answer. The completeness gauge counts sections with evidence; it does not read the evidence.


M-TRACE — Traceability of units leaving the building

Your obligation: EU MDR Article 27(4) · EU MDR Article 20(5) · EU MDR Annex I §23.2(e) · EU MDR Annex I §23.4(d) · ISO 13485 §7.4.3 · ISO 13485 §7.5.9 · 21 CFR §801.109

What our tests establish. A label for a device that is implantable, supplied sterile or single-use cannot be issued without a lot or a serial number, so the printed carrier holds a production identifier and not only a device identifier; a template proof is the one exception and is marked as not for shipment. Dates are refused where the expiry is not after the manufacture date, where the manufacture date is in the future, or where the expiry has already passed, at label issuance and at goods receipt alike. A Class IIa or above device sold in the EU cannot be labelled without its notified body's number beside the CE marking, and the printed label carries the UDI-DI under the UDI symbol, never the Basic UDI-DI. A shipment cannot be recorded without a linked production batch or a lot or serial number. Where the shipment's lot cannot be deducted from inventory, the reason is recorded on the audit trail and shown to the person who shipped, rather than passing silently. Material received from a supplier who is not approved is quarantined whatever the location's default, and new locations default to quarantine. The product identifier is normalised to fourteen digits in one place, so production and labelling cannot stamp different identifiers on the same device.

traceability-rules.test.ts:

  • an implantable does
  • anything supplied sterile does
  • a single-use device does
  • a reusable, non-sterile, non-implantable device does not
  • refuses a sterile implantable with no lot and no serial
  • accepts it with a lot
  • accepts it with a serial and no lot
  • treats whitespace as no identifier at all
  • allows a template proof with no identifier — it is not for shipment
  • does not require an identifier for a plain reusable device
  • refuses an expiry before the manufacture date
  • refuses a manufacture date in the future
  • refuses an expiry that has already passed
  • allows a reprint of a label whose stock has expired
  • says nothing about dates that were not entered
  • refuses the receipt the tester made: manufactured Aug 2026, expiring Jan 2026
  • refuses equal dates — a device that expires the moment it is made
  • refuses the shipment the tester made: no batch, no lot, no serial
  • accepts a shipment with the batch linked
  • accepts a lot without a batch — some shipments are not made in-house
  • requires an identifier even for a device with no special characteristics
  • refuses a Class IIb EU label with no notified-body number
  • allows Class I, which is self-declared
  • allows a US-only label — the CE mark is not printed there
  • applies to a MULTI-market label, which carries the CE mark
  • allows it once the number is there
  • says nothing about a product that has not been classified yet
  • is printed only when the device is prescription-only
  • is not printed on an EU-only label
  • pads a 13-digit code to 14, as Application Identifier (01) requires
  • leaves a 14-digit code alone, so both modules agree
  • ignores separators a person may type

recall-chain.integration.test.ts (against a real database, as a signed-in user):

  • refuses the shipment the tester made — no batch, no lot, no serial
  • accepts it with the batch linked, and the record carries the identifier
  • records why stock was not deducted, rather than saying nothing
  • quarantines material from a supplier who is not approved, even in a cleared location
  • says in the audit trail why it was quarantined
  • refuses a lot that expires before it was made

What they do not cover — and so what your PQ must. Whether the lot number entered is the lot that physically left, and whether the device characteristics recorded on the template match the device, are yours. The platform refuses a shipment that carries no identifier; it cannot tell a correct identifier from a plausible one. The two-dimensional DataMatrix carrier is not yet rendered for production printing, and the interface says so.


M-PROD — Product register and market release

Your obligation: EU MDR Article 19 · EU MDR Article 27 · EU MDR Annex IV · ISO 13485 §7.5.9

What our tests establish. A UDI-DI is unique within the organisation and, for a GS1 identifier, has a valid check digit; a product cannot take a sibling's UDI-DI. A device cannot be set ON MARKET without an approved or effective Declaration of Conformity on the product or its family, under any market's declaration type, unless a written justification is recorded; PRE MARKET is not gated. Every stage change is on the audit trail with the actor, the previous stage and the justification.

product-udi.integration.test.ts (against a real database, as a signed-in user):

  • refuses a new product whose UDI-DI another product in the organisation already carries, naming it
  • refuses editing a product's UDI-DI to a sibling's value
  • lets a product keep its own UDI-DI on edit
  • refuses an invalid GS1 check digit and says what it should be
  • accepts a valid new GTIN, one held by another organisation, and an HIBCC identifier

product-release-gates.integration.test.ts (against a real database, as a signed-in user):

  • PRE_MARKET is not gated: conformity assessment happens before the declaration exists
  • ON_MARKET with no declaration and no justification is refused, and nothing changes
  • a declaration still in draft does not count
  • a justification of substance releases the device, and the reason and the actor are on the trail
  • 'ok' is not a justification
  • an approved declaration on the product releases it without a justification
  • an effective declaration on the family covers every member (MDCG 2020-16 §5: the dossier is the family's)
  • a market-specific declaration counts too

What they do not cover — and so what your PQ must. Whether the declaration is correct, signed by the right person and covers the device as configured is yours. The justification path exists because release may be controlled under your own procedure; the platform records that you said so, it does not check it. Devices brought in by bulk import are recorded at the stage you give them, not gated.



QMSN-MEA-001 · v1.5.0 · pack rev. J (2026-09-07)
Published at qmsnordic.com/legal/validation/module-evidence. Cite the version above in your validation record — a pack is evidence, and evidence has to stay retrievable at the version you validated against.

© 2026 Aitech International ApS · Denmark · All rights reserved.QMS Nordic™ is owned, developed, and copyright-protected by Aitech International ApS.
PrivacyTermsSecuritySub-processorsAI ActValidationHome