chore: crush git history - reborn from consolidation on 2026-03-10
This commit is contained in:
@@ -0,0 +1,433 @@
|
||||
# Multi-Framework Feasibility and Roadmap
|
||||
|
||||
Status: Proposal
|
||||
Audience: APOPHIS maintainers and platform strategy owners
|
||||
Purpose: assess whether APOPHIS can expand beyond Fastify into Express, Python, and Go without turning into a platform rewrite
|
||||
|
||||
Current decision:
|
||||
|
||||
- APOPHIS is remaining Node-first and Fastify-first for now.
|
||||
- There is no active multi-language expansion roadmap at this time.
|
||||
- This document is retained as feasibility analysis, not as an execution commitment.
|
||||
- Express is the only plausible near-term adapter candidate, and even that is optional rather than planned.
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
Short answer:
|
||||
|
||||
- **Express**: feasible
|
||||
- **Python**: feasible only through a narrower first step
|
||||
- **Go**: feasible only later, and only with a smaller ambition than a native feature-parity port
|
||||
|
||||
The practical recommendation is:
|
||||
|
||||
1. extract a framework-neutral core inside the current Node codebase
|
||||
2. ship a CLI/spec-first mode that can hit any running server from an OpenAPI document
|
||||
3. validate the adapter seam with **Express** next
|
||||
4. defer native Python and Go adapters until the core and CLI are proven
|
||||
|
||||
If the goal is “Fastify + Express + generic spec-driven CLI,” this is tractable.
|
||||
|
||||
If the goal is “feature-parity native integrations for Fastify, Express, Python, and Go all at once,” that is too large and should be deferred.
|
||||
|
||||
For the current product strategy, this means:
|
||||
|
||||
- do not start multi-language work now
|
||||
- do not let speculative portability drive the core redesign
|
||||
- only revisit Express later if the Node adapter seam becomes cheap and the Fastify product is already strong
|
||||
|
||||
## 2. Why This Is Plausible At All
|
||||
|
||||
APOPHIS already has a meaningful split between:
|
||||
|
||||
- behavioral contract semantics
|
||||
- execution and test orchestration
|
||||
- framework integration
|
||||
|
||||
The following parts are reusable after adapter extraction:
|
||||
|
||||
- APOSTL parser and evaluator
|
||||
- contract extraction from schema annotations
|
||||
- schema-to-contract inference
|
||||
- state/resource/invariant helpers
|
||||
- chaos engine and much of the reporting stack
|
||||
|
||||
The following parts are currently Fastify-shaped:
|
||||
|
||||
- route discovery through `onRoute`
|
||||
- request execution through `fastify.inject()`
|
||||
- runtime validation hooks bound to Fastify lifecycle
|
||||
- OpenAPI/spec exposure through `@fastify/swagger`
|
||||
- cleanup and route storage assumptions
|
||||
|
||||
That means APOPHIS is **not** currently framework-agnostic, but it is also **not** trapped in Fastify everywhere.
|
||||
|
||||
## 3. The Current Coupling Problem
|
||||
|
||||
The real coupling is not just “HTTP framework.”
|
||||
|
||||
The real couplings are:
|
||||
|
||||
1. route discovery
|
||||
2. schema and annotation access
|
||||
3. test execution transport
|
||||
4. runtime middleware or hook semantics
|
||||
5. OpenAPI acquisition
|
||||
|
||||
Fastify makes these unusually convenient because it has:
|
||||
|
||||
- route-local schemas
|
||||
- predictable registration hooks
|
||||
- `inject()` for in-process execution
|
||||
- strong plugin lifecycle hooks
|
||||
|
||||
Express, Python, and Go differ in route metadata access, request injection support, and lifecycle hook semantics.
|
||||
|
||||
That is why a direct “port the plugin” mindset is dangerous.
|
||||
|
||||
## 4. Prior Systems That Validate Parts Of The Model
|
||||
|
||||
These systems show that the general space is real.
|
||||
|
||||
### 4.1 JavaScript / Node
|
||||
|
||||
- **Dredd**: language-agnostic CLI validating API behavior against OpenAPI or Swagger
|
||||
- **express-openapi-validator**: OpenAPI-based request and response validation middleware for Express
|
||||
- **openapi-backend**: framework-agnostic OpenAPI routing, validation, and mocking in Node
|
||||
|
||||
What this validates:
|
||||
|
||||
- spec-driven runtime behavior is normal in Node
|
||||
- CLI-driven cross-framework contract testing is viable
|
||||
- APOPHIS does not need to remain Fastify-only to stay coherent
|
||||
|
||||
### 4.2 Python
|
||||
|
||||
- **Connexion**: spec-first Python framework from OpenAPI
|
||||
- **openapi-core**: framework-agnostic request and response validation against OpenAPI
|
||||
- **Schemathesis**: OpenAPI-driven property-based testing and stateful API testing
|
||||
|
||||
What this validates:
|
||||
|
||||
- OpenAPI-driven request and response validation is mature in Python
|
||||
- property-based testing from schemas is already accepted and valuable
|
||||
- Python is feasible if APOPHIS enters through a spec-based testing layer, not by immediately building deep framework hooks everywhere
|
||||
|
||||
### 4.3 Go
|
||||
|
||||
- **kin-openapi**: mature OpenAPI parsing and request/response validation primitives
|
||||
- **oapi-codegen**: server/client generation and middleware integration around OpenAPI
|
||||
- **Huma**: Go framework centered on OpenAPI and JSON Schema
|
||||
|
||||
What this validates:
|
||||
|
||||
- Go has strong OpenAPI infrastructure already
|
||||
- APOPHIS should not try to replace that infrastructure
|
||||
- a Go expansion should differentiate on behavioral contracts, generative testing, and diagnostics rather than basic schema validation
|
||||
|
||||
## 5. Feasibility Ranking
|
||||
|
||||
### 5.1 Express
|
||||
|
||||
Feasibility: **high**
|
||||
|
||||
Why:
|
||||
|
||||
- same language and runtime
|
||||
- same property-based tooling can be reused
|
||||
- same outbound mocking and deterministic machinery can mostly stay in Node
|
||||
- same CLI can target Express services without much product change
|
||||
|
||||
Main work:
|
||||
|
||||
- route discovery strategy
|
||||
- spec acquisition strategy
|
||||
- middleware-phase mapping for observe mode
|
||||
- local test execution path if no `inject()` equivalent is standardized
|
||||
|
||||
Recommendation:
|
||||
|
||||
- make Express the first non-Fastify adapter
|
||||
|
||||
### 5.2 Python
|
||||
|
||||
Feasibility: **medium**, but only with narrower scope
|
||||
|
||||
Why:
|
||||
|
||||
- strong OpenAPI ecosystem already exists
|
||||
- property-based testing from schema has prior art
|
||||
- FastAPI and Connexion are good initial targets because they are already spec-first or OpenAPI-native
|
||||
|
||||
Constraints:
|
||||
|
||||
- current APOPHIS engine is Node-shaped
|
||||
- runtime hooks and lifecycle assumptions do not transfer directly
|
||||
- full feature parity would likely require a native implementation or a language-neutral service protocol
|
||||
|
||||
Recommendation:
|
||||
|
||||
- enter Python through CLI/spec mode first
|
||||
- consider a native adapter only after proving demand in one framework such as FastAPI
|
||||
|
||||
### 5.3 Go
|
||||
|
||||
Feasibility: **medium-low** in the near term
|
||||
|
||||
Why:
|
||||
|
||||
- the OpenAPI ecosystem is mature
|
||||
- the framework ecosystem is more fragmented in behavior and metadata patterns
|
||||
- typed codegen and middleware are already strong in Go, so APOPHIS has to bring something more specific than validation
|
||||
|
||||
Constraints:
|
||||
|
||||
- current JS/Node runtime assumptions do not transfer cleanly
|
||||
- property-based and stateful testing experience would need careful native design
|
||||
- deep native adapter work is much closer to a new product than a thin port
|
||||
|
||||
Recommendation:
|
||||
|
||||
- defer native Go work until a framework-neutral route manifest and CLI/test protocol are stable
|
||||
|
||||
## 6. The Architecture Split Required
|
||||
|
||||
This expansion is only realistic if APOPHIS is explicitly split into:
|
||||
|
||||
### 6.1 Core
|
||||
|
||||
Framework-neutral pieces:
|
||||
|
||||
- APOSTL parser/evaluator
|
||||
- contract extraction/inference
|
||||
- route/operation model
|
||||
- request generation rules
|
||||
- runners for verify and qualify
|
||||
- result shaping, deduplication, replay artifacts
|
||||
- chaos and qualification logic
|
||||
|
||||
### 6.2 Adapter layer
|
||||
|
||||
Framework-specific pieces:
|
||||
|
||||
- route discovery
|
||||
- spec acquisition
|
||||
- in-process request execution or test client integration
|
||||
- runtime observe integration
|
||||
- cleanup behavior
|
||||
|
||||
### 6.3 CLI and remote execution layer
|
||||
|
||||
A language-neutral layer that can:
|
||||
|
||||
- load OpenAPI documents
|
||||
- select operations and routes
|
||||
- generate requests from schema
|
||||
- hit a live server or a framework-specific test adapter
|
||||
- evaluate APOPHIS behavioral contracts on observed responses
|
||||
|
||||
This layer is the bridge to Python and Go without requiring a full immediate reimplementation.
|
||||
|
||||
## 7. The Minimal Adapter Contract
|
||||
|
||||
To support more than Fastify, APOPHIS needs a small explicit host contract.
|
||||
|
||||
Conceptually, an adapter should provide:
|
||||
|
||||
```ts
|
||||
interface ApophisAdapter {
|
||||
listRoutes(): RouteManifest[]
|
||||
execute(request: ExecutableRequest): Promise<EvalContext>
|
||||
getSpec?(): Record<string, unknown>
|
||||
installObserveMode?(opts: ObserveOptions): Promise<void> | void
|
||||
cleanup?(): Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
And for cross-language operation, a language-neutral manifest should exist:
|
||||
|
||||
```ts
|
||||
interface RouteManifest {
|
||||
method: string
|
||||
path: string
|
||||
schema?: Record<string, unknown>
|
||||
annotations?: {
|
||||
requires?: string[]
|
||||
ensures?: string[]
|
||||
category?: string
|
||||
timeout?: number
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Without this seam, “support another framework” means spreading Fastify assumptions into more code.
|
||||
|
||||
## 8. The Best Near-Term Product Strategy
|
||||
|
||||
The best expansion strategy is **not** “port the Fastify plugin everywhere.”
|
||||
|
||||
It is:
|
||||
|
||||
1. keep Fastify as the deepest adapter
|
||||
2. make the CLI/spec mode the main portability wedge
|
||||
3. use adapters only where the ergonomics justify it
|
||||
|
||||
This aligns with prior art like Dredd and Schemathesis and avoids competing directly with full spec-first frameworks.
|
||||
|
||||
## 9. Proposed Roadmap
|
||||
|
||||
### Phase 0: Internal Core Extraction
|
||||
|
||||
Goal:
|
||||
|
||||
- make the adapter boundary explicit without changing outward behavior yet
|
||||
|
||||
Work:
|
||||
|
||||
- rename Fastify-shaped interfaces to neutral names
|
||||
- define a route manifest model
|
||||
- define an execution adapter contract
|
||||
- move route discovery behind an adapter boundary
|
||||
- build adapter conformance tests
|
||||
|
||||
Exit criteria:
|
||||
|
||||
- current Fastify implementation passes through the new adapter seam
|
||||
- runners no longer need direct Fastify concepts in their public types
|
||||
|
||||
### Phase 1: CLI Spec Mode
|
||||
|
||||
Goal:
|
||||
|
||||
- support `verify` and selected `qualify` workflows against **any running HTTP server** using OpenAPI plus APOPHIS extensions
|
||||
|
||||
Scope:
|
||||
|
||||
- input: OpenAPI document URL or file
|
||||
- target: base URL of running service
|
||||
- output: APOPHIS verify report, replay artifacts, seeds
|
||||
|
||||
Supports initially:
|
||||
|
||||
- verify
|
||||
- variants
|
||||
- selected qualify modes like scenario and protocol flows
|
||||
|
||||
Does not support initially:
|
||||
|
||||
- native runtime observe middleware
|
||||
- in-process cleanup hooks
|
||||
- full framework lifecycle integration
|
||||
|
||||
Why this phase matters:
|
||||
|
||||
- it gives immediate value to Express, Python, and Go without deep adapter work
|
||||
- it measures cross-language demand before native adapter investment
|
||||
|
||||
Exit criteria:
|
||||
|
||||
- APOPHIS can run useful spec-driven checks against a live OpenAPI-described service from the CLI alone
|
||||
|
||||
### Phase 2: Express Adapter
|
||||
|
||||
Goal:
|
||||
|
||||
- deliver the first non-Fastify in-process integration in the same language runtime
|
||||
|
||||
Scope:
|
||||
|
||||
- Express route discovery via registered manifest or explicit spec file
|
||||
- local verify path
|
||||
- limited observe middleware path if safe
|
||||
|
||||
Design note:
|
||||
|
||||
- Express may require explicit spec or explicit route manifest rather than introspecting route-local schemas the way Fastify does
|
||||
|
||||
Exit criteria:
|
||||
|
||||
- one real Express sample app can run `verify`
|
||||
- documentation supports the first successful `verify` setup as directly as the Fastify guide
|
||||
|
||||
### Phase 3: Python CLI-First Support
|
||||
|
||||
Goal:
|
||||
|
||||
- support Python services without a native Python APOPHIS runtime yet
|
||||
|
||||
Scope:
|
||||
|
||||
- documented FastAPI and Connexion integration through spec mode
|
||||
- optional hooks or fixtures for auth/test data setup
|
||||
- replayable verify runs in CI
|
||||
|
||||
Exit criteria:
|
||||
|
||||
- one reference FastAPI app passes APOPHIS CLI-driven verification
|
||||
- the product story is useful without native middleware or runtime hooking
|
||||
|
||||
### Phase 4: Go CLI-First Support
|
||||
|
||||
Goal:
|
||||
|
||||
- support Go services via spec mode and existing OpenAPI middleware ecosystem
|
||||
|
||||
Scope:
|
||||
|
||||
- reference integrations with `kin-openapi` or `oapi-codegen` based services
|
||||
- verify-focused first
|
||||
- qualify later only for flows with identified adoption demand and reproducible CI value
|
||||
|
||||
Exit criteria:
|
||||
|
||||
- one reference Go service passes CLI-driven verification
|
||||
|
||||
### Phase 5: Decide Whether Native Python or Go Adapters Are Worth It
|
||||
|
||||
This should be a market and adoption decision, not an assumption.
|
||||
|
||||
Only proceed if:
|
||||
|
||||
- CLI/spec mode is proving useful in those ecosystems
|
||||
- users want runtime observe or deeper in-process integration
|
||||
- APOPHIS can differentiate from ecosystem-native validators and codegen tools
|
||||
|
||||
## 10. What Not To Do
|
||||
|
||||
Do not:
|
||||
|
||||
- promise feature parity across Fastify, Express, Python, and Go immediately
|
||||
- try to own request validation stacks that each ecosystem already solved well
|
||||
- tie multi-language expansion to full runtime hooks on day one
|
||||
- port Fastify-specific docs language directly into other ecosystems
|
||||
- assume route-local annotation ergonomics exist outside Fastify without explicit manifests
|
||||
|
||||
## 11. Recommended Scope Boundary
|
||||
|
||||
The feasible product boundary is:
|
||||
|
||||
- APOPHIS as a behavioral contract engine and qualification CLI for OpenAPI-described services
|
||||
- APOPHIS adapters where implementation cost is low and CI value is clear
|
||||
|
||||
The infeasible near-term boundary is:
|
||||
|
||||
- APOPHIS as a fully native, feature-parity runtime plugin across all major JS, Python, and Go frameworks
|
||||
|
||||
## 12. Recommendation
|
||||
|
||||
Current recommendation:
|
||||
|
||||
1. do not pursue multi-language expansion now
|
||||
2. keep APOPHIS focused on Node and Fastify
|
||||
3. continue with CLI, docs, first-signal flow, and `verify / observe / qualify` simplification first
|
||||
4. revisit Express only if a cheap adapter seam emerges after the Fastify redesign stabilizes
|
||||
|
||||
Deferred roadmap, if revisited later:
|
||||
|
||||
1. extract core and adapter seam
|
||||
2. build CLI/spec mode
|
||||
3. ship Express next
|
||||
4. validate demand through Python and Go via CLI first
|
||||
5. only then decide whether native adapters are worth it
|
||||
|
||||
Anything broader should be treated as a major platform strategy, not a routine extension of the current Fastify product.
|
||||
Reference in New Issue
Block a user