๐ WIA Delivery Robot Standard Ebook | Chapter 7 of 8
The previous four chapters described what a WIA ROB-010 implementation has to do: emit Phase 1 payloads, serve the Phase 2 REST surface, behave according to the Phase 3 navigation contract and plug into a Phase 4 fleet. This chapter is about proving it. A buyer, a building operator or a city permitting office does not want to read your source code; they want a verifiable claim of the form "this build of this robot stack conforms to WIA ROB-010 v1.0.0 at tier X, and here is the evidence." The chapter explains what the standard's three conformance tiers mean in practice, how to build test vectors from the schemas and error cases you already know, how to assemble and sign an evidence package, what the reference CLI does and does not check, how to measure the Phase 3 behavioural targets honestly, and where WIA conformance ends and product safety certification begins.
One caution runs through the whole chapter. The conformance machinery of v1.0.0 is described in three places โ the README (tiers), the non-normative Annexes EโG repeated at the end of each PHASE document, and the cli/delivery-robot.sh script โ and none of them defines tier requirements in detail. Where this chapter goes beyond those texts, it says so and labels the material as the author's recommendation.
The README defines conformance in one line each: Surface covers data formats, Verified adds an annual third-party audit, and Anchored adds a continuous evidence package. The tiers are cumulative in spirit: an Anchored implementation that emits non-conformant JSON is not meaningfully Anchored. Read together with Annex G, a practical interpretation is as follows.
$ids and either find violations or not.| Tier | README definition | Minimum evidence | Who checks | Cadence |
|---|---|---|---|---|
| Surface | Data formats | Vector matrix for Phase 1 (and Phase 2 error cases), OpenAPI document, declared profile | Vendor; any customer can re-check | Every release |
| Verified | Annual third-party audit | Surface evidence plus Phase 3 behavioural test records, Phase 4 integration logs, signed audit report | Independent auditor | At least annually, and on each major version |
| Anchored | Continuous evidence package | Verified evidence plus SBOM, Sigstore-signed manifest with transparency-log entry, quarterly re-publication | Automated verification by consumers | Quarterly and on every release |
Two things the tiers do not say should be stated plainly. First, the public documents do not specify who is qualified to act as the Verified-tier auditor, nor a WIA accreditation scheme for auditors. Until one exists, choose an auditor whose independence and competence can be demonstrated โ for instance a body accredited to ISO/IEC 17065 (product certification) or a testing laboratory accredited to ISO/IEC 17025 โ and name them in the evidence package. Second, no tier is a safety certification. A robot can conform at the Anchored tier and still be unsafe on a crowded pavement; section 7.7 returns to this.
The annexes also refer to a tier-scoring annex and to another annex that do not exist in any of the four PHASE files. Do not cite them in your own documents; cite the README for tier names and Annex G for evidence shape.
The same software can be deployed in very different ways, and an auditor cannot judge isolation, availability or evidence freshness without knowing which. The CLI's profiles command lists four named profiles:
| Profile | CLI description | Typical delivery-robot case | What testing must additionally show |
|---|---|---|---|
single-tenant | One runtime per organization | A campus operator running its own fleet manager | Nothing beyond the base vectors; simplest to audit |
multi-tenant | Shared runtime, header-based isolation | A fleet platform serving several merchants or building owners | Negative vectors proving tenant A's token cannot read tenant B's robots, packages or telemetry topics |
federated | Peer-to-peer mesh of runtimes | Two operators sharing a building's elevators and doorways | Cross-runtime identity, clock agreement, handling of a peer that is offline |
air-gapped | Batch evidence package, no live connectivity | A hospital or factory site with no outbound internet | Evidence exported in batches; signatures verifiable offline (see 7.4) |
Annex E asks implementations to declare their operational scope in the OpenAPI document, but lists only three scopes (single-tenant, multi-tenant, federated), while the CLI lists four. Declare whichever applies, including air-gapped, and record the discrepancy in your conformance notes. OpenAPI 3.1 has no dedicated field for this, so a specification extension on the info object is the least surprising place:
openapi: 3.1.0
info:
title: Example Fleet Platform โ WIA ROB-010 Phase 2
version: 2.4.0
x-wia-conformance:
standard: WIA ROB-010
standardVersion: 1.0.0
tier: surface
profile: { named: multi-tenant, version: 1 }
tenantHeader: X-Tenant-Id
The x-wia-conformance key is an author proposal, not text from the standard; the x- prefix is the mechanism OpenAPI provides for extensions. For a multi-tenant profile, naming the isolation header explicitly lets an auditor write the cross-tenant negative vectors without guessing.
Annex G sets out the rule simply: every normative requirement in a PHASE has at least one positive vector and one negative vector, stored under tests/phase-vectors/<phase>/ with one directory per PHASE (phase-1-data-format, phase-2-api-interface, phase-3-protocol, phase-4-integration). Implementations claiming conformance must run all vectors in CI and publish the pass/fail matrix. Annex G describes these vectors, but at the time of writing you should not assume a complete official vector set is available in the public repository; check the repository yourself, and be prepared to write your own vectors and publish them alongside your matrix.
A positive vector demonstrates that a correct input is accepted or a correct behaviour occurs. A negative vector demonstrates that an incorrect input is rejected, or that a fault triggers the required response. Negative vectors are the ones that catch real defects: a validator configured so loosely that it accepts everything will pass every positive vector.
Annex G does not define the file format of a vector. The following shape, a proposal of the author, keeps each vector self-describing so the matrix can be traced back to the requirement it tests:
{
"vector_id": "P1-RS-BATTERY-NEG-01",
"phase": "phase-1-data-format",
"requirement": "RobotState.battery_level is a number in [0, 100]",
"kind": "negative",
"schema": "https://wiastandards.com/schemas/delivery-robot/v1/robot-state.json",
"input": {
"robot_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-01T09:15:00Z",
"version": "1.0.0",
"position": { "latitude": 37.5665, "longitude": 126.9780, "source": "fused" },
"battery_level": 104
},
"expect": { "valid": false, "error_path": "/battery_level" }
}
The error_path matters. A negative vector that only asserts "invalid" will pass even if the payload is rejected for an unrelated reason โ for example because the validator cannot resolve a $ref. Pinning the expected failure location makes the vector test the rule it claims to test.
Chapter 3 gives you almost every rule you need. Walk each schema keyword and write one pair per rule:
required (RobotState: robot_id, timestamp, version, position, battery_level) โ a negative vector with the field removed;minimum/maximum โ values at the boundary (positive: battery_level 0 and 100, heading 360) and just outside it (negative: โ0.1, 100.1);enum โ one listed value (positive) and a plausible near-miss (negative: mode = "navigating", which is a Phase 3 state but not a Phase 1 mode);pattern โ version "1.0" and access code "12ab" as negatives;format โ a non-UUID package_id such as the Phase 2 example value pkg-2025-12-26-0001 as a negative.Two technical traps catch most first attempts. First, in JSON Schema 2020-12, format is by default an annotation, not an assertion; many validators will accept "robot_id": "hello" unless you switch format checking on, and some format checkers silently skip date-time when an optional dependency is missing. Your format negative vectors will expose this immediately โ which is why they exist. Second, the published RobotState schema references CargoStatus, ActiveRoute and Error, which are not defined anywhere in Phase 1 (Chapter 3.7). The schema will not compile until you supply those definitions. Because the references are local (#/$defs/CargoStatus), they must resolve inside your local copy of robot-state.json: assemble that copy with all the $defs the spec prints separately (Position, SensorReadings), and for the missing ones add entries that point to your own clearly named definitions file, for example "CargoStatus": { "$ref": "https://schemas.example.com/wia-dr-local-defs.json#/$defs/CargoStatus" }. Include both files in the evidence package so the auditor sees exactly what you filled in.
Phase 2 vectors are HTTP exchanges rather than documents: a request, the expected status code and, for failures, the expected error envelope code. The requirements of Chapter 4 translate directly:
| Requirement | Positive vector | Negative vector |
|---|---|---|
| Bearer token required | Valid token โ 200 | No Authorization header โ 401 with error envelope |
| Scope enforcement | robot:control token starts navigation โ 202 with command_id | robot:read-only token calls commands/start โ 403 |
| Unknown resource | Existing robot โ 200 | Unknown robot_id โ 404, code = ROBOT_NOT_FOUND |
| Input validation | Valid package โ 201 | Package with weight_kg = โ1 โ 400 |
| Rate limiting | Headers X-RateLimit-* present on 200 | Limit exceeded โ 429, code = RATE_LIMIT_EXCEEDED, retry_after present |
| Error envelope shape | โ | Every 4xx/5xx body has code, message, timestamp, request_id |
The last row deserves a vector of its own because error paths are where implementations drift: a framework's default 404 page or a reverse proxy's 502 body is rarely in the WIA envelope. For multi-tenant deployments, add the cross-tenant negatives from Table 7-2.
Behavioural requirements cannot be checked by validating a document. A Phase 3 vector is a scenario: a recorded or synthesized sensor stream fed to the autonomy stack, and an assertion over the resulting commands and telemetry. For example, "LiDAR stream stops for 5 s โ commanded speed limit drops by 50 %", or "GPS fix absent for 30 s โ position.source leaves gps". The negative counterpart checks that the response does not fire early โ LiDAR silent for 1 s must not halve the speed โ because a robot that degrades at every hiccup is also out of specification. Phase 4 vectors look similar at the message level: a duplicated QoS 1 message on fleet/robots/{robot_id}/state must be de-duplicated by the consumer (Chapter 6), and a robot at 18 % battery must not be offered a task that the assignment rule excludes.
The following Python runner handles document vectors (Phase 1 and the envelope checks of Phase 2). It uses the jsonschema library with its referencing registry so that $refs resolve to local copies of the schemas, and it turns format assertion on.
# tools/run_vectors.py โ install: pip install "jsonschema[format-nongpl]"
import json, pathlib, sys
from jsonschema import Draft202012Validator
from referencing import Registry, Resource
SCHEMAS = pathlib.Path("schemas") # local copies, incl. your own $defs
VECTORS = pathlib.Path("tests/phase-vectors")
def load_registry():
resources = []
for p in SCHEMAS.glob("*.json"):
doc = json.loads(p.read_text())
resources.append((doc["$id"], Resource.from_contents(doc)))
return Registry().with_resources(resources)
def run():
registry, rows = load_registry(), []
for vf in sorted(VECTORS.rglob("*.json")):
v = json.loads(vf.read_text())
if v.get("skip"):
rows.append({"id": v["vector_id"], "result": "skipped",
"justification": v.get("justification")})
continue
schema = registry.contents(v["schema"])
validator = Draft202012Validator(
schema, registry=registry,
format_checker=Draft202012Validator.FORMAT_CHECKER)
errors = list(validator.iter_errors(v["input"]))
ok = (not errors) == v["expect"]["valid"]
if ok and errors and "error_path" in v["expect"]:
ok = any(e.json_path.replace("$", "", 1).replace(".", "/")
== v["expect"]["error_path"] for e in errors)
rows.append({"id": v["vector_id"], "result": "pass" if ok else "fail"})
json.dump(rows, sys.stdout, indent=2)
bad = [r for r in rows if r["result"] == "fail"
or (r["result"] == "skipped" and not r.get("justification"))]
sys.exit(1 if bad else 0)
if __name__ == "__main__":
run()
The path comparison is deliberately simple and works for flat field names such as /battery_level; extend it for array indices if your vectors need them. Note the exit rule: Annex G states that a test skipped without recorded justification is treated as a failure, and the runner enforces exactly that. A skip with a justification is still reported in the matrix so the auditor can judge whether the reason is acceptable.
Annex G describes the compliance package as a tarball containing four things: a software bill of materials (CycloneDX 1.5 or SPDX 2.3), the OpenAPI document, the test-vector matrix and a signed manifest. In practice it is worth adding the schemas you actually validated against (including your filled-in $defs) and, for Verified and Anchored tiers, the behavioural test records. A layout that keeps these easy to find:
evidence-2026Q3/
โโโ manifest.json # identity of the build and the claim
โโโ manifest.sigstore.json # Sigstore bundle: signature, certificate, Rekor entry
โโโ sbom.cdx.json # CycloneDX 1.5 (or sbom.spdx.json, SPDX 2.3)
โโโ openapi.yaml # the Phase 2 surface you actually serve
โโโ schemas/ # Phase 1 schemas + your own $defs
โโโ vector-matrix.json # output of the runner, incl. skips
โโโ behaviour/ # Phase 3 scenario results and field logs
โโโ attestations/ # in-toto statements (build, test)
The SBOM answers "what is inside this build?" For a delivery robot, that includes the on-robot image (ROS 2 packages, drivers, perception models) and the cloud services, which are usually separate builds with separate SBOMs. Generate the SBOM from the artefact you ship, not from a developer's workstation, so that it matches the build digest in the manifest. With Syft, for example, syft <image> -o cyclonedx-json=sbom.cdx.json produces a CycloneDX JSON document; confirm that the specVersion field reads the version you claim (1.5 in the annex).
Annex G specifies Sigstore signatures using a DSSE envelope and a Rekor transparency-log entry, so that consumers can verify provenance "without trusting a private CA". The three pieces play distinct roles. DSSE (Dead Simple Signing Envelope) wraps the signed payload together with its type, so a signature over a manifest cannot be replayed as a signature over something else. The Sigstore keyless flow binds the signature to a short-lived certificate issued to a workload identity โ for instance a CI workflow โ instead of a long-lived private key. Rekor records the signing event in an append-only public log, which gives the "continuous" in Anchored its meaning: anyone can see that the Q3 package was signed, and when.
With the cosign tool, one workable pattern is to attach the manifest to the evidence tarball as an in-toto attestation (cosign v2-series commands shown; check the flags against the version you install):
# in CI, with an OIDC identity available to cosign
tar -czf evidence-2026Q3.tar.gz evidence-2026Q3/
cosign attest-blob --yes \
--predicate evidence-2026Q3/manifest.json \
--type https://wiastandards.com/attestations/delivery-robot/conformance/v1 \
--bundle evidence-2026Q3.sigstore.json \
evidence-2026Q3.tar.gz
# consumer side
cosign verify-blob-attestation \
--bundle evidence-2026Q3.sigstore.json \
--type https://wiastandards.com/attestations/delivery-robot/conformance/v1 \
--certificate-identity-regexp 'https://github.com/example-org/.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
evidence-2026Q3.tar.gz
The predicate-type URI above is an author choice; the standard does not define one. What matters is that it is stable and published, so verifiers can require it. For the air-gapped profile, keep the bundle next to the tarball: a Sigstore bundle contains the material needed for offline verification, provided the verifier has a copy of the Sigstore trust root distributed out of band.
The CLI lists the in-toto Attestation Framework among its reference frameworks. Beyond the conformance attestation, two further statements are useful: a build provenance statement tying the image digest to the source commit, and a test statement tying the vector matrix to the same digest. Together they let a consumer check that the tested build and the shipped build are one and the same, which is the question auditors most often have to answer by hand.
Annex G asks for the package to be re-published every quarter even if the source did not change, so that consumers can notice environmental drift โ a new compiler, an updated base image, a patched dependency. Rebuild, regenerate the SBOM, rerun the vectors, and sign again. If the new SBOM differs from the previous one while the source commit is unchanged, that difference is exactly the drift the quarterly rule is designed to reveal; record it in the manifest notes rather than hide it.
Retention of evidence packages is a separate question from telemetry retention. Phase 4 gives "auto-delete old telemetry (e.g., 90 days)" as a privacy measure, while evidence packages and audit records are kept for as long as your auditor, certification body or regulator requires. Annex E states a seven-year figure and attributes it to ISO/IEC 17065 audit expectations, but gives no source for that link; derive your retention period from the actual requirements that apply to you, and keep the two clocks apart so that deleting telemetry never deletes evidence.
The repository ships a Bash script, cli/delivery-robot.sh (version 1.0.0), with four commands. A typical session looks like this:
$ ./cli/delivery-robot.sh info
WIA delivery-robot
Version: 1.0.0
Conformance tiers (see README.md): Surface / Verified / Anchored.
Conformance package follows CycloneDX 1.5 + Sigstore (DSSE + Rekor).
$ ./cli/delivery-robot.sh profiles
Supported conformance profiles for delivery-robot:
- single-tenant one runtime per organization
- multi-tenant shared runtime, header-based isolation
- federated peer-to-peer mesh of runtimes
- air-gapped batch evidence package, no live connectivity
...
$ ./cli/delivery-robot.sh manifest-template > manifest.json
$ ./cli/delivery-robot.sh validate manifest.json
OK: manifest.json declares standardSlug=delivery-robot
$ ./cli/delivery-robot.sh validate robot-state.json
standardSlug mismatch: got '', expected 'delivery-robot'
The last two lines are the most instructive in the chapter. A perfectly valid RobotState payload fails validate, and a manifest full of placeholder values passes it. That is because validate checks one thing only: that the file's standardSlug equals delivery-robot. It is a manifest sanity check, not a payload validator, and it proves nothing about Phase 1โ4 conformance.
The template emitted by manifest-template has six top-level fields. Filled in for a hypothetical release, it looks like this (all values are examples):
{
"documentId": "wia-delivery-robot-0007",
"standardSlug": "delivery-robot",
"version": "1.0.0",
"implementation": {
"name": "example-sidewalk-stack",
"build": "sha256:3f5c0dโฆ(image digest)",
"sbom": "https://evidence.example.com/2026Q3/sbom.cdx.json"
},
"profile": { "named": "multi-tenant", "version": 1 },
"issuedAt": "2026-09-30T00:00:00Z"
}
| Field | Meaning | Practical note |
|---|---|---|
documentId | Identifier of this manifest | Template value wia-delivery-robot-XXXX must be replaced; keep IDs unique per publication |
standardSlug | Which WIA standard | Always delivery-robot; the only field the CLI checks |
version | Standard version claimed | This is the standard's version, not your product's |
implementation.name | Product or service name | Template value REPLACE_ME |
implementation.build | Git SHA or image digest | Prefer the image digest; it is what the SBOM and signature cover |
implementation.sbom | Where the SBOM lives | Should resolve to the file inside this package or a durable copy |
profile | Named deployment profile and its version | One of the four profiles in 7.2 |
issuedAt | Issue time | The template hard-codes a fixed date; always overwrite it |
Notice what the manifest lacks: a tier, a list of PHASEs covered, and a pointer to the vector matrix. Until the template grows those fields, add them under a clearly namespaced extension object (for example "x-wia": { "tier": "anchored", "phases": [1,2,3,4], "vectorMatrix": "vector-matrix.json" }) rather than inventing new top-level keys that a future template might define differently.
Besides the narrow scope of validate, two implementation details are worth fixing in your fork. The Python fallback (used when jq is absent) interpolates the file name into Python source code, so a path containing a quote character breaks it; pass the path as an argument instead. And the script never verifies signatures, so it cannot tell a signed package from an unsigned one. A minimal extension adds a validate-payload command that delegates to the vector runner's validator:
validate_payload() {
local schema_id="$1" file="$2"
python3 - "$schema_id" "$file" <<'PY'
import json, sys
sys.path.insert(0, "tools")
from run_vectors import load_registry
from jsonschema import Draft202012Validator
schema_id, path = sys.argv[1], sys.argv[2]
reg = load_registry()
v = Draft202012Validator(reg.contents(schema_id), registry=reg,
format_checker=Draft202012Validator.FORMAT_CHECKER)
errs = sorted(v.iter_errors(json.load(open(path))), key=lambda e: e.json_path)
for e in errs:
print(f"{e.json_path}: {e.message}")
sys.exit(1 if errs else 0)
PY
}
# add to the case statement:
# validate-payload) validate_payload "$2" "$3" ;;
With that in place, validate-payload https://wiastandards.com/schemas/delivery-robot/v1/robot-state.json robot-state.json performs a genuine Surface-tier check of one document, and the same code path runs in CI.
Phase 3 ยง8 lists performance targets, and ยง6 adds the emergency-stop and failure-mode timings. They are simple to state and easy to measure badly. The core difficulty is that each target is a statement about a time interval or a rate, and the spec does not define exactly where the interval starts or what the denominator is. Your test plan must fix those definitions and write them into the evidence package.
| Spec target | Start/end or denominator to declare | Instrumentation |
|---|---|---|
| Position error < 0.5 m, 95 % of the time | Horizontal error against ground truth, per sample, over declared routes | Reference trajectory from a surveyed RTK receiver or surveyed markers; report the 95th percentile, not the mean |
| Obstacle detection rate > 99.9 % | Detected obstacles รท obstacles presented, per scripted encounter | Scripted encounters with labelled targets; see the sample-size note below |
| False positive rate < 5 % | Declare it: per detection, per encounter or per kilometre | Labelled logs; review every stop that had no real obstacle |
| Reaction time < 100 ms, detection to evasive action | From sensor capture timestamp (worst case) or perception output (best case) โ report both | Common clock across sensors and motor controller (NTPv4 or PTP per Annex E) |
| Emergency-stop motor cutoff < 100 ms | From trigger (button edge, command receipt on the robot, perception event) to measured drop in motor current | External measurement, e.g. a logic analyser or current probe, not software logs |
| Route deviation < 10 % | Actual path length รท reference optimal length โ 1 | Declare the reference planner and map used to compute "optimal" |
| Failure-mode timers (GPS 30 s, LiDAR 5 s, comms 60 s, stuck 30 s, battery < 15 %) | From fault injection to observable response in telemetry | Fault injection in simulation and on a closed course; negative vectors for early triggering |
Why external instrumentation for the emergency stop? A software log proves that the stop command was issued; it does not prove that current stopped flowing to the motors. The whole point of a safety-relevant timing is the physical effect, and a relay or motor driver that lags by tens of milliseconds is invisible in application logs.
Simple kinematics shows why these two numbers must be tested together. Take, as an example only, a robot travelling at 1.5 m/s. In 100 ms it covers 0.15 m before the motors are cut. If it then decelerates at an assumed 2 m/sยฒ, the braking distance is vยฒ/(2a) = 1.5ยฒ / 4 โ 0.56 m. The total stopping distance is about 0.71 m โ more than twice the 0.3 m obstacle trigger in ยง6.1. The conclusion is not that the spec is wrong, but that the 0.3 m trigger is a last-resort threshold: the local planner and the speed limits of Chapter 5 must keep the robot slow enough, and far enough away, that the emergency stop is rarely the only line of defence. A good Phase 3 scenario vector therefore measures stopping distance at the robot's maximum permitted speed, not just the cutoff latency.
Rate targets need sample sizes that match them. A standard statistical rule of thumb, the "rule of three", states that if an event is observed zero times in n independent trials, the 95 % upper confidence bound on its probability is approximately 3/n. To support "miss rate below 0.1 %" (detection above 99.9 %) with zero misses, you therefore need roughly 3,000 independent encounters; with even one miss you need more. Twenty passes on a test track tell you almost nothing about a 99.9 % target. State the trial count and the confidence bound in the evidence package, and keep the encounters varied (lighting, weather, obstacle classes, approach angles) so that they are genuinely independent.
A sound progression has three stages. Simulation runs the Phase 3 scenario vectors at scale, including fault injection that would be unsafe or impractical to reproduce physically; it is the only practical way to reach thousands of encounters early. Closed-course testing repeats a representative subset with physical sensors, real braking and external timing instruments, and calibrates how far simulation results can be trusted. Pilot operation in the intended environment, under whatever local authorization applies, then produces the field logs that support the operator KPIs below.
The simulator published with the standard has a "Safety & Testing Suite" panel with scenario and sensor-suite selectors, a "Run Safety Test" button and a compliance checklist. It is a demonstration of what a test report might look like: the result it prints is a fixed object with the same timings and a "passed": true field on every run, and the checklist items (for example a GPS accuracy figure and an ingress-protection rating) are not requirements of the PHASE documents. Use it to explain the idea to stakeholders; do not put its output in an evidence package.
Phase 4 ยง6.1 lists fleet KPIs with targets. They describe how well a service runs, not whether an implementation conforms, and they are best treated as operator targets agreed with customers.
| KPI | Spec target | Definition in the spec | Measurement note |
|---|---|---|---|
| Delivery success rate | > 99 % | Delivered รท total deliveries | Declare how cancellations by the customer and returns are counted |
| Average delivery time | < 15 min | Mean from assignment to delivery | Report the distribution too; a mean hides long tails |
| Fleet utilization | > 80 % | Time in active delivery รท total time | Declare whether charging and maintenance time is in the denominator |
| Energy efficiency | > 5 km/kWh | Distance รท energy consumed | Measure energy at the charger or from the battery management system consistently |
| Customer satisfaction | > 4.5 / 5 | Survey ratings | Not a technical measurement; keep it out of conformance claims |
| Incidents per 1,000 deliveries | < 1 | Safety events รท total deliveries | Define "safety event" before the pilot starts, including near misses |
WIA ROB-010 is a data and protocol standard. Conformance, even at the Anchored tier, answers the question "does this implementation speak the common language correctly and prove it continuously?" It does not answer "is this robot safe to operate among people?" or "is this robot permitted on this pavement?" Those are separate tracks with their own bodies and procedures.
| Track | Question answered | Typical assessor | Output |
|---|---|---|---|
| WIA ROB-010 conformance | Correct data, API, behaviour contract and fleet integration | Vendor (Surface), independent auditor (Verified), public verification (Anchored) | Vector matrix, signed evidence package, audit report |
| Product safety | Is the robot acceptably safe? For example, assessment against ISO 13482, where the certification body judges that standard applicable | Certification body accredited to ISO/IEC 17065 | Product certificate |
| Operating permission | May it operate here? For example, Korea's operating-safety certification for outdoor mobile robots, or a city's sidewalk permit | National or local authority and its designated bodies | Certificate, permit or licence with conditions |
| Information security | Is the organization's security management adequate? | ISO/IEC 27001 certification body | Management-system certificate |
| Privacy | Is camera and location data processed lawfully? | Internal or external assessment under PIPA, GDPR or other applicable law | Impact assessment, records of processing |
The tracks reinforce each other. A safety assessor examining an emergency-stop function will be glad to see your Table 7-5 measurements with external instrumentation; an authority reviewing a pilot application can use the Phase 4 incident records. But the evidence flows one way: a WIA badge must never be presented as, or next to, a safety claim in a way that suggests one implies the other.
Annex E recommends a monthly error-budget summary โ p95 latency, error rate and violation hours โ "in the format defined by the WIA reporting profile" so that operators can be compared without exposing tenant data. That reporting profile is not published with v1.0.0. Until it is, a small, explicit document is better than none. The shape below is an author proposal and the values are placeholders:
{
"standardSlug": "delivery-robot",
"period": "2026-08",
"profile": "multi-tenant",
"slo": { "latency_p95_ms": 300, "error_rate": 0.001 },
"observed": {
"latency_p95_ms": 0,
"error_rate": 0.0,
"violation_hours": 0
},
"scope": ["/api/v1/robots", "/api/v1/packages", "/api/v1/routes", "/api/v1/fleet"],
"method": "server-side histograms, 1-minute buckets, 5xx and timeouts counted as errors"
}
Define "violation hour" before the first report (for example, any clock hour in which an SLO was breached) and keep the definition stable; a changing definition makes the month-to-month comparison meaningless. Report aggregates across tenants, never per-tenant figures, to stay within the privacy intent of the annex.
The list below collects the chapter into one pass that a team can walk through before claiming a tier.
CargoStatus, ActiveRoute, Error, Contact, Location) in a separate schema file and publish it.issuedAt.A GitHub Actions workflow that runs the vectors on every change and once per quarter might look like this:
name: wia-rob010-conformance
on:
push:
pull_request:
schedule:
- cron: "0 3 1 1,4,7,10 *" # quarterly recheck (Annex G)
jobs:
vectors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- run: pip install "jsonschema[format-nongpl]"
- run: python tools/run_vectors.py > vector-matrix.json
- uses: actions/upload-artifact@v4
if: always()
with: { name: vector-matrix, path: vector-matrix.json }
sign:
needs: vectors
if: github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions: { id-token: write, contents: read }
steps:
- uses: actions/checkout@v4
- uses: sigstore/cosign-installer@v3
- run: ./tools/build_evidence.sh # SBOM, tarball, cosign attest-blob (7.4)
The if: always() on the upload step ensures that a failing matrix is still published: Annex G asks vendors to report negative results with the same fidelity as positive ones, and a matrix that disappears whenever it is red would defeat that rule. build_evidence.sh stands for your own script combining the steps of section 7.4. The next chapter looks at what the standard does not yet cover โ mission manifests, hand-off events and incident reporting โ and how to extend it without breaking the conformance story built here.
โ Chapter 6: Phase 4 Fleet Integration โ Telemetry, Dispatch, Charging and OTA | Back to Index | Chapter 8: Extensions and the Road Ahead โ Mission Manifests, Hand-offs, Incident Reporting and the Roadmap โ