Chapter 7

Chapter 7: Conformance Testing and Certification

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.

7.1 Conformance Claims and the Three Record-Level Tiers

7.1.1 A gap in the published documents

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.

7.1.2 The three tiers

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 coversChaptersExample requirement IDs
C — Core RecordsSchema validity of facility, training, incident, and compliance-result records; ID prefixes; ISO 8601 UTC timestamps; additive-only schema evolution; certification and training expiry detection2BIO017-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 — WorkflowIncident state machine and permitted transitions; notification timers by severity; RCA and CAPA records; compliance-finding codes; role checks on transitions3, 4BIO017-W-002 legal state transitions only; BIO017-W-003 severity-based notification timer; BIO017-W-006 CAPA owner and due date required
X — ExchangeMessage envelope, signature, idempotency, replay protection; append-only hash-chained audit events; custody transfer and receipt records; pseudonymized personnel IDs in outbound payloads5, 6BIO017-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.

7.1.3 Pass/fail, not a percentage

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.

7.1.4 Wording a claim

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.

7.2 Test Vectors

7.2.1 What Annex G requires

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.

7.2.2 Anatomy of a vector

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.

7.2.3 Four worked vectors

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 IDRequirementTierInput (summary)Expected
C-004-pos-01BIO017-C-004CCertified facility, expiry after asOfValid, no findings
C-004-neg-01BIO017-C-004Ccertified: true, expiry before asOfInvalid; B010
C-005-pos-01BIO017-C-005CAll authorized personnel hold current trainingValid
C-005-neg-01BIO017-C-005COne authorized person's training expiredInvalid; B009 naming that ID
C-005-neg-02BIO017-C-005CAuthorized person with no training recordInvalid; B009, reason "no record"
W-002-pos-01BIO017-W-002Wresolved → closed by an authorized reviewerAccepted; audit event written
W-002-neg-01BIO017-W-002Wclosed → under-investigation without reopenHTTP 409; record unchanged
W-002-neg-02BIO017-W-002Wopen → resolvedHTTP 409; record unchanged
W-003-neg-01BIO017-W-003WSeverity 3 incident, no notification after the 1-hour target (spec §7.1.1)Overdue-notification flag raised
C-009-pos-01BIO017-C-009CNew optional field addedSchema diff: additive
C-009-neg-01BIO017-C-009CnextTrainingDue renamedSchema diff: breaking; build fails

7.2.4 Running vectors in CI

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/ }

7.2.5 Negative results start at home

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.

7.3 The Evidence Package

7.3.1 Contents

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.

ItemSourcePurpose
SBOM in CycloneDX 1.5 or SPDX 2.3Annex GLists every component and version, so consumers can check for known vulnerabilities and licence issues
OpenAPI documentAnnex 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 matrixAnnex GOne row per vector, including skipped vectors with their justification
Profile manifestAnnex IPer-requirement status: supported, partial, or excluded (Section 7.4)
Changelog mappingAnnex HMaps each supported PHASE version to a build, container digest, or SDK version
Signed manifestAnnex GDigest 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

7.3.2 Signing and transparency

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.

7.3.3 What must never go into the package

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.

7.3.4 Quarterly re-publication

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.

7.4 The Profile Manifest

7.4.1 Statuses and signing

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.

7.4.2 Declaring exclusions honestly

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.

7.4.3 When a profile widens

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.

7.5 Software Conformance Is Not Facility Certification

7.5.1 Three different decisions

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.

AspectWIA-BIO-017 software conformanceFacility certification / permitIBC approval
SubjectA software system and its record handlingA physical facility and its operationA research project or protocol
Who decidesThe implementer self-declares; partners and auditors verify the evidenceThe competent national authority or its designated bodyThe institutional biosafety committee
EvidenceVectors, matrix, SBOM, signed manifestInspection, documentation, and criteria set by the authorityRisk assessment and project documentation reviewed by the committee
Where it appears in the recordsProfile manifest, outside the record storecertification block of BiosaftyFacilityAuthorization record referenced by approval ID (Chapter 2)
What it provesThe system stores, validates, and exchanges records as specifiedThe facility meets the authority's requirementsThe project may proceed under stated conditions

7.5.2 The certification block records; it never decides

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.

7.5.3 Self-declaration as the default model

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.

7.6 Versioning and Deprecation

7.6.1 Semantic versioning

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.

7.6.2 Two conflicts in the text, and how the book resolves them

The annexes disagree with each other in two places, and a reader who follows one annex without the other will build the wrong policy.

TopicAnnex F / Annex EAnnex HThis book
Overlap after a breaking changeAt least 90 days (Annex F)At least 180 days of parallel maintenance180 days: the stricter value satisfies both
Renaming or removing a fieldTriggers a minor version bump (Annex E)Incompatible changes require a major bumpMajor 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.

7.6.3 The deprecation timeline

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:

PhaseDurationStatus of old majorWhat implementers do
Parallel windowAt least 180 days from releaseStableBuild and test against the new version; keep publishing evidence for the old one
Sunset window12 monthsDeprecatedMigrate stored records and partners; publish the new manifest; keep the old one verifiable
After sunset—RetiredClaims 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.

7.6.4 Versioning stored records

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.

Summary

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

  1. Why must every expiry-related vector pin an asOf time, and what goes wrong if the validator reads the system clock?
  2. A vendor's matrix shows 96% of vectors passing and no skipped rows. Under the rules in this chapter, can it claim the Core Records tier?
  3. Which items in an evidence package could leak sensitive facility information, and how would you prevent it before signing?
  4. Explain why assessExposure should appear in the profile manifest at all, given that the deployment has disabled it.
  5. A developer renames a field in a minor release, citing Annex E. How do you respond, and what alternative do you propose?

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.