13 KiB
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:
- extract a framework-neutral core inside the current Node codebase
- ship a CLI/spec-first mode that can hit any running server from an OpenAPI document
- validate the adapter seam with Express next
- 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:
- route discovery
- schema and annotation access
- test execution transport
- runtime middleware or hook semantics
- 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:
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:
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:
- keep Fastify as the deepest adapter
- make the CLI/spec mode the main portability wedge
- 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
verifyand selectedqualifyworkflows 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
verifysetup 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-openapioroapi-codegenbased 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:
- do not pursue multi-language expansion now
- keep APOPHIS focused on Node and Fastify
- continue with CLI, docs, first-signal flow, and
verify / observe / qualifysimplification first - revisit Express only if a cheap adapter seam emerges after the Fastify redesign stabilizes
Deferred roadmap, if revisited later:
- extract core and adapter seam
- build CLI/spec mode
- ship Express next
- validate demand through Python and Go via CLI first
- 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.