Predicate Schema: stella.ops/federatedTelemetry@v1

Status

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 id seed contains siteId, aggregatedAt, totalFacts, suppressedBuckets, epsilonSpent, the canonical non-suppressed buckets, consentSetCommitment, and createdAt. Property names are emitted exactly as shown (camelCase) because the serializer uses no property-naming policy.

Validation Rules

  1. id is a deterministic UUID with the RFC 4122 version-4/variant bit layout (see the id field description). It is reproducible from the canonical seed, not randomly generated. VerifyAsync rejects a bundle whose envelope payload id does not equal the bundle’s id.
  2. siteId is sourced from Platform:TelemetryFederation:SiteId (default empty). Enabled federation fails startup when the installation identity is empty. VerifyAsync rejects a bundle whose envelope payload siteId does not equal the bundle’s source site id.
  3. epsilonSpent is the sum of per-bucket epsilon actually charged against the PrivacyBudgetTracker; the tracker refuses any spend that would push the period total above Platform:TelemetryFederation:EpsilonBudget (default 1.0, resetting every BudgetResetPeriod, default 24h). A bucket whose epsilon cannot be charged is suppressed.
  4. consentSetCommitment identifies the exact active consent set used for the aggregation. VerifyAsync rejects 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.
  5. K-anonymity is evaluated against distinct consenting tenant IDs per CVE (Platform:TelemetryFederation:KAnonymityThreshold, default 5). Buckets with fewer distinct tenants are suppressed. artifactCount independently reports distinct contributing artifact digests after per-tenant contribution bounds.
  6. noisyCount values are non-negative (Laplacian-noise-adjusted and clamped via max(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):

Configuration

Bound from the Platform:TelemetryFederation options section (FederatedTelemetryOptions):

KeyDefaultPurpose
SiteId""This site’s identifier in the federation mesh (siteId); required when enabled.
BundlePredicateTypestella.ops/federatedTelemetry@v1Predicate / DSSE payloadType for bundles.
ConsentPredicateTypestella.ops/federatedConsent@v1Predicate type for consent attestations.
KAnonymityThreshold5Minimum distinct consenting tenants per CVE bucket before suppression.
EpsilonBudget1.0Total differential-privacy epsilon budget per reset period.
BudgetResetPeriod24hHow often the privacy budget resets.
AggregationInterval15mInterval between automated aggregation cycles.
SealedModeEnabledfalseWhen 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.
AllowUnsignedDsseFallbackfalseEmit 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.