Chapter 7
How a biosafety records system proves that it implements WIA-BIO-017: conformance tiers, test vectors, signed evidence, profile manifests, and the versioning rules that keep a claim valid over time.
The previous six chapters described what a WIA-BIO-017 records system stores, how it runs the incident workflow, which interfaces it exposes, how it exchanges and audits records, and how it protects them. This chapter answers the question that a procurement officer, an IBC secretariat, or a partner institution will eventually ask: how do we know this system actually does all of that? The answer the WIA PHASE documents give is not a logo or a certificate on the wall. It is a body of machine-readable evidence: test vectors that exercise every requirement, a pass/fail matrix published without omissions, a software bill of materials, and a signed manifest that states honestly which requirements are supported, partially supported, or excluded.
One distinction runs through the whole chapter and deserves to be stated at the outset. Conformance testing examines software and records. It says nothing about whether a laboratory is safe, whether its containment works, or whether its staff are competent. Those questions belong to the facility certification and inspection regime of the competent authority, and to the institution's own biosafety officer and IBC. Section 7.5 returns to this boundary in detail, because blurring it is the most damaging mistake a vendor or an institution can make.
Annex E of each PHASE document asks implementations to declare their operational scope "so that downstream auditors can score the deployment against the correct conformance tier in Annex A." No PHASE document contains an Annex A, and the main specification's Appendix A covers a different subject altogether. Annex I also asks implementations to list "normative requirement IDs," but none of the PHASE documents assigns such IDs. In other words, v1.0 describes the machinery of conformance (vectors, evidence, manifests) in some detail while leaving out the two things that machinery operates on: a tier structure and a list of numbered requirements.
An implementer cannot wait for v1.1 to publish evidence. This book therefore proposes a tier structure and a requirement numbering scheme, derived from the record model and workflows in Chapters 2 through 6. Everything in this section is the book's proposal, not text from the standard. It is designed so that it can be replaced by an official Annex A without rewriting the test vectors: each vector cites a requirement ID, and a later mapping table can translate the book's IDs into official ones.
The tiers follow the layers of the record model rather than the size of the deployment. Core Records is mandatory for any claim. Workflow and Exchange each build on Core Records but are independent of each other: an inspector's read-only portal may need Exchange without running an incident workflow, while a single-department pilot may run the full workflow and exchange nothing.
| Tier (book proposal) | What it covers | Chapters | Example requirement IDs |
|---|---|---|---|
| C — Core Records | Schema validity of facility, training, incident, and compliance-result records; ID prefixes; ISO 8601 UTC timestamps; additive-only schema evolution; certification and training expiry detection | 2 | BIO017-C-001 facility schema; BIO017-C-004 certification expiry; BIO017-C-005 training currency of authorized personnel; BIO017-C-009 no breaking change within a major version |
| W — Workflow | Incident state machine and permitted transitions; notification timers by severity; RCA and CAPA records; compliance-finding codes; role checks on transitions | 3, 4 | BIO017-W-002 legal state transitions only; BIO017-W-003 severity-based notification timer; BIO017-W-006 CAPA owner and due date required |
| X — Exchange | Message envelope, signature, idempotency, replay protection; append-only hash-chained audit events; custody transfer and receipt records; pseudonymized personnel IDs in outbound payloads | 5, 6 | BIO017-X-001 envelope signature verified; BIO017-X-004 audit chain unbroken; BIO017-X-007 no direct personal identifiers in exchanged incidents |
A claim then takes a compact form such as WIA-BIO-017 v1.0 — Core Records + Workflow, always accompanied by the profile manifest described in Section 7.4. The manifest carries the detail; the headline claim only names the tiers for which every requirement is either supported or excluded with a justification that an auditor accepts.
The Technical Requirements table in the PHASE documents lists ">95% accuracy" as an acceptance criterion. That figure is template text; it has no defined measurement in a records context, and applied to conformance it would mean that one requirement in twenty could fail while the system is still called conformant. The book uses a stricter and simpler rule: a tier is claimed only if every requirement in it has passing positive and negative vectors, or is explicitly excluded in the manifest. There is no aggregate score.
For the same reason, the SDK's complianceScore field (Chapter 4) should not be used as a conformance metric. Reading the v1.0.0 source shows that it is a heuristic rather than a ratio of checks passed: one violation and no warnings yields 50, two violations yield 33, and the denominator changes with the number of findings. It is useful as a rough sort key in a dashboard and nothing more.
The words used in a claim matter as much as the evidence behind it. Acceptable: "Our biosafety records platform conforms to WIA-BIO-017 v1.0, Core Records and Workflow tiers (self-declared; evidence package published quarterly)." Not acceptable: "WIA-certified BSL-3 software," "guarantees biosafety compliance," or any sentence that attaches a containment level to the software itself. Software does not have a biosafety level; facilities do, and only the competent authority confers it.
Annex G sets out the vector discipline in five points, and they carry over to biosafety records unchanged. Every normative requirement has at least one positive vector (input that must be accepted) and at least one negative vector (input that must be rejected with a specific finding). Vectors live under tests/phase-vectors/<phase>/, for example tests/phase-vectors/phase-1-data-format/. Implementations run all vectors in continuous integration and publish the resulting pass/fail matrix. Negative results are reported with the same fidelity as positive ones. And a vector that is skipped without a recorded justification is treated by auditors as a failure.
The last rule is the one that changes behavior. In an ordinary test suite, a skipped test is an inconvenience; under Annex G it is a finding. If a deployment does not implement custody transfers, the correct response is to mark the custody requirements excluded in the profile manifest (Section 7.4) and let the vectors be skipped with that justification attached, not to delete them quietly.
The PHASE documents do not prescribe a file format for vectors. A workable format has four parts: the requirement being tested, a fixed evaluation instant, the input records, and the expected outcome. The fixed instant, called asOf below, is essential for a biosafety records system because so many of its checks are about expiry. A vector that compares a training record against "now" will pass today and fail next year for no reason related to the software. Every date comparison in the validator must take the evaluation time as a parameter, and every vector must pin it.
{
"vectorId": "C-005-neg-01",
"requirement": "BIO017-C-005",
"phase": "phase-1-data-format",
"polarity": "negative",
"asOf": "2026-03-02T00:00:00Z",
"policy": { "trainingExpiryField": "expirationDate" },
"input": {
"facility": {
"facilityId": "FAC-EXAMPLE-0012",
"name": "Example Institute Teaching Lab B",
"bslLevel": "BSL-2",
"authorizedPersonnel": ["PER-0142", "PER-0187"]
},
"trainingRecords": [
{ "personnelId": "PER-0142", "trainingType": "refresher",
"trainingDate": "2025-02-10T00:00:00Z",
"expirationDate": "2026-02-10T00:00:00Z",
"certificationIssued": true },
{ "personnelId": "PER-0187", "trainingType": "initial",
"trainingDate": "2025-11-03T00:00:00Z",
"expirationDate": "2026-11-03T00:00:00Z",
"certificationIssued": true }
]
},
"expected": {
"valid": false,
"findings": [
{ "code": "B009", "subject": "PER-0142" }
]
}
}
All identifiers are fictitious and the fixture contains no agent or inventory data. The policy block records the institutional assumption the vector depends on: here, that the expiry date written on the training record is authoritative. Refresher intervals are set by institutional policy, not by the standard (Chapter 2), so a vector must never hard-code an interval such as "one year after the training date." If a different institution computes expiry from its own policy table, it writes its own policy block and its own vectors; the requirement ID stays the same.
The following four cases are chosen because each of them catches a defect that a plain schema check cannot. For each, the negative vector is described below; its positive twin differs only in the detail that makes it valid.
1. Expired certification. A facility record has certification.certified: true and an expirationDate earlier than asOf. The record is schema-valid, which is exactly why it is dangerous: a dashboard that reads only the boolean shows the facility as certified. The validator must derive the effective status from the dates and report finding B010 (CERTIFICATION_REQUIRED in the SDK's BiosaftyErrorCode enum). Note that validateBSLLevel in the reference SDK does not perform this check; it belongs to the implementer's record validator. The positive twin moves the expiration date past asOf.
2. Training lapse on an authorized person. This is the vector shown above. A person listed in authorizedPersonnel has a latest training record whose expiry precedes asOf, and the validator must report B009 (TRAINING_EXPIRED) naming that person's ID. The check is a join across two record types, which is why it is so often missed. A useful second negative vector covers a person listed as authorized who has no training record at all; the expected finding is the same code, and the report should say "no record" rather than "expired," because the remedy is different.
3. Illegal incident state transition. An incident whose status is closed receives an update setting it directly to under-investigation, without the explicit reopen event defined in Chapter 3. A second negative vector sends open straight to resolved, a path that Chapter 3 deliberately omits because resolution presupposes an investigation. Both must be rejected with HTTP 409 and the incident must remain unchanged. The SDK's error enum has no dedicated code for this case. Rather than borrow B007 (INVALID_PARAMETERS), which would hide the nature of the failure, the vector asserts the HTTP status and a problem type such as invalid-transition, and the gap is recorded as a v1.1 issue (Chapter 8).
4. Schema-breaking rename. A new build renames nextTrainingDue to nextDueDate while keeping the same major version. This vector is different in kind: it runs against the schema, not against a record. The CI job compares the candidate JSON Schema with the last published one and fails if a field was removed or renamed, or if an optional field became required. Its positive twin adds a new optional field, which is additive and allowed. Section 7.6 explains why a rename counts as breaking even though Annex E suggests a smaller version bump.
| Vector ID | Requirement | Tier | Input (summary) | Expected |
|---|---|---|---|---|
| C-004-pos-01 | BIO017-C-004 | C | Certified facility, expiry after asOf | Valid, no findings |
| C-004-neg-01 | BIO017-C-004 | C | certified: true, expiry before asOf | Invalid; B010 |
| C-005-pos-01 | BIO017-C-005 | C | All authorized personnel hold current training | Valid |
| C-005-neg-01 | BIO017-C-005 | C | One authorized person's training expired | Invalid; B009 naming that ID |
| C-005-neg-02 | BIO017-C-005 | C | Authorized person with no training record | Invalid; B009, reason "no record" |
| W-002-pos-01 | BIO017-W-002 | W | resolved → closed by an authorized reviewer | Accepted; audit event written |
| W-002-neg-01 | BIO017-W-002 | W | closed → under-investigation without reopen | HTTP 409; record unchanged |
| W-002-neg-02 | BIO017-W-002 | W | open → resolved | HTTP 409; record unchanged |
| W-003-neg-01 | BIO017-W-003 | W | Severity 3 incident, no notification after the 1-hour target (spec §7.1.1) | Overdue-notification flag raised |
| C-009-pos-01 | BIO017-C-009 | C | New optional field added | Schema diff: additive |
| C-009-neg-01 | BIO017-C-009 | C | nextTrainingDue renamed | Schema diff: breaking; build fails |
A vector runner is a small program: load each vector, call the validator with the pinned asOf, compare the findings with the expectation, and append one row to the matrix. The essential design choice is that the validator receives the evaluation time rather than reading the system clock.
import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { validateRecords } from '../src/record-validator'; // implementer's validator
type Row = { vectorId: string; requirement: string; result: 'pass' | 'fail' | 'skipped'; note?: string };
export function runVectors(dir: string, excluded: Map<string, string>): Row[] {
const rows: Row[] = [];
for (const file of readdirSync(dir).filter((f) => f.endsWith('.json'))) {
const v = JSON.parse(readFileSync(join(dir, file), 'utf8'));
const reason = excluded.get(v.requirement);
if (reason) {
rows.push({ vectorId: v.vectorId, requirement: v.requirement, result: 'skipped', note: reason });
continue; // skipped WITH justification taken from the profile manifest
}
const got = validateRecords(v.input, { asOf: new Date(v.asOf), policy: v.policy });
const codes = got.findings.map((f) => `${f.code}:${f.subject ?? ''}`).sort();
const want = (v.expected.findings ?? []).map((f: any) => `${f.code}:${f.subject ?? ''}`).sort();
const ok = got.valid === v.expected.valid && JSON.stringify(codes) === JSON.stringify(want);
rows.push({ vectorId: v.vectorId, requirement: v.requirement, result: ok ? 'pass' : 'fail' });
}
return rows;
}
The exclusion map is read from the profile manifest, so that the only way to skip a vector is to have declared the requirement excluded in a signed document. The pipeline around the runner is equally short:
# .github/workflows/conformance.yml (example)
name: conformance
on: [push, pull_request]
jobs:
vectors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npm run typecheck && npm test
- run: node dist/tools/run-vectors.js tests/phase-vectors --manifest profile-manifest.json --out evidence/vector-matrix.json
- run: node dist/tools/schema-diff.js schemas/published schemas/current # fails on breaking change
- run: npx @cyclonedx/cyclonedx-npm --output-file evidence/sbom.cdx.json
- uses: actions/upload-artifact@v4
with: { name: evidence, path: evidence/ }
Annex G's insistence on reporting negative results applies to the reference material too, and an honest reading of the v1.0.0 SDK directory is instructive. The published api/typescript folder contains package.json and src/ only: there is no tsconfig.json and no test files. Jest, which the test script invokes, exits with a non-zero status when it finds no tests unless it is run with --passWithNoTests. When the two source files are type-checked with TypeScript 5.3 in strict mode, the compiler reports 34 errors, all of the same kind: names that are exported at their declaration are exported a second time by the export type { … } and export { … } blocks at the end of each file (TS2323 and TS2484). The fix is mechanical: remove the duplicate export lists.
The CLI has a related trap. wia-bio-017 validate-bsl prints "NON-COMPLIANT" when it finds violations, but the script ends with exit 0 regardless of the outcome. A CI step that relies on the exit status will therefore always pass. Until the CLI returns a non-zero status on a finding, the pipeline must inspect the output:
out="$(./cli/wia-bio-017.sh validate-bsl --pathogen BSL-2 --facility BSL-2 --procedure standard)"
printf '%s\n' "$out"
if printf '%s' "$out" | grep -q 'NON-COMPLIANT'; then
echo "record-level mismatch found" >&2
exit 1
fi
None of this is a reason to distrust the standard. It is precisely the kind of finding that the evidence discipline exists to surface, and an implementer who documents it, works around it, and files it upstream is demonstrating conformance culture rather than undermining it.
Annex G defines the compliance package as a tarball with a fixed set of contents. Annex H and Annex I add two more items that belong in the same bundle. Together they let an auditor or partner institution verify a claim without re-running the implementer's test matrix.
| Item | Source | Purpose |
|---|---|---|
| SBOM in CycloneDX 1.5 or SPDX 2.3 | Annex G | Lists every component and version, so consumers can check for known vulnerabilities and licence issues |
| OpenAPI document | Annex G; PHASE Technical Requirements (OpenAPI 3.0) | Describes the interface actually deployed and declares the operational scope (single-tenant, multi-tenant, federated) as Annex E asks |
| Vector pass/fail matrix | Annex G | One row per vector, including skipped vectors with their justification |
| Profile manifest | Annex I | Per-requirement status: supported, partial, or excluded (Section 7.4) |
| Changelog mapping | Annex H | Maps each supported PHASE version to a build, container digest, or SDK version |
| Signed manifest | Annex G | Digest of every file above, signed with Sigstore in a DSSE envelope and logged in Rekor |
evidence-2026Q1/
├── sbom.cdx.json
├── openapi.yaml
├── vector-matrix.json
├── profile-manifest.json
├── changelog-map.json
├── evidence-manifest.json # sha256 of each file above
└── evidence-manifest.sigstore.json # DSSE bundle incl. Rekor entry
Annex G chooses Sigstore so that "downstream consumers can verify provenance without trusting a private CA." In practice the manifest is signed with Sigstore tooling such as cosign, producing a bundle that contains the signature, the signing certificate, and proof of inclusion in the Rekor transparency log. A partner institution can then check that the package it received is the one the vendor published and that it has not been altered since.
The transparency log has a consequence that biosafety teams should think about before the first signature. Rekor is a public, append-only log. Whatever identity is used for keyless signing, typically an e-mail address or a CI workload identity, becomes visible in that log permanently. Use an organizational workload identity rather than an individual's mailbox, and make sure that nothing in the signed subject names or annotations reveals a facility, a room, or a project.
Evidence packages are meant to be shared, sometimes published. Chapter 6 identified facility locations, inventory metadata, and personnel data as the sensitive core of a biosafety records system; none of it belongs in conformance evidence. Test fixtures are synthetic by construction: fictitious facility IDs, fictitious personnel IDs, no agent or material registry entries, no building or room names that exist. The OpenAPI document is generated from the code, not exported from a production gateway that might include internal hostnames in its server list. The matrix reports vector IDs and outcomes, never the payloads. A reviewer should run the redaction checklist from Chapter 6 over the package before it is signed, because a signature makes a mistake permanent in the public log.
Annex G asks implementations to re-publish the package every quarter even when no source code has changed. The reasoning is sound: compilers, dependencies, base images, and operating systems change underneath a stable codebase, and a fresh SBOM and matrix show consumers whether anything drifted. For an institution, a quarterly rhythm also fits naturally with committee cycles: the biosafety officer can attach the latest package to the IBC's periodic systems report, and a partner can compare two consecutive matrices to see exactly what changed.
Annex I describes the profile manifest as the place where an implementation states, for every requirement, whether it is supported, partial (with a reason), or excluded (with a justification). The manifest is signed with the same Sigstore identity used for the SBOM. Its purpose, in the annex's words, is to let deployments of different scope "advertise the subset of normative requirements they satisfy without misrepresenting partial conformance as full conformance."
Profile names are versioned with SemVer. A deployment advertising WIA-P1-DATA-FORMAT-Edge-only/2 asserts conformance with the second major version of the named "Edge-only" profile for PHASE-1, not its second deployment. Registry entries are immutable; a new deployment shape gets a new name rather than an amended entry. The manifest also declares the deployment topology from Annex J (single-tenant edge, multi-tenant gateway, federated mesh, or air-gapped batch), and a topology change requires a new signature. Federated deployments publish an aggregated manifest summarizing the union and intersection of their members' profiles, so that a caller can route an exchange to the lowest common profile.
This book sets two legacy SDK functions outside the scope of a management records system (Chapter 4 states the boundary): assessExposure and generatePPERequirements. Their outputs are technical safety judgments that belong to qualified professionals and to authority guidance, and a deployment should disable them behind a feature flag. The manifest is where that decision becomes visible to auditors. Leaving the functions unmentioned would imply support; marking them excluded with a justification is both honest and, under Annex I, the correct way to keep the claim valid.
The risk-score hook deserves a partial status rather than either extreme. The institution's own risk-assessment result is stored as a record (Chapter 4), while the SDK's calculateRiskScore is not used because its stated 0–100 range is inconsistent with its own input bounds and its thresholds are uncalibrated. The manifest says exactly that.
{
"manifestVersion": "1.0.0",
"implementation": {
"name": "Example University Biosafety Records Platform",
"version": "3.4.0",
"sdk": "@wia/bio-017@1.0.0 (patched: duplicate exports removed)"
},
"standard": "WIA-BIO-017",
"standardVersion": "1.0",
"requirementScheme": "book-proposed/1",
"profile": "WIA-BIO017-Campus-Core-Workflow/1",
"topology": "single-tenant-edge",
"operationalScope": "single-tenant",
"tiersClaimed": ["C", "W"],
"requirements": [
{ "id": "BIO017-C-001", "status": "supported" },
{ "id": "BIO017-C-004", "status": "supported" },
{ "id": "BIO017-C-005", "status": "supported" },
{ "id": "BIO017-C-009", "status": "supported" },
{ "id": "BIO017-W-002", "status": "supported" },
{ "id": "BIO017-W-003", "status": "partial",
"reason": "Timers run for severity 2-4; severity 1 is batched into a daily digest by institutional policy." },
{ "id": "BIO017-X-001", "status": "excluded",
"justification": "No inter-institution exchange in this deployment; Exchange tier not claimed." },
{ "id": "SDK-calculateRiskScore", "status": "partial",
"reason": "Institution-supplied risk-assessment result stored as a record; SDK formula not used (range inconsistency, uncalibrated thresholds)." },
{ "id": "SDK-assessExposure", "status": "excluded",
"justification": "Technical safety assessment is reserved to qualified professionals and authority guidance; function disabled by feature flag." },
{ "id": "SDK-generatePPERequirements", "status": "excluded",
"justification": "Technical safety guidance is out of scope for a records system; function disabled by feature flag." }
],
"evidence": {
"vectorMatrix": "vector-matrix.json",
"sbom": "sbom.cdx.json",
"openapi": "openapi.yaml"
}
}
Two details in this example are deliberate. The requirementScheme field states that the IDs follow the book's proposal, so that a reader in two years' time will not confuse them with official numbering. And the sdk field records that the reference SDK was patched, which is exactly the kind of fact the changelog mapping in Annex H is meant to preserve.
When the institution later adds partner exchange and claims the X tier, it publishes a new manifest under a new profile version. Annex I requires the prior manifest to remain valid and signed for the deprecation window defined in Annex H. This matters for audits: an inspector reviewing an incident from last year must be able to see which profile the system claimed at that time, not only today's.
An institution running a WIA-BIO-017 system lives with at least three kinds of approval, and each is issued by a different party on different evidence. Confusing them causes real harm: a vendor who implies that conformant software makes a laboratory compliant is misleading the customer, and an institution that treats a green dashboard as proof of certification has handed a regulatory judgment to a computer.
| Aspect | WIA-BIO-017 software conformance | Facility certification / permit | IBC approval |
|---|---|---|---|
| Subject | A software system and its record handling | A physical facility and its operation | A research project or protocol |
| Who decides | The implementer self-declares; partners and auditors verify the evidence | The competent national authority or its designated body | The institutional biosafety committee |
| Evidence | Vectors, matrix, SBOM, signed manifest | Inspection, documentation, and criteria set by the authority | Risk assessment and project documentation reviewed by the committee |
| Where it appears in the records | Profile manifest, outside the record store | certification block of BiosaftyFacility | Authorization record referenced by approval ID (Chapter 2) |
| What it proves | The system stores, validates, and exchanges records as specified | The facility meets the authority's requirements | The project may proceed under stated conditions |
The certification block (certified, certificationDate, expirationDate, certifyingAuthority, nextInspectionDate) is a transcription of the authority's decision. Three rules keep it that way. First, no code path may set certified to true by computation; the field is written only by a person in the biosafety-officer role, and the write must reference the authority's document by number. Second, every write produces an audit event (Chapter 5) with the before and after hashes, so that a change of status is attributable. Third, the system may downgrade the effective status automatically when the expiry passes, as vector C-004 demands, but it may never upgrade it.
In Korea the relevant permits and reports for research facilities are governed by the LMO Act regime, and the requirements for each facility grade are set and updated by the competent authorities. This book does not restate them. The system's job is to hold the reference to the authority's decision and to warn when a date approaches; the institution should confirm current requirements directly with the authority and the national biosafety information center.
The PHASE documents describe shared services such as a WIA Standards registry (Annex H), a profile registry (Annex I) and a directory service (Annex J), but this book does not assume that any third-party WIA certification service is operating. The model that Annex J describes for single-tenant deployments, in which the organization signs its own manifest, is sufficient and verifiable: anyone can check the signature, the transparency-log entry, and the vector matrix. Where an institution wants independent assurance, it can commission an audit of the evidence package, but that audit remains a statement about software. Similarly, certification of an institution's biorisk management system against ISO 35001 is performed by management-system certification bodies and is a separate matter again; a conformant records system can make that audit easier, but it cannot substitute for it.
Annex H adopts Semantic Versioning 2.0.0 for the PHASE documents. A major version signals a backwards-incompatible change to a normative requirement; a minor version adds requirements without breaking existing implementations; a patch contains editorial changes only. Implementations should apply the same rule to their own schemas and to the profile names in their manifests.
The annexes disagree with each other in two places, and a reader who follows one annex without the other will build the wrong policy.
| Topic | Annex F / Annex E | Annex H | This book |
|---|---|---|---|
| Overlap after a breaking change | At least 90 days (Annex F) | At least 180 days of parallel maintenance | 180 days: the stricter value satisfies both |
| Renaming or removing a field | Triggers a minor version bump (Annex E) | Incompatible changes require a major bump | Major bump: a rename breaks every consumer that reads the old name, which is the SemVer definition of incompatible |
The practical effect of the second resolution is that vector C-009 fails any build that renames a field within a major version. The team then has two options: keep the old field as a deprecated alias alongside the new one (an additive change, allowed in a minor release), or schedule the rename for the next major version with the full deprecation cycle. The first option is almost always cheaper, and it is the same approach Chapter 2 recommends for the SDK's "Biosafty" spelling: keep the original identifier verbatim and add a correctly spelled alias.
Annex H defines two windows. During the parallel window of at least 180 days, both the old and new major versions are marked Stable in the WIA registry and either may be cited as conformant. After that, the old version enters a 12-month sunset window marked Deprecated, with a migration note that explains what replaced the requirement and why. The book reads the two windows as consecutive, which gives the following schedule for a new major version released on an example date:
| Phase | Duration | Status of old major | What implementers do |
|---|---|---|---|
| Parallel window | At least 180 days from release | Stable | Build and test against the new version; keep publishing evidence for the old one |
| Sunset window | 12 months | Deprecated | Migrate stored records and partners; publish the new manifest; keep the old one verifiable |
| After sunset | — | Retired | Claims against the old version are no longer "WIA-conformant"; historical evidence stays archived |
Patch-level errata need no window, because they do not change normative behavior. Annex H requires them to be tracked in a public errata register with each entry signed by the working-group chair. Many of the v1.0 issues listed in Chapter 8, such as identifier typos and document labels, are errata candidates; the risk-score range inconsistency, by contrast, changes behavior and would need at least a minor version.
A biosafety records system has one obligation that a stateless API does not: it keeps records for years, across several versions of the schema. Every stored record should therefore carry the schema version under which it was written. Migration from one major version to the next is itself an auditable operation: it runs as a named job, writes an audit event for each batch with before and after hashes, and never rewrites the historical evidence packages that referenced the old form. Retention periods for records and evidence are set by the laws of each jurisdiction and by the institution's policy; the PHASE documents' suggestion of a seven-year window should be treated as a practical minimum to check against local law, not as a statement of legal sufficiency.
Finally, Annex H asks implementations to publish a changelog mapping every supported PHASE version to the concrete build, container digest, or SDK version that satisfies it. Combined with quarterly evidence packages and retained manifests, this gives an auditor a complete line of sight: for any date, which version of the standard the system claimed, which build was running, and what the vector matrix said about it.
Conformance to WIA-BIO-017 is demonstrated with evidence, not asserted with a badge. Because v1.0 lacks the Annex A tier table and numbered requirements that its annexes refer to, this book proposes three record-level tiers (Core Records, Workflow, Exchange) and a requirement numbering that vectors can cite. Every requirement gets positive and negative vectors with a pinned evaluation time; skipped vectors need a justification from the signed profile manifest. The evidence package bundles SBOM, OpenAPI document, vector matrix, manifest, and changelog mapping under a Sigstore signature, contains only synthetic data, and is republished quarterly. The manifest declares out-of-scope SDK functions as excluded. Software conformance never substitutes for facility certification by an authority or for IBC approval. Versioning follows SemVer with a 180-day parallel window and a 12-month sunset, resolving the conflicts between Annexes E, F, and H in favor of the stricter rule.
Review questions
asOf time, and what goes wrong if the validator reads the system clock?assessExposure should appear in the profile manifest at all, given that the deployment has disabled it.Technical safety content: consult official biosafety authorities. This chapter covers software and record conformance only. For containment requirements, facility certification criteria, and all technical biosafety guidance, refer to the competent national authority (in Korea, the KDCA and the Ministry of Science and ICT with the national biosafety information center), the WHO Laboratory Biosafety Manual, and the BMBL.