Assurance Setup Prerequisites v1

This contract is the readiness vocabulary for Stella Ops Assurance packs — it names the setup prerequisites (sealed-environment config, tenant/operator settings, and live source data) that a tenant must satisfy before a regulator- facing export or handoff can be treated as production-ready, and separates them so setup can explain what is missing without ever storing secret material. It is for operators completing pack setup, Web/CLI authors building readiness screens, and reviewers tracing a blocked readiness result back to its cause. As the note below explains, the prerequisite-id taxonomy here is a design vocabulary; the two shipped runtimes it abstracts are ExportCenter (assurance-evidence-export-v1) and Notify (assurance-reporting-timeline-v1).

Contract ID: CONTRACT-ASSURANCE-SETUP-PREREQUISITES-V1-005 Status: Draft (forward design spec) Owner: Authority, Web, CLI Schema version: assurance-setup-prerequisites-v1

Implementation note (verified against source 2026-05-30). The assurance-setup-prerequisites-v1 schema name in this document is a forward design vocabulary; it is not emitted by any service today. Two concrete readiness surfaces implement these ideas in shipped code and use their own schema versions:

  • Signed-export readiness — ExportCenter, schema assurance-evidence-export-v1, exposed at GET /v1/exports/assurance/profiles/{profileId}/readiness (AssuranceExportEndpoints, AssuranceExportProfileRegistry). Requires the export.viewer scope (StellaOpsScopes.ExportViewer).
  • Operator-handoff / reporting-timeline readiness — Notify, schema assurance-reporting-readiness-v1, exposed at GET /api/v1/assurance/reporting-timeline-profiles/{timelineProfileId}/readiness (AssuranceReportingProfileEndpoints, AssuranceReportingProfileRegistry). Requires the notify.viewer scope (StellaOpsScopes.NotifyViewer).

The “Response Shape” section below documents both shipped shapes verbatim. The prerequisite-id, status-code, and scope/secretHandling taxonomy in the earlier sections remains a design abstraction that is not serialized by either runtime; the per-example statusCodes[] lists are aspirational unless explicitly cross-referenced to a shipped reason code below.

Purpose

assurance-setup-prerequisites-v1 describes readiness checks for optional Assurance packs. It separates sealed/environment prerequisites from tenant/operator settings so setup can explain what is missing without storing secret material or deployment posture in tenant settings. packId and frameworkId cross-reference the assurance-pack-v1catalogue.

Prerequisite Fields

FieldTypeRequiredNotes
schemaVersionstringyesMUST be assurance-setup-prerequisites-v1.
prerequisiteIdstringyesStable readiness id.
packIdstringyesPack id from assurance-pack-v1.
frameworkIdstringyesFramework id.
scopestringyessealed-environment, tenant-operator, or source-data.
requiredFor[]string arrayyesLifecycle states or export profiles that require it.
ownerModulestringyesModule that owns the setting or readiness check.
statusCodes[]string arrayyesStable missing/configured/invalid reason codes.
secretHandlingstringyesno-secret, secret-ref-only, or sealed-only.
operatorMessagestringyesHuman-readable setup message.

Scope Rules

ScopeMeaningStorage rule
sealed-environmentDeployment or sealed runtime configuration.Do not store in tenant/operator settings. Surface only status/reason codes.
tenant-operatorCustomer/operator choice such as enablement, approver, retention, channel destination, or public recipient key.Store through Authority operator settings.
source-dataRequired live evidence source such as Policy snapshot or EvidenceLocker bundle ref.Owned by the source module.

Example: NIS2 SoA Live Export

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "nis2.soa.live-export",
  "packId": "nis2",
  "frameworkId": "nis2",
  "scope": "sealed-environment",
  "requiredFor": ["export-ready", "nis2.statement-of-applicability"],
  "ownerModule": "ExportCenter",
  "statusCodes": [
    "authority-profile-url-missing",
    "storage-root-missing",
    "signing-key-missing",
    "signing-provider-missing",
    "tenant-export-trust-roots-missing",
    "configured"
  ],
  "secretHandling": "sealed-only",
  "operatorMessage": "Configure Authority profile access, ExportCenter storage, signing provider, and tenant export trust roots before starting signed NIS2 SoA export runs."
}

The statusCodes above match the reason codes emitted by AssuranceExportProfileRegistry.AddNis2SoaReadinessReasons for profile nis2.statement-of-applicability (all category signed-export): the implementation does not emit a source-control-register-missing code, so it has been removed.

Required readiness checks (per AddNis2SoaReadinessReasons):

The Policy control-register snapshot is a source-data input that the shipped registry surfaces as the deterministicInputs entry policy.control-register.snapshot; it is not currently emitted as a blocking readiness reason code.

The source-dashboard-required / configured codes and ownerModule: Platform match the shipped nis2.effectiveness-report branch in AssuranceExportProfileRegistry.GetReadiness. Note the reason is non-blocking in code (Blocking: false): the profile reports signedExportReady = true because sealed export settings are validated by the shared signed-export checks, and the dashboard source report is a runtime input supplied at run start.

Example: NIS2 Effectiveness Monthly Export

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "nis2.effectiveness.monthly-export",
  "packId": "nis2",
  "frameworkId": "nis2",
  "scope": "source-data",
  "requiredFor": ["export-ready", "nis2.effectiveness-report"],
  "ownerModule": "Platform",
  "statusCodes": [
    "source-dashboard-required",
    "configured"
  ],
  "secretHandling": "no-secret",
  "operatorMessage": "Provide the monthly NIS2 effectiveness dashboard source report when starting the effectiveness export."
}

Example: DORA Major Incident Handoff

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "dora.major-incident.handoff",
  "packId": "dora",
  "frameworkId": "dora",
  "scope": "tenant-operator",
  "requiredFor": ["handoff-ready", "dora.major-incident-report", "dora.article19.incident"],
  "ownerModule": "Notify",
  "statusCodes": [
    "csirt-destination-missing",
    "pgp-recipient-key-missing",
    "webhook-signing-key-missing",
    "operator-approval-missing",
    "publication-handoff-not-configured",
    "auto-submit-disabled",
    "configured"
  ],
  "secretHandling": "secret-ref-only",
  "operatorMessage": "Configure the tenant DORA handoff destination, recipient key, webhook signing key, and operator approval before treating DORA major-incident handoffs as production-ready."
}

Corrected against source. The DORA major-incident handoff readiness is implemented in two places, neither of which emits the tenant-compliance-profile-missing, lei-missing-or-invalid, dora-financial-entity-flag-missing, or schema-taxonomy-package-missing codes that earlier revisions of this document listed (no such codes exist in source):

  1. Notify operator-handoff — timeline profile dora.article19.incident (AssuranceReportingProfileRegistry). The statusCodes above are the real reason-code constants: csirt-destination-missing, pgp-recipient-key-missing, webhook-signing-key-missing, operator-approval-missing, publication-handoff-not-configured, auto-submit-disabled, configured. auto-submit-disabled is an auto-submit-only code that does not block operator handoff.
  2. ExportCenter signed export — profile dora.major-incident-report (AssuranceExportProfileRegistry.AddDoraMajorIncidentReportReadinessReasons), which emits the signed-export codes (storage-root-missing, signing-key-missing, signing-provider-missing, tenant-export-trust-roots-missing) plus the source-data codes dora-major-incident-report-source-missing, dora-major-incident-report-owner-approval-missing, and dora-major-incident-report-schema-mapping-missing (legal pin dora-major-incident-report-eu-2025-302).

The local-contract encoder can be ready while official EBA XBRL validation is still blocked. The readiness response must distinguish local handoff readiness from the official schema-mapping pin (dora-major-incident-report-schema-mapping-missing in the signed-export surface).

Example: DORA RoI Local-Contract Export

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "dora.roi.local-contract-export",
  "packId": "dora",
  "frameworkId": "dora",
  "scope": "source-data",
  "requiredFor": ["export-ready", "dora.roi"],
  "ownerModule": "Findings",
  "statusCodes": [
    "storage-root-missing",
    "signing-key-missing",
    "signing-provider-missing",
    "tenant-export-trust-roots-missing",
    "dora-roi-register-source-missing",
    "dora-roi-owner-approval-missing",
    "dora-roi-schema-mapping-missing",
    "configured"
  ],
  "secretHandling": "no-secret",
  "operatorMessage": "Provide the DORA RoI register source rows, owner approval, and pinned schema mapping (and configure ExportCenter signed-export settings) before producing the annual RoI handoff."
}

Corrected against source. The shipped profile id is dora.roi (AssuranceExportProfileRegistry.DoraRoiProfileId), and AddDoraRoiReadinessReasons emits the codes above — the shared signed-export codes (storage-root-missing, signing-key-missing, signing-provider-missing, tenant-export-trust-roots-missing, category signed-export) plus three blocking source-data codes: dora-roi-register-source-missing (owner module Findings), dora-roi-owner-approval-missing (owner module Authority), and dora-roi-schema-mapping-missing (owner module ExportCenter). The earlier codes (tenant-compliance-profile-missing, lei-missing-or-invalid, asset-registry-snapshot-missing, integration-roi-metadata-incomplete, retention-policy-invalid, prior-year-hash-missing, official-roi-taxonomy-package-missing) do not exist in source. The deterministicInputs declared by the profile are dora.entity-register.snapshot, dora.ict-service-register.snapshot, dora.provider-contract-register.snapshot, authority.tenant-compliance-profile, and evidence-locker.bundle-ref.

dora-roi-schema-mapping-missing blocks official XSD validation and fileable-XBRL claims. It must not be collapsed into generic export failure when the local-contract ZIP can still be generated and verified.

Example: DORA Information-Sharing Channel

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "dora.info-sharing.channel",
  "packId": "dora",
  "frameworkId": "dora",
  "scope": "tenant-operator",
  "requiredFor": ["handoff-ready", "dora.info-sharing"],
  "ownerModule": "Notify",
  "statusCodes": [
    "storage-root-missing",
    "signing-key-missing",
    "signing-provider-missing",
    "tenant-export-trust-roots-missing",
    "dora-info-sharing-source-missing",
    "dora-info-sharing-subscriber-approval-missing",
    "dora-info-sharing-channel-disabled",
    "dora-info-sharing-schema-mapping-missing",
    "configured"
  ],
  "secretHandling": "secret-ref-only",
  "operatorMessage": "Configure ExportCenter signed-export settings, supply the STIX/TAXII source bundle, obtain subscriber approval, and explicitly enable the per-tenant Article 45 TAXII channel before live sharing."
}

Corrected against source. The shipped profile id is dora.info-sharing and AddDoraInfoSharingReadinessReasons emits the codes above: the shared signed-export codes plus dora-info-sharing-source-missing (owner module Notify, category source-data), dora-info-sharing-subscriber-approval-missing (owner module Authority, category source-data), dora-info-sharing-channel-disabled (owner module Notifier, category live-publication — the live TAXII channel is default-off and must be explicitly enabled per tenant), and dora-info-sharing-schema-mapping-missing (owner module ExportCenter, contract dora-info-sharing-event-v1). The earlier codes (dora-purpose-channel-missing, subscriber-approval-missing, endpoint-allowlist-missing, verification-key-missing, redaction-profile-missing) are not present in source.

General webhook or custom Notify channels are not valid substitutes for this prerequisite: the live TAXII publication channel (dora-info-sharing-channel-disabled) is default-off and must be explicitly enabled in per-tenant configuration.

Example: DORA TLPT Evidence Pack

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "dora.tlpt.evidence-pack",
  "packId": "dora",
  "frameworkId": "dora",
  "scope": "source-data",
  "requiredFor": ["export-ready", "dora.tlpt-evidence-pack"],
  "ownerModule": "EvidenceLocker",
  "statusCodes": [
    "storage-root-missing",
    "signing-key-missing",
    "signing-provider-missing",
    "tenant-export-trust-roots-missing",
    "dora-tlpt-evidence-pack-scope-missing",
    "dora-tlpt-evidence-pack-white-team-signoff-missing",
    "dora-tlpt-evidence-pack-schema-mapping-missing",
    "configured"
  ],
  "secretHandling": "secret-ref-only",
  "operatorMessage": "Configure ExportCenter signed-export settings, then provide the live Graph asset-registry TLPT scope, white-team sign-off, and pinned TLPT schema mapping before treating TLPT evidence packs as production-ready."
}

Corrected against source. The shipped profile id is dora.tlpt-evidence-pack (AssuranceExportProfileRegistry.DoraTlptEvidencePackProfileId), and AddDoraTlptEvidencePackReadinessReasons emits the codes above — the shared signed-export codes (storage-root-missing, signing-key-missing, signing-provider-missing, tenant-export-trust-roots-missing, category signed-export) plus three blocking source-data codes: dora-tlpt-evidence-pack-scope-missing (owner module TlptScoper; scope rows derived from a live Graph Asset Registry snapshot asset-registry.v1), dora-tlpt-evidence-pack-white-team-signoff-missing (owner module EvidenceLocker), and dora-tlpt-evidence-pack-schema-mapping-missing (owner module ExportCenter; contract tlpt-evidence-pack-v1). The earlier codes (tlpt-scope-missing, tlpt-baseline-missing, asset-registry-snapshot-missing, reachability-subgraph-missing, audit-action-emitter-missing) do not exist in source. The profile deterministicInputs are tlpt-scoper.live-asset-registry-snapshot, tlpt-scoper.baseline-ref, evidence-locker.tlpt-controls-inventory, and evidence-locker.bundle-ref.

Example: CRA Product Security Publication

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "cra.product-security.publication",
  "packId": "cra.product-security",
  "frameworkId": "cra",
  "scope": "sealed-environment",
  "requiredFor": ["publication-ready"],
  "ownerModule": "Router",
  "statusCodes": [
    "security-mailbox-unverified",
    "intake-key-expired-or-missing",
    "rotation-roles-missing",
    "support-lifecycle-metadata-missing",
    "configured"
  ],
  "secretHandling": "no-secret",
  "operatorMessage": "Verify product-security mailbox delivery/access and publish a non-expired encryption-capable intake key before live public CRA product-security publication."
}

This prerequisite is a live-publication gate. It does not block local signed CRA technical-file or conformity-dossier export.

Example: CRA Technical Documentation Signed Export

{
  "schemaVersion": "assurance-setup-prerequisites-v1",
  "prerequisiteId": "cra.technical-documentation.signed-export",
  "packId": "cra.technical-documentation",
  "frameworkId": "cra",
  "scope": "sealed-environment",
  "requiredFor": ["export-ready", "cra.technical-file", "cra.conformity-dossier"],
  "ownerModule": "ExportCenter",
  "statusCodes": [
    "storage-root-missing",
    "signing-key-missing",
    "signing-provider-missing",
    "tenant-export-trust-roots-missing",
    "configured"
  ],
  "secretHandling": "sealed-only",
  "operatorMessage": "Configure ExportCenter storage, signing, and tenant export trust roots before treating CRA technical-documentation exports as production signed evidence."
}

Corrected against source. Both shipped CRA profiles — cra.technical-file (CraTechnicalFileProfileId) and cra.conformity-dossier (CraConformityDossierProfileId) — compute signed-export readiness solely via AddAssuranceSignedExportReadinessReasons, which emits only the four shared signed-export codes (storage-root-missing, signing-key-missing, signing-provider-missing, tenant-export-trust-roots-missing). They do not emit an evidence-bundle-ref-missing code (no such code exists in source); the evidence-locker bundle ref is a deterministicInputs/readinessPrerequisites entry, not a blocking reason. Both profiles additionally surface the CRA live-publication preflight codes (see “CRA Product Security Publication” example) via AddCraPublicationReadinessReasons, reported as a separate livePublicationReady boolean.

The ExportCenter Assurance registry exposes these signed-export checks through GET /v1/exports/assurance/profiles/{profileId}/readiness. The response reports only booleans and stable reason codes, with secretValuesExposed=false; it must not echo storage paths, key material, provider secrets, or public/private key contents.

Response Shape

The abstract prerequisiteId/status/reasonCodes/secretHandling vocabulary used in the examples above is a design abstraction; it is not the wire shape of either shipped runtime. The two concrete readiness responses are documented verbatim below from source.

Signed-export readiness (ExportCenter)

Emitted by GET /v1/exports/assurance/profiles/{profileId}/readiness (AssuranceExportReadinessResponse):

{
  "schemaVersion": "assurance-evidence-export-v1",
  "profileId": "nis2.statement-of-applicability",
  "tenantId": "tenant-a",
  "frameworkId": "nis2",
  "packId": "nis2",
  "exportType": "statement-of-applicability",
  "state": "blocked",
  "signedExportReady": false,
  "livePublicationReady": null,
  "reasonCodes": ["signing-provider-missing"],
  "reasons": [
    {
      "code": "signing-provider-missing",
      "category": "signed-export",
      "summary": "Export signing provider is not registered in this runtime.",
      "ownerModule": "ExportCenter",
      "blocking": true
    }
  ],
  "secretValuesExposed": false
}
state is one of export-ready or blocked (`signedExportReady ? “export-ready”
“blocked”).livePublicationReadyisnullfor profiles with no live- publication surface and a boolean for the CRA profiles. There is no service- emitteddisabled/unavailable/unknownstate; an unrecognisedprofileIdreturns HTTP 404 (assurance_export_profile_not_found), and an unknown profile matched at runtime yields theprofile-unavailablereason withsignedExportReady = false. Consumers must still treat any non-export-ready` state as fail-closed for production export.

Operator-handoff / reporting-timeline readiness (Notify)

Emitted by GET /api/v1/assurance/reporting-timeline-profiles/{timelineProfileId}/readiness (AssuranceReportingProfileReadiness):

{
  "schemaVersion": "assurance-reporting-readiness-v1",
  "timelineProfileId": "dora.article19.incident",
  "frameworkId": "dora",
  "packId": "dora",
  "reportType": "major-ict-incident",
  "claimBoundary": "operator-support",
  "tenantId": "tenant-a",
  "status": "blocked",
  "operatorHandoffReady": false,
  "autoSubmitReady": false,
  "reasonCodes": ["operator-approval-missing", "publication-handoff-not-configured"],
  "operatorHandoffReasonCodes": ["operator-approval-missing", "publication-handoff-not-configured"],
  "autoSubmitReasonCodes": ["auto-submit-disabled", "operator-approval-missing", "publication-handoff-not-configured"],
  "secretValuesExposed": false,
  "updatedAt": "2026-05-01T00:00:00Z"
}

status is one of configured or blocked (operatorHandoffReady ? "configured" : "blocked"). Operator-handoff readiness and auto-submit readiness are reported separately; auto-submit-disabled is an auto-submit-only code that never blocks operator handoff. Both runtimes set secretValuesExposed = false and never echo secret material.

Security Rules