Product CVD Policy Contract v1
Contract: stella.ops/productCvdPolicy@v1 Status: Active — documentation / planning intake schema (not runtime-served). Sprint: SPRINT_20260430_001 Owner: Stella Ops maintainer of record (security) Schema-pinning policy: Pinned per Stella minor release; do not auto-track upstream policy templates. New fields require a v2 contract bump and a corresponding update to consumers of /.well-known/stella-product-security.json (served by the Router Gateway; see stella-product-security-metadata-v1.md). Deterministic fixture location: Golden examples for the served well-known metadata live in the Router integration tests (src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/ProductMetadataEndpointsTests.cs); the well-known endpoint sprint is SPRINT_20260430_002_Web_well_known_endpoints.md. This contract document is the source of truth for the CVD policy parameters. Replay/offline expectations: This document and any rendered intake JSON must be readable, parseable, and verifiable in offline-kit installations without external network access.
What this document is. A versioned, machine-checkable record of the agreed Coordinated Vulnerability Disclosure (CVD) policy parameters, kept aligned with the human-readable policy. It is not a runtime-served artifact: as of this revision no Stella service serializes, deserializes, or validates a
productCvdPolicy@v1document, and there is no runtime validator for this pin. The “runtime validators reject documents whoseschemaVersiondoes not match a supported pin” guarantee is forward design intent — the Router validates the release manifest schema versions inProductMetadataDocumentProvider, not this intake schema. See the Implementation status section below for the full doc/code reconciliation.
Purpose
Defines the structured intake schema that backs Stella’s public Coordinated Vulnerability Disclosure (CVD) policy (../security/coordinated-vulnerability-disclosure.md). The fields below mirror the policy parameters committed in that human-readable policy (SLOs, embargo handling, CVE issuance, escalation contact).
This contract is intended to be consumed by the systems listed below. Current implementation status (verified against src/ on 2026-05-30):
- The
/.well-known/stella-product-security.jsonendpoint (served by the Router Gateway —src/Router/StellaOps.Gateway.WebService/ProductMetadata/ProductMetadataDocumentProvider.cs, route inProductMetadataMiddleware.ProductSecurityJsonPath). Partial overlap only. The served document conforms to a different contract,stella.ops/productSecurityMetadata@v1(seestella-product-security-metadata-v1.md). ItsproductSecurityContactblock carries onlyintakeMailbox,policyUrl, andpreferredLanguages. The CVD-policy SLO/embargo/CVE/escalation fields defined here are NOT emitted in that served JSON; they remain documentation-only commitments enforced operationally. - Stella’s CSAF 2.0 advisory exporter (
src/Notify/__Libraries/StellaOps.Notify.Connectors.Csaf/ProductCsafAdvisoryExporter.cs). NOT IMPLEMENTED as described. The exporter’spublisherblock writes onlycategory,name, andnamespace; it does not stamppublisher.contact_details, and the exporter emits nodocument.acknowledgmentsarray at all. This is forward design intent, not current behaviour. - Documentation linters that verify the published policy and the structured intake remain in sync. Not present as an automated linter — the available offline check is the RFC 9116
security.txtlinter (docs/security/securitytxt-rfc9116-lint.ps1), which does not validate thisproductCvdPolicy@v1schema.
Implementation status (doc<->code reconciliation)
Verified against the main repo src/ tree on 2026-05-30. This section is authoritative for “what actually runs” versus “what this contract describes”.
| Area | This contract describes | Reality in src/ | Status |
|---|---|---|---|
productCvdPolicy@v1 document (de)serialization | A pinned intake document | No type, serializer, or DTO references productCvdPolicy; the string appears only in docs/** | Documentation-only schema |
Runtime schemaVersion validator for this contract | Validators reject unsupported pins | No validator exists for productCvdPolicy@v1; ProductMetadataDocumentProvider.LoadReleaseManifest validates the release manifest schema versions (productUpdateManifest@v1, productLifecycle@v1), not this intake schema | Not implemented |
Served well-known productSecurityContact block | Backed by these CVD fields | ProductMetadataDocumentProvider.GetProductSecurityJson emits intakeMailbox, policyUrl, preferredLanguages only (contract productSecurityMetadata@v1); no SLO/embargo/CVE/escalation fields | Partial — only intakeMailbox overlaps |
CSAF publisher.contact_details / document.acknowledgments | Stamped from this contract | ProductCsafAdvisoryExporter writes publisher = {category, name, namespace}; no contact_details, no acknowledgments | Not implemented |
| Committed example values | intakeMailbox / pgpFingerprint | Match the code constants ProductMetadataDocumentProvider.IntakeMailbox = "security@stella-ops.org" and PgpFingerprint = "1A045258307194881527D2FE095C5809C63DBA65" | Consistent |
| SLO / embargo / CVE-issuance values | 72h / 7d / 90d, 90-day window, MITRE | Match the human-readable policy docs/security/coordinated-vulnerability-disclosure.md §2-§5 (the binding source); not encoded in any served JSON | Consistent with policy doc, not machine-served |
Where this document previously implied runtime enforcement (“runtime validators reject…”, “consumed by the CSAF exporter when it stamps…”), treat those statements as forward design intent.
Schema version metadata
| Field | Value |
|---|---|
schemaVersion | stella.ops/productCvdPolicy@v1 |
schemaPinningPolicy | per-stella-minor-release |
breakingChangesRequire | new vN+1 document plus migration notes |
nonBreakingExtensions | additive optional fields permitted within v1 only when documented in this contract’s revision log |
Any document carrying schemaVersion = stella.ops/productCvdPolicy@v1 MUST conform exactly to the field set below.
JSON shape and committed planning example
The example below records the approved CRA-Q1 planning defaults. It is not, by itself, proof that the public endpoint may go live. The pgpFingerprint value is website-derived release-signing lineage evidence for the Stella key ceremony; live publication still requires a non-expired encryption-capable security-intake key or subkey, and the served metadata must use the verified live intake-key fingerprint if it differs from the lineage fingerprint.
{
"schemaVersion": "stella.ops/productCvdPolicy@v1",
"intakeMailbox": "security@stella-ops.org",
"pgpFingerprint": "1A045258307194881527D2FE095C5809C63DBA65",
"pgpKeyUrl": "https://stella-ops.org/.well-known/stella-product-security-pgp.asc",
"acknowledgementSloHours": 72,
"triageSloDays": 7,
"remediationSloDays": 90,
"embargoPolicy": {
"defaultDisclosureWindowDays": 90,
"extensionPolicy": "by-mutual-agreement",
"exploitInTheWildOverride": "stella-may-shorten-after-24h-notice"
},
"cveIssuanceMode": "mitre-cve-request",
"escalationContact": "product-security-escalation@stella-ops.org",
"lastReviewed": "2026-04-30"
}
Field definitions
| Field | Type | Required | Description |
|---|---|---|---|
schemaVersion | string | yes | Always stella.ops/productCvdPolicy@v1 for documents conforming to this contract. |
intakeMailbox | string (RFC 5322 mailbox) | yes | Canonical Stella security intake. The published default is security@stella-ops.org. |
pgpFingerprint | string | yes | OpenPGP key fingerprint for the intake mailbox. The string TBD-confirm-after-key-creation is permitted as a build-time placeholder; deployments MUST replace it before serving the well-known endpoint as live. The committed planning value is website-derived key-lineage evidence only; live publication still requires non-expired encryption-capable security-intake key material certified by that lineage, and the served value must be the verified live intake-key fingerprint if it differs. |
pgpKeyUrl | string (URL) | yes | Canonical URL where the intake PGP public key is published. MUST be served over HTTPS and MUST match the Encryption: line in security.txt. |
acknowledgementSloHours | integer | yes | Maximum hours between report receipt and a human acknowledgement. Default and minimum: 72 (per decisions-log.md §CRA-Q1). Lowering this is a non-breaking extension; raising it requires a v2 bump. |
triageSloDays | integer | yes | Maximum days from acknowledgement to triage decision (severity assignment plus accept/reject) for High and Critical reports. Default: 7. |
remediationSloDays | integer | yes | Target days from acknowledgement to a fix or documented mitigation for High and Critical reports. Default: 90. |
embargoPolicy | object | yes | Embargo handling rules. See sub-fields below. |
embargoPolicy.defaultDisclosureWindowDays | integer | yes | Default coordinated disclosure window in days. Default: 90. |
embargoPolicy.extensionPolicy | string enum | yes | One of: by-mutual-agreement, fixed, not-permitted. Default: by-mutual-agreement. |
embargoPolicy.exploitInTheWildOverride | string enum | yes | One of: stella-may-shorten-after-24h-notice, stella-may-disclose-immediately, no-override. Default: stella-may-shorten-after-24h-notice. |
cveIssuanceMode | string enum | yes | One of: mitre-cve-request (Stella requests CVEs through MITRE), cna (Stella is itself a CNA), upstream-only (Stella references upstream CVEs and does not issue its own). Default: mitre-cve-request. |
escalationContact | string | yes | Out-of-band escalation contact for actively exploited issues. The string TBD-product-or-legal-owner is permitted as a build-time placeholder; deployments MUST replace it before going live. The committed generic contact is product-security-escalation@stella-ops.org. |
lastReviewed | string (ISO-8601 date, UTC) | yes | Date of the most recent review of this contract document. |
Validation rules
These are conformance rules for a productCvdPolicy@v1 document and for the human-authored CVD policy it mirrors. They are not enforced by an automated runtime validator today (see “Implementation status”); they describe the constraints a future validator MUST apply and the manual review checklist used until then.
intakeMailboxMUST be a deliverable mailbox before the CVD policy is announced as live. (The Router fails the served well-known endpoint closed via theMailboxDeliveryVerified/MailboxAccessVerifiedpreflight flags inProductMetadataPreflightOptions; this CVD document is not itself served.)pgpFingerprintMUST be either a 40-character hex fingerprint (uppercase, no spaces) or the literal placeholderTBD-confirm-after-key-creation.acknowledgementSloHours <= 72. Documents with a higher value are non-conformant.triageSloDays <= 7for the High/Critical baseline.remediationSloDays <= 90for the High/Critical baseline.lastReviewedMUST be no more than 365 days in the past when the policy is announced as live. (This document is reviewed at least annually percoordinated-vulnerability-disclosure.md§9; the field is not consumed by the well-known endpoint, which uses the release-manifestlastModified/generatedAtUtcinstead.)
Field-level rationale (audit trail)
| Field | Rationale source |
|---|---|
acknowledgementSloHours = 72 | decisions-log.md §CRA-Q1, ENISA Good Practice Guide on Vulnerability Disclosure. |
triageSloDays = 7 | decisions-log.md §CRA-Q1. |
remediationSloDays = 90 | decisions-log.md §CRA-Q1; aligns with industry coordinated-disclosure norm. |
embargoPolicy.defaultDisclosureWindowDays = 90 | Coordinated disclosure norm; matches CRA Annex I Part II §5 enforcement expectations. |
cveIssuanceMode = mitre-cve-request | Default until Stella is onboarded as a CNA; revisitable without breaking the schema. |
Operational preflight
The committed 2026.9 planning document no longer contains placeholder values for pgpFingerprint or escalationContact.
The well-known endpoint (/.well-known/stella-product-security.json) MUST still fail closed when the live mailbox or PGP key preflight fails, and the served security.txt MUST NOT advertise a contact channel until those values are operationally verified.
Operational retention/access default: retain vulnerability reports, triage records, embargo notes, advisory drafts, and fix-disposition evidence for 7 years from closure; restrict mailbox/triage access to dedicated-product-security-primary, dedicated-product-security-secondary, and dedicated-product-security-fallback; review access quarterly. This is an operational default, not an additional v1 JSON field.
Revision log
| Date (UTC) | Change | Notes |
|---|---|---|
| 2026-05-30 | Doc<->code reconciliation. | Marked the contract a documentation-only schema; added “Implementation status” table; corrected the “consumed by” claims (served productSecurityContact carries only intakeMailbox/policyUrl/preferredLanguages; CSAF exporter writes no publisher.contact_details/acknowledgments; no runtime validator for this pin); pointed the served endpoint to the Router Gateway (ProductMetadataDocumentProvider). No schema field added. |
| 2026-04-30 | Recorded mailbox retention/access defaults. | 7-year report retention, three-role access, quarterly access review; no schema field added. |
| 2026-04-30 | Filled website-derived fingerprint and generic escalation contact. | Live publication remains gated by mailbox/key preflight. |
| 2026-04-30 | v1 introduced. | Stella-as-manufacturer CVD policy contract; initial pin matches decisions-log.md §CRA-Q1. |
