m5c smoke tests
m5c smoke runs runtime smoke scenarios against lowered package bundles. Use it after validation, tests, build, and lower to prove that generated resources can run against a Mach5 runtime.
Smoke tests complement package tests:
m5c testchecks source-level contracts, mappings, fixtures, and expected findings.m5c smokechecks a runtime scenario using lowered bundles.
Where smoke files live
Smoke scenarios are YAML files usually kept under package tests:
packages/security-analytics/
tests/
smoke/
source-to-detection.yaml
finding-to-case.yaml
Smoke files are runtime scenarios, not source-level unit tests. They should run after package lowering.
Build a smoke test
Build a smoke test in this order:
- Start with one high-value runtime path.
- Insert deterministic seed documents.
- Refresh materialized views that depend on those documents.
- Query app models to prove rows are visible.
- Execute app actions or workflows.
- Wait for async workflows when needed.
- Query final state.
- Keep the scenario small enough to debug quickly.
Smoke test document
kind: SmokeTest
name: finding-to-case
spec:
steps:
- type: insert_docs
index: security-manual-detection-results
documents:
- finding_id: finding:SMOKE-001:evt-001
dedupe_key: SMOKE-001:evt-001
detection_id: SMOKE-001
detection_title: Smoke test suspicious login
severity: high
confidence: 0.9
first_seen: "2026-05-22T08:00:00Z"
last_seen: "2026-05-22T08:00:00Z"
status: open
entity_kind: user
entity_id: smoke-user@example.com
- type: refresh_mv
name: security_findings_mv
- type: refresh_mv
name: security_alerts_mv
- type: query_model
app: security-soc-app-poc
model: alert
filters:
- field: alert_id
op: eq
value: finding:SMOKE-001:evt-001
expect_rows_min: 1
save_first_as: smoke_alert
- type: execute_action
app: security-soc-app-poc
action: create_case_from_alert
record_ref: smoke_alert
confirmed: true
expect_status: started
save_workflow_run_as: case_workflow
- type: wait_workflow
run_ref: case_workflow
expect_status: Completed
timeout_secs: 30
- type: query_model
app: security-soc-app-poc
model: case
filters:
- field: case_id
op: eq
value: case:finding:SMOKE-001:evt-001
expect_rows_min: 1
Top-level fields
| Field | Required | Meaning |
|---|---|---|
kind | Yes | Must be SmokeTest. |
name | Yes | Scenario name used in smoke output and reports. |
spec.steps | Yes | Ordered runtime steps. |
Steps run sequentially. A failing step fails the scenario.
Step: insert documents
Insert one or more documents into an index.
- type: insert_docs
index: security-manual-detection-results
documents:
- finding_id: finding:SMOKE-001:evt-001
status: open
| Field | Required | Meaning |
|---|---|---|
index | Yes | Target index name. |
documents | Yes | List of JSON-like YAML documents to insert. |
Use deterministic IDs and timestamps so the scenario can be re-run.
Step: refresh materialized view
Refresh a materialized view.
- type: refresh_mv
name: security_alerts_mv
mode: full
| Field | Required | Meaning |
|---|---|---|
name | Yes | Materialized view name. |
mode | Optional | Refresh mode. Defaults to full. |
Use refresh steps after inserts when later queries depend on materialized view output.
Step: query model
Query an application model and optionally save the first row for later steps.
- type: query_model
app: security-soc-app-poc
model: alert
filters:
- field: alert_id
op: eq
value: finding:SMOKE-001:evt-001
expect_rows_min: 1
save_first_as: smoke_alert
| Field | Required | Meaning |
|---|---|---|
app | Yes | Application ID. |
model | Yes | Model/resource name exposed by the app. |
filters | Optional | Model filters passed to the runtime. |
sorts | Optional | Model sorts passed to the runtime. |
limit | Optional | Maximum rows. Defaults to 100. |
expect_rows_min | Optional | Minimum row count required for success. |
save_first_as | Optional | Save the first result row under this name for later record_ref use. |
Use save_first_as when a later action should operate on the row returned by the query.
Step: execute action
Execute an app action.
- type: execute_action
app: security-soc-app-poc
action: create_case_from_alert
record_ref: smoke_alert
input:
case_id: case:finding:SMOKE-001:evt-001
confirmed: true
expect_status: started
save_workflow_run_as: case_workflow
| Field | Required | Meaning |
|---|---|---|
app | Yes | Application ID. |
action | Yes | Action name. |
record | Optional | Inline record passed to the action. |
record_ref | Optional | Name of a row saved by an earlier query_model step. |
input | Optional | Extra action input payload. |
confirmed | Optional | Whether to mark the action as confirmed. Defaults to false. |
expect_status | Optional | Expected action response status. |
save_workflow_run_as | Optional | Save workflow run ID from the action response for later wait_workflow. |
Use either record or record_ref when the action needs a selected record.
Step: wait for workflow
Wait for an async workflow run to reach a status.
- type: wait_workflow
run_ref: case_workflow
expect_status: Completed
timeout_secs: 30
| Field | Required | Meaning |
|---|---|---|
run_ref | Yes | Name saved by save_workflow_run_as. |
expect_status | Optional | Expected workflow status. Defaults to Completed. |
timeout_secs | Optional | Wait timeout. Defaults to 30. |
Use this after action steps that start workflows.
Typical flow
m5c validate apps/security-analytics --workspace --offline
m5c test apps/security-analytics --workspace
m5c build apps/security-analytics --out dist
m5c lower apps/security-analytics --dev --out lowered
m5c smoke apps/security-analytics --artifacts-dir /tmp/m5c-smoke
Smoke output includes scenario evidence and a report path that can be attached to release notes, CI runs, or app readiness reviews.
Runtime modes
Smoke scenarios can run against a managed temporary Mach5 One runtime or an externally supplied runtime, depending on the available command flags and environment.
Use managed smoke for repeatable local checks. Use external runtime smoke when validating against a shared development or staging environment.
Scenario design
Good smoke scenarios are narrow and deterministic.
Examples:
| Scenario | Proves |
|---|---|
| source-to-detection | Seeded source/detection rows produce expected findings or alerts. |
| finding-to-case | An alert can become a case through app actions and workflows. |
| automation-webhook-replay | Automation actions write expected delivery and job state. |
| enterprise-ai-cost | AI summary, RBAC, retention, or evidence workflows are wired correctly. |
Common mistakes
| Mistake | Fix |
|---|---|
| Running smoke before lowering | Run smoke after m5c lower. |
| Using nondeterministic IDs or times | Use fixed IDs and timestamps. |
| Querying before refreshing dependent MVs | Add refresh_mv steps before queries. |
| Depending on row order without sorts | Add sorts or filter to a unique row. |
Saving a row name and misspelling the later record_ref | Keep saved names short and consistent. |
| Using smoke as the only test gate | Keep m5c test fixtures for fast source-level validation. |
Best practices
- Keep smoke data deterministic.
- Run smoke after lowering, not before.
- Test one runtime path per scenario.
- Save and reuse queried records instead of duplicating payloads.
- Store reports as CI artifacts.
- Do not use smoke tests as the only validation gate; keep source-level tests fast and comprehensive.