CRA Compliance-Officer End-to-End Scenarios

Currency check 2026-10-07: owner paths/source placement verified against 3238bd511a37e199ae99d4f17be2f13eabec8dd7. The supported boundary is /api/offlinekit/v1/exports (src/OfflineKit/StellaOps.OfflineKit.WebService/Program.cs). Re-verify the host mount and owning endpoint extension together. This is source verification; deployment and broader audit coverage are separate evidence. Other dated findings retain their stated dates. Re-verify: rg -n "MapGroup|Map.*Endpoints|AddHostedService" src/OfflineKit/StellaOps.OfflineKit.WebService/Program.cs, then inspect the endpoint extension or library pointer cited at the operation.

Pack: CRA Assurance Packs — claim boundaries manufacturer-self / manufacturer-customer-support

Audience: a manufacturer’s compliance officer preparing certifiable CRA evidence with Stella Ops, plus the QA / Test Automation agents who execute these scenarios. Each scenario is end-to-end: a narrative, the concrete UI route + API calls against the live docker stack, expected assertions, and a claim-boundary note.

These scenarios drive the Playwright spec src/Web/StellaOps.Web/tests/e2e/compliance/cra-compliance-officer.e2e.spec.ts, executed against the live stack with the colocated live-auth fixture (tests/e2e/compliance/live-auth.fixture.ts, real OIDC login → Bearer token → apiRequest/tenantId fixtures) and the dedicated config src/Web/StellaOps.Web/playwright.compliance.config.ts (base https://stella-ops.local, ignoreHTTPSErrors, no mocking, testDir tests/e2e/compliance). The config is modelled on playwright.integrations.config.ts (the live-docker-stack target) and is shared by the sibling NIS2/DORA compliance specs.

Run (AUTHOR ONLY — a later wave executes these one-by-one):

cd src/Web/StellaOps.Web
PLAYWRIGHT_BASE_URL=https://stella-ops.local \
STELLAOPS_ADMIN_USER=admin STELLAOPS_ADMIN_PASS='<the password your installer printed>' \
  npx playwright test --config=playwright.compliance.config.ts \
    tests/e2e/compliance/cra-compliance-officer.e2e.spec.ts

Each test.describe is tagged with its scenario id (@cra-s1…@cra-s6); run a single scenario with --grep @cra-s3.

Two packs, never one “CRA mode”

CRA support is split into two optional Assurance packs with different manufacturer responsibilities. The scenarios keep them distinct and keep the two readiness-flag pairs un-conflated:

PackClaim boundarySurface
CRA Product Security Packmanufacturer-selfStella’s own CVD, advisory feed, support lifecycle, public publication preflight, Article 14 timeline.
CRA Technical Documentation Packmanufacturer-customer-support (or manufacturer-self when the product is Stella itself)Deterministic technical-file + conformity-dossier exports.

Two independent readiness splits the specs must assert separately:

Forbidden product copy (never assert/emit; see docs/compliance/README.md→ Forbidden product copy): “CRA compliant mode”, “Turn on CRA compliant mode”, or any copy collapsing the two packs.

Live routes used (verified against src/)

PurposeGateway routeBackendScope/policy
List Assurance export profilesGET /api/offlinekit/v1/exports/assurance/profiles?frameworkId=craExportCenter AssuranceExportEndpointsexport.viewer
One Assurance export profileGET /api/offlinekit/v1/exports/assurance/profiles/{id}ExportCenterexport.viewer
Assurance export readiness (two-flag split)GET /api/offlinekit/v1/exports/assurance/profiles/{id}/readinessExportCenter AssuranceExportProfileRegistry.GetReadinessexport.viewer
List reporting-timeline profilesGET /api/v1/assurance/reporting-timeline-profiles?frameworkId=craNotify AssuranceReportingProfileEndpointsnotify.viewer
Article 14 timeline profileGET /api/v1/assurance/reporting-timeline-profiles/cra.article14.incidentNotifynotify.viewer
Article 14 readiness (two-flag split)GET /api/v1/assurance/reporting-timeline-profiles/cra.article14.incident/readinessNotifynotify.viewer
Public product-security metadataGET /.well-known/stella-product-security.jsonRouter ProductMetadataMiddleware (root, fail-closed)anonymous
Public security.txtGET /.well-known/security.txtRouteranonymous

Current export prefix composition is verified in src/OfflineKit/StellaOps.OfflineKit.WebService/Program.cs and AssuranceExportEndpoints. Notify maps the reporting-timeline and profile endpoints in src/Notify/StellaOps.Notify.WebService/Program.cs; both hosts publish endpoint metadata when Router registration is enabled. An absent static rewrite in Gateway configuration does not establish route unavailability. Deployment and gateway reachability require current probes.

Profile id constants (verified)


Scenario CRA-S1 — CRA Technical File export (Annex VII)

Narrative. The compliance officer must assemble the Annex VII technical documentation file for a release the company places on the EU market. They first confirm Stella advertises the cra.technical-file Assurance profile, that it is deterministic + signed (offline-verifiable), and that ExportCenter reports whether the signed local bundle can be produced (signedExportReady) independently of any public publication.

Live drive (API).

  1. GET /api/offlinekit/v1/exports/assurance/profiles?frameworkId=cra -> list MUST contain cra.technical-file and cra.conformity-dossier only (framework filter excludes nis2/dora).
  2. GET /api/offlinekit/v1/exports/assurance/profiles/cra.technical-file -> descriptor.
  3. GET /api/offlinekit/v1/exports/assurance/profiles/cra.technical-file/readiness → readiness with the two-flag split.

Expected assertions.

Determinism + signature (Tier 2d, referenced — not run by these specs). The byte-identical bundle hash + DSSE/HMAC signature proof lives in the adapter test project src/OfflineKit/__Tests/StellaOps.ExportCenter.Adapters.Cra.Tests/ (CraTechFileAdapterTests, trait Intent=Regulatory) and the CLI stella export cra-tech-file / stella verify cra-tech-file (src/Cli/.../CraTechFileCommandTests). OfflineKit’s HTTP producer calls the production-signed adapter in current source. A discovery check alone does not prove production, deterministic bytes, or signature validation in the deployed stack; a current production/readback/download run needs separate evidence. For a discovery check, retain the descriptor assertions: signingRequired, supportsOfflineVerification, and the fixed schemaId/adapterId. Record the bundle-hash proof separately.

Claim boundary. manufacturer-self when the product is Stella itself, else manufacturer-customer-support. The export publishes nothing and implies no conformity route. Do not present readiness as “CRA compliant”.


Scenario CRA-S2 — Conformity dossier (Module A default)

Narrative. Having a technical file, the officer assembles the conformity dossier, which composes the Annex VII technical file (embedded at tech-file/cra-tech-file.tar.gz) with the selected conformity route overlay (Module A internal production control is the CRA-Q5 default for Stella; B+C and H remain available for customer products).

Live drive (API).

  1. GET /api/offlinekit/v1/exports/assurance/profiles/cra.conformity-dossier.
  2. GET /api/offlinekit/v1/exports/assurance/profiles/cra.conformity-dossier/readiness.

Expected assertions.

Structure proof (Tier 2d, referenced). That the dossier index references the embedded technical file (techFile.{path,indexHash,bundleHash,sizeBytes}), declared controls + evidence links (SBOM/advisory), and Module-A overlay is asserted byte-deterministically in src/OfflineKit/__Tests/StellaOps.ExportCenter.Adapters.Cra.Tests/ (ConformityBuild_ModuleA_ProducesDeterministicSelfAssessmentBundle) and via stella export conformity-dossier --module A. OfflineKit’s HTTP producer builds a signed inner technical file and assembles the conformity dossier in current source. The dossier index remains not-signed; discovery alone proves neither production nor signature acceptance in the deployed stack.

Claim boundary. Same as S1. The dossier is an evidence export; it does not make Stella the notified body and does not auto-file.


Scenario CRA-S3 — Article 14 incident reporting (24h / 72h / 14d)

Narrative. An actively-exploited vulnerability is confirmed in the manufacturer’s product. The officer needs the CRA Article 14 reporting timeline: early warning (24h), vulnerability notification (72h), final report (14 days). The default posture must be a locally signed operator handoff — Stella must NOT imply it auto-files with ENISA/an authority.

Live drive (API).

  1. GET /api/v1/assurance/reporting-timeline-profiles?frameworkId=cra → list contains cra.article14.incident.
  2. GET /api/v1/assurance/reporting-timeline-profiles/cra.article14.incident → profile with milestones.
  3. GET /api/v1/assurance/reporting-timeline-profiles/cra.article14.incident/readiness → two-flag readiness.

Expected assertions.

Claim boundary. manufacturer-self for Stella-as-manufacturer. For customer products the customer remains the reporting party; Stella provides timeline control + signed handoff packets only. Auto-submit is not a live regulator receipt.


Scenario CRA-S4 — Publication preflight (signed export ready ≠ live publication)

Narrative. The officer has a signed local technical-file/advisory artifact but must understand that public product-security publication (mailbox, intake key, advisory feed route, support-lifecycle metadata) is a separate gate. A blocked public publication preflight must NOT block local signed export, and the public well-known metadata document must fail closed when not fully configured.

Live drive (API + public route).

  1. GET /api/offlinekit/v1/exports/assurance/profiles/cra.technical-file/readiness — observe signedExportReady and the SEPARATE livePublicationReady.
  2. GET /.well-known/stella-product-security.json (anonymous, gateway root, Router-owned, fail-closed).
  3. GET /.well-known/security.txt (anonymous).

Expected assertions.

Claim boundary. manufacturer-self. The live-publication line is about Stella-as-manufacturer publication; it must never tell a customer tenant to configure Stella’s manufacturer mailbox for their own local evidence packs.


Scenario CRA-S5 — Pack separation invariant (no “CRA mode”)

Narrative. A cross-cutting guard: the two CRA packs are distinct surfaces with distinct claim boundaries, and the two readiness-flag pairs are never collapsed.

Live drive (API). Reuse S1 + S3 responses.

Expected assertions.


Scenario CRA-S6 — Assurance Console shows two distinct CRA packs (UI)

Narrative. The compliance officer opens the operator-facing pack-discovery surface and must see the CRA Product Security Pack rendered as its own card, with no “CRA compliant mode” copy and no collapsed single pack.

Live drive (UI). Navigate /assurance (the canonical pack-discovery surface, Nis2ControlRegisterPageComponent’s sibling assurance shell). Render against live data via the OIDC-authenticated liveAuthPage fixture.

Expected assertions.

Claim boundary. UI copy must use “CRA technical documentation support” / “Manufacturer publication preflight” — never “CRA compliant mode”.

Note: this UI scenario depends on the live /assurance shell exposing the documented data-testids. If those test ids differ in the running build, this is a test-id contract gap to record (do NOT edit shared FE component files).


Gaps noticed (report only — do NOT fix in this wave)