Files
apophis-fastify/docs/qualify.md
T
John Dvorak 6c39bd0a6c docs: final cleanup and accuracy pass before public push
- Fix const inference bug: wrap inferred contracts with status-code guards
- Add integration test for status-guarded contract inference
- Tighten and deduplicate docs across verify, qualify, getting-started, cli
- Fix broken cross-references and TypeScript→JavaScript conversions
- Fix factual errors: license, Date.now(), sampling defaults, cache env
- Add missing features: --workspace, --generation-profile, json-summary formats
- Move stale extension docs (AUTH-RATE-LIMIT-REVISED, HTTP-EXTENSIONS) to attic
- Update PLUGIN_CONTRACTS_SPEC status to Implemented
- Build: clean | Tests: 849 pass, 0 fail
2026-04-30 11:25:30 -07:00

227 lines
5.5 KiB
Markdown

# Qualify Mode
Run scenario, stateful, and chaos checks against non-production Fastify services.
## What Qualify Does
`apophis qualify` runs deeper testing than verify:
- **Scenario execution**: Multi-step protocol flows with capture/rebind
- **Stateful testing**: Constructor/mutator/observer/destructor sequences
- **Chaos engineering**: Controlled fault injection
- **Adversity checks**: Failure-path and edge-case validation
## When to Use It
- **Nightly CI**: Scenario and stateful checks for critical flows
- **Staging**: Protocol flow validation before production
- **Specialist teams**: Auth, billing, workflow systems
## Scenario Examples
### OAuth Flow
```javascript
profiles: {
'oauth-nightly': {
name: 'oauth-nightly',
mode: 'qualify',
preset: 'protocol-lab',
routes: [],
seed: 42
}
}
```
Run with: `apophis qualify --profile oauth-nightly --seed 42`
### Lifecycle Deep
```javascript
profiles: {
'lifecycle-deep': {
name: 'lifecycle-deep',
mode: 'qualify',
preset: 'protocol-lab',
routes: [],
seed: 42
}
}
```
## Stateful Testing
Stateful tests generate sequences of operations and track resources:
1. **Constructor**: Create resources (POST)
2. **Mutator**: Modify resources (PUT, PATCH)
3. **Observer**: Read resources (GET)
4. **Destructor**: Remove resources (DELETE)
APOPHIS tracks created resources and runs cleanup after test completion.
## Route Transparency
Artifacts include `executedRoutes` and `skippedRoutes` arrays. `skippedRoutes` contains reasons such as mode mismatch, environment policy, or route filter exclusion.
## Chaos and Adversity
Chaos testing injects controlled failures:
- **Delay**: Slow responses
- **Error**: Return error status codes
- **Dropout**: Connection failures
- **Truncate**: Truncated response bodies
- **Malformed**: Invalid JSON or content-type
- **Field-corrupt**: Random field mutation in response objects
Configure chaos in your preset:
```javascript
presets: {
'protocol-lab': {
name: 'protocol-lab',
depth: 'deep',
timeout: 15000,
parallel: false,
chaos: true,
observe: false
}
}
```
## Non-Prod Boundaries
Qualify mode is gated away from production by default:
| Environment | Scenario | Stateful | Chaos |
|---|---|---|---|
| local | enabled | enabled | enabled |
| test/CI | enabled | enabled | enabled |
| staging | enabled with allowlist | enabled | blocked on protected routes |
| production | disabled by default | disabled by default | disabled by default |
## Machine Output for CI
Qualify can produce large output. Use machine-readable formats and event filtering to keep CI logs manageable:
### Concise formats
- `--format json-summary` — emits a single JSON document with summary, failures, and warnings. Omits per-step traces and cleanup outcomes.
- `--format ndjson-summary` — emits three NDJSON lines: `run.started`, `run.summary`, `run.completed`. No per-route events.
### Filtering examples
```bash
# Extract only failed routes from full ndjson
apophis qualify --profile oauth-nightly --format ndjson | jq 'select(.type == "route.failed")'
# Write artifact to disk and parse the file instead of stdout
apophis qualify --profile oauth-nightly --format json --artifact-dir reports/apophis
```
### Recommended CI retention strategy
- Keep artifacts for 30 days in CI storage (S3, GCS, Artifactory).
- Use `--artifact-dir` to write artifacts automatically.
- Parse `json-summary` output for dashboards; keep full `json` artifacts for debugging.
## Exit Codes
| Code | Meaning |
|---|---|
| 0 | All qualifications passed |
| 1 | One or more qualifications failed |
| 2 | Safety violation or invalid config |
| 3 | Internal APOPHIS error |
| 130 | Interrupted (SIGINT) |
## Config Example
```javascript
// apophis.config.js
export default {
mode: 'qualify',
profile: 'oauth-nightly',
profiles: {
'oauth-nightly': {
name: 'oauth-nightly',
mode: 'qualify',
preset: 'protocol-lab',
routes: [],
seed: 42
},
'lifecycle-deep': {
name: 'lifecycle-deep',
mode: 'qualify',
preset: 'protocol-lab',
routes: [],
seed: 42
}
},
presets: {
'protocol-lab': {
name: 'protocol-lab',
depth: 'deep',
timeout: 15000,
parallel: false,
chaos: true,
observe: false
}
},
environments: {
local: {
name: 'local',
allowVerify: true,
allowObserve: true,
allowQualify: true,
allowChaos: true,
allowBlocking: true,
requireSink: false
},
test: {
name: 'test',
allowVerify: true,
allowObserve: true,
allowQualify: true,
allowChaos: true,
allowBlocking: true,
requireSink: false
},
staging: {
name: 'staging',
allowVerify: true,
allowObserve: true,
allowQualify: true,
allowChaos: false,
allowBlocking: false,
requireSink: true
}
}
};
```
## Gate Execution Counts
Human output shows per-gate execution counts (scenario, stateful, chaos, adversity) so you can verify which gates actually ran.
## Zero-Execution Guardrail
Qualify exits with code 1 if zero checks executed. This prevents silent passes when all routes are filtered out or gates are disabled.
## `--workspace` Flag
Run qualify across all packages in a monorepo workspace:
```bash
apophis qualify --workspace --profile oauth-nightly
```
## `--generation-profile` Flag
Control test data generation depth independently from the qualification profile:
```bash
apophis qualify --profile oauth-nightly --generation-profile quick
```