#!/usr/bin/env node /** * Fixture "real implementation" of orders.openapi.yaml, for the APIFae CLI * scenario tests (APIFAE-102). * * node backend.js # faithful to the spec * DRIFT=1 node backend.js # drifted four ways, deliberately * FLAKY_EVERY=5 node backend.js # every 5th GET /orders serves the drifted * # enum — an intermittent backend, for * # `apifae diff --samples N` (APIFAE-124) * * The four drifts are exactly the ones the backend persona said they would * otherwise never notice: * * 1. GET /reports/daily 500 body gains an undocumented `errorCode` field * 2. GET /orders/{id} `status` returns `refunded`, an enum value the spec * does not list * 3. GET /orders `note` comes back null; the spec says string * 4. POST /orders responds 200 where the spec says 201 * * Responses are fully deterministic — no timestamps, no random ids — so a diff * run is reproducible and any reported change is a real change. */ const http = require('http'); const PORT = Number(process.env.PORT || 9100); const DRIFT = process.env.DRIFT === '1'; // Supplementary probe (APIFAE-102): drift ONLY the enum, on the list endpoint, // which has no path parameters and is therefore actually checked by `diff`. const DRIFT_ENUM = process.env.DRIFT_ENUM === '1'; // Intermittent drift (APIFAE-124): every Nth GET /orders serves the // out-of-enum value, the rest are faithful. Counted rather than random so a // sampling run has an exactly predictable prevalence — 1 in N — and the test // asserting it cannot flake. const FLAKY_EVERY = Number(process.env.FLAKY_EVERY || 0); let ordersRequests = 0; const order = (id, status, note) => ({ id, status, total: 4250, currency: 'EUR', customerEmail: 'ada@example.com', note, createdAt: '2026-08-01T09:15:00Z', }); const send = (res, status, body) => { const payload = JSON.stringify(body); res.writeHead(status, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload), }); res.end(payload); }; const server = http.createServer((req, res) => { const url = new URL(req.url, `http://localhost:${PORT}`); const path = url.pathname; const method = req.method; // --- GET /orders ----------------------------------------------------- // Drift 3: `note` becomes null. if (method === 'GET' && path === '/orders') { ordersRequests += 1; const note = DRIFT ? null : 'Leave with the concierge'; const flaky = FLAKY_EVERY > 0 && ordersRequests % FLAKY_EVERY === 0; const s0 = DRIFT_ENUM || flaky ? 'refunded' : 'paid'; return send(res, 200, { data: [ order('ord_8f14e45fceea', s0, note), order('ord_1679091c5a88', 'pending', note), order('ord_e4da3b7fbbce', 'shipped', note), ], page: 1, total: 3, hasMore: false, }); } // --- POST /orders ---------------------------------------------------- // Drift 4: 201 quietly becomes 200. if (method === 'POST' && path === '/orders') { const status = DRIFT ? 200 : 201; return send(res, status, order('ord_8f14e45fceea', 'pending', 'Leave with the concierge')); } // --- GET /orders/{id} ------------------------------------------------ // Drift 2: `status` returns an enum value the spec never listed. const match = path.match(/^\/orders\/([^/]+)$/); if (method === 'GET' && match) { if (match[1] === 'missing') { return send(res, 404, { error: 'not_found', message: 'No such order' }); } const status = DRIFT ? 'refunded' : 'paid'; return send(res, 200, order(match[1], status, 'Leave with the concierge')); } // --- GET /reports/daily ---------------------------------------------- // Drift 1: an undocumented `errorCode` appears in the 500 envelope. if (method === 'GET' && path === '/reports/daily') { const body = { error: 'report_failed', message: 'Report worker is not available' }; if (DRIFT) body.errorCode = 'RPT-500'; return send(res, 500, body); } return send(res, 404, { error: 'not_found', message: `No route for ${method} ${path}` }); }); server.listen(PORT, () => { console.log(`orders backend listening on http://localhost:${PORT} (drift=${DRIFT ? 'on' : 'off'})`); });