Skip to content

V3 Journey Release Gate and Evidence Packet

OpenMed v3 release readiness is a signed, fail-closed decision. It is not inferred from issue closure, a single aggregate score, or a successful package build. The gate binds a tagged commit to frozen inputs and requires current, typed evidence across behavior, clinical NLP, privacy, interoperability, performance, recovery, security, and licensing.

This is technical release evidence. It is not clinical validation, certification, a medical-device determination, or permission for autonomous clinical action.

Public contracts

The release surface has two strict JSON contracts:

  • journey_release_manifest.schema.json describes the operator-supplied, aggregate evidence manifest.
  • journey_release_packet.schema.json describes the signed decision packet.

Both use schema version 1.0.0 and compatibility policy same_major. Unknown fields, duplicate JSON keys, non-finite numbers, unbounded free text, absolute paths, parent traversal, symlinked evidence, and incomplete gate metrics are rejected.

The packet retains all seven non-empty result states:

success, partial, unknown, conflict, unsupported, denied, and failure.

Only success can satisfy a mandatory release lane. A different state remains visible in the packet and makes the release NOT_READY; it is never converted to an apparent success.

Mandatory evidence lanes

Lane Required aggregate evidence Fail-closed conditions
Schema Public and persisted schema counts; invalid schema, span, and evidence counts Any invalid schema, span, or evidence locator
Provenance Hashed artifact count and link integrity Broken provenance, missing digest, or frozen-input mismatch
Clinical NLP Evaluated cases, required abstentions, high-risk review Unreviewed high-risk output or a missed required abstention
Privacy Evaluated cases, critical leakage, raw-value findings Any critical leakage or raw-value finding
Interoperability Conformance cases and disclosed round-trip loss Conformance failure or undisclosed loss
Application Test count, failures, typed terminal states, claim audit Failed behavior, untyped state, or prohibited public claim
Performance Hardware, dataset, quantization, concurrency, distribution, throughput, memory, age Missing context, stale evidence, invalid distribution, or SLO breach
Recovery Replay, migration, and recovery scenarios Non-idempotent replay, migration failure, or recovery failure
Security Threat cases and unresolved findings Unresolved high/critical finding or unmitigated threat
Licensing Model and data inventory plus distribution checks Unchecked asset or prohibited distribution

All ten lanes must be present exactly once. Each report records its generation time. The manifest policy sets a bounded maximum artifact age, up to one year; future-dated evidence is also rejected.

Performance evidence

A performance report is incomplete unless it states all of the following:

  • normalized hardware identifier and runtime environment;
  • dataset SHA-256 rather than source records;
  • quantization format;
  • concurrency, sample count, and warm-up count;
  • p50, p95, and p99 latency with p50 <= p95 <= p99;
  • throughput per second;
  • peak memory in MiB;
  • SLO-breach count; and
  • artifact age computed against the manifest's pinned evaluation time.

The environment and measurement fields identify the benchmark conditions. They do not imply performance on another device, dataset, concurrency level, or model format.

Frozen inputs and reproducibility

Every input path must be relative to the checked-out repository. The gate rejects paths that escape the root or traverse a symlink. It recomputes each file digest and copies only the following into the output packet:

  • a bounded input identifier;
  • provenance class (synthetic, aggregate, configuration, or software);
  • SHA-256 digest;
  • byte count; and
  • verification result.

The packet never copies the file path or the file contents. At least one input must assert synthetic provenance. A typical v3 packet binds the five-source scenario and its frozen golden result as synthetic inputs.

The release version must be semantic version text, and git_tag must equal v plus that version. The gate verifies both the current checkout and the tag target against the full 40-character commit in the manifest. A missing tag, an untagged checkout, or a mismatched tag yields NOT_READY.

The manifest also pins evaluated_at and the identical source_date_epoch. Given the same tagged checkout, manifest, frozen inputs, and signing key, the canonical packet digest and signature are reproducible.

Signing and verification

The packet uses HMAC-SHA256 and records a bounded key identifier, never the key. Supply at least 32 bytes through one of these boundaries:

export OPENMED_JOURNEY_RELEASE_KEY="$(security find-generic-password \
  -s openmed-journey-release -w)"

python scripts/release/journey_release_gate.py \
  --manifest journey-release-manifest.json \
  --output journey-release-packet.json

For offline CI, use a permission-restricted key file:

python scripts/release/journey_release_gate.py \
  --manifest journey-release-manifest.json \
  --signing-key-file /run/secrets/openmed-journey-release-key \
  --key-id production-release-2026 \
  --output journey-release-packet.json

The command refuses to replace an existing packet unless --overwrite is explicit. It writes through a temporary file, flushes it, and atomically replaces the destination. Exit status is:

  • 0: a signed READY packet was written;
  • 1: a signed NOT_READY packet was written; or
  • 2: the manifest, key, repository, or output contract was invalid, so no release decision could be produced safely.

Independent verification uses the public Python contract:

import json
from pathlib import Path

from openmed.eval.journey_release import JourneyReleasePacket

payload = json.loads(Path("journey-release-packet.json").read_text())
packet = JourneyReleasePacket.from_dict(payload)
assert packet.verify(signing_key)
assert packet.decision == "READY"

License and distribution gate

The manifest catalogs every model, dataset, vocabulary, and software asset using code-like metadata only: asset ID, type, license ID, role, redistributability, and distribution mode. The catalog itself is hashed into the packet.

Non-redistributable assets may be declared for user-supplied evaluation or an out-of-process boundary. They cannot be bundled, and they cannot be declared as training inputs for a distributable artifact. Restricted vocabularies, credentialed corpora, and data-use-agreement datasets remain user supplied. The gate also cross-checks catalog counts against the licensing report so an asset cannot disappear from the aggregate total.

Exceptions

Exceptions are coded, time-bounded, and tied to one gate. Free-form notes do not enter the packet. An accepted low- or medium-severity exception may be recorded, but it does not change a failing gate into a pass. Pending, rejected, or expired exceptions block release. High- and critical-severity exceptions are non-waivable in this gate.

Critical privacy leakage, broken provenance, invalid spans or evidence, non-idempotent processing, migration failures, unreviewed high-risk output, and unresolved critical security findings therefore cannot be bypassed by an exception record.

Supported claims

A ready packet requires these precise claims:

  • local-first operation;
  • offline operation after explicitly requested assets are present;
  • synthetic release evidence;
  • human review for high-risk output; and
  • typed failure states.

The packet also requires these limitations:

  • not clinically validated;
  • not a medical device;
  • no autonomous clinical action;
  • local validation is required; and
  • restricted assets remain user supplied.

Public material must not turn technical conformance, synthetic fixtures, or a signed packet into a claim of clinical efficacy, regulatory certification, patient-outcome improvement, or autonomous diagnosis or treatment.

Deployment boundary

The gate is local and read-only with respect to release inputs. It does not download models or data, call a hosted verifier, publish a package, change a model pointer, modify a database, or promote a deployment. Promotion remains a separate action that may consume a verified READY packet.

For production deployment:

  1. Produce lane reports on the intended artifact and hardware.
  2. Freeze aggregate reports, the synthetic journey, schemas, policies, and license catalog in the tagged checkout.
  3. Run the gate in that checkout with network access disabled.
  4. Verify the packet signature in a separate process.
  5. Archive the manifest and packet under the release retention policy.
  6. Require a separate authorized promotion step.

Standards boundaries

The interoperability lane can record FHIR, HL7 v2, DICOM SR, OMOP, and table conformance evidence, but the packet does not certify conformance for every profile, implementation guide, terminology release, message variant, or downstream system. Declare the exact versions and fixtures in the hashed input artifacts. Loss that is explicit and typed may remain inspectable; undisclosed round-trip loss blocks release.