AircraftComponent record, and ends by writing and testing a JSON Schema 2020-12 definition for it. The avionics LRU is the running example because it stresses the data model in ways a structural part does not.
"Avionics" covers the electronic systems an aircraft carries: navigation, communication, surveillance, flight management, displays, autoflight, and the monitoring equipment that ties them together. On a transport aircraft most of them live in racks of boxes in an electronics bay, wired to antennas, sensors and cockpit displays. The engineering question is what each system does and how accurate or redundant it must be. The records question, the subject of this book, is which physical unit, running which software, was installed where, and on what approval basis.
Satellite navigation (GNSS) derives position from constellations such as GPS, GLONASS, Galileo and BeiDou. Aviation receivers continuously check the integrity of the solution, and many use a satellite-based augmentation system (SBAS) that broadcasts corrections and integrity data from geostationary satellites. Examples are WAAS in North America, EGNOS in Europe, MSAS in Japan, GAGAN in India and KASS in Korea. SBAS is what allows approaches with vertical guidance without ground-based landing aids at every runway. The accuracy figures in the PHASE-2 source depend on receiver class and geometry. Treat them as indicative, not as requirements the data format checks.
An inertial reference system (IRS) integrates accelerations and rotation rates, usually measured by ring-laser or fibre-optic gyros in airliners. It needs no external signal, so it survives GNSS outages and jamming, but its position error grows with time. Navigation-grade systems are usually described as "about 1 nautical mile per hour class" free-inertial performance, and they must align while the aircraft is stationary, taking longer at high latitudes. The flight management system (FMS) sits above both sensors. It holds a navigation database revised on the ICAO 28-day AIRAC cycle and an aircraft-specific performance database, and it computes lateral (LNAV) and vertical (VNAV) guidance. The FMS shows why avionics records are not just "one part number": the same hardware can carry different software releases and a database that changes every four weeks.
Air-traffic voice communication uses VHF amplitude-modulated radios in the band from about 118 to 137 MHz. Congestion in Europe led to 8.33 kHz channel spacing, which splits each historical 25 kHz channel into three. The 19 MHz band therefore holds about 760 channels at 25 kHz but roughly 2,280 at 8.33 kHz. Under 8.33 kHz spacing, the six-digit "channel name" a pilot selects is not always equal to the carrier frequency, so a record that stores "the frequency" should say which one it means. VHF propagation is essentially line-of-sight, so range grows with altitude:
d [NM] ≈ 1.23 × √h [ft] (standard-atmosphere radio horizon)
Aircraft at h = 35,000 ft, ground station at sea level:
√35,000 ≈ 187.1 → d ≈ 1.23 × 187.1 ≈ 230 NM
Two aircraft, both at 35,000 ft:
d ≈ 230 + 230 ≈ 460 NM (terrain, power and receiver sensitivity permitting)
That geometry is why the PHASE-2 source describes VHF coverage as a few hundred nautical miles at cruise. Beyond line of sight, aircraft use HF radios with single-sideband voice and HF data link, relying on ionospheric propagation that varies with time of day, season and solar activity. SATCOM provides voice and data through geostationary systems such as Inmarsat and low-earth-orbit systems such as Iridium, the latter also covering the polar regions. Data rates differ widely by generation and service, so a record should store the terminal's part number and configuration rather than a data-rate figure. ACARS messaging and controller–pilot data link communications (CPDLC) run over these bearers.
TCAS II, the equipment implementing ICAO's ACAS II, interrogates nearby transponders on 1030 MHz and receives replies on 1090 MHz. From range, range rate and altitude it estimates time to closest approach, then issues a traffic advisory (TA) and, if needed, a resolution advisory (RA), a vertical manoeuvre coordinated with the other aircraft's TCAS. The warning times are not fixed. The thresholds grow with altitude through a set of sensitivity levels, spanning roughly 20–48 seconds for a TA and 15–35 seconds for an RA, so the single figures in the PHASE-2 source are one point in that range. The logic version (currently 7.1) is itself a configuration item a records system should show.
ADS-B turns the idea around: the aircraft broadcasts its own GNSS-derived position, velocity and identity, most commonly on 1090 MHz Extended Squitter (1090ES). ADS-B Out is mandated in several jurisdictions, including the United States and Europe, but rules, dates and airspace differ, and the United States also accepts 978 MHz UAT equipment in some airspace. A component record should capture what the unit is capable of and approved for, and leave "is this aircraft compliant here?" to the operator's configuration management.
Most avionics functions are packaged as line-replaceable units (LRUs): sealed boxes a line mechanic can swap at the gate, with the failed unit sent to a shop. Form-factor standards such as ARINC 600 standardise racks, connectors and cooling, and data buses such as ARINC 429 and ARINC 664 Part 7 (AFDX) connect the boxes. Four identities matter for each unit:
| Function | Typical equipment | Configuration facts beyond P/N and S/N |
|---|---|---|
| Navigation | GNSS receiver, IRS, FMS computer | Software P/N, navigation database cycle, SBAS capability, installed position |
| Communication | VHF, HF and SATCOM transceivers, data link unit | Software P/N, 8.33 kHz capability, enabled data link applications, modification status |
| Surveillance | TCAS II computer, Mode S transponder with ADS-B Out | Collision-avoidance logic version, ADS-B output version; the 24-bit aircraft address belongs to the airframe |
| All LRUs | — | Approval basis (e.g., TSO), DO-160G categories, DAL of hosted software, release certificate reference |
The transponder's 24-bit ICAO address is set at installation for the airframe registration; it does not belong to the box. That distinction between the unit and its installation recurs throughout this chapter. The WIA record describes the unit. The installation is a relationship over time, recorded by the traceability operation group (Chapter 5) and the maintenance-event flow (Chapter 6).
The PHASE-1 document states its scope in one sentence: it defines "the canonical data structures for aircraft component identification, structural envelopes, material certification records, and traceability metadata," expressed in JSON Schema 2020-12 and stable for the lifetime of the phase. Each phrase corresponds to a group of fields in the reference types:
| PHASE-1 concern | What it answers | Fields in the reference types |
|---|---|---|
| Component identification | Which design, and which individual unit? | id, type, partNumber, serialNumber, manufacturer, manufacturingDate |
| Structural envelope | How big and heavy, and what loads was it shown to carry? | dimensions, structuralAnalysis |
| Material certification | What is it made of, with which properties? | material |
| Traceability metadata | What approvals, inspections and history attach to it? | status, certification, inspectionHistory, metadata |
Component data moves between organisations in many shapes: a supplier's ERP export, a PDF release certificate, an MRO shop's work-order system, an airline's technical records database. Each describes the same serial number in its own vocabulary, and every hand-off is a place where a digit is transposed or a modification status is lost. A canonical format does not replace those systems. It gives them one representation to exchange, which a receiver can validate mechanically before a person looks at it. That is why PHASE 1 precedes the API (PHASE 2) and the protocol (PHASE 3): an interface is only as precise as the data it carries.
JSON Schema 2020-12 is the draft that OpenAPI 3.1 aligns with, which matters because PHASE 2 describes its interface in OpenAPI. One schema can then validate stored records, API request bodies and inter-organisation messages. The draft also introduced $defs for reusable sub-schemas and moved format checking into an optional vocabulary, a detail that matters in Section 4.6.
After its short introduction, the PHASE-1 file consists of engineering reference material (fuselage, wing and tail construction; aluminium, titanium and composite properties), which Chapter 2 covered. It contains no machine-readable schema. The concrete shape of the record is defined by the TypeScript reference types in the SDK package @wia/aircraft-component (api/typescript/src/types.ts). This chapter treats those types as the normative shape and derives a JSON Schema from them. Where the types leave a question open, the answer given here is marked as a proposal. The file's reference list also cites a hardware-component identification standard that could not be verified, so this book does not rely on it. The quality-system references it names, AS9100D and AS9145, are real and return in Chapter 7.
AircraftComponentAircraftComponent is the root object: one record per physical, serialised component. The table lists every field of the reference type, its unit or format, whether it is mandatory, and the real-world document that normally supplies the value. The last column matters most in practice, because a field without a clear source gets filled inconsistently.
| Field | Type | Unit / format | Required | Typical source document |
|---|---|---|---|---|
id | string | opaque (UUID recommended) | yes | Assigned by the creating system |
type | ComponentType | 9 enum values | yes | Engineering classification |
status | ComponentStatus | 6 enum values | yes | Lifecycle state (see below) |
partNumber | string | as marked | yes | Nameplate, drawing, parts catalogue |
serialNumber | string | as marked | yes | Nameplate, release certificate |
manufacturer | string | legal name | yes | Production approval holder, CoC |
manufacturingDate | string | ISO 8601 date | yes | Production record |
dimensions | Dimensions | mm, kg | yes | Outline and installation drawing |
material | MaterialSpecification | MPa, kg/m³ | yes | Material certificate, drawing notes |
structuralAnalysis | StructuralAnalysis | kN, MPa, cycles | no | Stress report |
certification | Certification | ISO 8601 dates | no | Approval document |
inspectionHistory | Inspection[] | array, may be empty | yes | Inspection reports, work orders |
metadata | object | free-form | no | Anything not modelled above |
The id is the record's key inside a system. It should be opaque, such as a UUID, and never built from part and serial number: part numbers change when a unit is modified and re-identified, and records are merged when systems are reconciled, and an identifier that encodes business data breaks in both cases. The business identity of a unit is manufacturer + part number + serial number (Section 4.5).
type takes one of nine values: fuselage, wing, tail, landing-gear, flight-control, hydraulic-system, fuel-system, avionics, engine-mount. This coarse taxonomy supports search (ComponentSearchQuery.type, Chapter 5) and tells a reader which other fields are meaningful. It does not replace the industry's ATA iSpec 2200 chapter numbering, in which communications is chapter 23, navigation 34 and auto flight 22. For avionics, record the ATA chapter in metadata as well.
status takes design, testing, certified, production, maintenance and retired, and the list mixes two lifecycles. The first three describe a design, and they are the same for every serial number of that part number. The last three describe an individual unit: produced, in the maintenance loop, retired. For serialised records this book uses the unit reading. A newly released unit is production, a unit removed to a shop is maintenance, a scrapped or life-expired unit is retired. The earlier states are reserved for prototypes and test articles, such as a qualification unit that went through DO-160 testing and will never fly. Chapter 6 formalises the transitions. An implementation should declare its interpretation, ideally in its profile manifest (Chapter 8).
The example describes a fictional VHF transceiver, and every name, number and dimension in it is illustrative. The material block reuses the PHASE-1 values for 2024-T3 only to show the units. A real chassis alloy comes from the manufacturer's drawing. Facts the reference types cannot hold have gone into metadata (Section 4.5).
AircraftComponent record for a VHF transceiver LRU{
"id": "3f2b8c1e-6a4d-4e0b-9c57-1d2e8a7b5f10",
"type": "avionics",
"status": "production",
"partNumber": "EXV-2100-01",
"serialNumber": "VX21-004517",
"manufacturer": "Example Avionics Co.",
"manufacturingDate": "2024-03-15",
"dimensions": { "length": 320, "width": 60, "height": 194, "weight": 3.2 },
"material": {
"type": "aluminum-2024",
"grade": "2024-T3 (chassis sheet)",
"strength": 470,
"fatigueLimit": 140,
"density": 2780,
"corrosionResistance": "medium"
},
"inspectionHistory": [
{
"id": "insp-2024-000871",
"inspectionDate": "2024-03-18",
"inspector": "QA-017",
"method": "visual",
"result": "pass",
"findings": "Receiving inspection: nameplate, connector pins, seals and labels conform."
}
],
"metadata": {
"wiaSchemaVersion": "1.0.0",
"manufacturerCode": { "scheme": "CAGE", "value": "EX001" },
"ataChapter": "23",
"hardwareModStatus": "B",
"softwareParts": [ { "role": "radio application", "partNumber": "EXV-SW-2100-0304" } ],
"approvalBasis": [ { "authority": "FAA", "basis": "TSO-C169a" } ],
"environmentalQualification": "RTCA DO-160G, categories per the unit's declaration",
"capabilities": { "channelSpacingKHz": [25, 8.33] },
"releaseCertificate": { "form": "FAA Form 8130-3", "trackingNumber": "EX-000123" },
"usage": { "hoursSinceNew": 0, "cyclesSinceNew": 0, "asOf": "2024-03-18" }
}
}
Three things are absent on purpose. There is no structuralAnalysis, because an LRU's mechanical qualification is its DO-160 vibration and shock testing, and inventing an applied load to fill the field would make the record less truthful. There is no certification, for a reason explained in Section 4.4. And there is no installed position or registration, because those belong to the installation.
DimensionsDimensions holds length, width and height in millimetres and weight in kilograms. The "weight" is a mass, not a force, and a system converting it to newtons or pounds-force must know that. The three lengths are a bounding envelope for handling, packaging and storage, not a geometric model: for a wing panel the "height" is a few millimetres over a span of metres. Where the drawing allows a weight tolerance, record the measured weight of the unit, since that is what the aircraft's weight-and-balance records ultimately depend on.
MaterialSpecificationMaterialSpecification carries type (aluminum-2024, aluminum-7075, titanium-ti6al4v, carbon-fiber, fiberglass, aramid, composite), a free-text grade, strength and fatigueLimit in MPa, density in kg/m³, and a three-level corrosionResistance. Chapter 2 covered the materials themselves. Four conventions are needed to write them down consistently:
2.78 here is almost certainly a unit error, which a schema can catch (Section 4.6).metadata.fatigueBasis). Otherwise a reader may take it as a stress below which the part never fails.composite or a neighbouring alloy is misleading, and the honest route is to propose a new value (Section 4.5).StructuralAnalysisStructuralAnalysis summarises a stress analysis: appliedLoad (kN), calculatedStress (MPa), a dimensionless safetyFactor, fatigueLife (cycles), analysisDate and analyst. It is a summary, never the analysis. The stress report, with its load cases, finite-element model and margins at each critical location, stays in the design organisation's controlled documents, and the record should cite it by number and revision in metadata.
The field name safetyFactor is ambiguous. The ratio of allowable to applied stress is a reserve factor, and the margin of safety is that ratio minus one (MS = allowable/applied − 1, Chapter 1). The factor of safety of 1.5 in CS/FAR 25.303 is something else: it converts limit loads to ultimate loads before any comparison. Following Chapter 1, this book stores the ratio of the allowable to the ultimate-level design stress (special factors included) at the critical location for the governing load case, with the load case named in metadata. Under that convention the pass criterion is 1.0, so the SDK helper ComponentAnalyzer.isSafe, whose default threshold is 1.5, must be called with an explicit minimum of 1.0; its default only makes sense for a stress computed at limit load (Chapter 5). fatigueLife must come from the fatigue and damage-tolerance analysis (Chapter 7), never from the SDK's estimateFatigueLife, whose formula returns 10⁸ cycles when applied stress equals ultimate strength. Chapter 5 examines it as an anti-example.
CertificationCertification has six mandatory fields: standard, authority, certificateNumber, issueDate, expiryDate and a boolean compliance. The reference types' comment suggests "WIA-SPACE-016" as a standard, while PHASE 2's certification-package group speaks of evidence for aviation authorities, so the object is generic. Records should use precise values, such as "TSO-C169a" with "FAA", rather than a vague "FAA certified".
The difficulty is expiryDate. A TSO authorisation, a type certificate, an FAA Form 8130-3 or an EASA Form 1 has no calendar expiry. It stays valid until surrendered, suspended or superseded, or until the part's condition changes. Filling a required expiry field with an invented far-future date would falsify the record. That is why the LRU example omits the optional certification object and records its approval basis in metadata.approvalBasis. Things that genuinely expire, such as a sealant batch's shelf life or a test set's calibration, are better modelled as their own records.
InspectionEach Inspection has id, inspectionDate, inspector, method, result, and optional findings and nextInspectionDate. The five methods (visual, ultrasonic, radiographic, magnetic-particle, eddy-current) are NDI techniques, described in Chapter 7. Two gaps are immediate. Liquid penetrant inspection, one of the most common methods, is missing. So is any functional or bench test, which is how a shop actually checks an avionics unit against its acceptance test procedure. Until the enum grows, such tests belong in metadata or a maintenance event (Chapter 6), and visual should record only what was genuinely visual.
The result values are pass, fail and conditional. "Conditional" means within limits but to be watched, and without findings and nextInspectionDate it is not actionable. The schema in Section 4.6 enforces that pairing. inspector should be an identifier the quality system can resolve to a qualified person, not a name typed by hand. Many inspections are scheduled in hours or cycles, which a calendar nextInspectionDate cannot express. That is one more reason usage counters are needed.
A serial number is unique only within a manufacturer's part number, and sometimes only within a manufacturer. Two suppliers can both ship serial number 1001. The business key of a WIA record should therefore be the triple (manufacturer, partNumber, serialNumber), and a registry should reject a duplicate triple. Because manufacturer is free text, and "Example Avionics Co." and "Example Avionics Company" would compare as different, store a coded identifier in metadata too. In much of the aerospace supply chain that is the CAGE code, a five-character code assigned in the United States by the Defense Logistics Agency, with NCAGE codes for organisations in other participating nations. The example records it as {"scheme": "CAGE", "value": "EX001"} so that other schemes can be named explicitly.
Part and serial numbers must be stored exactly as marked, including dashes and leading zeros. Normalising them eases matching inside one database but destroys the match with the physical nameplate, which is what an inspector or an investigator of suspected unapproved parts will check. If a normalised form is needed for search, keep it as a derived value.
All dates are strings. This book requires ISO 8601 calendar dates in YYYY-MM-DD form (the RFC 3339 full-date) for manufacturingDate, inspectionDate, nextInspectionDate, issueDate, expiryDate and analysisDate. Events that need a time of day use a full RFC 3339 timestamp with an explicit UTC offset, since aircraft and shops span time zones. Units are fixed by the field definitions (mm, kg, kN, MPa, kg/m³, cycles) and are never written as strings with suffixes. A system that ingests inches or pounds converts at the boundary and may keep the original in metadata for audit.
The avionics example exposes facts a real records system needs and the reference types do not model. The proposed extensions are this book's suggestions for a future minor version of PHASE 1, not part of the current standard.
| Gap | Why it matters | Interim location | Proposed extension |
|---|---|---|---|
| Software part numbers | An LRU's function depends on loaded DO-178C software | metadata.softwareParts[] | Optional softwareParts array |
| Modification status | SB incorporation changes the unit without a new P/N | metadata.hardwareModStatus | Optional modStatus |
| Hours and cycles | Life limits and repeat inspections are counted in hours and cycles | metadata.usage | Optional usage object with an as-of date |
| Coded manufacturer | Free-text names do not compare reliably | metadata.manufacturerCode | Optional manufacturerCode {scheme, value} |
| Approval without expiry | expiryDate is required but many approvals do not expire | metadata.approvalBasis[] | New optional field beside Certification |
| Penetrant, functional test | Common inspections cannot be recorded | findings + metadata | Additional method values |
For usage counters, spell field names out. The records abbreviations TSN, CSN and TSO (time since new, cycles since new, time since overhaul) collide: "TSO" is also the technical standard order. Every counter needs the date it was valid on, since a cycle count without an as-of date goes stale the day after it is written.
Annex E of the PHASE documents says additive changes (new optional fields, new error codes) are non-breaking, while renaming or removing a field "MUST trigger a minor version bump." Annex H adopts Semantic Versioning 2.0.0, in which a backwards-incompatible change is a major version. The two disagree on renames and removals. This book follows Annex H, the dedicated versioning policy, and treats them as major.
Under those rules most of the proposals above are minor-version changes: they add optional fields that old producers never send and old consumers can ignore. Two need care. New enum values are formally additive but break consumers that validate strictly against the old list, so they should ship with an announcement, and a tolerant consumer should flag an unknown value for review rather than reject the record. Making the existing expiryDate optional would break consumers that assume it exists, which is why the table proposes a separate field. Until anything is standardised, the metadata keys used here form an implementation profile to be declared in the profile manifest (Chapter 8), and each record carries the schema version it was written against (metadata.wiaSchemaVersion).
The SDK package declares a dependency on the zod library, but its client code never calls it, and the CLI's validate and check commands currently print success without inspecting their input (Chapter 8). A deployment must supply its own validator. The schema below is derived from the reference types plus the constraints argued for in this chapter. It is this book's construction, offered as a starting point, not a schema published by the standard.
AircraftComponent (excerpt; $id is a placeholder){
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:example:wia-space-016:aircraft-component:1.0.0",
"title": "AircraftComponent",
"type": "object",
"required": ["id", "type", "status", "partNumber", "serialNumber",
"manufacturer", "manufacturingDate", "dimensions",
"material", "inspectionHistory"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"type": { "enum": ["fuselage", "wing", "tail", "landing-gear",
"flight-control", "hydraulic-system", "fuel-system",
"avionics", "engine-mount"] },
"status": { "enum": ["design", "testing", "certified",
"production", "maintenance", "retired"] },
"partNumber": { "type": "string", "pattern": "^\\S(.*\\S)?$" },
"serialNumber": { "type": "string", "pattern": "^\\S(.*\\S)?$" },
"manufacturer": { "type": "string", "minLength": 1 },
"manufacturingDate": { "type": "string", "format": "date" },
"dimensions": { "$ref": "#/$defs/Dimensions" },
"material": { "$ref": "#/$defs/MaterialSpecification" },
"structuralAnalysis":{ "$ref": "#/$defs/StructuralAnalysis" },
"certification": { "$ref": "#/$defs/Certification" },
"inspectionHistory": { "type": "array", "items": { "$ref": "#/$defs/Inspection" } },
"metadata": { "type": "object" }
},
"$defs": {
"Dimensions": {
"type": "object",
"required": ["length", "width", "height", "weight"],
"additionalProperties": false,
"properties": {
"length": { "type": "number", "exclusiveMinimum": 0 },
"width": { "type": "number", "exclusiveMinimum": 0 },
"height": { "type": "number", "exclusiveMinimum": 0 },
"weight": { "type": "number", "exclusiveMinimum": 0 }
}
},
"MaterialSpecification": {
"type": "object",
"required": ["type", "grade", "strength", "fatigueLimit",
"density", "corrosionResistance"],
"additionalProperties": false,
"properties": {
"type": { "enum": ["aluminum-2024", "aluminum-7075", "titanium-ti6al4v",
"carbon-fiber", "fiberglass", "aramid", "composite"] },
"grade": { "type": "string", "minLength": 1 },
"strength": { "type": "number", "exclusiveMinimum": 0 },
"fatigueLimit": { "type": "number", "minimum": 0 },
"density": { "type": "number", "minimum": 500, "maximum": 20000,
"$comment": "kg/m3; bounds catch g/cm3 entries" },
"corrosionResistance": { "enum": ["low", "medium", "high"] }
}
},
"Inspection": {
"type": "object",
"required": ["id", "inspectionDate", "inspector", "method", "result"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "minLength": 1 },
"inspectionDate": { "type": "string", "format": "date" },
"inspector": { "type": "string", "minLength": 1 },
"method": { "enum": ["visual", "ultrasonic", "radiographic",
"magnetic-particle", "eddy-current"] },
"result": { "enum": ["pass", "fail", "conditional"] },
"findings": { "type": "string" },
"nextInspectionDate": { "type": "string", "format": "date" }
},
"if": { "properties": { "result": { "const": "conditional" } } },
"then": { "required": ["findings", "nextInspectionDate"] }
}
}
}
StructuralAnalysis and Certification follow the same pattern and are omitted for space. All their fields are required, and compliance is a boolean. Three design decisions deserve comment:
metadata. additionalProperties: false rejects a misspelled field such as serialNo that would otherwise be stored silently while serialNumber was missing. Extensions go into metadata. The cost is that a 1.0.0 validator rejects a record from a later minor version with a new top-level field, so an ingesting system should choose the schema by the record's wiaSchemaVersion.exclusiveMinimum: 0 and the wide density range are not engineering limits. They are cheap traps for sign and unit errors. The range covers foams through heavy metals and exists to reject 2.78 entered in g/cm³.if/then block implements the conditional-result rule, and the identifier pattern forbids leading or trailing whitespace, a frequent spreadsheet artefact, without constraining the manufacturer's marking scheme.format trapIn 2020-12, format is by default an annotation, not an assertion, so a validator may accept "15/03/2024" as a date unless format validation is switched on. With the Ajv library that means using its 2020-12 build and registering the formats package:
import Ajv2020 from "ajv/dist/2020";
import addFormats from "ajv-formats";
import schema from "./aircraft-component.schema.json";
const ajv = new Ajv2020({ allErrors: true, strict: true });
addFormats(ajv); // without this, "format": "date" is not checked
const validate = ajv.compile(schema);
export function checkRecord(record: unknown): string[] {
if (validate(record)) return [];
return (validate.errors ?? []).map(
(e) => `${e.instancePath || "/"} ${e.message ?? "invalid"}`
);
}
Inside a TypeScript service it is convenient to validate with zod and derive static types from the same definition. The mirror below covers Inspection with the same conditional rule. Its date regular expression checks shape only, so a production mirror should also reject impossible dates such as 2024-02-30. Keeping the zod mirror and the JSON Schema in agreement is a testing task: run both against the same positive and negative examples in CI, as Chapter 8 describes for test vectors.
Inspection mirrorimport { z } from "zod";
const isoDate = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD");
export const Inspection = z.object({
id: z.string().min(1),
inspectionDate: isoDate,
inspector: z.string().min(1),
method: z.enum(["visual", "ultrasonic", "radiographic",
"magnetic-particle", "eddy-current"]),
result: z.enum(["pass", "fail", "conditional"]),
findings: z.string().optional(),
nextInspectionDate: isoDate.optional(),
}).strict().superRefine((v, ctx) => {
if (v.result === "conditional" && (!v.findings || !v.nextInspectionDate)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "conditional result needs findings and nextInspectionDate",
});
}
});
export type Inspection = z.infer<typeof Inspection>;
A schema is only as good as the wrong inputs it has been shown to reject. Each case below is a small mutation of the valid record in Section 4.3 and must fail. A test that checks the reported keyword, not merely "invalid", catches records that fail for the wrong reason.
| Mutation of the valid record | Expected failing keyword | Real-world cause |
|---|---|---|
serialNumber removed | required | Serial not captured at receiving |
serialNo instead of serialNumber | additionalProperties, required | Field-name drift between systems |
"type": "avionic" | enum | Hand-typed or legacy classification |
"manufacturingDate": "15/03/2024" | format (only with format assertion) | Locale-formatted spreadsheet dates |
"density": 2.78 | minimum | g/cm³ entered as kg/m³ |
"weight": -3.2 | exclusiveMinimum | Sign error in a conversion script |
Inspection "method": "penetrant" | enum | Correct failure under 1.0 that signals the missing enum value |
"result": "conditional" without nextInspectionDate | required (in then) | Open finding with no follow-up |
"partNumber": "EXV-2100-01 " | pattern | Trailing space from an export |
A record that passes this schema is well-formed. That does not make it true, and it does not make the component airworthy. The schema cannot know whether serial VX21-004517 was really produced under the approval claimed, whether its release certificate exists, or whether the listed software is what is loaded in the box. Those questions belong to the traceability and certification operations of the API (Chapter 5), the release and maintenance flows between supplier, MRO, operator and authority (Chapter 6), and the signed evidence packages of the quality system (Chapter 7). PHASE 1 makes those processes possible by ensuring every party talks about the same unit, in the same units, with the same field names. A schema is the cheapest place to enforce that agreement and the first test a new implementation should pass.