Predicate Schema: stella.ops/federatedTelemetry@v1
Status
- Status: IMPLEMENTED (verified against code 2026-07-11)
- Implemented in:
src/Telemetry/StellaOps.Telemetry.Federation(Bundles/FederatedTelemetryBundleBuilder.cs,Aggregation/TelemetryAggregator.cs,Security/HmacFederationDsseEnvelopeService.cs) - Owner: Telemetry Federation Guild
- Related contract: federated-consent-v1.md (
stella.ops/federatedConsent@v1) - Authority scopes:
platform:federation:read,platform:federation:write(StellaOps.Auth.Abstractions/StellaOpsScopes.cs)
Overview
This contract is for engineers integrating with Stella Ops federated telemetry. The stella.ops/federatedTelemetry@v1 predicate represents a privacy-preserving telemetry bundle produced by a Stella Ops instance participating in federated exploit intelligence sharing. Each bundle contains differentially private, aggregated CVE observation data. Consent for participation is governed by the companion federated-consent-v1.mdcontract.
The predicate document described below is the DSSE payload. The bundle builder serialises the payload as canonical JSON (no property-naming policy is applied, so field names are exactly as written below; WriteIndented = false) and wraps it in a DSSE envelope before transport. See DSSE Envelope for the envelope shape and signing scheme.
Predicate Type
stella.ops/federatedTelemetry@v1
The predicate type is configurable via the Platform:TelemetryFederation:BundlePredicateType option (FederatedTelemetryOptions.BundlePredicateType); the value above is the default and is also written into the DSSE envelope payloadType field.
Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "siteId", "predicateType", "aggregatedAt", "totalFacts", "suppressedBuckets", "epsilonSpent", "buckets", "consentSetCommitment", "createdAt"],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Deterministic bundle identifier. Derived from SHA-256 over a canonical seed (siteId, aggregatedAt, totalFacts, suppressedBuckets, epsilonSpent, non-suppressed buckets, consentSetCommitment, createdAt) with the RFC 4122 version-4 and variant bits set on the first 16 hash bytes. Identical logical inputs at the same createdAt produce an identical id (deterministic replay); it is NOT a random UUID v4."
},
"siteId": {
"type": "string",
"description": "Identifier of the originating federation site"
},
"predicateType": {
"type": "string",
"const": "stella.ops/federatedTelemetry@v1"
},
"aggregatedAt": {
"type": "string",
"format": "date-time",
"description": "Timestamp of the aggregation cycle"
},
"totalFacts": {
"type": "integer",
"minimum": 0,
"description": "Total number of telemetry facts processed"
},
"suppressedBuckets": {
"type": "integer",
"minimum": 0,
"description": "Number of buckets suppressed by k-anonymity or budget exhaustion"
},
"epsilonSpent": {
"type": "number",
"minimum": 0,
"description": "Total epsilon consumed in this aggregation"
},
"buckets": {
"type": "array",
"items": {
"type": "object",
"required": ["cveId", "noisyCount", "artifactCount"],
"properties": {
"cveId": {
"type": "string",
"description": "CVE identifier (e.g., CVE-2024-12345)"
},
"noisyCount": {
"type": "number",
"minimum": 0,
"description": "Observation count with Laplacian noise applied, clamped to a non-negative value (max(0, observationCount + noise)). Noise scale is sensitivity 1.0 over the per-bucket epsilon."
},
"artifactCount": {
"type": "integer",
"minimum": 0,
"description": "Number of distinct artifact digests contributing to this bucket. This is an exported aggregate, not the k-anonymity threshold count."
}
}
},
"description": "Non-suppressed aggregation buckets only (suppressed buckets are excluded from the bundle). Emitted in canonical order: cveId ascending (Ordinal), then noisyCount descending, then artifactCount ascending, then the underlying observationCount ascending."
},
"consentSetCommitment": {
"type": "string",
"description": "Commitment identifying the exact active consent set used for this aggregation."
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Timestamp when the bundle was created (sourced from the configured TimeProvider; part of the deterministic id/envelope seed)"
}
}
}
The deterministic
idseed containssiteId,aggregatedAt,totalFacts,suppressedBuckets,epsilonSpent, the canonical non-suppressedbuckets,consentSetCommitment, andcreatedAt. Property names are emitted exactly as shown (camelCase) because the serializer uses no property-naming policy.
Validation Rules
idis a deterministic UUID with the RFC 4122 version-4/variant bit layout (see theidfield description). It is reproducible from the canonical seed, not randomly generated.VerifyAsyncrejects a bundle whose envelope payloadiddoes not equal the bundle’sid.siteIdis sourced fromPlatform:TelemetryFederation:SiteId(default empty). Enabled federation fails startup when the installation identity is empty.VerifyAsyncrejects a bundle whose envelope payloadsiteIddoes not equal the bundle’s source site id.epsilonSpentis the sum of per-bucket epsilon actually charged against thePrivacyBudgetTracker; the tracker refuses any spend that would push the period total abovePlatform:TelemetryFederation:EpsilonBudget(default1.0, resetting everyBudgetResetPeriod, default 24h). A bucket whose epsilon cannot be charged is suppressed.consentSetCommitmentidentifies the exact active consent set used for the aggregation.VerifyAsyncrejects a bundle when the envelope payload commitment does not match the bundle’s recorded commitment (consent-set linkage check). Consent expiry/validity is enforced upstream by the consent manager, not by this predicate.- K-anonymity is evaluated against distinct consenting tenant IDs per CVE (
Platform:TelemetryFederation:KAnonymityThreshold, default5). Buckets with fewer distinct tenants are suppressed.artifactCountindependently reports distinct contributing artifact digests after per-tenant contribution bounds. noisyCountvalues are non-negative (Laplacian-noise-adjusted and clamped viamax(0, observationCount + noise); they may differ from the true observation count, which is never exported).
DSSE Envelope
The predicate payload above is not transported bare. FederatedTelemetryBundleBuilder serialises the payload to canonical UTF-8 JSON and signs it with HmacFederationDsseEnvelopeService, producing a DSSE-style envelope:
{
"payloadType": "stella.ops/federatedTelemetry@v1",
"payload": "<base64 of the canonical predicate JSON>",
"signatures": [
{ "keyid": "<DsseSignerKeyId>", "sig": "<base64 HMAC-SHA256 over the DSSE PAE>" }
]
}
Signing details (HmacFederationDsseEnvelopeService):
- The signature is an HMAC (default SHA-256, routed through the platform crypto abstraction and subject to the active compliance profile) over the DSSE Pre-Authentication Encoding
DSSEv1 <len> <payloadType> <len> <payload>. - The envelope digest (
bundleDsseDigeston the in-processFederatedBundlerecord) issha256:<lowercase-hex>over the serialized envelope bytes. - When no signer key material is configured and
Platform:TelemetryFederation:AllowUnsignedDsseFallbackistrue, an unsigned envelope (emptysignatures) is produced and tagged with key idoffline-unsigned-fallback; otherwise signing throwsFederationSignatureException(federation.dsse.signer_unavailable). - General local verification trusts keys from
Platform:TelemetryFederation:DsseTrustedKeysplus the active signer key; an envelope with no matching trusted signature, a mismatchedpayloadType, or a tampered payload/signature fails verification. - Inbound peer delivery is stricter: the verified key must be explicitly present in
DsseTrustedKeysand bound to the authenticated certificate’s source site byPeerSignerKeySiteBindings; the local outbound signer fallback is not accepted.
Configuration
Bound from the Platform:TelemetryFederation options section (FederatedTelemetryOptions):
| Key | Default | Purpose |
|---|---|---|
SiteId | "" | This site’s identifier in the federation mesh (siteId); required when enabled. |
BundlePredicateType | stella.ops/federatedTelemetry@v1 | Predicate / DSSE payloadType for bundles. |
ConsentPredicateType | stella.ops/federatedConsent@v1 | Predicate type for consent attestations. |
KAnonymityThreshold | 5 | Minimum distinct consenting tenants per CVE bucket before suppression. |
EpsilonBudget | 1.0 | Total differential-privacy epsilon budget per reset period. |
BudgetResetPeriod | 24h | How often the privacy budget resets. |
AggregationInterval | 15m | Interval between automated aggregation cycles. |
SealedModeEnabled | false | When true, federation runs sealed (no outbound traffic). |
DsseSignerKeyId | "" | Key id used to sign federation DSSE envelopes. |
DsseSignerSecret | "" | Local HMAC secret for the default DSSE signer. |
DsseTrustedKeys | {} | Trusted signer secrets keyed by DSSE key id for offline verification. |
PeerCertificateSiteBindings | {} | SHA-256 client certificate thumbprint to authenticated source-site bindings. |
PeerSignerKeySiteBindings | {} | Explicit inbound DSSE signer key ID to source-site bindings. |
AllowUnsignedDsseFallback | false | Emit unsigned envelopes (tagged offline-unsigned-fallback) instead of throwing when key material is missing. |
Example Payload
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"siteId": "site-production-us-east",
"predicateType": "stella.ops/federatedTelemetry@v1",
"aggregatedAt": "2026-02-20T14:30:00Z",
"totalFacts": 1547,
"suppressedBuckets": 3,
"epsilonSpent": 0.0833,
"buckets": [
{
"cveId": "CVE-2024-21626",
"noisyCount": 42.7,
"artifactCount": 12
},
{
"cveId": "CVE-2024-3094",
"noisyCount": 8.2,
"artifactCount": 6
}
],
"consentSetCommitment": "sha256:abc123def456...",
"createdAt": "2026-02-20T14:30:05Z"
}
The example above is the DSSE payload; on the wire it is base64-encoded into the payload field of the DSSE envelope.
