# Getting Started with APOPHIS Get from install to your first behavioral bug in 10 minutes. ## Prerequisites - Node.js 20.x or 22.x - A Fastify app with `@fastify/swagger` registered ## Step 1: Install ```bash npm install apophis-fastify fastify @fastify/swagger ``` ## Step 2: Scaffold ```bash apophis init --preset safe-ci ``` This creates: - `apophis.config.js` — config with a `quick` profile - `APOPHIS.md` — preset-specific guidance - Package script: `npm run apophis:verify` ## Step 3: Add One Behavioral Contract Pick one important route. Add an `x-ensures` clause that checks behavior across operations: ```javascript app.post('/users', { schema: { 'x-category': 'constructor', 'x-ensures': [ // BEHAVIORAL: Creating a user must make it retrievable 'response_code(GET /users/{response_body(this).id}) == 200' ] } }, async (request, reply) => { const { name } = request.body; const id = `usr-${Date.now()}`; reply.status(201); return { id, name }; }); ``` ## Step 4: Run Verify ```bash apophis verify --profile quick --routes "POST /users" ``` APOPHIS will: 1. Discover routes from your Fastify app 2. Filter to `POST /users` 3. Generate test data from the schema 4. Execute the route 5. Check the behavioral contract 6. Print pass/fail, seed, and replay command ## Example Failure If your `GET /users/:id` handler has a bug (always returns 404), APOPHIS catches it: ```text Contract violation POST /users Profile: quick Seed: 42 Expected response_code(GET /users/{response_body(this).id}) == 200 Observed GET /users/usr-123 returned 404 Why this matters The resource created by POST /users is not retrievable. Replay apophis replay --artifact reports/apophis/failure-2026-04-28T12-30-22Z.json Next Check the create/read consistency for POST /users and GET /users/{id}. ``` ## Step 5: Replay and Fix Copy the replay command and run it: ```bash apophis replay --artifact reports/apophis/failure-2026-04-28T12-30-22Z.json ``` Fix the bug in your handler. Re-run verify. The failure should now pass. ## Next Steps - Add more routes to your profile: `apophis verify --profile quick --routes "POST /users,PUT /users/:id"` - Run all routes: `apophis verify --profile quick` - Run only changed routes in CI: `apophis verify --profile ci --changed` - Add observe mode for runtime drift detection: see [docs/observe.md](docs/observe.md) - Add qualify mode for scenario, stateful, and chaos checks: see [docs/qualify.md](docs/qualify.md) ## Config Reference ```javascript // apophis.config.js export default { mode: 'verify', profile: 'quick', profiles: { quick: { name: 'quick', mode: 'verify', preset: 'safe-ci', routes: ['POST /users'] }, ci: { name: 'ci', mode: 'verify', preset: 'safe-ci', routes: [] } }, presets: { 'safe-ci': { name: 'safe-ci', depth: 'quick', timeout: 5000, parallel: false, chaos: false, observe: false } }, environments: { local: { name: 'local', allowVerify: true, allowObserve: true, allowQualify: false, allowChaos: false, allowBlocking: true, requireSink: false } } }; ``` ## Monorepo Workspaces APOPHIS supports workspace-wide operations with the `--workspace` flag. ### Root package.json scripts ```json { "scripts": { "apophis:verify": "apophis verify --workspace --profile quick", "apophis:doctor": "apophis doctor --workspace", "apophis:qualify": "apophis qualify --workspace --profile ci" } } ``` ### Workspace fan-out Run verify across all packages: ```bash apophis verify --workspace --profile quick --format json ``` Output is package-attributed: ```json { "exitCode": 0, "runs": [ { "package": "api", "cwd": "/repo/packages/api", "artifact": { ... } }, { "package": "web", "cwd": "/repo/packages/web", "artifact": { ... } } ] } ``` ### Supported commands - `apophis verify --workspace` - `apophis doctor --workspace` ## Exit Codes | Code | Meaning | |---|---| | 0 | Success | | 1 | Behavioral / qualification failure | | 2 | Usage, config, or environment safety violation | | 3 | Internal APOPHIS error | | 130 | Interrupted (SIGINT) |