diff --git a/src/cli/core/config-loader.ts b/src/cli/core/config-loader.ts index bf993b8..06640da 100644 --- a/src/cli/core/config-loader.ts +++ b/src/cli/core/config-loader.ts @@ -49,7 +49,7 @@ export interface EnvironmentPolicy { } export interface ProfileDefinition { - name: string; + name?: string; mode?: 'verify' | 'observe' | 'qualify'; preset?: string; routes?: string[]; @@ -68,7 +68,10 @@ export interface ProfileDefinition { } export interface PresetDefinition { - name: string; + name?: string; + mode?: 'verify' | 'observe' | 'qualify'; + routes?: string[]; + seed?: number; timeout?: number; parallel?: boolean; chaos?: boolean; @@ -83,18 +86,6 @@ export interface PresetDefinition { chaosSampleRoutes?: string[]; } -export interface PresetDefinition { - mode?: 'verify' | 'observe' | 'qualify'; - routes?: string[]; - seed?: number; - features?: string[]; - chaos?: boolean; - chaosStrategy?: 'one' | 'all' | 'sample' | 'routes'; - chaosSampleSize?: number; - chaosSampleRoutes?: string[]; - [key: string]: unknown; -} - export interface ScenarioConfigDef { name: string; steps: Array<{ diff --git a/src/cli/core/types.ts b/src/cli/core/types.ts index 49d685f..330f74c 100644 --- a/src/cli/core/types.ts +++ b/src/cli/core/types.ts @@ -116,7 +116,7 @@ export interface EnvironmentPolicy { * } */ export interface ProfileDefinition { - name: string; + name?: string; mode?: ApophisMode; preset?: string; routes?: string[]; @@ -150,7 +150,10 @@ export interface ProfileDefinition { * } */ export interface PresetDefinition { - name: string; + name?: string; + mode?: 'verify' | 'observe' | 'qualify'; + routes?: string[]; + seed?: number; timeout?: number; parallel?: boolean; chaos?: boolean; diff --git a/src/test/expressive-contracts.test.ts b/src/test/expressive-contracts.test.ts index ff9b49f..7ef1209 100644 --- a/src/test/expressive-contracts.test.ts +++ b/src/test/expressive-contracts.test.ts @@ -7,7 +7,7 @@ const FORMULA_EDGE_CASES = describe('expressive contracts: formula edge cases') test('if/then/else nesting: status-dependent body check', async (t) => { const fastify = Fastify() - await fastify.register(apophisPlugin, { runtime: 'off', profile: 'platform-observe' }) + await fastify.register(apophisPlugin, { runtime: 'off' }) fastify.post('/order', { schema: { @@ -22,7 +22,8 @@ test('if/then/else nesting: status-dependent body check', async (t) => { } } }, async (req, reply) => { - if (req.body.amount > 0) { reply.status(201); return { id: 'ord-1' } } + const body = (req.body as any) + if (body.amount > 0) { reply.status(201); return { id: 'ord-1' } } reply.status(400); return { error: 'amount must be positive' } }) @@ -52,7 +53,7 @@ test('request_headers and request_body accessors', async (t) => { response: { 200: { type: 'object', properties: { echoed: { type: 'string' } } } } } }, async (req) => { - return { echoed: req.body.message } + return { echoed: (req.body as any).message } }) await fastify.ready() @@ -104,7 +105,8 @@ test('comparison operators: ==, !=, >, <, >=, <=', async (t) => { response: { 201: { type: 'object', properties: { score: { type: 'number' }, grade: { type: 'string' } } } } } }, async (req, reply) => { - const score = Math.min(100, Math.max(0, req.body.raw)) + const b = req.body as any + const score = Math.min(100, Math.max(0, b.raw)) const grade = score >= 90 ? 'A' : score >= 75 ? 'B' : score >= 60 ? 'C' : 'F' reply.status(201) return { score, grade } @@ -136,7 +138,8 @@ test('logical operators: and, or, not', async (t) => { } }, async (req, reply) => { reply.status(201) - return { id: 'w-' + Math.random().toString(36).slice(2), color: req.body.color || 'red', size: req.body.size || 'm' } + const b = req.body as any + return { id: 'w-' + Math.random().toString(36).slice(2), color: b.color || 'red', size: b.size || 'm' } }) await fastify.ready() @@ -151,7 +154,7 @@ test('logical operators: and, or, not', async (t) => { test('cross-operation with previous(): verify created resource is retrievable', async (t) => { const fastify = Fastify() - await fastify.register(apophisPlugin, { runtime: 'off', profile: 'protocol-lab' }) + await fastify.register(apophisPlugin, { runtime: 'off' }) fastify.post('/projects', { schema: { @@ -166,7 +169,7 @@ test('cross-operation with previous(): verify created resource is retrievable', } }, async (req, reply) => { reply.status(201) - return { name: req.body.name } + return { name: (req.body as any).name } }) fastify.get('/projects/:name', { @@ -210,7 +213,7 @@ test('complex HATEOAS: linked resource route_exists and compliance', async (t) = }, async (req, reply) => { const id = 't-' + Math.random().toString(36).slice(2, 8) reply.status(201) - return { id, name: req.body.name, _links: { self: { href: `/tenants/${id}` } } } + return { id, name: (req.body as any).name, _links: { self: { href: `/tenants/${id}` } } } }) await fastify.ready() @@ -239,7 +242,7 @@ test('null handling: optional fields in response', async (t) => { } }, async (req, reply) => { reply.status(201) - return { id: 'u-1', name: req.body.name } + return { id: 'u-1', name: (req.body as any).name } }) await fastify.ready() @@ -295,7 +298,8 @@ test('concatenation and string formulas in ensures', async (t) => { response: { 200: { type: 'object', properties: { display: { type: 'string' } } } } } }, async (req) => { - return { display: req.body.first + ' ' + req.body.last } + const b = req.body as any + return { display: b.first + ' ' + b.last } }) await fastify.ready() @@ -322,7 +326,8 @@ test('boolean response field: truthiness in ensures', async (t) => { } }, async (req, reply) => { reply.status(201) - return { id: 'ft-1', name: req.body.name, enabled: req.body.name === 'dark-mode' } + const b = req.body as any + return { id: 'ft-1', name: b.name, enabled: b.name === 'dark-mode' } }) await fastify.ready() @@ -349,7 +354,8 @@ test('numeric computations: derived field must match formula', async (t) => { } }, async (req, reply) => { reply.status(201) - const total = req.body.quantity * req.body.unit_price + const b = req.body as any + const total = b.quantity * b.unit_price return { id: 'inv-1', line_total: total } }) @@ -383,7 +389,8 @@ test('guard conditions: special characters and unicode in strings', async (t) => ar: '\u0645\u0631\u062d\u0628\u0627', en: 'Hello \u2600' } - return { id: 'u-1', greeting: greetings[req.body.lang] || greetings.en } + const b = req.body as any + return { id: 'u-1', greeting: greetings[b.lang] || greetings.en } }) await fastify.ready() @@ -415,7 +422,8 @@ test('large response body: deep nested object with many keys', async (t) => { } }, async (req, reply) => { reply.status(201) - const count = Math.min(req.body.count, 100) + const b = req.body as any + const count = Math.min(b.count, 100) const items = Array.from({ length: count }, (_, i) => ({ index: i, name: `Item ${i}`, nested: { a: i, b: i * 2, c: { d: `deep-${i}` } } })) @@ -445,8 +453,8 @@ test('verification: runVerify surfaces failures from broken contracts', async (t response: { 201: { type: 'object', properties: { id: { type: 'string' } } } } } }, async (req, reply) => { - reply.status(200) - return { name: req.body.name } + (reply as any).status(200) + return { name: (req.body as any).name } }) await fastify.ready()