Initial public release of Apophis — invariant-driven automated API testing

This commit is contained in:
John Dvorak
2026-03-10 00:00:00 -07:00
parent d278c4b105
commit 3ac1daf7e9
82 changed files with 3902 additions and 1098 deletions
+39 -23
View File
@@ -10,15 +10,16 @@ Every command accepts these flags:
|---|---|---|
| `--config <path>` | Config file path | Auto-detect |
| `--profile <name>` | Profile name from config | First profile |
| `--generation-profile <name>` | Generation budget profile (built-in or config alias) | Depth-derived |
| `--cwd <path>` | Working directory override | `process.cwd()` |
| `--format <mode>` | Output format: `human`, `json`, `ndjson`, `json-summary`, `ndjson-summary` | `human` |
| `--color <mode>` | Color mode: `auto`, `always`, `never` | `auto` |
| `--quiet` | Suppress non-error output | false |
| `--verbose` | Enable verbose logging | false |
| `--artifact-dir <path>` | Directory for artifact output | `reports/apophis/` |
| `--artifact-dir <path>` | Directory for artifact output. Artifacts written on failure or when explicitly configured. | `reports/apophis/` |
| `--workspace` | Run supported commands across workspace packages | false |
Note: `json-summary` and `ndjson-summary` are only supported by `verify` and `qualify` commands.
## Commands
### `apophis init`
@@ -37,8 +38,8 @@ apophis init --preset safe-ci
| Flag | Description |
|---|---|
| `--preset <name>` | Preset name: `safe-ci`, `platform-observe`, `llm-safe`, `protocol-lab` |
| `--force` | Overwrite existing files |
| `-p, --preset <name>` | Preset name: `safe-ci`, `platform-observe`, `llm-safe`, `protocol-lab` |
| `-f, --force` | Overwrite existing files |
| `--noninteractive` | Skip all prompts, require explicit flags |
**Examples:**
@@ -60,10 +61,10 @@ apophis verify --profile quick --routes "POST /users"
| Flag | Description |
|---|---|
| `--profile <name>` | Profile name from config |
| `--generation-profile <name>` | Override generation budget for this run |
| `--routes <filter>` | Route filter pattern (comma-separated, supports wildcards) |
| `--seed <number>` | Deterministic seed (generated and printed if omitted) |
| `--changed` | Filter to git-modified routes only |
| `--workspace` | Run across all workspace packages |
| `--format <mode>` | Output format: `human`, `json`, `ndjson`, `json-summary`, `ndjson-summary` |
**Examples:**
@@ -118,7 +119,6 @@ apophis qualify --profile oauth-nightly --seed 42
| Flag | Description |
|---|---|
| `--profile <name>` | Profile name from config |
| `--generation-profile <name>` | Override generation budget for this run |
| `--seed <number>` | Deterministic seed (generated and printed if omitted) |
**Examples:**
@@ -126,18 +126,6 @@ apophis qualify --profile oauth-nightly --seed 42
```bash
apophis qualify --profile oauth-nightly --seed 42
apophis qualify --profile lifecycle-deep
apophis qualify --profile oauth-nightly --generation-profile quick
```
You can define aliases in config:
```js
export default {
generationProfiles: {
pr: 'quick',
nightly: { base: 'thorough' },
},
}
```
### `apophis replay`
@@ -171,6 +159,7 @@ apophis doctor [--mode verify|observe|qualify] [--strict]
|---|---|
| `--mode <mode>` | Filter checks to a specific mode |
| `--strict` | Treat warnings as failures |
| `--workspace` | Run across all workspace packages |
**Checks:**
@@ -210,6 +199,31 @@ apophis migrate --dry-run
apophis migrate --write
```
## Common Tasks
### CI workflow with machine output
```bash
apophis verify --profile ci --format json-summary --artifact-dir reports/apophis
```
### Monorepo workspace verification
```bash
apophis verify --workspace --profile quick
apophis doctor --workspace
```
### Replay a failure
```bash
apophis replay --artifact reports/apophis/failure-*.json
```
## Gotchas
- `--changed` requires a git repository
- `migrate` defaults to `--dry-run` (safe by default)
- `--workspace` is fully implemented by `verify` and `doctor`. `observe` and `qualify` accept the flag but run in the current package only.
- Seeds ensure deterministic generation; handler nondeterminism (e.g., `Date.now()`) can still cause replay divergence
## Exit Codes
| Code | Meaning |
@@ -226,10 +240,12 @@ apophis migrate --write
|---|---|---|---|---|
| `verify` | enabled | enabled | optional | optional, usually off |
| `observe` | optional | optional | enabled | enabled |
| `qualify: scenario` | enabled | enabled | enabled with allowlist | disabled by default |
| `qualify: stateful` | enabled | enabled | synthetic-only | disabled by default |
| `qualify: chaos` | enabled | enabled | canary-only | disabled by default |
| outbound mocks | enabled | enabled | allowlisted only | disabled by default |
| `qualify` | enabled | enabled | optional | disabled by default |
| `chaos` | enabled | enabled | optional | disabled by default |
| runtime throw-on-violation | optional | optional | exceptional | disabled by default |
Operational rule: Production must never inherit qualify capabilities accidentally from a generic config file.
Notes:
- `qualify` is gated as a whole. The code does not distinguish scenario, stateful, and chaos sub-modes in environment policy.
- `chaos` on protected routes requires `allowChaosOnProtected: true`.
- `observe` blocking requires `allowBlocking: true`.
- Production must never inherit qualify capabilities accidentally from a generic config file.