chore: crush git history - reborn from consolidation on 2026-03-10

This commit is contained in:
John Dvorak
2026-03-10 00:00:00 -07:00
commit d278c4b105
313 changed files with 87549 additions and 0 deletions
@@ -0,0 +1,36 @@
/**
* APOPHIS configuration for broken-behavior fixture.
*/
export default {
mode: "verify",
profiles: {
quick: {
name: "quick",
mode: "verify",
preset: "safe-ci",
routes: ["POST /users"],
},
},
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,
},
},
};
+100
View File
@@ -0,0 +1,100 @@
/**
* Broken behavior fixture: POST /users returns 201 but GET /users/{id} returns 404.
* This is the canonical "wow" failure for APOPHIS CLI acceptance tests.
*/
import Fastify from "fastify";
import apophisPlugin from "../../../index.js";
const app = Fastify({ logger: false });
// Register swagger (required by APOPHIS)
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Broken API", version: "1.0.0" },
},
});
// Register APOPHIS plugin for route discovery
await app.register(apophisPlugin, { runtime: "off" });
app.post(
"/users",
{
schema: {
description: "Create a user",
body: {
type: "object",
required: ["name"],
properties: {
name: { type: "string" },
},
},
response: {
201: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
},
},
},
// Behavioral contract: created resource must be retrievable
"x-ensures": [
"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 };
}
);
app.get(
"/users/:id",
{
schema: {
description: "Get a user by ID",
params: {
type: "object",
required: ["id"],
properties: {
id: { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
},
},
404: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},
},
async (request, reply) => {
const { id } = request.params;
// BUG: Always returns 404, even for resources that were just created
reply.status(404);
return { error: `User ${id} not found` };
}
);
export default app;
// Start server if run directly
if (process.argv[1] === new URL(import.meta.url).pathname) {
await app.ready();
await app.listen({ port: 3000 });
console.log("Broken behavior app running on http://localhost:3000");
}
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-broken-behavior",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,40 @@
/**
* LEGACY APOPHIS configuration (old-style, for migration tests).
* This uses deprecated field names that should be detected by `apophis migrate`.
*/
export default {
// Deprecated: 'mode' used to be 'testMode'
testMode: "verify",
// Deprecated: 'profiles' used to be 'testProfiles'
testProfiles: {
quick: {
name: "quick",
// Deprecated: 'preset' used to be 'usesPreset'
usesPreset: "safe-ci",
// Deprecated: 'routes' used to be 'routeFilter'
routeFilter: ["GET /legacy"],
},
},
// Deprecated: 'presets' used to be 'testPresets'
testPresets: {
"safe-ci": {
name: "safe-ci",
// Deprecated: 'depth' used to be 'testDepth'
testDepth: "quick",
// Deprecated: 'timeout' used to be 'maxDuration'
maxDuration: 5000,
},
},
// Deprecated: 'environments' used to be 'envPolicies'
envPolicies: {
local: {
name: "local",
// Deprecated: 'allowVerify' used to be 'canVerify'
canVerify: true,
},
},
};
+25
View File
@@ -0,0 +1,25 @@
/**
* Legacy config fixture: old-style config for migration tests.
* Uses deprecated field names and structure.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Legacy App", version: "1.0.0" },
},
});
app.get("/legacy", async () => ({ status: "legacy" }));
export default app;
// Start server if run directly
if (process.argv[1] === new URL(import.meta.url).pathname) {
await app.ready();
await app.listen({ port: 3000 });
console.log("Legacy config app running on http://localhost:3000");
}
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-legacy-config",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,30 @@
/**
* Root-level APOPHIS config for monorepo.
* Packages can override with their own configs.
*/
export default {
mode: "verify",
profiles: {
"api-quick": {
name: "api-quick",
mode: "verify",
preset: "safe-ci",
},
"web-quick": {
name: "web-quick",
mode: "verify",
preset: "safe-ci",
},
},
presets: {
"safe-ci": {
name: "safe-ci",
depth: "quick",
timeout: 5000,
parallel: false,
chaos: false,
observe: false,
},
},
};
@@ -0,0 +1,12 @@
{
"name": "@apophis/fixture-monorepo",
"version": "1.0.0",
"private": true,
"type": "module",
"workspaces": [
"packages/*"
],
"scripts": {
"test": "npm run test --workspaces"
}
}
@@ -0,0 +1,43 @@
/**
* API package in monorepo fixture.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "API Package", version: "1.0.0" },
},
});
app.get("/health", async () => ({ status: "ok" }));
app.post(
"/users",
{
schema: {
body: {
type: "object",
required: ["name"],
properties: { name: { type: "string" } },
},
"x-ensures": [
"response_code(GET /users/{response_body(this).id}) == 200",
],
},
},
async (request, reply) => {
const id = `usr-${Date.now()}`;
reply.status(201);
return { id, name: request.body.name };
}
);
app.get("/users/:id", async (request) => ({
id: request.params.id,
name: "Test User",
}));
export default app;
@@ -0,0 +1,12 @@
{
"name": "@apophis/fixture-monorepo-api",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,17 @@
/**
* Web package in monorepo fixture.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Web Package", version: "1.0.0" },
},
});
app.get("/", async () => ({ message: "Hello from web" }));
export default app;
@@ -0,0 +1,12 @@
{
"name": "@apophis/fixture-monorepo-web",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,36 @@
/**
* APOPHIS configuration for observe-config fixture.
*/
export default {
mode: "observe",
profiles: {
"staging-observe": {
name: "staging-observe",
mode: "observe",
preset: "observe-safe",
routes: ["/health", "/events"],
},
},
presets: {
"observe-safe": {
name: "observe-safe",
depth: "quick",
timeout: 5000,
parallel: false,
chaos: false,
observe: true,
},
},
environments: {
staging: {
name: "staging",
allowVerify: true,
allowObserve: true,
allowQualify: false,
allowChaos: false,
allowBlocking: false,
requireSink: true,
},
},
};
@@ -0,0 +1,55 @@
/**
* Observe config fixture: app with observe configuration and sink setup.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Observe App", version: "1.0.0" },
},
});
app.get("/health", async () => ({ status: "ok" }));
app.post(
"/events",
{
schema: {
description: "Record an event",
body: {
type: "object",
required: ["type", "payload"],
properties: {
type: { type: "string" },
payload: { type: "object" },
},
},
response: {
201: {
type: "object",
properties: {
id: { type: "string" },
received: { type: "boolean" },
},
},
},
},
},
async (request, reply) => {
const id = `evt-${Date.now()}`;
reply.status(201);
return { id, received: true };
}
);
export default app;
// Start server if run directly
if (process.argv[1] === new URL(import.meta.url).pathname) {
await app.ready();
await app.listen({ port: 3000 });
console.log("Observe config app running on http://localhost:3000");
}
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-observe-config",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,42 @@
/**
* Fastify app that attempts duplicate APOPHIS plugin registration.
* Doctor should detect the duplicate and warn, not fail hard.
*/
import Fastify from "fastify";
import apophisPlugin from "/home/johndvorak/Business/workspace/Apophis/dist/index.js";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Duplicate Plugin Test", version: "1.0.0" },
},
});
// First registration
await app.register(apophisPlugin, { runtime: "off" });
// Second registration (duplicate) - this should be handled gracefully
// In real Fastify this would throw "decorator already added"
// But doctor should detect pre-registration and skip its own attempt
app.get(
"/health",
{
schema: {
description: "Health check",
response: {
200: {
type: "object",
properties: {
status: { type: "string" },
},
},
},
},
},
async () => ({ status: "ok" })
);
export default app;
@@ -0,0 +1,9 @@
{
"name": "@apophis/fixture-plugin-duplicate",
"version": "1.0.0",
"type": "module",
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,36 @@
/**
* Fastify app without APOPHIS plugin registered.
* Doctor should detect plugin is missing and warn.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "No Plugin Test", version: "1.0.0" },
},
});
// NOTE: APOPHIS plugin is NOT registered here
app.get(
"/health",
{
schema: {
description: "Health check",
response: {
200: {
type: "object",
properties: {
status: { type: "string" },
},
},
},
},
},
async () => ({ status: "ok" })
);
export default app;
@@ -0,0 +1,9 @@
{
"name": "@apophis/fixture-plugin-not-registered",
"version": "1.0.0",
"type": "module",
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,33 @@
import Fastify from "fastify";
import apophisPlugin from "/home/johndvorak/Business/workspace/Apophis/dist/index.js";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Pre-registered Plugin Test", version: "1.0.0" },
},
});
// Plugin is already registered here - doctor should detect this
await app.register(apophisPlugin, { runtime: "off" });
app.get(
"/health",
{
schema: {
description: "Health check",
response: {
200: {
type: "object",
properties: {
status: { type: "string" },
},
},
},
},
},
async () => ({ status: "ok" })
);
export default app;
@@ -0,0 +1,9 @@
{
"name": "@apophis/fixture-plugin-pre-registered",
"version": "1.0.0",
"type": "module",
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,36 @@
/**
* APOPHIS configuration for protocol-lab fixture.
*/
export default {
mode: "qualify",
profiles: {
"oauth-nightly": {
name: "oauth-nightly",
mode: "qualify",
preset: "deep",
routes: ["POST /oauth/authorize", "POST /oauth/token", "GET /api/user"],
},
},
presets: {
deep: {
name: "deep",
depth: "deep",
timeout: 30000,
parallel: false,
chaos: true,
observe: false,
},
},
environments: {
local: {
name: "local",
allowVerify: true,
allowObserve: true,
allowQualify: true,
allowChaos: true,
allowBlocking: true,
requireSink: false,
},
},
};
+169
View File
@@ -0,0 +1,169 @@
/**
* Protocol lab fixture: OAuth-like multi-step flow app.
* Demonstrates stateful testing with multi-step protocols.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
// In-memory token store (for demo only)
const tokens = new Map();
const authCodes = new Map();
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Protocol Lab", version: "1.0.0" },
},
});
// Step 1: Request authorization code
app.post(
"/oauth/authorize",
{
schema: {
description: "Request authorization code",
body: {
type: "object",
required: ["client_id", "redirect_uri"],
properties: {
client_id: { type: "string" },
redirect_uri: { type: "string" },
scope: { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
code: { type: "string" },
state: { type: "string" },
},
},
},
},
},
async (request, reply) => {
const { client_id, redirect_uri } = request.body;
const code = `auth-${Date.now()}`;
authCodes.set(code, { client_id, redirect_uri, used: false });
return { code, state: "xyz" };
}
);
// Step 2: Exchange code for token
app.post(
"/oauth/token",
{
schema: {
description: "Exchange authorization code for access token",
body: {
type: "object",
required: ["code", "client_id", "client_secret"],
properties: {
code: { type: "string" },
client_id: { type: "string" },
client_secret: { type: "string" },
redirect_uri: { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
access_token: { type: "string" },
token_type: { type: "string" },
expires_in: { type: "number" },
},
},
400: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},
},
async (request, reply) => {
const { code, client_id, client_secret } = request.body;
const auth = authCodes.get(code);
if (!auth || auth.used) {
reply.status(400);
return { error: "invalid_grant" };
}
if (auth.client_id !== client_id) {
reply.status(400);
return { error: "invalid_client" };
}
auth.used = true;
const token = `tok-${Date.now()}`;
tokens.set(token, { client_id, createdAt: Date.now() });
return {
access_token: token,
token_type: "Bearer",
expires_in: 3600,
};
}
);
// Step 3: Use token
app.get(
"/api/user",
{
schema: {
description: "Get current user with access token",
headers: {
type: "object",
required: ["authorization"],
properties: {
authorization: { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
id: { type: "string" },
client_id: { type: "string" },
},
},
401: {
type: "object",
properties: {
error: { type: "string" },
},
},
},
},
},
async (request, reply) => {
const auth = request.headers.authorization;
if (!auth || !auth.startsWith("Bearer ")) {
reply.status(401);
return { error: "invalid_token" };
}
const token = auth.slice(7);
const data = tokens.get(token);
if (!data) {
reply.status(401);
return { error: "invalid_token" };
}
return { id: `user-${token}`, client_id: data.client_id };
}
);
export default app;
// Start server if run directly
if (process.argv[1] === new URL(import.meta.url).pathname) {
await app.ready();
await app.listen({ port: 3000 });
console.log("Protocol lab app running on http://localhost:3000");
}
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-protocol-lab",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,36 @@
/**
* APOPHIS configuration for tiny-fastify fixture.
*/
export default {
mode: "verify",
profiles: {
quick: {
name: "quick",
mode: "verify",
preset: "safe-ci",
routes: ["POST /users"],
},
},
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,
},
},
};
+99
View File
@@ -0,0 +1,99 @@
/**
* Minimal Fastify app with one route and one behavioral contract.
* This is the "hello world" fixture for APOPHIS CLI.
*/
import Fastify from "fastify";
const app = Fastify({ logger: false });
// Register swagger (required by APOPHIS)
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Tiny API", version: "1.0.0" },
},
});
let apophisPlugin;
try {
({ default: apophisPlugin } = await import("../../../index.js"));
} catch {
({ default: apophisPlugin } = await import("../../../../dist/index.js"));
}
await app.register(apophisPlugin, { runtime: "off" });
app.post(
"/users",
{
schema: {
description: "Create a user",
body: {
type: "object",
required: ["name"],
properties: {
name: { type: "string" },
},
},
response: {
201: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
},
},
},
// Behavioral contract: created resource must be retrievable
"x-ensures": [
"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 };
}
);
app.get(
"/users/:id",
{
schema: {
description: "Get a user by ID",
params: {
type: "object",
required: ["id"],
properties: {
id: { type: "string" },
},
},
response: {
200: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
},
},
},
},
},
async (request, reply) => {
const { id } = request.params;
// In a real app, this would fetch from DB
// For this fixture, we always return the user
return { id, name: "Test User" };
}
);
export default app;
// Start server if run directly
if (process.argv[1] === new URL(import.meta.url).pathname) {
await app.ready();
await app.listen({ port: 3000 });
console.log("Tiny Fastify app running on http://localhost:3000");
}
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-tiny-fastify",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,21 @@
export default {
mode: "verify",
profiles: {
quick: {
name: "quick",
mode: "verify",
preset: "safe-ci",
routes: ["GET /health"],
},
},
presets: {
"safe-ci": {
name: "safe-ci",
depth: "quick",
timeout: 5000,
parallel: false,
chaos: false,
observe: false,
},
},
};
@@ -0,0 +1,32 @@
import Fastify from "fastify";
import apophisPlugin from "../../../index.js";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Verify No Contracts", version: "1.0.0" },
},
});
await app.register(apophisPlugin, { runtime: "off" });
app.get(
"/health",
{
schema: {
description: "Health check route with schema only",
response: {
200: {
type: "object",
properties: {
status: { type: "string" },
},
},
},
},
},
async () => ({ status: "ok" }),
);
export default app;
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-verify-no-contracts",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,21 @@
export default {
mode: "verify",
profiles: {
quick: {
name: "quick",
mode: "verify",
preset: "safe-ci",
routes: ["GET /broken"],
},
},
presets: {
"safe-ci": {
name: "safe-ci",
depth: "quick",
timeout: 5000,
parallel: false,
chaos: false,
observe: false,
},
},
};
@@ -0,0 +1,33 @@
import Fastify from "fastify";
import apophisPlugin from "../../../index.js";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Verify Parse Fail", version: "1.0.0" },
},
});
await app.register(apophisPlugin, { runtime: "off" });
app.get(
"/broken",
{
schema: {
description: "Route with invalid behavioral contract",
"x-ensures": ["this is not a valid contract!!!"],
response: {
200: {
type: "object",
properties: {
status: { type: "string" },
},
},
},
},
},
async () => ({ status: "ok" }),
);
export default app;
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-verify-parse-fail",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}
@@ -0,0 +1,21 @@
export default {
mode: "verify",
profiles: {
quick: {
name: "quick",
mode: "verify",
preset: "safe-ci",
routes: ["GET /slow"],
},
},
presets: {
"safe-ci": {
name: "safe-ci",
depth: "quick",
timeout: 5000,
parallel: false,
chaos: false,
observe: false,
},
},
};
@@ -0,0 +1,37 @@
import Fastify from "fastify";
import apophisPlugin from "../../../index.js";
const app = Fastify({ logger: false });
await app.register(import("@fastify/swagger"), {
openapi: {
info: { title: "Verify Timeout Route", version: "1.0.0" },
},
});
await app.register(apophisPlugin, { runtime: "off" });
app.get(
"/slow",
{
schema: {
description: "Slow route with timeout metadata",
"x-timeout": 1,
"x-ensures": ["response_code(this) == 200"],
response: {
200: {
type: "object",
properties: {
ok: { type: "boolean" },
},
},
},
},
},
async () => {
await new Promise((resolvePromise) => setTimeout(resolvePromise, 100));
return { ok: true };
},
);
export default app;
@@ -0,0 +1,13 @@
{
"name": "@apophis/fixture-verify-timeout-route",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node app.js",
"test": "node --test"
},
"dependencies": {
"fastify": "^5.0.0",
"@fastify/swagger": "^9.0.0"
}
}