Chapter 7

Chapter 7: Conformance Testing and Certification

A flood-warning system is only as trustworthy as the evidence behind it. This chapter explains how an implementation of WIA-ENE-033 proves what it supports: the two conformance vocabularies in the v1.0 documents, test vectors, the signed evidence package, interoperability profiles, the versioning policy, and the MRV reporting that checks operational performance after go-live. It ends with a self-assessment you can run before any auditor is involved.

Earlier chapters asked what an implementation must do. This chapter asks what it can show. The two are not the same. A forecasting node can produce correct RiverLevelData and valid CAP 1.2 warnings every day and still fail an audit because nobody can trace which build produced a given alert, which requirements were tested, or why a test was skipped. The ENE-033 conformance annexes are about that traceability. This chapter reads them with the same care it gave the data model: it says clearly what v1.0 publishes, what it only refers to, and where its documents contradict each other.

Three facts shape everything below. First, the conformance machinery (Annexes G, H, I and J) is marked non-normative in all four PHASE documents. It sets the shape of the evidence, not a certification scheme with an accredited body behind it. Second, several artefacts that the annexes depend on (Annex A, the tests/phase-vectors/ tree, the api/openapi.yaml document) are cited but not present in the v1.0 repository. Third, Annexes E to J are word-for-word identical across the four PHASE documents, apart from the PHASE name. So a rule stated in one PHASE applies in the same words to all four. That includes the rules that conflict with one another.

7.1 Two Vocabularies for Conformance

A reader who looks for "the ENE-033 conformance levels" finds two unrelated lists. The release notes describe a three-tier model: Surface (data formats), Verified (annual third-party audit) and Anchored (a continuous evidence package signed with Sigstore). The release notes say this model is documented "in the README and Annex A". The README in the v1.0 repository does not in fact contain it, and Annex A has not been published. PHASE-4 §14.1, under the heading 인증 요구사항 (certification requirements), gives a second list of four certification levels: Bronze (basic prediction), Silver (early-warning system), Gold (inundation simulation) and Platinum (fully integrated system). The heading appears twice in PHASE-4 with the same content, an editorial duplicate that says nothing new.

The two lists measure different things, and it helps to say so plainly. Surface / Verified / Anchored describes how strong the evidence is: from a self-declared format check, to an external audit at a fixed point in time, to evidence that is renewed and publicly verifiable. Bronze to Platinum describes how much function is in scope: whether the system only forecasts, or also warns, simulates inundation and integrates with external systems. Neither list defines test criteria. Neither names who may award a level. And neither says how the two relate.

AspectEvidence tiersFunctional badges
Where statedRelease notes (refers to README and Annex A)PHASE-4 §14.1
LevelsSurface, Verified, AnchoredBronze, Silver, Gold, Platinum
What it gradesStrength and freshness of the evidenceBreadth of functions implemented
Defining documentAnnex A (cited, not published in v1.0)One line per level; no criteria
Who assessesSelf (Surface); third-party auditor (Verified); public verification of signatures (Anchored)Not stated
Typical ENE-033 objects in scopeAny, depending on profileBronze: FloodPredictionResult; Silver: + FloodAlert/CAP; Gold: + inundationArea from a simulation; Platinum: + SystemIntegration and evacuation data

This book offers one reading that keeps both lists useful until Annex A is published: treat them as two axes of a grid. A claim then looks like "Silver / Verified". It means that forecasting and CAP warning publication are in scope, and that an external auditor has examined the evidence within the last year. A city early-warning system that only consumes upstream forecasts and issues local warnings might honestly claim "Silver / Anchored". A national service running inundation models and connecting to smart-city platforms, but still with a manual evidence process, might be "Platinum / Surface". This reading is the book's interpretation, not text from the standard. When you use it, say so in your documentation. Do not present it as an official scheme.

Pitfall — "certified" is not a word v1.0 can support

ENE-033 v1.0 names no accreditation body, no certificate format and no register of certified products. What an implementer can truthfully publish is a signed evidence package and a profile manifest that others can check. Marketing lines such as "ENE-033 Gold certified" cannot be verified against any published criterion, and procurement teams should treat them that way. Describe the implementation instead by the profile it declares and the evidence it publishes.

7.2 Test Vectors

Annex G sets the rule on which the rest of the conformance work depends: every normative requirement has at least one positive vector and one negative vector. A positive vector is an input that a conformant implementation must accept and handle correctly. A negative vector is an input it must reject, or an output condition it must never produce. Vectors are grouped by PHASE under tests/phase-vectors/phase-1-data-format/, phase-2-api-interface/, phase-3-protocol/ and phase-4-integration/. Implementations that claim conformance MUST run all vectors in continuous integration and publish the pass/fail matrix.

In v1.0 that directory does not yet exist. The practical result is that each implementer must write their own vectors now and replace them with the official set once it is published. This is less wasteful than it sounds. Most of the vectors that matter for flood prediction follow directly from the data model and the SDK, and writing them forces the team to decide how it handles the known spec/SDK differences described in Chapters 2 to 4. The table below shows the kind of pairs a Phase-1 and Phase-2 suite should contain. The vector identifiers are examples.

Vector (example ID)PolarityInputExpected behaviour
p1-river-level-pos-01PositiveComplete RiverLevelData with current, levels, trend and statusAccepted; units preserved (m, m³/s, m/h)
p1-river-level-neg-01Negativecurrent.waterLevel sent as the string "4.2m"Rejected with a validation error naming the field
p1-request-neg-01NegativetimeHorizon: "12h"Rejected; only 1h, 6h, 24h, 72h are valid (see isValidTimeHorizon)
p1-result-neg-01NegativeFloodPredictionResult with key "contributing factors" (with a space)Rejected or flagged, not silently dropped
p1-result-neg-02NegativeriskLevel: "LEVEL-5"Rejected; RiskLevel ends at LEVEL-4
p2-warning-pos-01PositiveA FloodAlert published through warningPublishBoth the WIA envelope and a CAP 1.2 document are emitted
p2-warning-neg-01NegativeCAP output whose sent time uses the letter ZMust never be emitted; CAP 1.2 forbids alphabetic time-zone designators, so UTC is written as -00:00
p2-warning-neg-02NegativeA CAP polygon whose first and last coordinate pairs differMust never be emitted; CAP 1.2 requires a closed ring of at least four pairs

Three points about the table deserve emphasis. First, negative vectors test behaviour, not just schema shape. The two CAP vectors check the output of the converter rather than any input, because a converter that turns ENE-033 ISO 8601 timestamps (which end in Z) directly into CAP fields produces invalid CAP without any error being raised. Second, some vectors only have meaning in relation to a stated decision. Take a FloodPredictionRequest that leaves out the include* flags. PHASE-1 §5.1 lists the flags as required, while the SDK makes them optional. The vector passes or fails depending on which reading the implementation chose, and that choice must be written down in the profile manifest (§7.4). Third, a vector suite for PHASE-3 has to separate deterministic checks, such as "a result at LEVEL-3 with probability 60 % sets evacuationRequired", from statistical ones, such as forecast skill. Only the deterministic checks belong in the vector matrix. Skill is reported through MRV (§7.6).

The pass/fail matrix and negative-result reporting

Annex G requires vendors to report negative results with the same care as positive ones, and states that "a test that is skipped without recorded justification is treated by auditors as a failure." That one sentence decides the format of the matrix. Every row must hold a result, and every row that is not a clean pass must say why. The fragment below shows one way to lay out such a matrix. Field names are illustrative. The annex fixes the content, not a schema.

{
  "standard": "WIA-ENE-033",
  "standardVersion": "1.0",
  "phase": "phase-1-data-format",
  "implementation": { "name": "basin-forecast-node", "version": "2.4.1" },
  "vectorSet": { "source": "local", "revision": "example-rev-17" },
  "results": [
    { "id": "p1-river-level-pos-01", "requirement": "P1-5.4-RiverLevelData",
      "polarity": "positive", "result": "pass" },
    { "id": "p1-river-level-neg-01", "requirement": "P1-5.4-RiverLevelData",
      "polarity": "negative", "result": "pass",
      "observed": "HTTP 400, error names current.waterLevel" },
    { "id": "p1-request-neg-01", "requirement": "P1-5.1-FloodPredictionRequest",
      "polarity": "negative", "result": "fail",
      "observed": "legacy parser accepted timeHorizon 12h",
      "tracking": "issue #212 (example)" },
    { "id": "p1-drainage-pos-01", "requirement": "P1-5.6-DrainageData",
      "polarity": "positive", "result": "skipped",
      "justification": "DrainageData is excluded in profile manifest (see 7.4)" }
  ],
  "summary": { "pass": 2, "fail": 1, "skippedWithJustification": 1,
               "skippedWithoutJustification": 0 }
}

Two design choices are worth copying. The vectorSet.source field records whether the results come from local vectors or from an official set. When the official vectors appear, a reader can then tell at once which matrices need to be run again. And the summary counts unjustified skips separately, even when the count is zero, so an auditor does not need to search for them.

Pitfall — requirement IDs do not exist yet

Both the vector matrix and the profile manifest refer to "normative requirement IDs", but no PHASE document in v1.0 numbers its requirements. The IDs used in this chapter (P1-5.4-RiverLevelData and so on) follow a local convention: PHASE, section number, object or operation. Pick a convention, publish it with your evidence, and plan to map it to official IDs once they exist. Do not present home-made IDs as part of the standard.

7.3 The Evidence Package

Annex G defines the compliance package as a tarball containing four things: a software bill of materials in CycloneDX 1.5 or SPDX 2.3, the OpenAPI document, the test-vector matrix, and a signed manifest. Signatures use Sigstore: a DSSE (Dead Simple Signing Envelope) around the signed payload, and an entry in the Rekor transparency log. Anyone can then check provenance without trusting a private certificate authority. The release notes add in-toto Attestation 1.0 to this list. PHASE-4 names CycloneDX 1.5 in its references and frames the package as something submitted to a "competent authority".

The tree below shows one package layout that meets Annex G and leaves room for the items that later annexes and MRV add. The directory names are examples.

ene033-evidence-2026Q3/            (example package name)
├── manifest.json                  index: every file with its SHA-256 digest
├── manifest.sigstore.json         Sigstore bundle for manifest.json (DSSE + Rekor entry)
├── sbom/
│   └── forecast-node.cdx.json     CycloneDX 1.5 (or SPDX 2.3) SBOM
├── openapi/
│   └── openapi.yaml               the OpenAPI document the deployment actually serves
├── vectors/
│   ├── phase-1-data-format.matrix.json
│   ├── phase-2-api-interface.matrix.json
│   ├── phase-3-protocol.matrix.json
│   └── logs/                      raw CI logs referenced by the matrices
├── profiles/
│   ├── WIA-P1-DATA-FORMAT.profile.json
│   ├── WIA-P2-API-INTERFACE.profile.json
│   └── *.sigstore.json            signatures, same signing identity as the SBOM
├── attestations/
│   └── build.intoto.jsonl         in-toto statement(s) linking source, build and image digest
├── changelog-mapping.json         PHASE version → build / container digest / SDK version
└── mrv/
    └── error-budget-2026-08.json  monthly p95 latency, error rate, violation hours

Each part answers a different question for the reader. The SBOM answers "what is inside this build?" For a forecasting node that usually includes a numerical hydraulics library, a machine-learning runtime and GIS libraries, and each of these can carry its own vulnerabilities and licences. The OpenAPI document answers "what does this deployment claim to offer?" It must be the document the deployment actually serves, not the SDK's hoped-for shape. Chapter 4 showed that the SDK has no ingest endpoint and that /evacuation/capacity in the README differs from the SDK's /evacuation/shelters/{id}. The package should record what exists. The vector matrices answer "what was tested and with what result?" The profile manifests answer "which requirements does this deployment claim?" The in-toto statements connect a source commit and a build process to a container digest. The changelog mapping, which Annex H recommends, lets an auditor go from "PHASE-2 v1.0" to a specific image without running the matrix again.

Signing, identity and the transparency log

Annex I says the profile manifest is signed "using the same Sigstore key used for the SBOM". With Sigstore's usual keyless flow there is no long-lived key: a short-lived certificate is issued for an OIDC identity (for example a CI workload identity), and the signature is recorded in Rekor. In that setting, "the same key" should be read as "the same signing identity". A verifier checks the certificate identity and issuer, not a fingerprint. Deployments that use a managed key pair instead should document where the key is held and how it is rotated. PHASE-2 notes that manifest signing keys are rotated "per the deployment policy", without setting an interval.

The Rekor entry matters more than it first appears. A warning-publishing authority that later has to explain a missed or false warning can show, from a public log, which evidence package was current on that day. The authority does not need to be trusted for this, because the log entry predates the incident. The same property is why Annex G asks for a quarterly re-publication even when nothing has changed. Compiler, dependency and operating-system updates drift under a build that looks unchanged, and a fresh, dated signature shows that the evidence was checked again.

Where the package goes

Annex G does not say where packages are published. PHASE-2 sets a discovery point at /.well-known/wia/ene-033 (the RFC 8615 mechanism covered in Chapter 4) with a signed manifest. A sensible arrangement is for that discovery document to point to the current package by digest, while the package itself is stored in an ordinary release location. Federated and air-gapped topologies (Annex J, Chapter 6) change the transport, not the content. An air-gapped runtime writes a signed package for each batch, and an operator carries it across the gap. The signatures still verify on the other side.

7.4 Interoperability Profiles

Few flood systems implement everything. A river-basin authority may run forecasting and warning but leave urban drainage to cities. A city system may consume forecasts without running any hydraulic model. Annex I exists so that such deployments can state their scope without passing partial conformance off as full conformance. Each implementation publishes a JSON profile manifest listing requirement IDs with one of three statuses: supported, partial (with a reason), or excluded (with a justification). The manifest is signed with the same identity as the SBOM.

Profiles have names from a public registry kept by the working group. Registry entries are immutable, and new shapes get new names. Names carry a Semantic Versioning major number, so WIA-P2-API-INTERFACE-Edge-only/2 claims conformance with the second major version of the "Edge-only" profile for PHASE-2. It does not mean the second deployment of that profile. "Edge-only" and "Federated-with-replay" are the examples the annex gives. It does not publish their contents, so treat any registry name as a label you must define for your readers until the registry is published.

The manifest below is an example for a basin forecasting node's PHASE-1 profile. The three status values and the reason/justification fields come from Annex I. The remaining field names are illustrative.

{
  "profile": "WIA-P1-DATA-FORMAT-Edge-only/1",
  "standard": "WIA-ENE-033",
  "phase": "PHASE-1-DATA-FORMAT",
  "standardVersion": "1.0",
  "requirementIdConvention": "local: PHASE-section-object (no official IDs in v1.0)",
  "implementation": {
    "name": "basin-forecast-node",
    "version": "2.4.1",
    "image": "sha256:(digest of the deployed container)"
  },
  "topology": "single-tenant-edge",
  "requirements": [
    { "id": "P1-5.3-PrecipitationData", "status": "supported" },
    { "id": "P1-5.4-RiverLevelData",    "status": "supported" },
    { "id": "P1-5.5-DamStatusData",     "status": "supported" },
    { "id": "P1-5.1-FloodPredictionRequest", "status": "partial",
      "reason": "include* flags accepted as optional (SDK behaviour); PHASE-1 5.1 lists them as required. Missing flags default to true." },
    { "id": "P1-5.6-DrainageData", "status": "excluded",
      "justification": "The basin node operates no pump stations or detention basins; municipal systems publish DrainageData." }
  ],
  "evidence": {
    "package": "ene033-evidence-2026Q3.tar.gz",
    "sha256": "(digest of the package)"
  }
}

The partial entry is the most useful line in the file. It turns an ambiguity in the standard into a stated, testable behaviour ("missing flags default to true"). A consumer can plan around that, and a vector can check it. By contrast, a manifest that marks everything supported while the matrix shows skips and failures is internally inconsistent. An auditor should flag it no matter how good the forecasts are.

Federation and profile history

Federated deployments, such as a national service that aggregates provincial networks, publish an aggregated manifest that summarises the union and the intersection of their members' profiles. The intersection matters most: a directory service uses it to send a request to the lowest common profile an interaction needs. If one provincial network does not support DamStatusData, a national dashboard must not assume dam data is available for every basin. When a deployment moves to a wider profile, the old manifest stays valid and signed for the deprecation window of Annex H, so an audit of last year's warnings can still be checked against the profile that applied then. Annex J adds that a change of topology (for example, from single-tenant edge to a multi-tenant gateway) MUST be reflected in a new manifest signature.

7.5 Versioning and Deprecation Policy

Annex H applies Semantic Versioning 2.0.0 to each PHASE document. A major version marks a backwards-incompatible change to a normative requirement. A minor version adds normative requirements without breaking existing implementations. A patch covers editorial fixes only. Patch-level errata are issued without a deprecation window, are kept in a public errata register, and each entry is signed by the working-group chair. Deprecated major versions go through a 12-month sunset, during which the registry marks them Deprecated and adds a migration note explaining what replaced the requirement and why.

Implementers need to know about three inconsistencies, because each one changes a date or a version number in a real migration plan.

TopicOne annex saysAnother saysSuggested handling
Parallel window after a breaking changeAnnex F: at least 90 days of overlap with the prior major version on WIA reference implementationsAnnex H: the prior major version is maintained in parallel for at least 180 daysPlan for 180 days. Report both figures and do not quote either one alone as "the rule".
Renaming or removing a fieldAnnex E: MUST trigger a minor version bumpAnnex H: backwards-incompatible changes require a major bumpTreat renames and removals as breaking (major). A consumer's parser breaks either way.
What gets versionedPHASE documents: SemVer per Annex HAnnex F: reference material (vectors, simulator, TypeScript SDK) is versioned separatelyRecord both in changelog-mapping.json. SDK 1.0.0 is not the same thing as PHASE v1.0.

The third row is easy to miss because the numbers look alike. The TypeScript SDK and the CLI both report 1.0.0, and the SDK sends X-WIA-Version: 1.0.0 on every request. The PHASE documents are "Version 1.0". Annex F explicitly lets reference material be fixed without amending the PHASE documents. An SDK 1.0.3 that fixes a bug in estimateTimeToOverflow, for example, says nothing about the standard's version. The changelog mapping keeps these separate: one row per PHASE version supported, and in each row the build, container digest and SDK version that satisfy it.

Release dates call for similar care. The README gives "Version 1.0.0 (2025-12-25)", while the release notes give a release date of 2026-04-26. Evidence packages should refer to the standard as "WIA-ENE-033 v1.0 (Stable)" and, where a date is needed, cite the document it comes from.

7.6 Verifying Operational Performance (MRV)

Conformance evidence shows that an implementation handles the standard's formats and protocols correctly. It says nothing about whether the forecasts are any good or the warnings reach people in time. The README's MRV (measurement, reporting and verification) protocol covers that second question with three reporting tiers. Note that "tier" now has a third meaning in this standard, next to the conformance tiers of §7.1 and the Stable / Provisional / Reference stability tiers of Annex F. Evidence and reports should always say which one they mean.

MRV tierCadenceAudienceContent (README)Closest SDK type
Tier 1 — public dashboardReal timeResidents, mediaCurrent risk level, main river levels, active alerts, number of people evacuatingMonitoringDashboard, GET /alert/active
Tier 2 — management reportDailyOperators, supervising agencyForecast accuracy statistics, alert issue/cancel history, system uptime, data-quality indicatorsKPIDashboard (PredictionKPIs, ResponseKPIs)
Tier 3 — detailed analysisMonthlyManagement, auditorsDetailed model performance, sensor calibration records, drill evaluation, third-party verification reportFloodResponseReport (per event), plus the error-budget summary of Annex E

The SDK types give MRV its structure. PredictionKPIs groups accuracy (overall, short, medium and long term), leadTime (average, minimum, maximum) and reliability (falseAlarmRate, missedEventRate, confidenceScore). ResponseKPIs covers alerting (delivery time, delivery success, public awareness), evacuation (completion rate, average time, shelter use) and damage reduction. FloodResponseReport is event-based. It combines PredictionPerformance (lead time in hours, accuracy in %, counts of false alarms and missed events), ResponsePerformance, an ImpactAssessment with economic loss in KRW, and LessonsLearned.

Several fields have no stated unit or definition. falseAlarmRate could be a ratio or a percentage, and it could be computed over issued warnings or over non-events. Chapter 5 showed that these give very different numbers for rare floods. publicAwareness and overallScore (0–100) have no method at all. An MRV report that others can compare must say, for each KPI, the unit, the formula, the event definition (which threshold counts as a flood at which gauge) and the verification period. Put these definitions in the Tier 3 report and version them. A change of event definition can move a KPI more than any model improvement.

Targets are not results

The README lists KPI values such as 85 % short-term accuracy (6 h), 75 % medium-term accuracy (24 h), a false-alarm rate of at most 15 %, average lead time of at least 6 h, alert delivery within 5 minutes and 99.9 % availability. PHASE-3 has similar targetPerformance values. These are design targets stated in the specification. They are not measured results, and no evidence package should repeat them as achieved performance. Note also that "accuracy" and "false-alarm rate" are given without a shared definition. For rare events a high accuracy figure can go together with a system that misses most floods. Report the contingency-table counts behind every percentage.

Privacy also shapes MRV. Tier 1 shows the number of people evacuating, and ResponsePerformance counts evacuated people and opened shelters. Publish these as aggregates at a level that cannot identify households, and keep recipient lists and shelter occupancy records out of the evidence package entirely. Chapter 6 covers data minimisation. For conformance purposes, the rule is simple: an evidence package is meant to be public, so it must hold nothing that the deployment's privacy regime would not allow to be published.

Tier 3 calls for a "third-party verification report" without saying who counts as a third party. The standard does not name an accreditation scheme. So the report should state the verifier's independence from the operator and the scope of the review. The same goes for the audit-retention note in Annex E. It says that seven years is sufficient for ISO/IEC 17065:2012 audit expectations in most jurisdictions. ISO/IEC 17065 sets requirements for certification bodies and does not prescribe a seven-year period. Set retention from the national rules that actually apply to the operator, and record the source.

7.7 A Self-Assessment Walk-Through

The procedure below puts the chapter into practice. A team can run it on its own before bringing in an auditor, and each step produces a file that goes into the evidence package of §7.3. It assumes Node.js 18 or later (the SDK's stated engine), xmllint, an SBOM generator and the Sigstore cosign tool. Commands are examples. Check the options of the tool versions you use.

Step 1 — Derive schemas from the published types

v1.0 publishes TypeScript interfaces, not JSON Schema files, even though PHASE-1 says schemas are expressed in JSON Schema 2020-12. Until official schemas appear, generate them from types.ts and record that you did so.

$ npx ts-json-schema-generator \
    --path api/typescript/src/types.ts \
    --type RiverLevelData \
    > evidence/schemas/RiverLevelData.schema.json
# Repeat for FloodPredictionRequest, FloodPredictionResult, DamStatusData,
# DrainageData, PrecipitationData and FloodAlert.
# Note: the generator's default output declares an older JSON Schema draft,
# not 2020-12. Record this deviation in the manifest.

Decide at this step whether generated schemas allow extra properties. If they do, the negative vector for the "contributing factors" key cannot fail, because the misspelt key is simply ignored. For conformance runs, a strict setting (no additional properties) is the more useful choice.

Step 2 — Run the positive and negative vectors

$ npx ajv-cli validate -s evidence/schemas/RiverLevelData.schema.json \
    -d "vectors/positive/river-level-*.json"
$ for f in vectors/negative/river-level-*.json; do
    if npx ajv-cli validate -s evidence/schemas/RiverLevelData.schema.json -d "$f" \
         >/dev/null 2>&1; then
      echo "FAIL (accepted): $f"
    else
      echo "pass (rejected): $f"
    fi
  done

The inverted check for negative vectors is where suites most often go wrong. A negative vector that "passes validation" is a failure of the implementation. Behavioural vectors (the isValidTimeHorizon and evacuationRequired checks, and the API responses for bad requests) run in the project's normal test runner. The SDK's package.json already sets up Jest. Their results go into the same matrix format as in §7.2.

Step 3 — Validate the CAP 1.2 output

PHASE-2 requires warningPublish to emit CAP 1.2 in addition to the WIA envelope. Turn a set of test FloodAlert objects into CAP documents with your converter and check them against the CAP 1.2 XML schema published by OASIS:

$ xmllint --noout --schema cap-1.2.xsd out/cap/alert-*.xml
out/cap/alert-0001.xml validates
out/cap/alert-0002.xml validates

Schema validity is necessary but not enough. The XSD checks element structure and some value formats, but to it a polygon is only a string, so an unclosed ring still validates. Keep the rule-based checks from §7.2 for cases like this, and check that the mapping decisions from Chapter 3 hold: severity, urgency and certainty map to CAP's fixed values, and event.onset/expiry become CAP onset/expires.

Step 4 — Produce the SBOM and the manifests

$ syft dir:. -o cyclonedx-json > evidence/sbom/forecast-node.cdx.json
# Check the "specVersion" field; pin CycloneDX 1.5 if your tool allows it,
# or produce SPDX 2.3 instead.
$ sha256sum evidence/**/*.json evidence/openapi/openapi.yaml \
    > evidence/digests.txt     # input for manifest.json

Then write the profile manifests (§7.4) and the changelog mapping (§7.5). Before signing, check the manifests against the matrices: every requirement marked supported should have at least one positive and one negative vector that passed. Every excluded requirement should have skipped vectors that cite the same justification.

Step 5 — Sign, verify and publish

$ cosign sign-blob --yes \
    --bundle evidence/profiles/WIA-P1-DATA-FORMAT.profile.sigstore.json \
    evidence/profiles/WIA-P1-DATA-FORMAT.profile.json
$ cosign verify-blob \
    --bundle evidence/profiles/WIA-P1-DATA-FORMAT.profile.sigstore.json \
    --certificate-identity "(your CI workload identity)" \
    --certificate-oidc-issuer "(your OIDC issuer)" \
    evidence/profiles/WIA-P1-DATA-FORMAT.profile.json
Verified OK
$ tar -czf ene033-evidence-2026Q3.tar.gz -C evidence .

Always verify as a stranger would, using only the public bundle and the expected identity. A signature that verifies only on the build machine proves nothing to a downstream municipality. Finally, sign the manifest that indexes the tarball, point the discovery document to the new package digest, and set a calendar entry for the next quarterly re-publication.

Checklist

#CheckSourceEvidence file
1Conformance claim states which vocabulary is meant, and does not say "certified"Release notes; PHASE-4 §14.1README of the package
2Local requirement-ID convention is written downAnnexes G, Imanifest.json
3Each claimed requirement has at least one positive and one negative vectorAnnex Gvectors/*.matrix.json
4No skip without justification; failures listed with tracking referencesAnnex Gvectors/*.matrix.json
5CAP 1.2 output validated, including time-zone and polygon rulesPHASE-2 (API Operations)CAP validation log
6Spec/SDK differences resolved as partial with a reasonAnnex Iprofiles/*.profile.json
7SBOM in CycloneDX 1.5 or SPDX 2.3 matches the deployed buildAnnex Gsbom/
8OpenAPI document matches the endpoints actually servedAnnex Gopenapi/openapi.yaml
9Manifests and profiles signed with one Sigstore identity; verified independentlyAnnexes G, I*.sigstore.json
10PHASE version, build, container digest and SDK version mappedAnnexes F, Hchangelog-mapping.json
11Topology declared; a new signature after any topology changeAnnex Jprofile manifests
12KPI definitions (unit, formula, event definition) published; targets not presented as resultsREADME MRV / KPImrv/
13No personal data in the package; retention period taken from applicable national rulesPHASE-4 §13.2; Annex Eprivacy statement
14Quarterly re-publication scheduledAnnex Grelease calendar

What this chapter established

ENE-033 v1.0 gives a clear shape for conformance evidence: vectors in pairs, packages with a signature, profiles that admit partial support, and SemVer with published deprecations. It does not yet give the content that would make the evidence comparable across vendors: official requirement IDs, official vectors, Annex A, or a single conformance vocabulary. The right response is not to wait. Build the evidence pipeline now with local conventions that are clearly labelled. Write down every place where the documents disagree and the choice you made. Keep the MRV reports honest about what is target and what is measured. When the missing parts are published, a team that has done this only needs to remap its IDs. A team that has been claiming "Gold certified" will have to explain what that meant. Chapter 8 returns to these missing pieces in the v1.1 roadmap.