Release register
What changed in each release, which modules it touches, and our assessment of whether a controlled function was affected — so you can risk-assess a release against the state you qualified.
The classification on each change is our assessment of what we changed. It is an input to your decision, never a substitute for it. We do not know what you qualified, what your intended use is, or how you scoped your performance qualification — so nothing here is a statement that your system remains validated. That conclusion is your quality function's to reach.
- Re-qualification recommendedA control changed — an electronic signature, a lifecycle rule, an access restriction, record retention, or how records are handled. Re-executing the affected part of your performance qualification is the conservative course.
- Review against your intended useThe behaviour of a controlled function changed. Check whether the change falls inside the intended use you validated, and whether your performance qualification still covers it.
- No controlled function changedThis change did not alter a function that operates under your quality system — presentation, internal structure, performance, or content. It is not a statement that you need take no action; that remains your assessment.
Three more separation-of-duties checks — complaint closure, NCR closure and audit closure — now refuse to proceed when they cannot be performed. This is the same correction published yesterday for risk, change control and design validation, and it means yesterday's entry understated which modules were affected. If you acted on that entry, please re-read this one: the review it recommended needs to cover three further record types. Separately, the validation package no longer claims 21 CFR 211 (drug GMP) within the scope it validates — no requirement was ever traced against it. If you hold a copy taken before today, replace it.
Closing a complaint, closing an NCR and closing an internal audit each look up who signed the previous step, so that the same person cannot sign both. If that look-up FAILED — a momentary database problem rather than a normal result — the check was skipped and the signature was allowed. All three now stop and say the check could not be performed. ⚠️⚠️ This is the identical defect corrected yesterday in risk assessments, change controls and design validations, and yesterday's register entry told you those were the only three affected. That was wrong. Six checks had the fault, not three. ⚠️ The everyday behaviour is unchanged in all three: where the look-up works, exactly the same people are allowed and refused as before. Only the failure path changed. Specifically: the investigator of a complaint still cannot sign its closure; whoever approved an NCR disposition still cannot close the NCR; whoever issued an audit report still cannot close the audit.
Why this classification: Classified “review” for the same reason as yesterday's correction: a controlled function changed behaviour in a failure mode rather than in normal use, and no record, signature or audit entry was altered, with nothing changed about access or storage. ⚠️⚠️ The reason to look rather than file this away, and the reason to look AGAIN if you already looked yesterday: for the period before this release it was possible, though it required a database read to fail at the exact moment of signing, for one person to sign both sides of these separations too. Indelio cannot tell you whether that happened on your instance, because the skipped check left no trace. If you performed the review recommended yesterday, it covered risk assessments, change controls and design validations only — extend it to complaints, NCRs and internal audits, checking the signature history for cases where the same person signed both steps. Every signature is in your audit trail and in your records export, so this remains answerable from your own data without our help. ⭐⭐ The distinction worth recording for anyone maintaining a qualified state is about how the first three were found and why the second three were not. The check that found them derives its own scope from an internal register naming, per module, the guard that enforces each published claim. For these three modules that register named the ROLE requirement (closure needs a quality or approver role) and not the identity check sitting beside it, so all three fell outside what was examined — while the automated check reported itself as covering the area. The register now grades each entry against the code it points at, and refuses an entry that records the weaker of two controls. ⚠️ Stated plainly because it bears on how much weight to place on our automated evidence generally: the check was correct and its scope was wrong, and a scope error of that kind reports as a pass. Needs no database change and no action on any existing instance beyond the review above.
copy-claims.test.tsThe validation package no longer states that 21 CFR 211 (drug GMP) is within the scope it validates. The Validation Plan, the User Requirements Specification and the Part 11 Validation Summary each opened by naming Part 11, 21 CFR 820 (QMSR / ISO 13485) and 21 CFR 211 as the regulations the system is qualified against. Part 211 did not belong in that list: none of the 65 requirements in the URS is written or traced against it, and the one record type that is specific to drug GMP — batch records / device history records — is already marked out of scope in the module coverage map. All three documents now name Part 11 and 820/QMSR only, and each states explicitly that drug GMP and EU Annex 11 are outside the package. ⚠️ Individual Part 211 section numbers still appear elsewhere in the product — §211.198 beside ISO 13485 §8.2.2 on complaints, for example. Those are unchanged and are correct: they name the drug-side analogue of a device requirement the system does implement, so a reader can orient themselves. They were never a claim of validated scope, and the plan now says so in as many words. ⚠️⚠️ A SECOND CORRECTION IN THE SAME DOCUMENT, AND THE MORE SERIOUS OF THE TWO: the Part 11 traceability matrix (§11.10(g), authority checks) listed “plan-approver ≠ closer” among the segregation-of-duties rules enforced for CAPA. That rule was REMOVED in July 2026 on independent validation-review advice — it is not required by regulation and can block closure outright in a small QA team — and this document went on describing it for six weeks afterwards. CAPA closure is restricted to the QA role, and QA independence is what carries that clause. The row now lists the separations actually enforced, module by module, with a note recording what was removed and why rather than deleting the claim quietly. It also now distinguishes which separations are enforced by IDENTITY and which by ROLE, since a role check is satisfied by one person holding both roles and a reviewer needs to know which kind each module has.
Why this classification: Classified “review” although no software behaviour changed at all, because the document that changed is the one a customer uses to decide what our evidence covers, and it previously claimed more than it delivered. ⚠️⚠️ If you hold a copy of the validation package taken before today, its scope statement is wrong in a way that matters: it names a regulation against which nothing was ever tested. If you cited that scope statement in your own validation file, in a supplier assessment, or to an auditor, replace it with the current version — take a fresh copy from the Validation page. ⚠️ Nothing you validated has become less true; the qualification evidence itself is unchanged, and the Part 11 and 820/QMSR coverage it describes is exactly what it always was. What was removed was a claim to a THIRD regulation that no requirement backed. ⭐ Recorded here rather than treated as a documentation tidy-up because it is the same failure this register described earlier today in the software: an asserted scope with nothing behind it, where the assertion reads as evidence to anyone who does not go looking for the trace. A pharmaceutical manufacturer intending to qualify Indelio for a Part 211 use case would need to establish that scope themselves; we do not and did not.
validation-doc.test.tsAn exported copy of your quality system now contains the uploaded files themselves, not only a list of them, and the export now checks your stored files against the records that refer to them. Separately, that list was incomplete: it named evidence attached to records, but not your uploaded controlled documents or your migration source files. Any export taken before this release understates how many files your organization holds.
When you export your organization's records, the archive contains a file called files-index.csv that lists every uploaded file — its name, size, storage location and the record it belongs to. That list covered only ONE of the three places this system stores a file. Evidence attached to a quality record was listed. Your uploaded controlled documents — the ones you attached a PDF or Word file to, which for most organizations means your SOPs themselves — were NOT listed, and neither were the source files staged by a bulk migration. Measured on the live system before the correction, the index named 3 of the 79 files actually held. ⚠️ The archive also stated, in both its README and its manifest, that the index named "every uploaded file", and reported the export as complete. So the shortfall was not visible from inside the export: an incomplete list was indistinguishable from a complete one, which is the specific failure this export was designed to prevent. The index now covers all three sources and carries a `source` column naming which one each file came from; if any source cannot be read, the archive names it as failed per source and reports the export as incomplete, rather than omitting those files silently. The file contents themselves are still not included in the archive — that is unchanged, and stated plainly rather than implied.
Why this classification: Classified “requalify” rather than “review” because the correction is retrospective: an export you already took and filed is inaccurate, not merely different from what you would get today. If you hold an exported archive as your organization's copy of its records — under 21 CFR 11.10(b), which requires the ability to generate accurate and complete copies for inspection — that archive's file inventory understates what you hold, and the archive itself asserts it is complete. ⚠️ No records, signatures, audit-trail entries or files were lost, altered or deleted; nothing about how your data is stored or reached changed, and no action is required on the instance. What was wrong was the INVENTORY of files inside the export, and the claim of completeness printed beside it. The conservative course is to take a fresh export and to treat any previously-filed archive's files-index.csv as understating your file holdings — the records CSVs in those archives were not affected. ⭐ The distinction worth recording for anyone maintaining a qualified state is one this register has now drawn several times: a control can be correct in the place it was written and absent from an adjacent place nobody scoped. The table inventory in this export was derived from the database schema and checked in both directions on every build; the FILE inventory was a single table name written inside a function, and no check compared it to where files actually live. It is now derived and checked the same way, so a future change that adds a place files are stored fails the build unless the export is told about it.
export-files.test.tsexport.test.tsExporting your organization's records (Settings → Export your records) now places the uploaded files in the archive, under a files/ folder arranged by the record each belongs to. Previously the archive listed your files and you retrieved them one at a time from the records they were attached to; a bulk import had no matching bulk export. ⭐ Every file remains listed in files-index.csv whether or not its contents are present, and an "outcome" column states which — there are exactly three reasons contents can be absent, and each names itself against the file it applies to: bulk-migration SOURCE files are excluded by decision (on commit the same file becomes a controlled-document version, which IS included, so including both would place every migrated document in your archive twice); the archive holds at most 250 MB of file contents, and anything beyond that is listed as over the limit with its record still exported in full; and a file that could not be retrieved from storage is listed as failed, with the reason. ⭐⭐ Where a controlled document's contents are included, the export re-computes the file's SHA-256 and compares it to the value that document's electronic signatures are bound to, recording whether they match. This lets you establish from the archive alone — with no access to Indelio and no cooperation from us — that the file you hold is the file that was signed. A file that does NOT match is reported as a mismatch, the export is reported as incomplete, and the discrepancy is stated in the archive's notes.
Why this classification: Classified “review” because the behaviour of a controlled function changed — what a records export contains is now materially different — while no quality record, signature, audit entry or access rule was altered, and nothing about how your data is stored or reached changed. ⚠️ It is not “none”: if your procedures describe what a records export produces, or if a performance qualification exercised the export, both now describe an archive of a different shape, with a files/ folder, additional columns in files-index.csv, and additional fields in manifest.json. Check whether that falls inside the intended use you qualified. ⭐ The distinction worth recording for anyone maintaining a qualified state is about the SIGNATURE CHECK, because it changes what the export can be used to prove rather than only what it contains: previously an archive let an independent reader re-walk the audit hash chain; it now additionally lets that reader verify a signed document file against the hash its signature was taken over. That is evidence you can act on without the vendor, which is the property that matters if we are not here. ⚠️ A mismatch reported by that check is a serious finding requiring immediate assessment, not a scheduled one — it means stored bytes and signed bytes disagree. ⚠️ Note the 250 MB ceiling explicitly: an organization holding more than that receives a deliberately partial archive which SAYS it is partial and names every file left out. It is never a silent truncation, but it does mean a very large organization needs more than one export to hold every file, and that is a fact to account for in a records-retention procedure. Needs no database change and no action on any existing instance.
export-files.test.tsexport.test.tsAn export now also checks your stored files against the records that refer to them, in both directions, and reports the result in the archive (storage-reconciliation.csv). Two things were previously invisible: a file sitting in storage that no record refers to, and a record that refers to a file which is no longer stored. ⚠️ The two are reported differently on purpose. A record pointing at a file that is not there is a gap in your records, so the export is reported as INCOMPLETE. A stored file that nothing refers to is not — nothing in your quality system points at it, so the archive was never meant to contain it; it is named so you know it is there, and its contents are not included because there is no record to file it under. ⭐ If the check cannot be completed — including for an organization holding more stored folders than the check will walk in one pass — the archive reports NOT VERIFIED rather than reporting nothing found. Those are different statements and only one of them is reassuring.
Why this classification: Classified “review” because what a records export reports about itself changed, while no quality record, signature, audit entry or access rule was altered and no stored file was moved, changed or removed — this check only reads. ⭐ The distinction worth recording for anyone maintaining a qualified state is that this is the first check Indelio performs of your STORED FILES against your RECORDS. Until now every completeness statement an export made was derived from the database alone, so a file that had gone missing from storage could not be detected by reading the records — the records were self-consistent. If your procedures rely on the export as evidence that your file holdings are intact, that evidence now exists where it previously did not, and an export that reports a missing file is reporting a real discrepancy that warrants investigation rather than a formatting change. ⚠️ An export that reports NOT VERIFIED for this check is NOT evidence that your files are intact; it is evidence that the question was not answered. Needs no database change and no action on any existing instance.
export-files.test.tsThree separation-of-duties checks now refuse to proceed when they cannot be performed, instead of allowing the action through unchecked. Approving a risk assessment, closing a change control, and signing design validation each look up who signed the previous step, so the same person cannot sign both. If that look-up FAILED — a momentary database problem rather than a normal result — the check was skipped and the signature was allowed. A failure to check was being treated the same as a successful check that found nothing. All three now stop and say the check could not be performed. ⚠️ The everyday behaviour is unchanged: where the look-up works, exactly the same people are allowed and refused as before. Only the failure path changed. The same treatment was already in place for CAPA effectiveness signing and Corrections closure, which is why those two were not affected.
Why this classification: Classified “review” because a controlled function changed behaviour — in a failure mode rather than in normal use — while no record, signature or audit entry was altered and nothing about access or storage changed. ⚠️⚠️ The reason to look rather than file this away: for the period before this release it was POSSIBLE, though it required a database read to fail at the exact moment of signing, for one person to sign both sides of one of these three separations. Indelio cannot tell you whether that happened on your instance, because the skipped check left no trace — that is precisely what was wrong with it. If your quality system relies on any of these three separations, the conservative course is to review the signature history on risk assessments, change controls and design validations for cases where the same person signed both steps; every signature is in your audit trail and in your records export, so this is answerable from your own data without our help. ⭐ The distinction worth recording for anyone maintaining a qualified state is one this register has drawn before in other words: a check that did not run is not a check that passed, and a control which cannot distinguish those two states is not enforcing anything in the moment it matters most. Needs no database change and no action on any existing instance beyond that review.
copy-claims.test.tsThe published order in which this system's database migrations must be applied contained one file in the wrong position, and following it as written would have stopped part-way through installation. Corrected, and a complete installation onto an empty database is now performed automatically on every build.
The automated installation check now DEMONSTRATES that one organization cannot read another organization’s records, by actually attempting it: the check reads, through the signed-in person’s own session, records belonging to a different organization on the same instance, and requires that nothing comes back. Until now the check read the access rules and confirmed they were written to confine each organization to its own data. Those are different claims — the rules can be correct and not be the rules in force, because switching row-level security off on a table leaves every rule listed against it exactly as before. ⚠️ The check reports NOT VERIFIED rather than a pass in three situations, each of which produces the same empty result a correctly-isolated instance produces: an instance with only one organization, an instance whose other organization holds no records, and — the one that matters — a session that cannot see its OWN organization’s records either, because a session that is not properly signed in sees nothing belonging to anybody and is otherwise indistinguishable from perfect isolation. The check reads only; it creates no organizations, no users and no records.
Why this classification: Classified “review” because no controlled function changed — tenant separation behaves exactly as before, and nothing about how your data is stored or reached was altered. What changed is that the evidence now demonstrates the separation operating on the instance being qualified, rather than reporting that it is configured correctly. ⚠️ It is not “none”: if this check FAILS on an instance, that instance is disclosing one customer’s quality records to another, which is the most serious finding this system can produce and would require immediate assessment rather than a scheduled one. ⭐ The distinction worth recording for anyone maintaining a qualified state is the same one drawn for the append-only rules above — a configuration reading and a behavioural demonstration are different pieces of evidence — with one addition specific to a negative test: an empty result is only evidence when it is known that there was something to find and that the reader could see anything at all. An existing automated test does perform a cross-organization read, but against a disposable database built for testing, which is a different database from the one being qualified. Needs no database change and no action on any existing instance.
iq-check.test.tsiq-coverage-map.test.tsThe automated installation check now confirms that the database rule preventing anyone — including the system's own privileged account — from altering an audit-trail entry or an electronic signature actually TAKES EFFECT, by attempting exactly that and confirming it is refused. Until now the check confirmed only that the rule was registered against the table. Those are different claims: a rule can be registered and switched off, and the registry still lists it, so the previous check would have reported an instance whose audit trail was fully writable as sound. ⚠️ This is the only check that attempts a write, so its safety is designed rather than assumed: each attempt runs inside its own nested transaction which is deliberately abandoned whether the attempt is refused OR succeeds, so the path where the rule is missing is the very path that undoes the write. The attempt also sets a value to itself, so even a hypothetical completion would change no data. ⚠️ A table with no rows is reported as NOT VERIFIED rather than as a pass — the rule operates per row, so an attempt that matches nothing demonstrates neither that it works nor that it is broken.
Why this classification: Classified “review” because no controlled function changed — the append-only rules and the privileged account behave exactly as before. What changed is that the evidence now demonstrates the control operating rather than recording that it is configured. ⚠️ It is emphatically not “none”: if this check FAILS on an instance, that instance permits its audit trail or its signature records to be altered, which is the single assumption every other control in the system rests on, and it would be a finding of the most serious kind. ⭐ The distinction worth recording for anyone maintaining a qualified state is that a configuration reading and a behavioural demonstration are different pieces of evidence, and only the second answers the question the installation protocol actually asks. The same distinction applies to controls beyond this one. Requires a new database function, supabase/iq_probe_append_only.sql, to be installed before the next installation check; without it this check records itself as NOT VERIFIED rather than passing.
iq-check.test.tsiq-coverage-map.test.tsThe automated installation check now confirms that every state value the migrations define is actually present on the instance — for example, that a controlled document can be placed in every state the system knows about. Nothing had ever examined these. ⚠️ Closing this required correcting the installation protocol itself, not only adding a check: the protocol listed six document states by name and the system has seven. A state added by a later migration was never written back into the protocol, so somebody performing an installation qualification against a perfectly correct instance would have found a state that was not on their list, and would have had to decide on the spot whether to raise it as a problem or tick it anyway. The protocol no longer lists the states in prose at all; the check derives them from the migrations, so a future migration that adds a state updates the expectation automatically.
Why this classification: Classified “review” because no controlled function changed and any instance built by applying the migrations in the published order already has every state. What changed is that the evidence now examines them, and that a stale sentence in the protocol was corrected. ⚠️ It is not “none” because a FAILURE here would mean a real one: an instance missing a state cannot put a record into it, so a lifecycle path the procedure describes would simply not be available. The realistic case is an instance that received one migration and not a later one — the table is there and every column is there, so the two existing schema checks both stay green and only reading the state list can see it. ⭐ The lesson worth recording is that this was a documentation defect discovered while building a check, not a software defect: the safeguard against it recurring is that the expected values are now generated from the migrations rather than typed into a document, because a typed list goes stale the moment somebody adds to the system without re-reading the prose. Two configuration tables were also added to the list the check verifies; they had simply never been on it. Requires supabase/iq_run.sql to be re-applied before the next installation check, as with the two preceding items.
iq-check.test.tsiq-coverage-map.test.tsschema-manifest.test.tsThe automated installation check now confirms that the shared secret the four scheduled jobs use to authenticate is actually configured. It was already being read and reported, and no check ever examined it. ⚠️ This is recorded as a critical check, and the reason is the opposite of what it looks like: with the secret missing, the scheduled endpoints do not become open to the public — they refuse every request, including the scheduler's. So nothing is exposed; instead all four scheduled jobs stop, silently. The one that matters most is the daily job that moves an approved document to effective on the date it was scheduled for: a document given a future effective date would simply never take effect, and nothing anywhere would report it. A refusal returned to an automated scheduler looks like silence rather than like a failure.
Why this classification: Classified “review” because no controlled function changed — the scheduled jobs and their authentication behave exactly as before. What changed is that the installation evidence now examines a setting it had always collected and never looked at. ⚠️ It is not “none” because if this check FAILS on an instance, that instance has four dormant scheduled jobs and at least one document-lifecycle rule that has quietly not been running, which is a finding requiring its own assessment rather than a documentation matter. ⭐ The pattern is worth recording because it is not a missing check so much as an unfinished one: somebody wrote the code to gather the fact, which is the harder half, and never wrote the line that judges it. A reader of the evidence would see the setting listed and reasonably assume it had been checked. Unlike the two preceding items this needs no database change and no action on any existing instance.
iq-check.test.tsiq-coverage-map.test.tsThe automated installation check now confirms that the two database rules preventing a document from having more than one effective version, and from having more than one revision under way at a time, are not merely present but are defined with the right scope. Neither had ever been examined by any automated check. ⚠️ The one that matters is the second. That rule was originally written to cover revisions that were in draft or under review; it was later widened so that an approved revision waiting for its effective date also holds the document's slot. Both versions carry the SAME NAME, so an instance that received the earlier version and not the later one looks correct to any check that asks whether the rule exists — while a second revision could in fact be started underneath one that is already approved and awaiting release. The check now reads the rule's scope, not only its presence. ⚠️ ACTION: re-apply supabase/iq_run.sql to your instance before your next installation check, as with the previous item; without it this check records itself as NOT VERIFIED rather than passing.
Why this classification: Classified “review” because no controlled function of the product changed — the rules themselves are exactly as they were, and any instance built by applying the migrations in the published order already has the wider version. What changed is that the installation evidence now examines them. ⚠️ It is not “none” because if this check FAILS on an instance, that instance genuinely permits something the document control procedure says it does not, and that would be a finding requiring its own assessment rather than a documentation matter. ⭐ The reason it is recorded at this length is the failure mode it addresses: a rule that exists under the right name with the wrong scope. A check asking “is it there?” passes; a check asking “what does it cover?” does not. The same shape has now been found four times in this system — a control that was present, named correctly, and narrower than the thing it was believed to enforce. ⭐ Three further ways of being wrong are graded rather than assumed, because each fails differently: a rule of the right name that is not enforced as unique constrains nothing at all; a rule with no scope restriction whatsoever would be the opposite failure and a far more visible one, since it would prevent any document from ever being revised; and an instance that cannot report its rules at all is recorded as NOT VERIFIED rather than as passing.
iq-check.test.tsiq-coverage-map.test.tsThe automated installation check now confirms that the database function which identifies a signed-in user's organisation is not merely present but is defined with the elevated privilege it needs in order to work. Previously the check confirmed only that a function of that name existed. That function reads the user's organisation from a table that is itself access-restricted, so without the elevated definition it returns nothing at all — and every access rule written in terms of “the organisation this user belongs to” then matches no records. The failure mode is silent: not an error message, an empty result everywhere. ⚠️ ACTION FOR ANYONE WHO HAS ALREADY PERFORMED AN INSTALLATION QUALIFICATION: re-apply supabase/iq_run.sql to your instance before your next installation check. An instance still carrying the previous version of that routine cannot report the new fact, and the check will record itself as NOT VERIFIED — which blocks a qualified verdict in the same way a failure does, deliberately, because “we could not look” is not “we looked and it was fine”.
Why this classification: Classified “review” rather than “requalify” because no controlled function of the product changed — the system behaves exactly as it did. What changed is how much of its own subject the installation qualification evidence covers, and that is something a reader of that evidence is entitled to know. ⚠️ It is listed as “review” rather than “none” for two reasons: an existing instance will report NOT VERIFIED until the routine above is re-applied, and if the new check FAILS on any instance then that instance carries a real defect in how tenant separation is enforced, which would be a finding requiring its own assessment. ⭐ The defect worth recording is not the missing check, which is a few lines. It is HOW it stayed missing. The check that existed was titled with the function's name, so anyone comparing the qualification protocol against the automated checks saw the name in both places and concluded the step was covered. It had been covered on paper and never in fact, on every instance ever checked. This was found by deriving a coverage map from what each check's code ACTUALLY ASSERTS rather than from what it is called — a comparison that also showed the qualification protocol's forty-nine steps to be seven fully automated rather than the nineteen a count of checks suggests. ⚠️ A second finding came out of testing the fix and is recorded because it is the same shape a third time: the rule distinguishing “the instance did not report this” from “the instance reported that nothing qualifies” was written inline where it could not be tested, and deliberately breaking it changed no test result. Confusing those two would have invented a critical failure out of a reading that never happened. It was moved somewhere it could be tested, and is.
iq-check.test.tsiq-coverage-map.test.tsThe check that a CAPA's effectiveness is signed off by somebody other than the person who carried out the actions now considers EVERYONE who ever marked an action complete, not only the most recent person to do so. Previously that was recorded in a single field, and completing an action a second time overwrote it. So if one person marked an action complete, the action was reopened, and a second person marked it complete, the first person was erased from the record — and could then sign the effectiveness check with no challenge and nothing written down. ⚠️ This CHANGES BEHAVIOUR: somebody who was previously allowed to sign that check without comment may now be asked either to hand it to a colleague or to record why they are signing it themselves.
Why this classification: Classified “requalify” because a qualification step that closes a CAPA may now meet a challenge it did not meet before, and because the control this restores is a segregation-of-duties default (ISO 13485 §8.5.2). Nobody is barred — the default may still be overridden by recording a reason, exactly as before, and a person who never completed an action is unaffected. ⛔ The part worth reading is HOW it failed. The module already refused to erase the completer when an action was reopened, and the reason was written down in the code: blanking the field would hand somebody back an independence they had not earned by pressing a button twice. That reasoning was right, and it guarded the door it was pointed at. A second person completing the same action walked through a different one, and the outcome was worse than a refusal would have been: a refusal is visible, whereas this left the closure looking independent and wrote no exception anywhere, because the note recorded in the audit trail is decided by the same test that failed. ⭐ The set is maintained by the database itself rather than by application code. Everywhere else in this system the application is the control and the database is a second line of defence; here the requirement is that the record may only ever grow, and expressing that as read-then-write in application code invites precisely the lost update being prevented. ⚠️ No signature is affected: what a signature is bound to does not include who completed an action, so no existing record's seal moves. ⭐ This was found by verifying a backlog note that described it as a bookkeeping detail. It was not one. Two further defects were caught inside the fix while it was being written — one that would have challenged every signer whose identity could not be read, and one where the automated check for the database rule would have accepted a rule that had been renamed and therefore no longer ran.
capa-effectiveness-independence.test.tscapa.test.tsThe list stating the order in which this system's database migrations must be applied contained one file in the wrong position, and an installation following that list would have stopped part-way through with an error rather than completing. The file concerned removes two retired notification triggers that this product no longer uses, and one of the triggers it removes is attached to the audit trail table — which the list placed five files further on. Removing a trigger from a table that does not yet exist is an error rather than something the database skips, so installation halted there. The file has been moved to run after the table exists, which is the whole of the correction to the order. ⚠️ No customer instance has ever been provisioned from this list, and no deployed instance is affected: every existing instance was built up incrementally as the modules were written, so none of them ever executed the published order. What was wrong was the procedure, not any installed system.
Why this classification: Classified “requalify” because this list is the authority the installation qualification protocol cites, and it is the specific thing that protocol asks an executor to confirm. Anyone performing an installation qualification against it would have been unable to complete the installation, so a protocol referring to it rests on a procedure that did not work. ⭐ The defect worth recording is not the file's position, which is a one-line correction. It is that nobody had ever performed the installation. The order was checked by a program that reads each migration and works out what it needs to already exist — and that program understood five kinds of dependency and not a sixth. A trigger's target table was invisible to it, so it reported the order clean, confidently and in writing. It had done the same thing three times before, for three other kinds of dependency it did not model at the time; each was found by a person reading the output and asking why a particular file had sorted to the front. ⚠️ The correction is therefore two things, and the second is the one that matters: the file was moved, and the automated build pipeline now performs a complete installation of every migration onto an empty database on every single run. An incomplete dependency model still returns a clean answer. An installation that does not complete cannot. ⛔ This defect was found on the first run of that new installation check, which is the plainest available statement of how long it would otherwise have survived. ⭐ A second, smaller thing was corrected in the same work and is recorded because it would have been the more damaging of the two had it shipped: the first version of the widened dependency check treated a trigger on a table belonging to the underlying platform as though it were one of ours, and reported that the system depended on a table no migration creates. That is the strongest finding this check is capable of producing — it means the repository cannot install itself — and it would have been false.
sql-run-order.test.tsci-schema-coverage.test.tsThe automated adversarial test that attempts to forge an electronic signature now runs against every one of the twenty-three record types that hold signatures whenever it runs in the build pipeline. Previously the disposable database that pipeline uses had been set up by hand and carried only one of them, so the test reported on one record type and recorded the other twenty-two as absent. A shortfall in that coverage is now a failure of the build rather than a note in its output.
Why this classification: Classified “review” because no control changed and no customer instance is involved — what changed is how much of its own subject our evidence actually covers, which a reader of the previous release's deviation record should know about. ⚠️ That deviation listed as complete an action reading “the adversarial test was widened from one signature table to all twenty-three”. Widening the test was done. The pipeline running it reached one, printed that it had reached one, and passed anyway — so the evidence the pipeline produced covered a twenty-third of what the action claimed, and the only thing standing between that and a passing build was somebody reading a line of output. The action has been amended to say so in those terms. ⭐ Two things now prevent it recurring: the pipeline installs the complete schema before testing, so every record type exists to be attacked; and coverage is graded rather than reported, so a record type that is absent fails the build unless an exception is recorded by name with a reason. The exception list is empty and is asserted to be empty. ⭐ This is the same defect the deviation itself describes — something believed to be in force because a document said it was — found this time in our own evidence rather than in the product.
attack.test.tsci-schema-coverage.test.ts⚠️ DEVIATION. A control described in the release of 2026-08-20 does not hold in practice, and this entry records that rather than leaving it in correspondence. That release stated that the person signing must type their password at each signature, and that credential filling by a browser or password manager is suppressed on every signature field. The suppression is implemented as described. It is not sufficient. A web page can ask a browser not to fill a field; it cannot require it, and the signal we use suppresses automatic filling rather than the password manager's offer — so on the first signature on a freshly loaded page, which is the ordinary case, a stored password can still be offered and accepted with a single click. We have observed this repeatedly on our own instance, including one occasion where no device check of any kind was presented because the password manager's vault had been unlocked earlier in the session.
Why this classification: Classified “requalify” because a signing step that a customer qualified on the understanding that the password was typed by the signer cannot be assumed to have been performed that way, and because the shortfall goes to the second identification component itself. ⛔ Stated plainly, and with a measurement rather than an argument: on our own instance a valid signature was applied to a controlled document twelve minutes and twenty-two seconds after the signer had last proven their identity, with no challenge presented and nothing supplied that only that person could supply. Identity came from the browser session; the password came from a vault unlocked minutes earlier; the signer contributed a single click. We do not believe that meets the requirement for two distinct identification components. ⛔⛔ AND THE RECORD CANNOT SHOW WHICH SIGNATURES WERE AFFECTED. A signature where the password was typed and one where it was filled by a password manager are identical in our tables and in the audit trail, and there is no field that could ever separate them. That is a limit of the evidence and not a reason to assume the best: it means any signature made since 2026-08-20 may have been made this way, and we cannot tell you which. ⚠️ A device biometric check appears in some of these cases and MUST NOT be read as mitigation. It is the signer's own operating system releasing a stored credential to the browser; this system performs no biometric verification anywhere, and our server receives the same string it would have received had the password been typed. It is not our control and we do not claim it. ⭐ Follow-up actions, with status. (1) COMPLETE — disclosed in full to our independent validation reviewer, with the measurements and the reproduction, together with a correction to two statements in our own earlier draft that were stronger than the evidence supported. (2) COMPLETE — the interval between a document being delivered to a signer and that signer signing it is now recorded, so an implausible gap is visible on the record rather than invisible. (3) COMPLETE — claims that overstated this control have been removed from our own documentation, including any suggestion that a device biometric is a control of ours. (4) OPEN — a security key with user verification is the only mechanism we know of where the server can verify that a person was checked at the moment of signing. Whether our authentication provider actually enforces that property is undocumented; we have written a test to measure it and it cannot run until the capability is enabled. Until it returns a result we will not describe that approach as evidence a person was checked. (5) OPEN — the target control, and whether our sign-in page should stop inviting the browser to save the password at all, are decisions we have put to our validation reviewer rather than taken ourselves.
password-clearing.test.tsdocument-delivery.test.tsReopening a closed record now requires an electronic signature, in all nine modules where a closed record can be reopened — corrective and preventive actions, change control, complaints, corrections and removals, design controls, management review, nonconformance, projects and risk assessments. Reopening already required an approver or quality role and a written reason, and was already recorded in the audit trail; what it did not do was bind a named person to the act with their password re-verified at that moment, as every other disposition in those modules does. ⚠️ This CHANGES BEHAVIOUR: a person who could previously reopen a record by giving a reason must now also enter their password, and the reopening is recorded as a signature against the record.
Why this classification: Classified “requalify” because a qualification that exercised reopening will find an additional step, and because reopening is now evidenced differently — there is a signature on the record where previously there was only an audit entry. Nothing that was permitted is now forbidden: the same people may still reopen the same records, for the same reasons. ⭐ The reason this was found is worth recording, because it was not found by a test. The Part 11 backlog carried it as a single item about one module. Sweeping for the pattern rather than the reported instance showed it was nine — every module that can reopen anything. That is the third time in a week that a defect recorded as one instance turned out to be a whole class, and it is now the default assumption when one is reported. ⛔ One module was materially worse than the other eight and it is the one where it matters most. The corrections and removals module — field actions, which is to say recalls — presented the signer with a password box and the words “re-enter your password”, and then discarded what they typed. A wrong password reopened a closed field action exactly as a correct one did. Every other module verified it. We are recording that as its own statement rather than folding it into the general improvement, because a control the product ASSERTS and does not perform is a different fault from one it never claimed: the first misleads a user into believing they have been authenticated, and it is the fault we have found most often when checking our own claims against our own behaviour. ⚠️ Signatures are applied before the record's state changes, so a refused or failed signature leaves the record closed rather than reopened-but-unsigned.
reopen-signature.test.tscapa.test.tsThe file that enforces this system's inactivity timeout, two-factor step-up, password expiry and public/private page boundary has been renamed, from `middleware.ts` to `proxy.ts`, because the web framework this product is built on has deprecated the former name. No behaviour changed: the contents are the same, the controls are the same, and the running system does exactly what it did before. ⚠️ It is recorded here because of how it appears in this system's own change record — the controlled-file list published with each release shows one controlled file removed and a different one added, which is the same shape a genuine removal of a control would take. It was not a removal.
Why this classification: Classified “review” because nothing a customer could have qualified behaves differently: no step changes, no screen changes, and nothing that was permitted or forbidden has moved. It is not classified “none” because two things a reviewer actually reads will differ and would otherwise be unexplained — the controlled-file manifest shows a file disappearing, and the Part 11 traceability matrix now names a different file for four requirements. ⭐ The rename was made as its own release item rather than folded into other work, because the file carries four Part 11 controls and a change touching it should be visible on its own. ⭐ One property of it is worth recording, because it is the failure it could have caused rather than the one it did. The framework locates the function this file must export by NAME, and the name it looks for depends on the filename — so renaming the file without renaming the function inside it yields a system that typechecks, passes its test suite, deploys successfully, and then fails every single request, with no session handling, no timeout, no two-factor step-up and no page protection at all. We established which check catches that by deliberately introducing the fault rather than reasoning about it: the production build refuses it with an explicit error, and our first expectation — that only the running system would notice — was wrong. ⛔ Checking that also exposed something the rename did not cause and did not depend on. Every existing automated check on this file reads its CONTENTS; nothing anywhere asserted which requests reach the file in the first place, and that is decided by a single pattern near the bottom of it. Adding one page prefix to that pattern switches off all four controls for the affected pages, with every existing test, the typecheck and the build all still passing, and the only symptom being that a control silently does not fire. A new automated check now holds that pattern to a whitelist — framework internals and static files only — so any page added to the exemption has to be argued for rather than slipped in. That gap predates this release and was not introduced by it; it is recorded here because this is when it was found.
proxy-reach.test.tsidle-timeout.test.tsThe automated installation check now confirms that this system's privileged database credential — the one that can read and write every organization's records — is not configured in a way that would send it to the web browser. Nothing had ever examined this, and it is the single most consequential thing in the installation protocol that was going unchecked. ⚠️ There are two separate ways such a credential can reach a browser, and they have different owners, so this is closed by two separate mechanisms. The first is the software itself, and is checked automatically on every build, by examining the finished files a browser would download rather than by reading the source that produced them. The second is the instance's OWN configuration: a setting whose name begins with the reserved public prefix is copied into the web page by design, so a person configuring an instance can publish the credential without any change to the software at all. That second one is what the installation check now examines, on the instance being qualified, and it is complete for that route because the public prefix is the only way a setting reaches the browser. ⚠️ The check reports NOT VERIFIED rather than a pass if it can see no public settings at all, because a correctly configured instance always has at least one, so seeing none means the reading failed rather than that the instance is clean. ⚠️ It reports the NAME of any offending setting and never its value, because this evidence record is signed and retained.
Why this classification: Classified “review” because no controlled function changed — nothing about how records are stored, reached or protected behaves differently, and no correctly configured instance is affected in any way. What changed is that the installation evidence now examines a route that was previously left to somebody remembering to look. ⚠️ It is emphatically not “none”: if this check FAILS on an instance, that instance has published a credential that bypasses every separation rule in the system, and any visitor to the site can read and alter every organization's quality records while leaving audit entries indistinguishable from legitimate activity. That is not a finding to schedule — it requires the credential to be replaced at the database provider immediately, and an assessment of what was reachable while it was published. ⭐ The distinction worth recording for anyone maintaining a qualified state is that this step is recorded as PARTIALLY automated rather than fully, deliberately: the two mechanisms together cover the software and the configuration, but neither one inspects the delivered files of the specific instance being qualified. The remaining portion stays with the person performing the installation, and the coverage record says so rather than letting the two halves read as a whole. ⭐ The wider lesson is about the shape of the requirement rather than the check: the step reads as one question and is two, with two different owners, so a single check would have closed whichever half its author happened to have in mind and would have read, from its title, as closing the requirement. Needs no database change and no action on any existing instance.
iq-check.test.tsscan-client-bundle.test.tsiq-coverage-map.test.tsThe warning that appears when a record's content does not match its stored fingerprint now says what it actually checked, on every module. It previously said an electronic signature was broken, which is not what that check looks at.
On every record screen, the red warning shown when a record fails its integrity check has been reworded. It said the current content “no longer matches what was signed — the e-signature binding is broken”, or that the record “was altered after signing”. Neither is what the check measures: it compares the record against its own stored fingerprint and never against any signature. It now says the content does not match its own stored fingerprint, which means a field was changed without going through Indelio, and points to the E-signatures table where each signature's own binding is reported. Nineteen screens changed. No rule, record, signature or permission is affected.
Why this classification: Nothing about what the system does changes, and nothing that was accepted is now refused — which is why this is “review” and not “requalify”. It is recorded because a qualification script may check for particular words on screen, and because the previous words were wrong about a Part 11 control in a way that changes what a reader would do about it. Told that an e-signature binding is broken, a quality reviewer investigates the signature. The signature is fine; every in-app edit rewrites the record and its fingerprint together, so the check can only fail when something changed the row WITHOUT going through the application — a direct database edit, a restore, a migration run by hand. That is the more serious reading of the two, and it was the one nobody was being given. The same defect had already been corrected on the CAPA screen when scoped signature bindings shipped, and the other nineteen were left behind; both halves are now checked by an automated test that reads the rule out of the shipped code first and then asserts the wording against it, so a future relaxation cannot leave the copy behind again.
copy-control-claims.test.tsDesign Controls: where a design project has no state-independent fingerprint recorded, the integrity check now reports that it cannot be checked, instead of reporting the record as changed. Affects any instance where supabase/design_material_hash.sql has been applied but the accompanying backfill has not yet been run. The PDF traceability report carries the same three outcomes.
Why this classification: Classified “requalify” because a qualification script that recorded a red integrity warning against a design project, or a traceability PDF filed as evidence carrying the WARNING line, was recording a finding that did not exist — and after this change the same project reports differently. The mechanism is worth stating plainly. A design project's signatures bind to a fingerprint that includes the lifecycle state, frozen in that shape so that existing signatures are not orphaned. Advancing the state deliberately does NOT recompute that fingerprint, because recomputing it would break every signature on the record. A separate state-independent fingerprint was introduced so the integrity banner would stop false-tripping on lifecycle transitions, and the banner uses it — but where that value had never been recorded, the code fell back to the old comparison, which cannot hold once the state has moved. So a sound design project displayed as altered, and the fallback was reachable by an ordinary route: the migration only adds the column, and the backfill that populates it is a separate step. A fingerprint we do not hold cannot be compared, and “we cannot tell” must never be presented as “somebody changed this”. It is now a third outcome, worded as not comparable and coloured as information rather than as a finding, in both the screen and the PDF — the same treatment already given to signatures made before scoped bindings existed. ⚠️ No records were affected on the vendor's own instance, where the backfill had been run; that is a fact about one instance and not about the shipped code.
copy-control-claims.test.tsdesign-controls.test.tsThe application framework was upgraded two major versions (Next.js 14 to 16) and the user-interface runtime with it (React 18 to 19). This closes eleven published security advisories against the framework and four against a component it bundles, including one allowing unauthenticated disclosure of internal server-function endpoints; the dependency audit reports no known vulnerabilities after the upgrade, where it previously reported two high-severity findings that no patch on the previous major could resolve. No quality function, rule, signature, role or record behaviour was changed as part of this work.
Why this classification: Classified “requalify” because the software the qualified system runs on has changed by two major versions, and installation and performance qualification are executed against a specific deployed build. Nothing here is a change to a control, and the automated operational-qualification suite passes unchanged — the same 1,735 checks, including every access-control, signature, hash-chain and tenant-isolation test — which is the evidence that behaviour is preserved. But an executed IQ or PQ naming the previous build is evidence about a build that is no longer deployed, and that judgement belongs to whoever maintains it. What actually changed in the code is one thing, applied about a hundred and sixty times: the framework made reading cookies, headers and URL parameters asynchronous, so the data-access layer that every module reads through became asynchronous with it. The compiler identified every affected call site and the change was driven to zero compiler errors, which is why a change of that breadth was safe to make mechanically. Two configuration keys were relocated as the framework required; one of them controls whether the PDF and Word text extractors are bundled or loaded at runtime, and leaving it in its old position would have been accepted silently while reintroducing a defect that presented as PDF text extraction returning empty in production. ⚠️ One deprecation is deliberately NOT actioned in this release: the framework has renamed the request-interception file convention and warns on the old name. That file enforces the idle timeout, second-factor step-up, password ageing and the public-route boundary, and renaming it also moves it within our own controlled-file list, so it is being done as its own change rather than folded into an upgrade. The old name continues to work. ⭐ Verified beyond the test suite: a production build completes, the sign-in page renders and hydrates with no console errors, the automatic sign-out explanation still appears when the timeout flag is present — which exercises the asynchronous parameter change on a Part 11 access control — and an unauthenticated request to a protected module is still redirected to sign-in, which exercises the request interception and the cookie read. ⭐⭐ It was also verified by opening the upgraded build while signed in, because the failure this change could produce is not an error. A data read that lost its await renders an EMPTY LIST, which is indistinguishable from a module holding no records, so neither the compiler nor the test suite can stand in for looking at a screen. Controlled documents returned fourteen records with their versions and lifecycle states, corrective and preventive actions four with state, owner and due date, design projects four with their computed input and output counts, and the training matrix its assignments with overdue status. A design project was opened and both of its electronic signatures report their binding intact, which is the record-level integrity check reading a stored fingerprint back through the changed data layer. Where a list WAS empty — the signed-in user's own training assignments — other reads on that same page returned rows, and that is what separates a record set that is genuinely empty from a read that has broken.
idle-timeout.test.tsattack.test.tsCorrections & Removals now expects a field action to be closed by someone other than the person who approved its assessment. Where nobody else is available the same person may still close it, and records why.
The automated installation check now verifies that every column the database migrations add is actually present, and names any that are missing. It previously checked that tables, three database functions and two audit-trail columns existed, so a migration that only adds columns to existing tables could be missing entirely and the check would still report a clean instance. A database migration is required to enable it: run supabase/iq_columns.sql. Until it is run, the new check reports NOT CHECKED rather than passing.
Why this classification: Nothing about how records behave changes, and no signature, gate or permission is affected — this adds a check to the installation qualification evidence. It is classified “review” because the automated IQ report gains a step, and anyone whose installation qualification cites that report's contents should re-run it and re-file the output. The reason it exists is worth recording plainly, because it is a gap we found the hard way. A migration was committed with its code and never applied to the running instance. It added only columns, to tables that already existed. The consequences were invisible for a day: one action in the CAPA module failed every time it was attempted, because the write set a column that was not there, and a closure control degraded to half its intended scope — by design, so that closure would not become impossible, and therefore silently, because closure still succeeded and looked identical. The automated check would have reported the instance healthy throughout, since nothing in it had ever verified a column, and a migration that only adds columns is the ordinary case. Two properties deserve a validator's attention. The check reads `ALTER TABLE … ADD COLUMN` from the migrations and nothing else — it does not parse table definitions, so a pass means every column a migration adds is present, and never that the schema as a whole is correct; the wording in the report says so. And it FAILS TO “NOT CHECKED”. If the column map cannot be read — most likely because supabase/iq_columns.sql has not been run — it reports that it could not look, rather than reporting that nothing is missing. A clean result derived from a failed read is the precise failure this check was written to catch, and it would have been indefensible to reproduce it here. The check is not marked critical: a missing column is a real defect, reported by name, but it does not make the instance unsafe to operate the way a missing integrity trigger does, and making it critical would block qualification over a drift an executor can correct in a minute.
schema-manifest.test.tsiq-check.test.tsOn the CAPA screen, the confirmation or refusal shown after an action now disappears as soon as you edit that form, instead of staying on screen until the next time you submit it. Nothing about what is recorded changes; this only affects how long a message remains visible.
Why this classification: No rule, record or signature changes, and nothing is refused that was previously allowed — but it is worth recording because a qualification script may check for a message on screen, and a message that used to persist now clears when the form is touched. The reason for the change is the direction that matters. A result was held until the next submit, so it survived every edit made in between and went on describing a form state that no longer existed. Stale in one direction that is merely untidy: a refusal that names a person you have since removed from the form makes you look twice. In the other direction it is a false assurance — sign something, receive “recorded and signed”, then start filling the form in for the next one, and the confirmation sits beside your edited form reading as though that second act had succeeded. It had not. This was seen on a live system with a green “action plan approved” rendered directly beneath a red notice saying that approval no longer covered the plan, in the same card, with the reassuring message being the false one. The message now clears on the first edit after a submit, so a confirmation only ever describes the submission that produced it. ⚠️ Applied to the CAPA screen in this release. The same pattern exists on other record screens and is being changed module by module rather than all at once; no claim is made here that it is fixed elsewhere.
signing-feedback.test.tsA CAPA's dual plan approval now counts an approval that still covers the plan, rather than one that merely exists. If the plan is edited after somebody has approved it — which is possible, because the plan stays editable until both approvals are in — that approval's slot reopens and shows who approved the earlier version. The CAPA no longer advances to Implementation until both slots are held by approvals that cover the plan as it currently stands. The earlier signature is kept on the record. No migration is required beyond the one released with the scoped-binding change above.
Why this classification: This changes what it takes to move a CAPA from Investigation to Implementation, so a qualification script can now stall where it previously proceeded. That is why it is classified “requalify”. The specific sequence that changes: approve the plan as QA, then edit the root cause, the problem statement, an action or the effectiveness plan, then approve as Approver. Until now the second approval advanced the CAPA, because the check asked only whether a signature row with that meaning existed. It never asked whether the approval still covered the plan. The result was a CAPA in Implementation carrying two approvals of which only one had been given to the plan as it actually read — four-eyes satisfied on paper and not in fact. There was also no way to put it right: the first approver could not re-approve, because the slot already carried their name and the system replied that they had no open slot to sign. Both halves are fixed together. A slot is now held only by an approval whose binding still holds, so a broken one reopens the slot and the original approver can sign again; the CAPA advances only when both slots are genuinely held, by two different people, exactly as before. One property matters to anyone assessing this and is deliberate: an approval that CANNOT BE JUDGED holds its slot. Signatures made before scoped bindings existed recorded a hash of the whole record, and whether the plan changed underneath them is not recoverable. Treating those as broken would have reopened plan approvals on every CAPA in the instance the moment this shipped and demanded re-approval of work that was almost certainly sound, on no evidence at all. Only a definite break reopens a slot. Two smaller properties worth recording: signatures are append-only, so a repaired slot keeps the superseded approval visible in the E-signatures table rather than replacing it, and the panel now names who approved the earlier version instead of showing the slot as simply “pending”, because “nobody has approved this” and “the approval no longer covers the plan” are different facts and the second is the more urgent one.
capa.test.tsOn a CAPA, each e-signature is now checked against the fields that signature actually approved, rather than against the whole record. Recording the effectiveness result no longer shows the earlier action-plan approvals as broken. The Binding column gains a third state, “not comparable”, used for signatures made before this change — they recorded a hash of the whole record, and what their own fields held at the time cannot be recovered. Nothing is refused that was permitted before, and no existing signature is altered or re-verified. A database migration is required: run supabase/capa_signature_scope.sql.
Why this classification: No signing rule changed, nothing that was accepted is now refused, and the stored signatures themselves are untouched — which is why this is “review” and not “requalify”. What changed is what the record TELLS you about its own signatures, and that is worth a validator's attention because until now it told you something false. A CAPA's binding was checked by asking whether a signature's hash still equalled the record's hash. But a CAPA's content grows legitimately as it moves: recording the effectiveness result is required before closure, and doing so changed the hash that the action-plan approvals had bound to. The consequence was that every CAPA which reached closure displayed both of its plan approvals as broken, on a plan nobody had touched. It was found by walking a real record: an Approver signature was applied, the effectiveness result was saved six minutes later, and the signature then read broken. ⚠️ A tamper indicator that fires on one hundred per cent of correctly-handled records is not detection. It is worse than absent, because it teaches whoever reads it to ignore the one occasion it means something — which is the opposite of what 21 CFR 11.10 asks a binding to do. Each signature meaning now carries the set of fields it covers: approving a raised request covers the problem as stated, approving the action plan covers the problem, the root cause, the actions and the effectiveness plan, and closing the record covers all of it including the result. That set is hashed and frozen on the signature at the moment of signing, and re-checked against the record as it stands. So altering the root cause after the plan was approved still breaks that approval, and adding or rewriting an action still breaks it, while recording the effectiveness result correctly leaves it alone. Two properties deserve stating. The first is the third state: a signature made before this change cannot be judged either way, because a whole-record hash cannot separate “someone altered what this signature covered” from “the CAPA moved on”. Those are shown as “not comparable” and are deliberately not shown as intact or as broken; computing a value for them would fabricate evidence about a Part 11 control, and they will remain in this state permanently. The second is that an unrecognised signature meaning is bound to the whole record rather than to nothing, so a signature added in future breaks readily instead of silently reporting itself intact. The wording of the record-level warning above the panel has also been corrected. It compares the record against its own stored hash and never against any signature, so it can only indicate a change made outside Indelio; it previously said the e-signature binding was broken, which was not what it had measured. ⚠️ This applies to CAPA only, and the reason it was needed only here is worth stating, because an earlier version of this entry stated it wrongly. Twenty other record types do still compare each signature against the whole record. That was described here as a known limitation certain to produce the same false “broken” elsewhere; a module-by-module review on 2026-08-24 found that it does not, and the earlier wording is withdrawn. Every one of those modules refuses a change to any hashed field once the record leaves the state it is editable in — by an editable-state helper, by refusing anything but Draft, or by naming the signed state and refusing it — and the signature is applied at or after that transition, so no hashed field can move underneath a signature. CAPA is the exception because its lifecycle REQUIRES a hashed write after signing: the effectiveness result must be recorded before closure. No other module has a mandatory post-signature write of a hashed field. ⚠️ Two limits on that review, stated so it is not read as more than it is. It establishes that no module can produce the false “broken” CAPA produced; it does NOT make whole-record binding as precise as scoped binding, and a genuine edit in any of those modules still breaks every signature on the record rather than only the ones whose fields moved. And it covers the SIGNATURE binding only — a write that changed a hashed column without recomputing the record's own hash would show on the record-level integrity indicator, which is a different check and was not part of this review. If the migration is not applied, signing is deliberately NOT blocked — new signatures are recorded without a scope and shown as “not comparable”, because refusing signatures on an un-migrated instance would be a worse failure than an unanswerable column.
capa.test.tsA field action is now closed by default by someone other than the person who approved its assessment — the health-hazard evaluation, the recall classification and the 21 CFR 806 reportability decision. If you approved that assessment, closing the same record is refused unless you record why you are closing it yourself; having done so, you may close it. The reason is stored on the record and the closure signature is unchanged in every other respect. Closure still requires the QA role, and still requires a recorded effectiveness result or a documented rationale for not performing one.
Why this classification: A refusal now exists where none did before, at the point a field action is closed, so a workflow you qualified may stop and ask for something it did not previously ask for. That is why this is classified “requalify” and not “review”: if your performance qualification includes closing a field action, and the same person performs the assessment approval and the closure in that script — which is likely, because until now nothing prevented it — the script will now be refused at the final step unless a reason is recorded first. Re-executing that part is the conservative course. What was there before is worth stating plainly, because it is the reason this changed. Corrections & Removals had no identity control of any kind. Every step checked a ROLE and stopped there, so one person holding the QA role could raise a field action, approve its health-hazard evaluation, set the recall classification, decide whether FDA had to be told, and then close the record — alone, on a recall. Every comparable module in the product has step-to-step separation; this one did not, and the product's own module reference described a segregation-of-duties control it did not have. That wording was corrected on 22 August; this change makes the original claim true instead. ⚠️ This is a default Indelio chose, NOT a regulatory requirement, and nothing in the product should be read as saying otherwise. 21 CFR Part 806 requires the correction or removal to be reported; ISO 13485 §8.3.3 requires nonconforming product detected after delivery to be acted on. Neither imposes an independence rule on whoever closes the record, and Indelio cannot be cited for lacking one. It is shipped as a default worth having, in the same shape as the CAPA effectiveness change of 21 August and on the same reasoning given then by our validation reviewer: default the control on, allow a recorded exception, and never remove the rule — because a hard refusal in a two-person quality team does not make the record safer, it makes closure impossible and the rule gets switched off. The exception is deliberately a written justification rather than a permission setting, so the decision lands on the record an auditor reads rather than in a configuration screen nobody looks at. One property is worth a validator's attention: the check FAILS CLOSED. If the list of assessment signatures cannot be read, closure is refused and says so, rather than resolving to “nobody approved the assessment, so this person is independent” — which would clear the very check being made, on a recall record. A database migration is required: run supabase/corrections_closure_independence.sql. Until it is applied, recording the exception is refused with a message naming that file, and closure by the assessment approver stays blocked.
corrections.test.tscopy-control-claims.test.tsThe 30-minute inactivity auto-logout now applies wherever you are in Indelio, including the signed-in dashboard at the site root. Previously the check was skipped on pages marked public — and because the root is both the marketing page and the dashboard, arriving at indelio.io skipped the check while still resetting the inactivity clock. The practical effect was that the auto-logout did not fire for anyone entering the site normally. You will now be returned to the sign-in page after 30 minutes of inactivity, with a notice saying the session ended on a timeout rather than a fault.
Why this classification: This is an access control that was not operating, and is now. It is classified “requalify” because behaviour you may have qualified changes in a way people will notice: sessions that previously persisted indefinitely will now end after 30 minutes of inactivity, and any script or procedure that assumed a session stayed open across a long gap will stop where it did not before. If your performance qualification includes a step performed after a break, re-execute it. What was wrong is worth stating precisely, because the control was recorded as working and was not. The inactivity check was skipped on any page marked publicly reachable. The site root is on that list — necessarily, since it must serve the marketing page to signed-out visitors — but for a signed-in user the same route renders the dashboard. So the one page every user enters through was exempt from the check, while the code that refreshes the inactivity timestamp was not similarly scoped and stamped it forward anyway. Arriving at indelio.io therefore turned a stale session into a fresh one: the page that could not expire you was renewing you, and the next page you opened saw activity seconds old. Because that is the only entry point, the auto-logout had effectively never fired. Both halves are corrected together, and the correction is that the check and the refresh now share exactly one condition — a page that cannot log you out cannot keep you logged in either. Pages where a redirect would be wrong remain exempt and are named explicitly rather than inferred: the sign-in page itself, which is where an expiry sends you and would otherwise loop; the forced password-change flow, which must survive an expiry or a mandatory change deadlocks the account; and API and authentication callbacks, which cannot act on an HTML redirect. No database migration is required. ⚠️ This was reported by a user asking why the site opened straight into his previous session, not by our test suite — which asserted that the timeout logic was correct without ever asserting which pages it ran on. Tests covering that scope, and three injected mutations reproducing the original defect, ship with this change.
idle-timeout.test.tsA record that has never been signed no longer displays the warning that its electronic-signature binding is broken. Thirteen modules showed that banner whenever the stored content hash did not match the record, without first checking that any signature existed — so a brand-new draft could be shown, in red, that an integrity control on it had failed. Separately, a newly created field action now stores a content hash that describes the record as saved. It previously described the record as submitted, which differs whenever the database supplies a default the form did not, so field actions were created with a mismatched hash and displayed that warning immediately.
Why this classification: No control changed. Nothing that was permitted is refused, no signature, role or lifecycle rule moved, and no record's integrity was ever actually at risk from either half of this. It is classified “review” rather than “none” because what was wrong was an INTEGRITY REPORT, and a quality function may reasonably have acted on it. If anyone investigated a record because Indelio told them its signature binding was broken, that investigation was chasing a display fault; the underlying signatures were bound correctly to whatever the record held when they were taken. The first half is the banner. It was rendered on the hash comparison alone, so any record whose stored hash did not match — including one with no signatures at all — was told its binding had failed. That is worse than cosmetic: the message says an integrity control has failed, and firing it where nothing has been signed teaches people to disregard the one warning that must never be ignored. Five modules already had the correct form; the other thirteen have been brought into line, and a check now requires every page that renders this banner to gate it, so a new module cannot arrive without one. The second half is why the mismatch existed at all on field actions. The content hash was computed from the values being submitted and the record was then inserted, at which point the database applied its own column defaults — reportability defaults to “Undecided” when the form leaves it unset. The stored hash therefore described a row that had never existed, one where reportability was null. The hash is now recomputed from the row the database returns and settled before the create completes, which is correct for every column default rather than for the one that was noticed. Existing records are unaffected in substance; a field action created before this change carries the old hash until it is next edited, at which point it is recomputed correctly through the normal audited update. ⚠️ Found by a user creating a field action and reading the screen, not by the test suite — which asserted the hash function was correct without ever asserting that the value stored alongside the record described that record.
corrections.test.tsui-surface.test.tsThree database migrations that had never been committed are now part of the shipped installation: row-level security on the organisations table, and the table definitions for per-organisation settings and per-user dashboard preferences. A running instance is unaffected — all three already exist there, and the migrations are written to change nothing where they are already in place. What changes is what a NEW installation produces. Two further consequences: the installation qualification protocol's migration count moves from 79 to 82, and the tenant data export now names per-organisation settings and per-user preferences as deliberate exclusions, each with its reason, rather than not mentioning them.
Why this classification: This is recorded as requalify because for any instance built from the shipped migrations, a tenant-isolation control that was absent is now present, and the installation qualification report gains steps. On the existing running instance nothing changes at all, and no record, signature, role or lifecycle rule is affected anywhere. The reason it matters is the direction of the gap. The running instance had row-level security enabled on the organisations table, but no committed migration ever enabled it — it had been switched on by hand, with no migration, no record and no change control on a tenant-isolation control. Two further tables, per-organisation settings and per-user preferences, existed on the instance with no definition in the shipped migrations at all; three separate migrations had been adding columns to a settings table that, as far as the shipped installation was concerned, did not exist. An organisation installing from the shipped migrations would therefore have got an installation that stopped partway, and — had it continued — one whose organisations table had row-level security switched off. A table in that state is readable with the public application key, which by design reaches the browser, so organisation names, tenancy types and trial dates would have been exposed. The step that says all migration files are applied would have been confirmed against an instance whose tenant isolation was never installed. ⛔ THE SECOND FINDING IS THE SERIOUS ONE, AND IT WAS FOUND ON THE RUNNING INSTANCE. Checking what access rules those hand-made tables actually carried showed that per-organisation settings granted every signed-in member of an organisation full read AND WRITE access to their own organisation's settings row, directly, using the public application key that by design reaches the browser. That row holds two switches which govern when an electronic signature may be taken: whether attached evidence must be opened before signing, and whether a reviewer must state a review context. Both could therefore be switched off by anyone in the organisation, whatever their role — including a role that deliberately carries no signing authority at all — without passing through the application, and so WITHOUT THE AUDIT ENTRY the application writes whenever either switch is changed. A control governing signatures could be disabled with no record of who disabled it, which is the property Part 11 exists to guarantee. The same rule exposed the organisation's encrypted AI key and the stored hash of its complaint-intake token to the same audience. This release removes that access rule outright rather than narrowing it to read-only: all twelve places in the application that touch this table use the privileged server connection, which is not subject to these rules at all, so removing it costs no function and returns the table to refusing everything. A check is included that refuses to install if any access rule is present on that table under any name, so it cannot return quietly. NOTHING IS KNOWN TO HAVE BEEN CHANGED THIS WAY — the audit trail carries every switch change made through the application, and no evidence of any other route was looked for or found; what is being reported is that the route existed and would have left no trace. Anyone whose qualification relies on those two switches having held their recorded value should consider that when reviewing this release. Two smaller notes for a validator. The organisations table is given no read rule at all, because nothing but the privileged connection reads it, and that is stated in the migration so it is not later mistaken for an omission. And the per-user preferences rule was compared against the live instance — name and expression both — before being written down, rather than reconstructed from intent; that comparison had to be run by hand, because the installation check counts these rules without reading them, which is precisely why a rule granting full write access sat beside a correct one and looked identical to it. ⚠️ Found by comparing the running instance's row-level security against every such statement in the shipped migrations. No test found it, and none could have: every check in the suite reasons about the migrations, and the gap was between the migrations and the database.
export.test.tsschema-manifest.test.tsprotocol-code-sync.test.tsiq-check.test.tsThe automated installation check now reads what each database access rule actually permits, instead of only counting how many exist, and fails the installation if any rule lets an ordinary signed-in user WRITE to a table. A database migration is required to enable it: run supabase/iq_policies.sql. Until it is run, the new check reports NOT CHECKED rather than passing.
Why this classification: No record, signature, role or lifecycle rule changes; this adds a step to the installation qualification evidence, and anyone whose installation qualification cites that report's contents should re-run it and re-file the output. The reason it exists is worth recording plainly. The two access-rule checks that already existed asked whether protection was switched on for every table, and whether each table had at least one rule. Neither ever asked what a rule SAID. A rule granting every signed-in member of an organisation full read and write access to their own organisation's rows scored exactly the same as one granting read-only access, and the release above is the case in point: a rule of the first kind sat one row away from a rule of the second kind, both checks reported the installation clean, and what found it was a person running a query by hand. An installation check that cannot distinguish those two is not evidence about access control; it is evidence about arithmetic. The new check reads the rules and fails if any of them grants a write to a role the browser can reach. Three properties deserve a validator's attention. It treats the wildcard ALL as a write, which is the specific thing that was missed — a wildcard rule reads as a scoping rule and is one, it simply scopes writing as well as reading. It ignores rules scoped only to the privileged server connection, which is correct, because that connection is not subject to these rules at all. And it FAILS TO NOT CHECKED in two separate ways: if the rules cannot be read, and — this is the one worth noting — if the rules come back EMPTY while the older count says rules exist. Two readings of the same objects that disagree is not a clean result, and an empty list would otherwise have graded as “nothing to object to”, which is the precise failure this check was written to catch and would have been indefensible to reproduce. ⚠️ SCOPE, STATED SO IT IS NOT OVERSOLD: it asks who may write, not whether a rule's tenant-scoping expression is correct. A rule that grants read access using the wrong expression is a different defect and this check will not find it. It is also worth recording that the shipped migrations declare twenty tables with wildcard rules that the write-lockdown migration does not name; whether those are in force on any given instance is now something the installation check answers on every run, rather than something someone has to think to ask.
iq-check.test.ts⛔ SECURITY. Forty-three database access rules across thirty-seven tables allowed any signed-in member of an organisation to CHANGE records directly, using the public application key, without going through the application. Nine of those allowed INSERTING A ROW INTO A SIGNATURE TABLE — that is, applying an electronic signature that the application never authorised, never bound to the record, and never recorded in the audit trail. All forty-three are removed by supabase/rls_lockdown.sql, which must be run. Reading is unaffected: twenty of the removed rules also served reads, and each has been replaced by a read-only rule carrying the identical scoping expression.
Why this classification: This is the most serious finding recorded here and it should be read in full. The application writes every row through a privileged server connection that is not subject to these access rules; the browser's connection is used for reading only. An access rule granting the browser permission to write is therefore never load-bearing and always an exposure — it is a second way into the data that goes around the code where authorisation, segregation of duties, the binding of a signature to the record's content, and the audit entry all live. THE NINE SIGNATURE TABLES ARE THE PART THAT MATTERS. On the affected tables the only condition on inserting a signature was that the row named your own organisation. No role was checked, no password was re-entered, nothing was bound to what was being signed. The append-only protection on those tables does not prevent it: it is present on all nine, and it blocks changing or deleting an existing signature, which is a different act from creating one that never happened. Nor is the consequence confined to display. The design-controls module READS one of those tables to enforce that a verifier and a validator are different people, so a fabricated row naming somebody else does not merely appear genuine — it feeds that decision and inverts the control, making the named person appear to have signed and changing who the system will then permit to sign. In Part 11 terms this reaches signature/record linking and the signature-components requirement, and the audit trail would show nothing, because the write never reached the code that writes audit entries. NOTHING IS KNOWN TO HAVE BEEN DONE THIS WAY. The audit trail records every signature applied through the application; a signature applied by this route would not appear there, so its absence is not proof either way, and no evidence of use was sought or found. What is being reported is that the route existed. Anyone relying on signatures in the design, equipment, management-review, human-factors, assessment or usability records should take that into account when reviewing this release. The modules listed are derived from the affected tables rather than chosen: assessments, CAPA (action items), design controls, document configuration, equipment, the five human-factors modules, management review, risk review, and trend disposition. HOW IT SURVIVED THIS LONG IS THE PART WORTH FIXING. An earlier migration closed exactly this hole and closed it correctly — for the twenty tables that existed when it was written — and an automated attack suite proves it live across six. Both were true and both were narrow. Every module shipped since added its own rules and joined neither list. A hand-maintained list fell behind the schema, and nothing compared the list to the schema. Two checks now do, and they cover different things on purpose: one derives every write-granting rule the migrations declare and refuses to merge unless a lockdown file removes it, so a new module cannot ship this shape; the other reads the LIVE instance during installation qualification and refuses to qualify it while any such rule is in force. The second is what found these — the two older access checks, which ask whether protection is switched on and whether each table has at least one rule, both reported the instance clean. ⚠️ THE REPLACEMENT READ RULES ARE NOT COSMETIC: twenty of the removed rules were the only rule on their table and served reads as well as writes. Removing them without replacement would have taken those modules offline for every tenant. All twenty were confirmed to carry the identical scoping expression before the replacements were written, and a check refuses this migration if any table it strips is left unreadable. ⭐ RECORDED AS A DEVIATION, WITH FOLLOW-UP ACTIONS. Independent validation review confirmed on 2026-08-24 that for a defect of this kind, a register entry carrying the deviation and its associated follow-up actions is a sufficient record, and that no separate corrective-action file is required. THE DEVIATION: for a period ending 2026-08-24, an electronic signature could be recorded against a quality record without passing through the application — and therefore without the identity re-verification at the moment of signing, the segregation-of-duties checks, the binding of the signature to the record's content, and the audit entry that the application applies to every signature. There is no evidence that this occurred. By the nature of the defect there would be no evidence either way: a write taking that route leaves no audit entry, which is the reason it cannot be ruled out rather than a reason to assume it happened. That is stated here rather than left for a reader to infer. FOLLOW-UP ACTIONS AND THEIR STATUS. (1) COMPLETE — the removal migration is now GENERATED from the schema instead of hand-maintained. Two hand-written versions preceded it and both fell behind as new modules shipped, which is the mechanism that allowed this to accumulate rather than any single mistake. (2) COMPLETE — the installation qualification gained a check that reads what each access rule PERMITS and refuses to qualify an instance where any rule lets a browser-reachable role write, plus a second check that every read rule is scoped to a single organisation. The two checks that existed before asked only whether protection was switched on and whether each table had at least one rule; both reported this instance clean throughout. (3) COMPLETE — the adversarial test that runs against a live instance was widened from one signature table to all twenty-three. It had been cited as evidence that signature forgery by direct write is blocked, and it tested that on a single table. ⚠️ AMENDED 2026-08-25, because COMPLETE was too strong and the way it was too strong is worth stating. Widening the test was done. The automated pipeline that runs it, however, reached only ONE of the twenty-three, because the disposable database that pipeline uses had been built by hand from three files and carried only that one table. The remaining twenty-two were recorded on every run as absent and the run passed regardless, so the evidence the pipeline actually produced covered a twenty-third of what this action claimed. Nothing was wrong with any individual check. What was missing was anything that judged how much of the subject had been reached. The pipeline now installs the complete schema from the migrations before it tests, so all twenty-three exist and are attacked there, and a shortfall in coverage is now a failure rather than a line in a log. That is the same defect this deviation records — a control believed to be in force because a document said it was — found this time in our own evidence rather than in the product. (4) COMPLETE — a repository check now compares the access rules the migrations leave in force against the rule that no browser-reachable role may write, so a new module cannot ship this defect and remain green. (5) OPEN — nine tables are deliberately excluded from the tenant-isolation check, each with a written reason, and that exclusion list has not been reviewed by anyone independent. Our validation reviewer has recorded that assessing it calls for information-security expertise rather than quality-systems expertise. An independent security review of those nine exclusions is outstanding and is the remaining open action on this entry.
rls-lockdown.test.tsiq-check.test.tsThe installation check's list of tables that are private by design — closed to everyone except the server's privileged connection — now records WHY each one is on it, names them all on the report rather than passing over them silently, and fails the installation if an access rule ever appears on one of them. Six tables were added to that list after their access paths were read: the two vendor compliance tables, the failed-login lockout table, the signup queue, the per-organisation settings table and the organisations table.
Why this classification: No record, signature, role or lifecycle rule changes; this affects the installation qualification report, so anyone whose qualification cites it should re-run and re-file. Three things changed and the second is the one that matters. First, the list was a bare set of table names, and the check's PASS read "every tenant-facing table has at least one access rule" without ever saying which tables it had waived. An exemption nobody can see is indistinguishable from a check that is not looking, so each entry now carries its reason and the report names every table it waived. Second, being on that list is a CLAIM — that nothing reads the table except the privileged server connection, and therefore that having no access rule is correct rather than an omission. The check now enforces the other half of that claim: if an access rule appears on one of those tables it FAILS, because the claim has been broken by hand, outside the migrations. That is precisely what happened to the settings table, where a hand-made rule granted every tenant member full write access and sat unnoticed because the check only ever asked whether a rule existed — and one did. Third, the six additions were made only after reading every place in the code that touches each table: twenty-four for the organisations table, twelve for settings, and all of them use the privileged connection. ⚠️ Being on this list REMOVES a table from a tenant-isolation check, so it is not a way to quiet a failure, and the reason recorded beside each name is what an independent reviewer should challenge.
iq-check.test.tsThe order in which the database migrations must be applied is now written down, in supabase/run-order.json, and the installation protocol cites it. It is NOT alphabetical — applying them in the order a directory listing shows them will fail. Two corrections come with it: one file that was being counted as a migration to apply is a historical record that says DO NOT RUN and contains no executable statements, so the number of files to apply is 83 rather than 84; and the per-organisation settings migration written the previous day is now pinned ahead of the three migrations that add columns to it.
Why this classification: No record, signature, role or lifecycle rule changes. It is classified review because it changes an installation qualification step that a customer's executor performs, and because the step as previously written could not be performed correctly. The protocol said the migrations are "applied in order" and never said what the order was, so the real order existed only in the builder's head while the protocol asked somebody else to confirm the result. It is not alphabetical by a wide margin: under an alphabetical listing, 172 files need a table, function or type that a later file creates. The core migration defines the tenancy tables and the function nearly every access rule calls, and does not sort first. So the order is declared in a file, the protocol names that file as the authority, and a check holds the two together — every migration must be either in the order or on a short exclusion list with a stated reason, and none may need something a later one creates. Two things surfaced while building it, both worth recording. One file in the migrations folder is a HISTORICAL RECORD rather than a migration: it is entirely inside a block comment, states DO NOT RUN, and preserves the definitions of two retired privileged functions so the removed objects stay describable. It was being counted among the files to apply, so the stated count was 84 when the number an executor should actually apply is 83; running it would have been harmless, but the instruction was wrong. And the per-organisation settings migration released the previous day had not finished the job it was written for — it fixed three migrations that altered a table nothing created, and simply MOVED the hazard, because it must now run before those three and nothing said so. ⚠️ THE HONEST CAVEAT IS ABOUT THE CHECK ITSELF. Its dependency model was incomplete three times over, and each time it returned a confident clean answer against an order that could not have installed — first ignoring foreign keys, then function calls, then enum types. Every one was found by reading the generated order and asking why a particular file was first, never by the check reporting a problem. It now models tables, functions and enum types, and it models nothing else; a pass means no migration needs one of those three things too early, and never that the order is correct in every respect.
sql-run-order.test.tsprotocol-code-sync.test.tsThe installation check now also verifies what each READ rule is limited to, not only who is allowed to write. A rule letting the browser read a table fails the installation unless it names the current organisation, compares it to the row's organisation, is not an unconditional "allow everything", and is not widened by an OR. Nothing on the running instance fails it — all eighty-six rules are already correctly limited — so this prevents a future mistake rather than correcting a present one.
Why this classification: No record, signature, role or lifecycle rule changes, and no rule on the running instance changed; this adds a step to the installation qualification evidence, so anyone whose qualification cites that report should re-run it and re-file the output. It exists because the check added earlier in this release asks only who may WRITE, and the two failures are different. A write rule lets somebody create or alter a record inside their own organisation, going around the application. A badly limited READ rule hands one customer another customer's records, which is the single guarantee a shared system cannot afford to get wrong. Each of the four conditions is there because a rule can satisfy the others and still leak: an unconditional "allow everything" reads as a rule and exposes the whole table; naming the current organisation but comparing it to the wrong column limits nothing; and an OR only ever widens what is visible. A STRICTER rule passes — the per-user preferences table additionally limits each person to their own rows — and write rules are left to the other check rather than double-reported. ⚠️ THE LIMIT IS WORTH STATING PLAINLY, AND IT IS SHARPER THAN THE OTHER CHECKS'. This proves a rule NAMES the tenancy condition and is not obviously widened. It does NOT prove the condition is correct: a rule that joins to the wrong parent table would satisfy every one of the four and still be wrong. It narrows the range of possible mistakes, it does not eliminate them, and an OR being reported is a request that a person read the rule rather than an assertion that it is faulty. Verified against the running instance when written: eighty-five of the eighty-six rules are the same single expression, the eighty-sixth is the stricter one, and the check reports nothing.
iq-check.test.tsThe two database access-lockdown migrations are replaced by ONE, and it is now generated from the schema rather than written by hand. Applying it requires a short one-time step first, because twenty access rules created yesterday revert to their original names; the rules themselves are unchanged. No rule gains or loses any permission — this was verified against the running instance, rule by rule, before the change was made.
Why this classification: No record, signature, role or lifecycle rule changes, and no permission changes anywhere; what changes is how the lockdown is maintained. It is classified review rather than none because it alters a migration a customer applies and renames twenty access rules, so an installation qualification that lists them by name should be re-run and re-filed. The reason is the pattern rather than the file. There were two lockdowns. The first was written by hand for the twenty tables that existed when it was written. The second existed ONLY because the first had fallen behind a schema that kept growing — by the time anyone looked, forty-three access rules across thirty-seven tables let ordinary signed-in users write, nine of them into signature tables. Writing a third by hand would have gone stale in exactly the same way, for exactly the same reason, so the list is now derived: a script reads every access rule the migrations declare, finds the ones still in force that permit writing, and emits the removals along with a read-only replacement for any table that would otherwise be left unreadable. A check asserts the committed file is current, so a new module that ships a permissive rule and forgets to regenerate cannot merge. Two safeguards deserve a validator's attention. Each read-only replacement carries the ORIGINAL rule's own tenancy expression, copied rather than defaulted, so what each tenant can read is unchanged — and the generator REFUSES to produce a file at all if an expression cannot be read, rather than substituting a plausible one, because a guessed tenancy condition applied to a customer's database would silently widen or narrow access with nothing to show for it. And the result was checked against the running instance before being adopted: eighty-six rules before, eighty-six after, every one matching on table, permission and tenancy condition, with the only differences being the twenty names.
rls-lockdown.test.tssql-run-order.test.tsPowerPoint decks and Word documents stored as controlled documents can now be read on screen inside Indelio, so a reviewer can see the document they are signing instead of downloading a file. Where that happens the system records that it was displayed to that person, which is a different and stronger record than a download — and is still not a record that they read it. In Design Controls, a design review now records who took part and the function each of them represented, and the rule that the signer could not be the person who created the design project has been withdrawn. In CAPA, the effectiveness check now expects to be signed by someone other than the person who carried the actions out.
An organization administrator can now download the whole of their quality system from Settings, as a zip containing one CSV per table — every record, the complete audit trail with its hash columns intact, and every electronic signature. The archive states what it contains and what it does not: file CONTENT is not included, and an index names every uploaded file, its size, and the record it belongs to. The audit hash chain in the export can be re-walked by anyone, using nothing but the CSV, with no access to Indelio and no cooperation from us. The download is itself recorded in the audit trail, including whether it came out complete.
Why this classification: Nothing you previously qualified behaves differently, nothing that was permitted is now refused, and no signature, role or lifecycle rule changed — so this is not a requalification. It is classified “review” rather than “none” for two reasons, and both are worth a quality reviewer’s attention. The first is that it addresses a Part 11 clause our own validation package records as only partially met. §11.10(b) requires the ability to generate accurate and complete copies of records, in human-readable and electronic form, suitable for inspection and copying by the agency; until now the only routes were per-record PDFs, one record at a time, which is a poor answer to an inspector asking for the complete set. Whether this clause should now be assessed differently is a judgement for your validator and ours, not one we make by shipping the feature — the status in our Part 11 matrix is deliberately left where it is pending independent review. The second is that a new bulk export of every quality record is a data-egress capability your own procedures may need to speak to. It is restricted to the Administrator role and every download writes an EXPORT_ORG_DATA entry to the immutable audit trail naming who took it and when, so the act is visible; but if your quality system controls who may remove records from the system, that control is now yours to state. It is deliberately NOT gated on a signing role: taking your own records out is an administrative act rather than a quality decision, and it would be perverse to make the vendor the gatekeeper of your route out of the vendor. Three properties determined how it was built, and each exists because the opposite failure is the dangerous one. An export that quietly omits something is worse than no export, because it is indistinguishable from a complete one — so a table that cannot be read is recorded as FAILED in the manifest and its CSV carries the failure text, never an absent or empty file, and the archive marks itself incomplete whenever that happens or the audit chain does not verify. The set of tables exported is checked against the database schema on every build, in both directions, so a table added in future that nobody adds to the export breaks the build rather than silently going missing from customers’ archives. And one table carrying an organization identifier is deliberately excluded and named as excluded: the vendor’s own signup queue, whose rows hold other prospects’ contact details and whose organization link is stamped after provisioning rather than being a tenancy anchor. Finally, values are neutralised against spreadsheet formula injection, because this artefact exists to be opened in a spreadsheet, which is exactly where a stored value beginning with an equals sign stops being text. No database migration is required; the export reads what is already there.
export.test.tsSix statements in the product that described a segregation-of-duties control Indelio does not enforce have been corrected — in the in-product help, the module reference, the FAQ, the admin page, the document signing panel, and SOP-QMS-001 in the SOP template library. Nothing about how the product behaves has changed. What changed is that it now describes the controls it actually has. Two corrections matter most. Indelio does NOT prevent the author of a document from signing a REVIEW of their own document — it prevents them approving it — and five places said otherwise, including the panel where that review is signed and the Document Control SOP template. And Corrections & Removals is NOT subject to a segregation-of-duties rule: one person holding the QA role can raise a field action, approve its health-hazard evaluation, recall classification and 806 reportability decision, and close it.
Why this classification: No controlled function changed, nothing is refused that was permitted before, and no signature, role or lifecycle rule was altered. It is classified “review” rather than “none” because the statements being corrected are statements about CONTROLS, and you may have relied on them. If you wrote either of the two above into your own procedures on the strength of ours, that is worth correcting on your side, and if your quality system requires design or document reviews to be independent of the author, or requires a field action to be closed by someone other than the person who assessed it, those are now procedural controls you state and evidence rather than ones the system refuses for you. How this happened is worth stating, because it is the more useful part. Neither statement was wrong when written. Each described a control that was later relaxed on deliberate advice — the CAPA closer-versus-plan-approver rule in July 2026, and the document author’s review signature in August 2026, the latter because the stricter form could leave a document that nobody was able to approve. In both cases the rule was changed and the sentences describing it were not, and nothing in the build could notice: automated tests assert what the code does, and until now nothing asserted that what the product SAYS matches it. A test suite has been added that derives each rule from the shipped function and checks the wording against it, including one check deliberately written to fail if a segregation-of-duties control is ever added to Corrections & Removals, so that the wording is updated as part of that change rather than afterwards. The SOP-QMS-001 template has been updated; a template seeds a DRAFT that runs your own review and approval, so no procedure you have already approved changed under you, but if you adopted an earlier copy of it the paragraph on segregation of duties and the Author and Reviewer role rows are the ones to re-read.
copy-control-claims.test.tsfour-eyes.test.tstemplates-sync.test.tsClosing a CAPA now expects the effectiveness check to be signed by someone other than the person who carried the actions out — either the owner of an action or whoever marked it Done. If that is you and nobody else is available, you can still close it, but you must record why; the reason is kept with the CAPA and printed on its report. Completing a CAPA action now also records who completed it, on the action itself. Two statements about CAPA that were not true have been corrected at the same time: the in-product help said the person who closes a CAPA cannot be the one who created it, and the module reference said the effectiveness signer must differ from the person who approved the plan. Neither was enforced.
Why this classification: A closure gate was added (ISO 13485 §8.5.2). A CAPA that you would previously have closed may now be refused until either another QA user closes it or you record a reason for closing it yourself, so if your performance qualification exercises CAPA closure, add the case: close a CAPA whose actions you owned, confirm the refusal, record the reason, confirm the closure. State plainly what this is and is not. It is an Indelio DEFAULT, not a regulatory requirement: §8.5.2(f) requires the effectiveness of a corrective action to be reviewed and sets no independence rule for who reviews it, and the wording you see says so — we will not tell you a standard obliges something it does not. It was recommended by an independent regulatory consultant (RAC) reviewing the module, whose advice was to default the control on and allow a recorded exception rather than choose between enforcing it and dropping it. Three properties matter to a quality reviewer. The gate reads who OWNED an action and who MARKED IT DONE, because ownership is an assignment rather than a record of doing, and a gate reading only ownership is satisfied by assigning the work to someone else and doing it yourself. Reopening a completed action does not erase who completed it. And where a CAPA’s actions cannot be read, the closure is REFUSED rather than allowed — a read that failed must never resolve to “no implementers, therefore this signer is independent”. Separately, the two corrected statements: neither described anything Indelio enforced. The data layer stores who created a CAPA and has never compared it to the person closing it, and the rule that the closer differed from the plan approver was deliberately relaxed in July 2026 on validation-review advice, because it is not required by regulation and can block closure in a small quality team — QA closing the record independently is the control that matters, and it is unchanged. If you wrote either statement into your own procedures on the strength of ours, that is worth correcting on your side too. ⚠ This release requires a database migration (supabase/capa_effectiveness_independence.sql). Until it is applied, existing records are unaffected, but marking a CAPA action Done will fail and the new closure gate will read only action ownership.
capa-effectiveness-independence.test.tscapa.test.tsA design review in Design Controls now records who took part and the function each of them represented, and will not be signed until it does. You are recorded as a participant of the review you sign and state your own function alongside the others; a participant does not need an Indelio account, so a contract engineer, consultant or clinician can be named. Where nobody else took part, the review is still accepted — but you must record why, and that reason is kept and shown with the review. At the same time, the rule that a design review could not be signed by the person who created the design project has been WITHDRAWN: that person may now sign a design review, provided the participants are recorded. Both changes appear on the design page and in the Design History File report.
Why this classification: Two controls changed in opposite directions, and both belong in your assessment. A restriction was REMOVED: until this release Indelio refused a design review signed by the creator of the design project, and it no longer does. The grounds are that the requirement it was enforcing does not exist — legacy 21 CFR §820.30(e) is RESERVED under the QMSR, and ISO 13485 §7.3.5 sets no independence rule for design reviews — so the check enforced a good practice as though it were a regulatory requirement being failed, which is not a defensible position for a system to take on your behalf. The removal was reviewed by an independent regulatory consultant (RAC) and authorised by name and date by Indelio’s founder before it was made. It is NOT a relaxation of segregation of duties elsewhere: the four-eyes rule on document release, and the rule that the validation signer cannot be the verification signer, are untouched. A requirement was ADDED in its place, and it is the one the standard actually states: ISO 13485 §7.3.5 requires the review record to include the identification of the design under review, the participants involved, and the date. Indelio recorded the design, the date, the outcome and the single signer — so it recorded the signature and called it the review, and there was nowhere to put anybody else. A design review is now refused until the participants and their functions are recorded. If your quality system requires design reviews to be independent of the designer, that requirement is yours to keep: state it in your design control procedure and evidence it through the participants now recorded on each review, because Indelio will no longer refuse the signature for you. Two things a quality reviewer should know about how it behaves. The single-participant case is an exception rather than an exemption — the review is accepted, the reason is mandatory, and it is stored and displayed only where it was actually taken, so a review with several participants can never appear to have claimed one. And where the participants of a review cannot be READ, Indelio says exactly that, on the page and in the DHF report, rather than showing the review as having none — an unreadable record must never be presented as an incomplete one next to a signature. ⚠ This release requires a database migration (supabase/design_review_participants.sql). Until it is applied, existing records are unaffected and unchanged, but a new design review cannot be recorded and the product will say so.
design-review-participants.test.tsfour-eyes.test.tsdesign-controls.test.tsA Word (.docx) controlled document can now be read inside Indelio. Its text, headings, lists, tables and pictures are drawn on screen, and the page header and footer are shown with it — so a reviewer or trainee can read the document without downloading it or having Word installed. Where the whole document is shown, that is recorded as a delivery in the same way viewing a PowerPoint deck is, and it satisfies the requirement to have been given the document before signing. If any part of the document cannot be shown, Indelio says which part, shows what it has, and records nothing. Legacy .doc and .ppt files are unchanged: Indelio cannot display them, they still save to your downloads, and the product now says that saving them as .docx or .pptx would let them be shown on screen instead. ⚠ Corrected shortly after release on the same day: for about an hour, a table in a Word document was drawn as an empty grid with its cell contents shown as ordinary paragraphs above it. The document's words were all present and none were altered, but a table did not read as a table. If you looked at a Word document containing a table in that window, look again.
Why this classification: A control changed, in the same way and for the same reason as the PowerPoint viewer earlier in this release: the precondition for signing a file-backed controlled document — that the document reached the signer — can now be satisfied a second way for Word files, by the document being displayed, in addition to the file being downloaded. The requirement itself is unchanged and no signature rule, role or lifecycle rule was altered, but the evidence a signature rests on is now produced by a path that did not exist before, so re-executing the part of your performance qualification covering review and approval of uploaded Word documents is the conservative course. One property is worth stating for a quality reviewer, because it determined how this was built. The conversion library Indelio uses renders the document body and discards headers and footers WITHOUT reporting that it has done so — confirmed by testing a file that carried text in those places. On a controlled document that is a serious omission to make silently, because the document number, revision, effective date and any print-control statement typically live there, and they are what a reviewer checks to confirm they are looking at the right document. Indelio therefore extracts and displays the header and footer itself, and decides whether a document was shown in full from its own examination of the file rather than from the library reporting success: comments, footnotes and endnotes are detected and named where present, tracked deletions are detected because a deletion does not render and the reader would otherwise see the document as if every deletion had been accepted, and any element the renderer does not recognise is recorded rather than skipped. Anything not shown is listed on the page and prevents the delivery record being written, so a partial rendering can never satisfy the signing gate. As with the deck viewer, this records that the document was displayed to a named person, from an identified set of bytes, at a stated time — it is not evidence that they read it, and the record is made against a signed-in session rather than against a pair of eyes.
docx-render.test.tsdocument-delivery.test.tsslide-viewer.test.tsA revision that was started and is not going ahead can now be discarded. Nothing is deleted: the version is kept and marked “Discarded”, the reason you give is recorded in the audit trail, and any signatures already applied to it stay exactly where they are. Until now there was no way to do this — the system refused a second revision with “Finish or discard it first” and offered no discard, so an abandoned revision held the document’s revision slot permanently and the only way out was to take an unwanted version through review and approval. The Effective version in force is untouched, and the document can be revised again afterwards. QA can discard any abandoned revision; the person who started one can discard their own only while nobody has signed it.
Why this classification: A lifecycle state was added and a new disposition of a controlled record with it (21 CFR 11.10(a), (e); ISO 13485 §4.2.4). Documents can now hold a version in a state your qualification has not seen, and a revision can leave the in-progress slot without having been approved, which is a path through the lifecycle that did not previously exist. If your performance qualification exercises the revision lifecycle, add the case: start a revision, discard it, confirm the Effective version is still the one served and that the document can be revised again. Three properties are worth stating for a quality reviewer. First, discard is not deletion and cannot be made into one — the version, its content hash and its signatures are retained, and the audit trail records who discarded it, from which state, whether it had been signed, and the reason they gave, which is mandatory. Second, “Discarded” is deliberately not “Obsolete”: an obsolete version was in force and has been superseded, while a discarded one was never in force, and collapsing them would attribute a history to the document that it never had. Third, an Approved version awaiting its effective date CANNOT be discarded by this — withdrawing a release that has already been signed off has different consequences for training and for anyone expecting it, and it is deliberately not covered here. ⚠ This release requires a database migration (supabase/discard_revision.sql). Until it is applied the rest of the product is unaffected and no existing behaviour changes, but attempts to discard a revision will fail.
doc-control-phase1.test.tsrelease-gate.test.tsEach electronic signature on a document stored as an uploaded file now also states how long before the signature the document was last put in front of that signer — for example “shown in Indelio, 4 seconds before signing” or “the file was sent, 2 days before signing”. The interval was always in the delivery record and was never shown. Separately, the slide viewer now states plainly that the record it writes is made against your signed-in session and cannot tell whether you, or software acting on your behalf, was at the screen.
Why this classification: No control changed. Nothing is refused that was previously permitted, no signing rule was altered, and the records are the ones the system has been writing since delivery was first recorded. It is classified “review” rather than “none” because a signature manifestation gains a clause, which a qualification script asserting that text will notice, and because the second half states a limitation of the evidence that a validation reviewer should see rather than infer. That limitation is the reason for the change and is worth stating here in full. A delivery record evidences that a document was displayed to a signed-in session. It cannot evidence who was at the screen: software operating a user’s own browser carries that user’s session, address and browser identity, and produces a delivery record identical to a person reading. Indelio does not attempt to detect that and makes no claim to. Attempting it would mean presenting a guess as evidence, and restricting delivery by address or by a time window would prevent none of it while obstructing ordinary use. What the system can do is report the interval, which is a fact rather than an inference, and let your quality function weigh it: a signature applied seconds after a long document was rendered and one applied two days later are different circumstances, and the record now shows which occurred. Nothing here is evidence that the signer read the document, and none of this wording says so — the electronic signature remains the signer’s own attestation, and this changes nothing about their accountability for it.
document-delivery.test.tsEach electronic signature on a document stored as an uploaded file now states how that signer received the file: shown on screen in Indelio's viewer, sent to them as a file, or both. It appears beside the signature, alongside the time, the content hash and the signer's IP address. The system already recorded this for every delivery; until now it was held in the database and shown nowhere, so the difference could only be retrieved with a direct database query. Where no delivery is on record the signature says so, and where the record could not be read it says that instead — those are different statements and are worded differently.
Why this classification: No control changed. Nothing is refused that was previously permitted, no rule about who may sign or what must precede a signature was altered, and the underlying records are the same ones the system has been writing since delivery was first recorded — this release only reads them back and displays them. It is classified "review" rather than "none" because it changes what a signature manifestation shows, and that is material to how you evidence document review: a qualification script that asserts the text beside a signature will now find an additional clause, and an auditor asking how you know a reviewer saw a document can be answered from the record rather than from a database query. Two properties are worth stating for anyone assessing it. First, it does not claim the signer READ the document, and no wording in it does — being shown a document and reading it are different, the system can only evidence the first, and that distinction is deliberately preserved here. Second, a delivery record that cannot be read is displayed as unreadable and never as an absence: an empty result beside a signature would read as evidence the signer was never served the document, which is a materially different and potentially damaging claim. Signatures applied before delivery was recorded at all will show that no delivery is on record; that is accurate and is not a defect in those signatures, which were applied under the rules in force at the time.
document-delivery.test.tsCreating a controlled document now requires the 'author' role. Until this release there was no role check on any of the three ways a document comes into being — typing one, drafting one with AI, uploading a file, or starting a revision of an existing document — so anybody who could sign in could bring a document under control and be recorded as its author. Reviewing, approving and signing are unchanged. The places that offer document creation now match the rule: Document Control's write / AI-draft / upload panels, the “Create revision” control, and the “Use this template” form on each SOP template are shown only to someone holding the role, and each says which roles you do hold instead of simply disappearing. A template's text remains readable by anyone — reading a procedure is not authoring one. An administrator who needs to write documents can grant themselves the role, and that grant is recorded in the audit trail and notified to the account holder.
Why this classification: An access control was added where there was none (21 CFR 11.10(d) — limiting system access to authorised individuals). No signature control was broken before this release, and that distinction matters when you assess it: the author of a document still could not approve it, every named reviewer still had to sign, and the delivery and four-eyes gates were all operating. What was missing was the authority to originate the record at all, which the signing gates were never asked to cover. Behaviour changes in a way a qualification script will notice, and it is the kind that fails closed rather than open: a user who holds admin, reviewer or approver but not author can no longer create a document, upload one, or start a revision, and any step that did so as such a user will now be refused. Check who in your organisation holds 'author' before upgrading — a new organisation's first user is provisioned with it, but a user created later may not have been given it, and the people most likely to be affected are administrators who have been writing documents without it. The role is grantable by any administrator. Records already created are untouched and remain valid; this governs who may create new ones. Bulk migration is unaffected and keeps its own separate authority, content-confirmation step and QA verification.
four-eyes.test.tsOpening a document from the training panel now always serves the Effective version — the one the trainee is assigned to read — rather than whichever version the document is currently showing. Previously, while a revision was open as a Draft with a replaced file, a trainee was sent that draft. Since the acknowledgment requires being shown the version being acknowledged, and the draft is a different version, the trainee could not complete their training at all: they were told to open the document, they opened it, and nothing changed. Reviewing and approving a document is unaffected and still shows the version under review, which is the version a reviewer needs to see.
Why this classification: No training rule changed, and nothing that was previously accepted is now refused: the acknowledgment still requires that the exact assigned version was shown to the trainee, and it still records only that the document was put in front of them. What changed is which version the training panel serves, and therefore whether that requirement can be met at all while a revision is in progress. Classified "review" rather than "requalify" because it removes a block rather than altering a control — but it is not "none", because the behaviour is observable and a qualification script may cover it: a step that revises a document and then checks that trainees on the current version can still complete their training would previously have failed, and a step that asserted the training link opens the same version as the document page will now find it opens the Effective one. Two related points for anyone assessing this. First, the version served is stated on the viewer itself, so a trainee can see which version they are reading. Second, this is the second half of the training-record correction recorded above: that entry stopped a trainee being shown one version and recorded as having read another; this one gives them a route to the version they are actually assigned. Requesting the version in force fails closed — a document with no Effective version serves nothing rather than falling back to a draft.
training.test.tsslide-viewer.test.tsWhen a document has an Effective version and someone is part-way through revising it, opening that document sends the revised DRAFT — and until this release the training system recorded the trainee as having read the EFFECTIVE version instead. Because a training assignment is bound to the effective version's content, that record then satisfied the requirement to open the document, and the trainee could apply a "read and understood" signature for a version the system had never put in front of them. The record of a trainee opening a document is now bound to the bytes that were actually sent to them. If those are not the bytes their training is about, nothing is recorded and the acknowledgment stays refused until they are shown the right version.
Why this classification: ⚠ THIS AFFECTS TRAINING RECORDS ALREADY IN YOUR SYSTEM. A completed read-and-understand acknowledgment carries an electronic signature asserting that the trainee read a stated version (21 CFR 11.10(e), 11.50; ISO 13485 §6.2). Where the conditions below held, the view record underlying that assertion describes a different set of bytes from the ones the trainee was shown, and both the view record and the signature are append-only, so neither can be removed or amended. The conditions are specific and you can check them: the document had an Effective version; a revision of it existed as a Draft; that draft's file had been REPLACED, so it was no longer the byte-for-byte copy of the effective file a draft starts as; the trainee held an open assignment on that document; and they opened it from the training panel between 18 August 2026, when the requirement to open a document before acknowledging it was introduced, and this release. An unmodified draft is not affected — it carries the same content as the effective version, so the record was accurate. If any of your completed training meets all of those conditions, the conservative course is to re-assign that training on the current effective version and have it acknowledged again, rather than relying on the existing record; superseding it is the correct treatment, not deleting it. Nothing about who must be trained, on which version, or what the acknowledgment binds to has changed, and no acknowledgment that would previously have been accepted on the correct version is now refused. The cause is worth recording for anyone assessing this: two parts of the system were each deciding on their own which version of a document was the relevant one, by different rules, and the fix was to have the part that sends the file state which version it sent rather than have the other part work it out again.
training.test.tsslide-viewer.test.tsdocument-delivery.test.tsA PDF controlled document is shown on its own page in an embedded preview. Until this release, that preview counted as the document having been delivered to whoever loaded the page — so the requirement to open a PDF before signing it could be satisfied by arriving at the page, without the reviewer opening anything, with only the first page visible in the frame. It no longer is. The preview now records nothing and says so beneath itself; what satisfies the requirement is asking for the document, which is the button beside the signing boxes or "Download original".
Why this classification: A Part 11 control was not operating as described, and this release makes it operate as described. The requirement itself never changed — a signature on a file-backed document still requires that the document reached the signer — but for PDFs the record evidencing it could be produced by a page load rather than by any act of the signer. Two consequences a quality reviewer has to weigh, and the second is the one that cannot be undone. First, behaviour changed in a way a qualification script will notice: a step that loads a PDF document's page and then signs it will now be refused, and must be updated to open the document first; a PowerPoint deck, a Word file and a typed document are unaffected, as is the download path for every type. Second, and more important: delivery records written for PDF documents between 2026-08-21, when the delivery requirement was introduced, and this release may have been produced by a page view rather than by a deliberate act, and the audit trail is append-only so those records cannot be removed or amended. If you held a PDF controlled document in that window, the conservative course is to treat any delivery record on it as unproven, re-execute the review or approval of that document, and re-run the part of your performance qualification covering signature of uploaded PDF documents. Indelio can tell you which records fall in that window on request. The defect existed for one day and arose from a combination rather than a single change: the embedded preview predates the delivery requirement by two months, and neither was wrong on its own.
document-delivery.test.tsOn a document stored as an uploaded file, the button beside the signing boxes now matches what will actually happen. A PDF opens in a new tab. A PowerPoint (.pptx) deck opens Indelio's slide viewer. A Word file or a legacy .ppt — which nothing here can display — is labelled "Download the document" and states that it saves to your downloads folder. Previously the button read "Open the document" in every case and always saved the file, including for PDFs that could have been displayed.
Why this classification: The requirement that a file reach a signer before they can sign it, and who may sign, are unchanged. It is classified "review" rather than "none" because the wording on the button is observable and may be written into a qualification script: a step reading "click Open the document" will find that button labelled "Download the document" for a Word file and "View the slides" for a PowerPoint deck, and should be updated to expect it. ⚠️ A Word document and a legacy binary .ppt still cannot be displayed inside Indelio; only .pptx decks and PDFs can. The delivery record continues to evidence that the document was put in front of a named person at a stated time, and does not evidence that they read it.
document-delivery.test.tsslide-viewer.test.tslayout.test.tsA PowerPoint (.pptx) controlled document can now be read inside Indelio. Its slides are drawn in the browser — text, pictures, tables and layout — so a reviewer or approver can see the deck without downloading it or having PowerPoint installed. Anything the viewer cannot draw is marked in place on the slide it belongs to, and is never silently left out. If any slide fails to draw, if any picture cannot be shown, or if any text would be drawn in the same colour as what is behind it, Indelio says so, does NOT record the document as having been delivered to you, and you must obtain the original file before you can sign.
Why this classification: A control changed. The precondition for signing a file-backed controlled document — that the document reached the signer — can now be satisfied a second way, by the slides being displayed, in addition to the file being downloaded. The requirement itself is unchanged and no signature rule, role or lifecycle rule was altered, but the evidence a signature rests on is now produced by a path that did not exist before, so re-executing the part of your performance qualification that covers document review and approval of uploaded decks is the conservative course. Two further points a quality reviewer should weigh. First, the delivery record now states HOW the document reached the person — 'viewer' where the slides were drawn on their screen, 'download' where the bytes were sent — because those are different facts and an auditor asking how you know an approver saw a deck deserves the difference; records written before this release are marked 'download', which is what they were. Second, and unchanged in principle: neither value is evidence that anybody READ the document. Someone can be shown a deck and look past it. The system records that the document was put in front of a named person, from an identified set of bytes, at a stated time. ⚠️ The viewer is Indelio's own rendering and is not PowerPoint: themes, animation, charts and SmartArt are not drawn, and the original file remains the record of what was signed. One consequence is worth stating for a reviewer assessing the evidence: the viewer checks that text is not being drawn in the same colour as its own background, and treats a slide where that happens as not shown — because a slide the reader cannot read is not a slide they were shown. It does not make that judgement about text placed over a photograph, where deciding readability would mean interpreting the picture.
slide-viewer.test.tspptx-render.test.tsdocument-delivery.test.tsThe slide viewer opens on a preview — the first three slides — so you can confirm a deck is the one you are about to sign or download without waiting for a hundred slides to be drawn. A button shows the whole deck. Viewing all of it is what gets recorded; the preview is not, and the page says so in place.
Why this classification: The recorded fact is unchanged: a delivery is written only when the whole document has been drawn for that person. What changed is that the viewer no longer draws the whole document by default, so a reviewer who opens it and stops at the preview has NOT satisfied the signing gate and will still be refused — which is why the preview states that plainly, and why the buttons leading to it say "view all the slides" rather than "view the slides". Classified "review" rather than "requalify" because no control moved: the same act produces the same record as it did before. A qualification script that steps through reviewing an uploaded deck should be checked for a step that assumes the viewer shows everything on arrival.
slide-viewer.test.tspptx-render.test.tsViewing a PowerPoint deck in Indelio also satisfies the training read requirement for that document, in the same way that downloading it already did.
Why this classification: Same reasoning as the change above, applied to the training acknowledgment gate: a trainee's read-and-understood acknowledgment is still refused until the exact effective version has been served to them, and that condition is unchanged — but it can now be met by the slides being displayed as well as by the file being downloaded. Classified conservatively because training records are the evidence of competence an inspector asks for first.
slide-viewer.test.tsWhen a signature or a submission for review is refused because the file has not yet been delivered, the message now directs you to the document button at the top of the Actions panel rather than naming that button by its label.
Why this classification: The refusal reasons and the conditions producing them are unchanged; only the sentence a blocked user reads is different. It was corrected because the message named a button by a label that the same release changed, so it directed people to a control that no longer existed under that name. Classified "review" because the refusal text is observable and a qualification script may assert it word for word.
document-delivery.test.tsIn the Versions table of a document, a two-word state such as "In Review" is no longer split across two lines, which had broken its coloured background into two separate rectangles.
Why this classification: Presentation only. No state, rule, permission or record changed — the same states are shown for the same versions, and only how the label is drawn is different.
layout.test.tsThe forgotten-password screen was found to disclose whether an email address has an account, and to report success when the reset had in fact failed — both corrected. Separately, people are now told when an administrator changes their roles, suspends or restores their account, or creates an account for them, and when a second factor is added to or removed from their own account.
When you request a password reset, the confirmation message is now the same whether or not that email address has an account. Previously the two cases were worded differently — an address with no account received "If that email has an account, a reset link is on its way", while an address with one received "Reset link sent — check your inbox" — so the reply itself revealed which addresses belong to your users. Anyone could do this without signing in. No reset link is sent to an address without an account, and none is sent to a deactivated account; neither is now distinguishable from a successful request.
Why this classification: The behaviour of a function available to unauthenticated visitors changed, and the text a user sees changed with it. No access rule was altered: who may reset a password, what the link grants, and how a new password is set are all unchanged, so nothing that previously succeeded now fails. The reason it is not classified "none" is that the confirmation wording is observable and may be written into a qualification script — a step reading "request a reset for a valid account and confirm the screen reports the link was sent" will now see the neutral wording instead, and should be updated to expect it. If your assessment covers disclosure of account existence to unauthenticated visitors, this is the change to point at.
password-reset.test.tsIf a password reset cannot be carried out, the screen now says so and states that no email was sent, instead of reporting that a link is on its way. Previously every failure — the authentication service being unreachable, an expired credential, a rate limit, a timeout — produced the same reassuring confirmation as a successful request, and the reason was discarded rather than recorded. Failures are now written to the server log with their cause.
Why this classification: A function that could previously fail while reporting success now reports the failure. Nothing that worked before behaves differently: a successful reset request is unaffected. The classification is "review" rather than "none" because the failure mode was invisible — if password recovery had stopped working for your organization, every user would have been told a link was coming and no record would have existed of it having failed, so an outage could not be evidenced after the fact. If your qualification recorded a pass on the forgotten-password path, that pass could not have distinguished a working path from a broken one; it can now.
password-reset.test.tsPeople are now emailed when an administrator changes their roles, suspends or restores their account, or creates an account for them — and when a second factor is added to or removed from their own account. Previously only two administrative actions were notified: a password reset and an administrator clearing someone's second factor. Role changes, suspensions and account creation were recorded in the audit trail but announced to nobody. Nothing about who may do what has changed, and no action is refused that was previously allowed.
Why this classification: A detective control was widened; no preventive control was altered. The reason it is not "none" is that it changes what your people receive and what your records contain: each of these actions now also records whether the notification was actually sent (`user_notified`), which appears in the audit entry's details. If your procedures describe how a user learns their access changed, or if your training or SOPs state that role changes are communicated manually, both should be reviewed against the system now doing it. Of the actions covered, the role change is the one to look at first — granting Approver or QA confers the ability to sign records, and it was the only such action that was both self-serviceable by an administrator and unannounced.
account-notices.test.tsThe email sent to a newly created user does NOT contain their temporary password. It tells them the account exists, who created it, which roles they hold, and that their administrator will supply a temporary password separately. The administrator continues to receive that password on their own screen exactly as before, to hand over by whatever means they judge appropriate.
Why this classification: The account-creation flow is unchanged in what it creates and in how the administrator receives the temporary password; what is new is that the person also gets a notice. The password is deliberately excluded from it. A newly created account may already carry Approver or QA, so its first credential can confer signing authority, and a credential delivered by email comes to rest in that mailbox, its backups, and every device it syncs to. If your onboarding procedure assumed the user receives nothing until the administrator contacts them, that is no longer true and the procedure should say so.
account-notices.test.tsPeople are now emailed when read-and-understand training is assigned to them, and when a document they were trained on is revised and their training is automatically re-assigned. Previously neither was notified: the assignment appeared on the training matrix and in the trainee's own training list, but nothing told them it existed. One email covers everything assigned in a single action rather than one per document. Whether each person was actually reached is recorded in the audit trail.
Why this classification: No training rule changed. Who must be trained, on which version, what the acknowledgment is bound to, and the requirement to open the document before signing are all exactly as before, and nothing that was previously accepted is now refused. The classification is "review" because your procedures may describe how a person learns training has been assigned to them — if an SOP says a supervisor informs them, or if your qualification recorded that the system does not notify, both should be checked against the system now doing it. Note also that the daily reminder digest still omits assignments that have no due date, and the due date on the manual assignment form is optional; the notice on assignment is now the reliable channel, and the digest remains a reminder rather than a first notification.
training-notice.test.tsA document that was UPLOADED as a file — a PDF, Word document or PowerPoint — can no longer be reviewed, approved or periodically reviewed until the system has actually delivered that file to the person signing. Opening the document with "Download original" satisfies it. Documents whose content is typed into Indelio are unaffected, because their content is displayed on the page above the signing box. If the file is replaced while the document is still a draft, everyone who is to sign must open it again.
Why this classification: A control was added to the electronic signature on a controlled document (21 CFR 11.10(a), 11.50). Signatures that would previously have been accepted are now refused until the file has been opened, so this changes behaviour you may have qualified. It was added because a file-backed document could be taken from upload to Effective with valid review and approval signatures from someone who had never been sent a byte of it — the same system already refuses a trainee's read-and-understand acknowledgment until the exact version has been delivered to them, and refuses a signature on twelve other record types until attached evidence has been delivered. If your performance qualification exercises review or approval of an uploaded document, that script now needs a step that opens the file before signing, and a document currently part-way through review will require its reviewers to open it again. Signatures already applied are unaffected and are not re-opened. The check records that the file was delivered; it is not evidence that it was read, and must not be described as such.
document-delivery.test.tsFor a document that was uploaded as a file, the document itself is now offered at the top of the Actions panel — an "Open the document" button beside the signing boxes, which says whether you have been sent this version and what is still required. It was previously a "Download original" link below the versions table. The author must also open an uploaded file before they can send it for review, and everyone named as a reviewer is now emailed that they have been asked, with whether each was reached recorded in the audit trail.
Why this classification: No signing rule changed — what is refused and what is permitted are exactly as released earlier today. What changed is where the document is offered and who is told. Two behaviours are new and may affect a qualification script: sending an uploaded document for review is now refused until the author has opened it, and being named as a reviewer sends an email. If your procedures describe how a reviewer learns they have been asked, or if a script sends a document for review immediately after uploading it, both should be checked. The reason for the change is worth recording: a reviewer who had been correctly refused reported that the download link was below the fold, that it was not clear opening it was required, and that a downloaded file is not the same as having seen the document. The first two are addressed here. The third is not — for anything other than a PDF the file still lands in the reader's downloads rather than on screen, and the wording on the panel now says plainly that the record shows the file was sent, not that it was read.
document-delivery.test.tsA new "Waiting on you" list shows each person the records held up until they sign — documents where they are an assigned reviewer, documents awaiting their approval, and training assigned to them. It appears on the dashboard, at the top of Reminders, and as a count in the navigation. Nothing about who may sign what has changed; this only shows people what was already true.
Why this classification: No control changed and nothing is refused that was previously allowed — this is a view over obligations the system already recorded and enforced. It is classified "review" rather than "none" because it changes how a person learns work is waiting for them, and your procedures may describe that. Until now the only list of outstanding items was organization-wide and driven by due dates, so a document sitting in review with a named reviewer against it appeared nowhere at all: a signature obligation has no due date. If an SOP says a reviewer is told by their supervisor, or if a qualification recorded that the system does not surface pending signatures, both should be checked against the system now doing so. One property is worth stating for anyone assessing it: if a source cannot be read, the list says so by name and the "nothing is waiting on you" message is suppressed entirely, so an empty list is never shown over a failed query.
waiting-on-you.test.tsThe "Waiting on you" list released earlier today duplicated an existing dashboard notice, so a reviewer saw the same document announced twice. The two have been merged into one list. The older notice has been removed, and the merged list now uses the stricter of the two calculations: a document is offered for your approval only once every assigned reviewer has actually signed it, where the newer list had offered any document sitting in review. Documents you authored yourself are not offered to you for approval, and a reviewer who has since been reassigned is no longer chased.
Why this classification: No signing rule changed, and nothing is refused that was previously allowed — both lists were views over obligations the system already enforced, and the approval gate itself was never in question. What changed is what the two lists claimed. The reason to record it rather than treat it as cosmetic is that the earlier of the two could name a document as awaiting your approval before its reviewers had signed; clicking through, you would have been refused at the point of signing, correctly, but the list had told you the work was yours to do. It now agrees with the gate because it asks the gate rather than re-deriving the answer. If a qualification script counted the items in this list, or recorded that a document appears there at the moment it enters review, both should be re-checked — a document now appears for approval later than it did this morning, and appears once rather than twice.
waiting-on-you.test.tsdocument-reviewers.test.tsTwo access controls were found not to be working as documented and were fixed, the tenant classification two controls depend on became a recorded property instead of a guess, two documents we publish were found to be out of date against their own sources, and an administrator who loses the device holding their authenticator can now be restored to access without leaving the system.
On a CAPA action plan, someone who has already signed one half of the dual approval is now told the other half needs a different person, instead of being offered a signing form that would be refused. The rule itself has not changed: the Approver and QA approvals still have to be signed by two different people, and that is still enforced when the signature is submitted.
Why this classification: The refusal now happens before the signing attempt rather than after it. The outcome is identical — the same person cannot fill both approval slots — but a qualification step written as "attempt to sign both slots as one person and verify the system refuses" will now find no form to submit, and will record no refused attempt. The server-side check is unchanged and still runs on every submission.
signing-feedback.test.tsThe idle session timeout now works after a browser restart. Previously the cookie tracking your last activity was discarded when the browser closed, while the sign-in itself persisted — so on any device that had restarted its browser, the inactivity logout never took effect and the session stayed open indefinitely. The interval is 30 minutes.
Why this classification: An access restriction changed (21 CFR 11.10(d), 11.300(d)). Sessions that previously remained open indefinitely will now be terminated after 30 minutes of inactivity, and the user is returned to the sign-in page. If your qualification tested the inactivity logout and recorded a pass, it was most likely exercised within a single browser session, which is the case that did work; the case that did not was resuming after closing the browser. Our published documentation stated 20 minutes while the system used 30 — the documentation has been corrected to match the system, not the other way round.
idle-timeout.test.tsEach electronic signature now records how long ago the signer last authenticated interactively, and that interval is kept as an append-only record. No signing rule changed — nothing is refused that was previously accepted, and the signature itself is unaltered.
Why this classification: The signing act now produces an additional record, so the behaviour of a controlled function changed even though no rule did. It was added because a browser password manager will re-supply a stored signing password for a period after one biometric check, and that period belongs to the manager rather than to Indelio — previously the interval could not be measured at all, because the signing check itself overwrote the only timestamp available. Recording it does not control it; it makes it observable.
signing-auth-age.test.tsWhether an organization is treated as a paying customer, an evaluation, a demonstration or an internal test tenant is now a property recorded on that organization and chosen when it is created. It was previously worked out each time by looking for words like "demo", "evaluation" or "northwind" in the organization's displayed name. Two things depend on the answer: whether multi-factor authentication is mandatory for administrator accounts, and whether sign-ins are notified to Indelio. An organization with no recorded value is treated as a customer, which is the stricter setting for both.
Why this classification: The scope of an access control changed (21 CFR 11.10(d), 11.300). The MFA requirement on administrator accounts is unchanged in substance, but which organizations it applies to is now determined by a recorded property rather than by the text of the organization's name. An organization whose name contains one of those words was previously outside the requirement and outside the sign-in-notification exclusion; if that describes yours, administrator MFA now applies to it and its sign-ins are no longer notified to us. Names are not otherwise used, so renaming an organization can no longer move it in or out of either.
tenant-type.test.tsmfa-policy.test.tsTrial expiry reminders are now sent reliably. The daily sweep read only the first page of accounts, so on a large installation the administrators of some organizations were never emailed their 7-day and 1-day warnings, and the organization was recorded as having been reminded regardless. An organization whose administrators have no reachable email address is now reported by name in the daily run instead of being skipped silently. When trials run out, access is suspended exactly as before — that behaviour is unchanged.
Why this classification: No function operating under your quality system was changed. This affects courtesy notifications about the commercial state of a trial account, not any record, signature, lifecycle rule or access restriction. Suspension of a lapsed trial — the part that does affect access — is untouched, and reminders were already best-effort by design. Listed because the register is a complete record of releases, not only of controlled changes.
trials.test.tsThe 21 CFR Part 11 Validation Package available under Compliance & Validation was out of date and has been corrected. The copy being served was generated on 9 August and was never regenerated after the source document was updated, so it stated that the idle session timeout was 20 minutes when the system uses 30, and it did not reflect the administrator multi-factor requirement. Its “last updated” date was fixed at 9 August by the build itself and could not move. The date now comes from the document, and the served copy is held to its source automatically. If you have downloaded this package, replace your copy.
Why this classification: No function operating under your quality system changed — this is a correction to a document that describes them, not to a control. It is recorded because the document is one you may have filed as part of your own assessment of this system, and it was wrong about a Part 11 access control interval. The behaviour of the idle timeout itself is covered by its own entry above; this entry concerns only what our documentation said about it.
validation-doc.test.tsidle-timeout.test.tsThe Supplier Qualification SOP template in the template library was an earlier draft than the one we maintain, and has been brought up to date. Its section on placing a supplier on hold now states the two ways a hold is closed more precisely, and adds that suppliers on hold are reviewed at management review. The other ten templates were unaffected. A template seeds a Draft in your document control and is reviewed and approved by you before it can become Effective, so no document already in force is changed by this.
Why this classification: No function operating under your quality system changed, and no controlled document was altered — a template is starting content, not a record, and it enters your document control as a Draft that your own review and approval must pass before it takes effect. It is recorded because the library is content we publish and it was out of date. If you seeded Supplier Qualification before this release, compare it against the current template when that document next comes up for periodic review.
templates-sync.test.tsRemoving or editing a finding on an internal audit now records what the finding said. Previously the audit trail entry read only “Audit finding removed” — it did not record which finding, its classification, or its text, so the trail could show that a major nonconformity had been raised during an audit and then deleted while preserving nothing about it. The entry now carries the finding’s number, classification and content, and an edit records the prior values alongside the new ones. Who may remove a finding is unchanged: only while the audit is Planned or In Progress, never after the report is signed.
Why this classification: The audit trail is a controlled function (21 CFR 11.10(e)) and what it records for these two actions changed, although no rule about who may do what changed with it. Nothing that was permitted is now refused. If your qualification checked the wording of the audit-trail entry for removing or editing a finding, the text it will now find is different and more complete.
audit-finding-trail.test.tsCorrected the register itself. The changes listed above shipped on 20 August but were initially recorded under the 19 August release, because that was the only release in the register at the time and entries were added to it rather than to a new one. They are now filed under the date they shipped. No entry's content was altered — only which release it sits under.
Why this classification: No function operating under your quality system changed. It is recorded because this register exists so you can decide whether a given release affects your qualified state, which makes the date each change shipped part of what you are relying on. If you assessed the 19 August release before this correction, the eight entries above were in what you read and are now attributed to 20 August.
releases.test.tsCorrections to the qualification material we publish, after four of our own documents were found to describe a product that had moved on. The PQ protocol template asked you to verify two behaviours the system no longer has: that an author is blocked from reviewing their own document, and that whoever approved a CAPA action plan may not close the record. Both rules were deliberately removed on independent validation-review advice — the first in August, the second in July — and executing those steps as written would have recorded a deviation against a control we took out on purpose. Both steps have been rewritten to expect what the system does, and the document-lifecycle scenario now demonstrates the four-eyes rule as it actually stands: an author may review their own document, and may not approve it. Separately, our OQ evidence index cited a test suite that exercised an internal model the product never ran, and that model had the review rule backwards; the model has been removed and the affected rows re-pointed at the suites covering the shipped code. A requirements traceability matrix is now generated from the requirements specification and published with it, replacing a hand-maintained copy that had fallen six requirements behind.
Why this classification: No function operating under your quality system changed — this is a correction to documents that describe them, and to internal code that was never executed. It is recorded because the PQ protocol is material you may have adapted and executed against your own instance: if you did, steps 1.4 and 2.10 as you received them will produce failures against a system that is behaving correctly, and any deviation raised against them should be reassessed rather than investigated. The behaviour of the two controls concerned is unchanged by this release and was last changed in the entries dated 19 August and in July respectively.
rtm-sync.test.tsfour-eyes.test.tsengine.test.tsThe password box on every electronic-signature field now refuses a pasted or dragged password, and asks each password manager that publishes an opt-out not to offer to fill it. You must type your password to sign. Signing in is unchanged and still works normally with a password manager, as does changing your password — this applies only to signature fields.
Why this classification: How a signer supplies the second component of an electronic signature changed (21 CFR 11.200(a)(1), 11.200(a)(3)). Nothing that was accepted is now refused at the server: the same password, typed, is accepted exactly as before. What changed is that the browser and password managers are no longer asked — and in the case of paste, no longer permitted — to supply it for you. If your qualification recorded a signing step performed by autofilling or pasting the password, that step now requires typing. ⚠️ Stated precisely, because the distinction matters to your assessment: this SUPPRESSES credential filling, it does not disable it. A web page cannot disable a password manager — browsers deliberately ignore the standard instruction to do so on password fields, and the additional attributes we send are honoured by each manager at its own discretion. It raises the bar on the ordinary path; it is not a guarantee that a signature component was supplied by the person, and we do not claim it as one.
password-clearing.test.tsAn administrator can now clear another person's two-factor authentication, so someone who has lost the device holding their authenticator can enrol a new one and sign in again. It removes the enrolled factor only — the password is unchanged, and anyone whose role requires a second factor is asked to enrol a new authenticator at their next sign-in. A reason must be given, the action is written to the audit trail, and the account holder is emailed to say it happened and why. Nobody can clear their own factor. Where an organization has only one administrator, and so nobody inside it can perform the recovery, Indelio can perform it from the platform console; that is recorded in your own audit trail, attributed to the Indelio administrator who did it.
Why this classification: An access restriction changed, and a new one was added (21 CFR 11.10(d), 11.300(b), 11.300(c)). §11.300(c) requires procedures to deauthorize a lost or compromised token and to issue a replacement under suitable, rigorous controls; until this release Indelio had no such path, and a lost authenticator on an administrator account could only be resolved by direct database access outside the audit trail. Your access-control procedure should now say who is permitted to perform this recovery and what they must establish before doing so — the system requires a stated reason and the acting administrator's own password, but it cannot confirm that the person asking is who they claim to be, and that verification is yours to define. If your qualification asserted that a second factor could not be removed from an administrator account, that assertion is no longer true and should be re-executed against the new behaviour.
mfa-recovery.test.tsTurning off two-factor authentication on your own account now tells you truthfully whether it was turned off. Previously, if the removal was refused — which happens when you are signed in through a password-reset link, or before entering your 6-digit code — the screen still said “Two-factor authentication disabled” and an entry saying so was written to your audit trail. The factor remained active throughout. Refusals are now shown as refusals, explained in plain language, and recorded as refusals.
Why this classification: ⚠ THIS AFFECTS RECORDS ALREADY IN YOUR AUDIT TRAIL. Any `MFA_DISABLED` entry written before this release may describe a removal that did not take place, because the error returned by the removal was discarded and success was reported regardless (21 CFR 11.10(e) — the audit trail as an accurate record of operator actions). If your trail contains such entries, verify against the account whether a second factor is in fact enrolled before relying on them, and supersede any that are wrong rather than deleting them — the trail is append-only by design. The underlying access control was never weakened: the removal was correctly refused every time, and no account was left less protected than it appeared. What was wrong was the reporting and the record. Two further changes come with it: a refused removal is now itself recorded (`MFA_DISABLE_REFUSED`), which did not previously appear anywhere, so a qualification that counted audit entries for this action will see entries it has not seen before; and a partial removal is reported as partial rather than as complete.
mfa-disable-honesty.test.tsmfa-policy.test.tsEvidence attached to a quality record is now retained once it has been signed over, and must be opened before the record is signed.
Attached evidence can no longer be deleted from a record once a signature has been applied to that record after the file was attached. Previously the rule was based on the record's state, so reopening or cancelling a signed record made its evidence deletable again, and three record types (Corrections & Removals, the Design History File, and the Summative Usability Test) had no retention rule at all.
Why this classification: Record retention behaviour changed (21 CFR 11.10(c)). Evidence that could previously be removed can no longer be, and attempted removals are now recorded in the audit trail. If your qualification covered removing an attachment from a closed or reopened record, that step will now be refused.
attachment-lock-coverage.test.tsA signature on a record that carries attached evidence is now refused until each attached file has been opened by the person signing. Records with no attachments are unaffected. The requirement can be switched off per organization by an administrator, under Settings.
Why this classification: A new precondition was added to the signing act itself. Any qualification step that signs a record carrying attachments will now require the file to be opened first, and will fail if it is not. This records that a file was delivered to the signer; it is not a record that anyone read or understood it.
attachment-lock-coverage.test.tsA document signature is now refused if your organization's configured signature meanings and review contexts cannot be read, instead of silently falling back to the built-in defaults.
Why this classification: The signature meaning is bound into the signature itself (21 CFR 11.50). Previously a failed settings read produced a signature stating wording your organization had not configured, and could switch off a configured mandatory-review-context policy without saying so. Signing now stops and says the policy could not be read.
pg-errors.test.tsThe password field used for electronic signatures is now cleared as soon as the form is submitted, whether the signature succeeded or was refused.
Why this classification: Previously the field kept its value, so a subsequent signature on the same screen could be applied without the signer re-entering either component. Signing now requires the password each time. No signature already applied is affected.
Responsive layout rules were being discarded by the browser and are now applied correctly. Affected the signed-in header on narrow screens and page breaks when printing the metrics page.
Why this classification: Presentation only. No record, signature, calculation, or control was involved.
inline-css.test.tsThe person who created a record can no longer apply its final approval signature. A second qualified person must sign. This affects assessments, change-notification determinations, management reviews, the quality policy, and all five human-factors records — the record types that previously reached their approved state on a single signature.
Why this classification: Segregation of duties on the approving signature changed (21 CFR 11.10(d), ISO 13485 §5.5.1). A qualification step in which one person both created and approved one of these records will now be refused and will need a second signer.
four-eyes.test.tsA controlled document now carries a named list of reviewers. Only a named reviewer may apply a review signature, and every named reviewer must have signed before the document can be approved. Documents already in review when this was released were not retro-fitted with a reviewer list.
Why this classification: The document lifecycle gained a precondition on approval (21 CFR 11.10(d), ISO 13485 §4.2.4). A document could previously reach Approved with no review signature recorded at all; approval is now refused and names the reviewers who have not signed. A qualification that approved a document without assigning reviewers will fail at that step.
document-reviewers.test.tsThe author of a controlled document may apply a review signature to it, but still may not apply its approval signature. Previously the author was blocked from every signature on their own document.
Why this classification: Who may sign what changed (21 CFR 11.10(d)). Together with the reviewer list above, the previous blanket restriction could leave a document that nobody was able to approve whenever its author was among the named reviewers. The four-eyes control on the approval signature itself is unchanged.
document-reviewers.test.tsMulti-factor authentication is now required of every administrator, and an administrator can no longer switch it off for their own account. An administrator who has not enrolled is held at an enrolment prompt before continuing.
Why this classification: An access control changed (21 CFR 11.10(d), 11.300). The policy already stated that administrators required MFA, but it was not enforced; it is now enforced at the point of use. An administrator account with no enrolled authenticator will not be able to proceed until it enrols.
mfa-policy.test.tsThe password field used for electronic signatures no longer asks the browser to offer a saved password, so a stored credential is not filled into it automatically. The signer types it. This does not prevent a password being pasted, and it does not make the password usable only by its owner.
Why this classification: The signing interaction changed, though no signing rule did. A browser password manager could previously supply the password component of a signature without the signer entering it. This reduces the chance the browser supplies it; it is a mitigation and not a control over who holds the password.
password-clearing.test.tsA public release register was added at /releases, listing each release, what changed in it, our assessment of the validation impact of each change, the reasoning behind that assessment, and the automated suites covering it.
Why this classification: No function operating under your quality system was changed. It adds a published record so each release can be risk-assessed; the assessment it carries is ours, and the decision it feeds is yours.
releases.test.tsThis register begins August 19, 2026. Changes released before that date were not recorded in this form, and we have not written them up after the fact.