Synthetic Mission Testing
The synthetic mission test harness gives maintainers a repeatable way to test mission-style metadata and non-happy-path payloads without using live sensors, real operational subjects, classified content, credentials, or infrastructure locators. It is designed as a safety tool for development and release evidence, not as a simulator of operational behavior.
The harness is implemented in nats_sinks.testing and can be used from Python
or from scripts/run-synthetic-harness.py.
flowchart LR
Profile[SyntheticScenarioProfile] --> Generator[generate_synthetic_scenario]
Generator --> Envelopes[NatsEnvelope list]
Envelopes --> CoreReport[Core report]
Envelopes --> FileSink[FileSink smoke adapter]
FileSink --> FileReport[Sanitized file report]
What It Generates
The default profile cycles through a fixed set of cases:
| Case | Purpose |
|---|---|
valid_json |
Normal JSON payload for baseline sink persistence. |
malformed_json_text |
Incomplete JSON-like text that should be wrapped safely by default payload handling. |
duplicate |
Redelivery-style duplicate that reuses the previous message's idempotency key. |
stale |
Older event timestamp for delayed-event and freshness testing. |
encrypted_marker |
Fake encrypted payload envelope shape without real key material. |
classified |
NATO-style classification value such as NATO SECRET. |
priority |
Urgency value such as urgent. |
labeled |
Semicolon-compatible labels including mission-test and F2T2EA example labels. |
empty |
Empty message body that must not crash the sink. |
For lifecycle phase examples such as find, fix, track, target_review,
engage_report, and assess, use the dedicated
F2T2EA Event Phase Tagging blueprint. The
synthetic harness provides fake event data; the blueprint explains the
metadata-only phase-tagging pattern and non-goals.
The generated data is intentionally fake. A typical generated envelope has a
subject like mission.synthetic.sensor.valid-json.0001, a stream like
MISSION_SYNTHETIC, a message ID like synthetic-00000001, and metadata such
as priority routine, classification NATO RESTRICTED, and labels
synthetic;mission-test.
Command-Line Examples
Generate a destination-neutral report:
python scripts/run-synthetic-harness.py --message-count 18
Generate a Markdown report:
python scripts/run-synthetic-harness.py \
--message-count 18 \
--format markdown \
--report-file .local/synthetic-report.md
Run through the local file sink without keeping files:
python scripts/run-synthetic-harness.py \
--sink file \
--message-count 18 \
--output-dir .local/synthetic-file-smoke
Run through the local file sink and keep output for inspection:
python scripts/run-synthetic-harness.py \
--sink file \
--message-count 18 \
--output-dir .local/synthetic-file-smoke \
--preserve-files
Run the file sink with gzip compression:
python scripts/run-synthetic-harness.py \
--sink file \
--compression gzip \
--message-count 18
Example sanitized JSON output:
{
"duplicate_messages": 2,
"encrypted_marker_messages": 2,
"file_count": 16,
"generated_messages": 18,
"malformed_json_text_messages": 2,
"profile": "mission-smoke",
"sink": "file",
"stale_messages": 2,
"unique_idempotency_keys": 16
}
The report intentionally does not include payloads, output directories, live service names, IP addresses, usernames, passwords, tokens, certificates, keys, or wallet material.
Python Example
from nats_sinks.testing import (
SyntheticScenarioProfile,
generate_synthetic_scenario,
synthetic_report,
)
profile = SyntheticScenarioProfile(message_count=18, seed=7)
messages = generate_synthetic_scenario(profile)
report = synthetic_report(messages, profile_name=profile.name)
assert report.duplicate_messages == 2
assert any(message.envelope.classification == "NATO SECRET" for message in messages)
Future Sink Profiles
Future sink adapters should accept the same generated NatsEnvelope objects and
produce a sanitized SyntheticScenarioReport. Do not create destination-specific
payload generators unless the destination has a unique storage contract that
cannot be represented by the common envelope.
For a new sink:
- Add a small adapter that writes the generated envelopes to the sink.
- Keep live services disabled by default.
- Store local test configuration under ignored
.local/paths. - Return sanitized counts and capability evidence.
- Add unit or smoke coverage that does not make network calls.
- Add an integration wrapper only when the required service can be explicitly enabled and isolated.
This keeps the framework reusable while still supporting mission-oriented testing and future sink certification.