Skip to content

Data-Centric Security Label Profile

nats-sinks can carry an optional data-centric security label profile next to each message. The profile is a structured JSON metadata object that extends the core priority, classification, and labels fields with policy-oriented attributes such as releasability, handling caveats, owner, originator, policy identifier, and retention category.

The profile is generic. It is useful in defence, public-sector, regulated, and mission-support environments, but it is not limited to those domains. A logistics platform might use the same shape for retention and audit policy. A secure telemetry fabric might use it to preserve data-owner and release-policy context before events are written to Oracle Database, Oracle Autonomous Database, the file sink, or a future destination.

The profile is metadata only. It can inform downstream authorization, routing, retention, and audit controls, but it does not enforce access control by itself. Destination systems and the surrounding platform must still enforce authorization, compartment rules, and data-release decisions.

Processing Model

Security labels are normalized by the core before a sink sees the message. This keeps Oracle, file, and future sinks consistent.

flowchart LR
    NATS[NATS message headers] --> Core[nats-sinks core]
    Core --> Priority[priority / classification / labels]
    Core --> Profile[security label profile]
    Profile --> Validate[Strict JSON and vocabulary validation]
    Validate --> Envelope[NatsEnvelope.security_labels]
    Envelope --> File[File sink JSON record]
    Envelope --> Oracle[Oracle SECURITY_LABELS_JSON]

If validation fails, the message is treated as a permanent pre-sink failure. If DLQ is configured, the original message is acknowledged only after the DLQ publish succeeds.

sequenceDiagram
    participant JS as JetStream
    participant Core as nats-sinks core
    participant DLQ as DLQ subject
    participant Sink as Destination sink

    JS->>Core: Deliver message
    Core->>Core: Parse security label header
    alt Valid profile
        Core->>Sink: write_batch(envelope)
        Sink-->>Core: Durable success
        Core-->>JS: ACK
    else Invalid profile
        Core->>DLQ: Publish sanitized failure payload
        DLQ-->>Core: Publish success
        Core-->>JS: ACK original
    end

Configuration

The feature is disabled by default.

{
  "security_labels": {
    "enabled": true,
    "header": "Nats-Sinks-Security-Labels",
    "max_bytes": 8192,
    "allowed_priorities": ["routine", "priority", "immediate", "flash"],
    "allowed_classifications": [
      "NATO UNCLASSIFIED",
      "NATO RESTRICTED",
      "NATO CONFIDENTIAL",
      "NATO SECRET"
    ],
    "allowed_releasability": ["NATO", "FVEY", "EU"],
    "allowed_handling_caveats": ["MISSION", "TRAINING", "EXERCISE"],
    "allowed_retention_categories": ["mission-log-30d", "mission-log-1y"],
    "default": {
      "profile": "nats-sinks.security-label.v1",
      "classification": "NATO RESTRICTED",
      "releasability": ["NATO"],
      "handling_caveats": ["MISSION"],
      "owner": "example-owner",
      "originator": "example-originator",
      "policy_id": "example-policy",
      "retention_category": "mission-log-30d"
    },
    "rules": [
      {
        "subject": "mission.sensor.>",
        "profile": {
          "profile": "nats-sinks.security-label.v1",
          "classification": "NATO SECRET",
          "releasability": ["NATO", "FVEY"],
          "handling_caveats": ["MISSION"],
          "owner": "example-sensor-domain",
          "originator": "example-originator",
          "policy_id": "example-mission-policy",
          "retention_category": "mission-log-1y"
        }
      }
    ]
  }
}

Configuration Options

Option Required Default Valid values Effect
enabled no false true or false Enables parsing, validation, and sink delivery of the security label profile.
header no Nats-Sinks-Security-Labels Non-empty header name without control characters Header read from each NATS message when producers provide the profile.
default no null JSON object or null Global profile used when the header is absent and no subject rule matches.
rules no [] Array of subject/profile rules Subject-specific defaults evaluated before the global default.
max_bytes no 8192 Integer from 1 to 262144 Maximum canonical JSON size for one profile.
allowed_priorities no [] Array of strings Optional fail-closed vocabulary for priority. Empty means unrestricted.
allowed_classifications no [] Array of strings Optional fail-closed vocabulary for classification. Empty means unrestricted.
allowed_releasability no [] Array of strings Optional fail-closed vocabulary for every releasability value.
allowed_handling_caveats no [] Array of strings Optional fail-closed vocabulary for every handling caveat.
allowed_retention_categories no [] Array of strings Optional fail-closed vocabulary for retention_category.

Subject rules have this shape:

Option Required Default Valid values Effect
subject yes none NATS subject pattern Applies the rule to matching subjects.
profile yes none JSON object or null Default profile for matching subjects. null clears the global default.

Profile Fields

The root object is intentionally small and allow-listed:

Field Type Required Description
profile string no Must be nats-sinks.security-label.v1. Missing values are normalized to that profile name.
priority string or null no Optional structured copy of the normalized message priority. If omitted, the core fills it from message_metadata.priority.
classification string or null no Optional structured copy of the normalized message classification. If omitted, the core fills it from message_metadata.classification.
labels array of strings no Optional structured copy of normalized labels. If omitted, the core fills it from message_metadata.labels.
releasability array of strings no Release audience markers such as NATO, FVEY, or another deployment-approved vocabulary.
handling_caveats array of strings no Handling caveats such as MISSION, TRAINING, or deployment-specific values.
owner string or null no Data owner, system owner, or policy owner. Use synthetic values in public examples.
originator string or null no Event originator or producing domain.
policy_id string or null no Reference to an internal policy, marking guide, or retention rule.
retention_category string or null no Retention category such as mission-log-30d.
extensions JSON object no Bounded deployment-specific extension object. Secret-looking key names are rejected.

Unknown root fields are rejected. This keeps the profile easy to review and prevents misspelled policy fields from silently entering storage.

Publisher Header Example

The header value is JSON:

Nats-Sinks-Security-Labels: {"profile":"nats-sinks.security-label.v1","classification":"NATO SECRET","releasability":["NATO","FVEY"],"handling_caveats":["MISSION"],"policy_id":"example-policy","retention_category":"mission-log-1y"}

The core never logs the full profile by default. Error messages identify the failed field or reason without echoing sensitive values.

Storage Effects

File sink records include the profile as top-level security_labels and inside the standard metadata.security_labels object:

{
  "schema": "nats_sinks.file.message.v1",
  "subject": "mission.sensor.track",
  "classification": "NATO SECRET",
  "labels_list": ["sensor", "track"],
  "security_labels": {
    "profile": "nats-sinks.security-label.v1",
    "priority": "immediate",
    "classification": "NATO SECRET",
    "labels": ["sensor", "track"],
    "releasability": ["NATO", "FVEY"],
    "handling_caveats": ["MISSION"],
    "owner": "example-owner",
    "originator": "example-originator",
    "policy_id": "example-policy",
    "retention_category": "mission-log-1y"
  }
}

Oracle rows store the same object in SECURITY_LABELS_JSON and in METADATA_JSON.security_labels. See Oracle Sink for the full table layout.

Deployments that use Oracle Label Security can use this persisted metadata as an input to a database-owned row-label mapping pattern. The profile itself does not enforce row visibility; Oracle Database policy administration and user authorization remain outside the sink runtime. See Oracle Label Security With Oracle Database for a conceptual blueprint.

Security Notes

  • Treat profile values as sensitive operational metadata.
  • Keep public examples synthetic.
  • Use allow lists when a deployment has an approved vocabulary.
  • Do not rely on labels alone for authorization.
  • Do not export profile values as high-cardinality Prometheus labels.
  • Keep DLQ handling, audit storage, backups, and retention aligned with the highest classification represented by the stored events.