Cross-Domain Handoff Package Blueprint
A cross-domain handoff package is a reviewable bundle of event data prepared
for a controlled review or transfer process. In nats-sinks, the package
blueprint is a documentation and schema pattern for preserving payload
references, normalized metadata, hashes, timestamps, labels, classification,
encryption state, and sink evidence in one bounded artifact.
This page is deliberately careful about scope. nats-sinks is not a
cross-domain guard, certification boundary, data diode, release authority,
sanitizer, targeting system, fire-control system, weapons-release mechanism,
rules-of-engagement engine, or autonomous decision platform. A package created
with this blueprint is evidence for review. It is not approval to transfer
data across a boundary.
flowchart LR
JS[NATS JetStream] --> Core[nats-sinks core]
Core --> Policy[Optional pre-sink policy]
Policy --> Sink[Durable sink operation]
Sink --> Package[Review package directory]
Package --> Review[Human or approved external review]
Review --> Guard[External cross-domain mechanism]
Policy -. validates .-> Meta[metadata, labels, encryption state]
Package -. contains .-> Manifest[manifest.json]
Current Scope
The current project scope is a public blueprint with a validated example. It defines a safe package shape that operators and future sink authors can use when they need a reviewable local artifact. It does not yet add a dedicated runtime package writer.
The recommended current shape is a directory package rather than a compressed archive. A directory package is easier to inspect, avoids archive extraction risks, and keeps path-safety validation straightforward. If archive output is added later, it should be implemented as a separate reviewed feature with strict limits for file count, uncompressed size, compression ratio, path normalization, and cleanup after failure.
Delivery Boundary
The ACK boundary depends on how the package is produced:
- If package creation is the configured durable sink operation, the core must ACK only after the package is fully written, flushed according to the sink policy, and committed to its final durable location.
- If a package is generated later from an already committed Oracle row, file record, or spool record, it is a separate export workflow. It does not change the original JetStream ACK decision that already happened.
- If package creation fails before its durable boundary, the message should remain eligible for redelivery or follow the configured DLQ path.
This preserves the project rule:
Commit first. ACK last. Design for redelivery.
Package Layout
A package directory should contain only bounded, reviewable files:
synthetic-review-package-00042/
manifest.json
metadata.json
payload.encrypted.json
evidence.json
The directory name and every file name must be generated by the sink or export tooling. Do not use publisher-provided subjects, labels, message IDs, filenames, or mission fields directly as path components without normalization and allow-list validation.
Manifest Schema
The proposed manifest schema is:
{
"schema": "nats_sinks.cross_domain_handoff_package.v1",
"package_id": "synthetic-review-package-00042",
"package_format": "directory",
"created_epoch_ns": 1770000005000000000,
"source": {
"stream": "SYNTHETIC_EVENTS",
"subject": "mission.sensor.synthetic",
"consumer": "review-worker"
},
"message": {
"stream_sequence": 42,
"consumer_sequence": 7,
"message_id": "synthetic-message-00042"
},
"metadata": {
"priority": "high",
"classification": "NATO SECRET",
"labels": "review-candidate;mission-test",
"labels_list": ["review-candidate", "mission-test"]
},
"payload": {
"mode": "encrypted_reference",
"path": "payload.encrypted.json",
"encrypted": true,
"algorithm": "AES-256-GCM",
"key_id": "synthetic-key-version-001"
},
"review": {
"purpose": "controlled-review-preparation",
"candidate_domain": "synthetic-review-domain",
"release_required": true,
"approval_state": "pending_review"
}
}
The tracked example under
examples/use-cases/defence/cross-domain-handoff-package/ includes the full
manifest, including size limits and SHA-256 values for each package file.
File Roles
| File | Purpose | Safety guidance |
|---|---|---|
manifest.json |
Package index, schema version, metadata summary, payload reference, review state, and limits. | Keep it small, UTF-8 JSON, and free of secrets. |
metadata.json |
Normalized nats-sinks metadata that reviewers can inspect without parsing the full persisted sink record. | Treat subjects, labels, mission metadata, and timestamps as sensitive operational data. |
payload.encrypted.json |
Optional encrypted payload envelope or opaque payload reference. | Keep encryption keys outside the package. A key ID may be included only when it is not secret. |
evidence.json |
Hashes, sink commit evidence, and validation summary. | Hashes are evidence, not encryption or release approval. |
Safety Constraints
Implementations that produce this package shape should enforce these rules:
- Reject absolute paths, parent-directory traversal, path separators in generated package IDs, empty file names, control characters, and hidden operating-system path tricks.
- Bound the number of files, manifest size, metadata size, payload size, and total package size before writing.
- Parse manifest and metadata with standards-compliant JSON parsers and reject malformed input early.
- Store hashes as lowercase SHA-256 hexadecimal strings when using this schema version.
- Keep passwords, tokens, private keys, seed material, certificates, wallet files, connection strings, private endpoints, and operator identities out of packages, examples, issue comments, logs, and release notes.
- Treat gzip compression as storage optimization only. Compression is not encryption and does not reduce classification handling requirements.
- Write to temporary files first and move files atomically into the final package directory when implementing a runtime package writer.
Example Package
The public example uses synthetic values only:
classification:NATO SECRETpriority:highlabels:review-candidate;mission-testapproval_state:pending_reviewpayload.encrypted:true
The encrypted payload values are intentionally synthetic and are used only to show the envelope shape. They are not operational cryptographic material.
sequenceDiagram
participant Sink as Package writer
participant Dir as Package directory
participant Rev as Reviewer
participant Ext as External approved mechanism
Sink->>Dir: write manifest, metadata, payload, evidence
Sink->>Sink: verify bounds and SHA-256 values
Sink-->>Dir: commit package to final path
Rev->>Dir: inspect manifest and evidence
Rev->>Ext: use approved process outside nats-sinks
Future Runtime Packaging
A future implementation could add a first-party package writer or an extension to the file sink. That feature should be handled as separate implementation work and should include:
- configuration that is disabled by default;
- deterministic package IDs for redelivery safety;
- strict path and size validation;
- cleanup after partial failure;
- sink certification tests proving ACK happens only after the package reaches its durable boundary;
- documentation that repeats the non-goal: this is not a cross-domain guard or certification boundary.