CRA Technical File v1
Contract ID: CONTRACT-CRA-TECH-FILE-V1-027 Status: Draft Owner: ExportCenter Last Updated: 2026-04-30
Purpose
cra-tech-file-v1 defines the deterministic bundle index used by ExportCenter to assemble a CRA (EU Cyber Resilience Act) Annex VII technical documentation file for a Stella product release. The bundle is evidence-pointer-first: sections cite immutable evidence references, hashes, signed release manifests, portable Evidence Locker bundles, and control-register snapshots instead of copying mutable runtime state.
Audience: ExportCenter engineers and regulatory-export operators producing CRA technical files, plus auditors verifying one offline. This contract is the building block embedded by conformity-dossier-v1; read that contract for the full conformity-assessment dossier that wraps this file.
Schema Pinning
schemaVersionMUST be exactlycra-tech-file-v1.- ExportCenter adapter id:
cra:tech-file(CraTechFileConstants.AdapterId). - Materialized bundle media type:
application/vnd.stellaops.cra.tech-file.v1+tar+gzip. - Section documents carry their own
schemaVersion = cra-tech-file-section-v1and media typeapplication/vnd.stellaops.cra.tech-file.section.v1+json. - EU signing payload registry id:
cra-tech-file-v1(docs/contracts/eu-signing-payload-registry-v1.md). - Producers MUST NOT auto-upgrade this contract based on later CRA harmonised standards. A future contract (
cra-tech-file-v2) is required for breaking section, evidence, or signing changes. - All hashes MUST be lowercase SHA-256 with the
sha256:prefix inindex.json. - JSON payloads MUST be canonicalized with ordinal-sorted object keys and UTF-8 without a BOM.
- Tar entries MUST use deterministic metadata: fixed mtime
2025-01-01T00:00:00Z, uid/gid0, empty user/group names, and fixed POSIX modes.
Bundle Layout
index.json
checksums.txt
sections/01-general-description.json
sections/02-design-development-manufacture.json
sections/03-risk-assessment.json
sections/04-eu-declaration-of-conformity.json
sections/05-harmonised-standards.json
sections/06-test-reports.json
sections/07-sbom.json
sections/08-attestations.json
sections/09-audit-log-slice.json
sections/10-control-register.json
sections/11-support-policy.json
signatures/index.dsse.json
signatures/index.cadenced.dsse.json
index.json is authoritative. signatures/index.dsse.json is present when the producer signs the bundle index, either through the local offline HMAC path or the production Signer/KMS path. signatures/index.cadenced.dsse.json is present only when production cadenced-envelope mode is requested. checksums.txt is a deterministic convenience file for offline operators and covers all bundle entries except itself.
Required index.json Fields
| Field | Type | Requirement |
|---|---|---|
schemaVersion | string | MUST equal cra-tech-file-v1. |
generatedAt | RFC3339 timestamp | UTC timestamp chosen by the caller, not wall-clocked inside the adapter. |
product | object | Product reference (productRef, name, version, manufacturer, optional description). |
release | object | Release version plus optional releaseManifestRef, sbomRef, placedOnMarketAt, and supportUntil. |
sourceRefs | object | Optional evidencePortableBundleRef, releaseManifestRef, and controlRegisterRef. |
sections | array | The fixed section list above, in numeric order. |
blockers | array | Missing upstream dependencies that prevent a complete Annex VII file (dependency, reason, optional sprintRef), sorted by dependency. |
signing | object | Current signing state for the bundle index. Signed bundles include status, payloadType, signerRef, algorithm, signaturePath, envelopeMode, cadesProfile, and cadesStatus; cadenced bundles also include cadencedSignaturePath. Unsigned local bundles MUST remain explicit with status = not-signed and carry a blockedBy reason. |
Each sections[] entry MUST include:
| Field | Type | Requirement |
|---|---|---|
sectionId | string | One of the fixed section ids in the bundle layout. |
annexViiRef | string | Human-readable Annex VII mapping. |
title | string | Stable display title. |
path | string | Relative bundle path. |
order | integer | 1-based numeric section order (matches the filename prefix). |
mediaType | string | Section media type (always application/vnd.stellaops.cra.tech-file.section.v1+json). |
sha256 | string | SHA-256 hash of the section file. |
sizeBytes | integer | Byte length of the canonicalized section file; the verifier rejects the bundle on a size mismatch (section_size_mismatch). |
status | string | complete, incomplete, or blocked. The eu-declaration-of-conformity section instead carries the DoC lifecycle status (template, operator-signed, or signature-invalid); the legacy stub value is retired. |
evidenceRefs | array | Immutable refs backing the section. |
EU Declaration Of Conformity (Annex V)
The eu-declaration-of-conformity section (Annex VII(4)) embeds a structured EU declaration of conformity (Annex V). Stella never authors or signs a legally-binding DoC on the operator’s behalf — it ships an operator-completable template pre-populated from known evidence and then embeds the operator’s own signed declaration. The unsigned state is always an explicit fail-closed value; it is never a false signed/valid.
The section’s euDeclarationOfConformity object (schemaVersion = cra-eu-declaration-of-conformity-v1) carries:
| Field | Type | Requirement |
|---|---|---|
schemaVersion | string | MUST equal cra-eu-declaration-of-conformity-v1. |
status | string | template (operator-completable, fail-closed — the default when no signed DoC is supplied), operator-signed (operator’s detached signature verified and content bound by hash), or signature-invalid (a supplied DoC whose signature failed verification — fail-closed). |
productName, productRef, productVersion, productDigest | string | Product identity pre-populated from release evidence. |
manufacturerName | string | Pre-populated from the product manufacturer. |
manufacturerAddress, signatoryName, signatoryRole | string | Legal fields — OPERATOR-TO-COMPLETE placeholders in a template; populated by the operator on signing. |
conformityAssessmentRoute, classificationRef | string | Conformity-assessment route (default self-assessment (Module A)) keyed off cra-product-classification.md. |
appliedStandards | array | Applied harmonised standards/specs (CraHarmonisedStandardRef). |
sbomRef, supportUntil | string / date | Pre-populated from release evidence. |
placeOfIssue, dateOfIssue | string / date | Place + date of issue (operator-completed). |
operatorSignature | object | Present once an operator-signed DoC is embedded: contentFormat (json/pdf), contentSha256 (binds the operator’s DoC content), contentPath, algorithm, signerKeyId, signaturePath, verified, optional verificationError. |
notes | array | Human-readable lifecycle notes. |
When the operator supplies a signed DoC, the producer validates the detached signature through StellaOps.Cryptography (ICryptoProviderRegistry → ICryptoSigner, so regional EIDAS/FIPS/GOST/SM/HSM plugins apply), binds the operator content by sha256, embeds eu-declaration-of-conformity/operator-doc.{json,pdf} and eu-declaration-of-conformity/operator-doc.sig into the bundle, and sets status = operator-signed (the section status becomes complete). An invalid/missing signature is rejected with a precise reason and nothing is embedded.
Evidence Reference Shape
{
"sectionId": "sbom",
"kind": "sbom",
"ref": "evidence://bundle/release-2026.04/sbom",
"sha256": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
"mediaType": "application/vnd.cyclonedx+json",
"description": "Release SBOM"
}
ref MUST be immutable or content-addressed. If a source system only has mutable URLs, the adapter MUST record a blocking risk rather than presenting the section as complete.
Signing And Audit
index.json is the DSSE payload for both local offline signing and production EU regulatory signing. The file-backed CLI path signs canonical index.json with HMAC-SHA256, records signing.algorithm = HS256, and stores the envelope at signatures/index.dsse.json:
{
"status": "signed",
"payloadType": "application/vnd.stellaops.cra.tech-file.index.v1+json",
"signerRef": "eu-local-cra-tech-file",
"algorithm": "HS256",
"signaturePath": "signatures/index.dsse.json",
"envelopeMode": "dsse",
"cadesProfile": "None",
"cadesStatus": "not_requested"
}
When no local signing key is supplied, the ExportCenter adapter records:
{
"status": "not-signed",
"payloadType": "application/vnd.stellaops.cra.tech-file.index.v1+json",
"blockedBy": "local signing key or production CRA technical-file signer is required",
"envelopeMode": "none",
"cadesProfile": "None",
"cadesStatus": "not_requested"
}
Production signing MUST use the EU signing payload registry id cra-tech-file-v1, signer profile tenant-regulatory-export, and the Signer/KMS crypto-provider contract (CraTechFileCryptoProviderSigner resolving an ICryptoProviderRegistry signer). The recorded signerRef is the resolved signer key id and algorithm is whatever the resolved signer reports (ICraTechFileDsseSigner.AlgorithmId); the crypto-provider signer defaults to ES256 (CraTechFileCryptoProviderSigningOptions.AlgorithmId = SignatureAlgorithms.Es256). The default production envelope mode is DSSE only:
{
"status": "signed",
"payloadType": "application/vnd.stellaops.cra.tech-file.index.v1+json",
"signerRef": "<resolved-signer-key-id>",
"algorithm": "ES256",
"signaturePath": "signatures/index.dsse.json",
"envelopeMode": "dsse",
"cadesProfile": "None",
"cadesStatus": "not_requested"
}
If the resolved signer reports a different signing algorithm (for example a regional-crypto plugin), algorithm reflects that value rather than ES256. BuildProductionSignedAsync rejects the bundle when the signature’s key id does not match the requested signer identity.
When envelopeMode = cadenced, the bundle keeps the direct index DSSE envelope and adds signatures/index.cadenced.dsse.json, an outer DSSE envelope over the cadenced envelope bytes. cadesProfile MAY be None, BaselineB, BaselineT, BaselineLT, or BaselineLTA. CAdES provider-pack availability is reported in the cadenced envelope companion metadata; missing production QES/QSCD or timestamp/archive providers MUST be represented as blocked companion metadata rather than silently fabricating long-term evidence.
Every Build/BuildProductionSignedAsync result also carries an in-bundle CraTechFileAuditEvent (schema cra-tech-file-audit-event-v1, event type cra.tech_file.bundle.materialized) recording the product ref, release version, index hash, bundle hash, signing status, and signer ref. This materialization event is produced for both signed and unsigned bundles and is returned alongside the bundle, not embedded in index.json.
The final exporter MUST emit durable regulatory evidence after the archive hash is known. RecordRegulatoryEvidenceAsync records an EvidenceLocker regulatory ArtifactSigned audit event (regime Cra, artifact type CraTechnicalFile) and upserts a CRA technical-file artifact-ledger record with the bundle hash, index hash, signer key id, signer fingerprint when verified, signature path (the cadenced path when present, otherwise the DSSE path), and source evidence refs (including a synthetic exportcenter://cra-tech-file/index/<indexHash> ref). Email-shaped actor refs are hashed to an opaque actor:sha256:<hex> form. That event is outside index.json to avoid a self-referential bundle hash and requires a signer identity.
HTTP Produce Surface
In addition to the stella export cra-tech-file CLI path, ExportCenter exposes an authenticated HTTP produce endpoint that reuses the same CraTechFileAdapter (BuildProductionSignedAsync) so the materialized bundle is byte-deterministic and the inner DSSE-signed index.json is identical to the CLI for the same frozen inputs (only the ECDSA signature bytes vary run-to-run). Sprint reference: SPRINT_20260616_006_ExportCenter_cra_dora_bundle_http_parity.md.
| Method | Route | Scope (policy) | Purpose |
|---|---|---|---|
POST | /v1/exports/assurance/profiles/cra.technical-file/runs | export.operator | Produce a signed bundle (run handle). |
GET | /v1/exports/assurance/profiles/cra.technical-file/runs/{runId} | export.viewer | Read the produce run. |
GET | /v1/exports/assurance/runs/{runId}/bundle | export.viewer | Download the produced bundle. |
- Fail-closed readiness gate: the endpoint refuses to materialize a bundle when the profile’s
GetReadinessisblocked(HTTP409carrying the readiness reasons). A CRA profile reachesexport-readyonly whenExport:Assurancesigning (SigningKeyIdresolved throughICryptoProviderRegistry), storage root, and tenant export trust roots are configured. - Determinism:
generatedAtis required in the request body (no wall-clock fallback). - Inputs map onto
CraTechFileBuildRequest(product/release + Annex VII evidence refs). - Run/artifact records persist through the existing ExportCenter
export_runs/export_artifactstables (already auto-migrated on startup — no new job-store table).
Offline And Replay Expectations
- Deterministic fixture location:
src/ExportCenter/StellaOps.ExportCenter.Adapters.Cra.Tests/. - Tests MUST prove byte-identical bundle output from identical inputs.
- Verification MUST be possible without network access by recomputing
checksums.txt, validatingindex.json, checking section hashes, and verifyingsignatures/index.dsse.jsonagainst the appropriate trust path. Production verification delegates the signed payload to the EU offline verifier with payload type idcra-tech-file-v1, schema pincra-tech-file-v1, signer profiletenant-regulatory-export, and tenant export trust roots. - The adapter MUST preserve references to Evidence Locker portable bundles when supplied through
sourceRefs.evidencePortableBundleRef.
Known v1 Blockers
- A complete
control-registersection still requires callers to providesourceRefs.controlRegisterRef; the adapter marks that sectionblockedwhen the source ref is absent. - Production QES/QSCD CAdES provider packs for timestamped or archive-grade
BaselineT,BaselineLT, andBaselineLTAevidence are outside this adapter. Cadenced mode surfaces those missing providers as explicit CAdES companion status.
Related Contracts
- CRA Conformity Dossier v1 — the conformity-assessment dossier that embeds this technical file.
- EU Signing Payload Registry v1 — pins the
cra-tech-file-v1payload type, schema, andtenant-regulatory-exportsigner profile. - Crypto Provider Registry — the
ICryptoProviderRegistrysigner resolution used by production signing.
