Open Foundry publishes three machine-readable API contracts. These are generated
from the merged schema at build time and attached to every GitHub release,
alongside a CycloneDX SBOM and a build provenance attestation (see
SECURITY.md).
| File | Format | Covers |
|---|---|---|
openapi.yaml |
OpenAPI 3.0.3 | REST endpoints — CRUD, actions, filters, pagination |
schema.graphql |
GraphQL SDL | Full GraphQL API — queries, mutations, subscriptions |
asyncapi.yaml |
AsyncAPI 2.6.0 | WebSocket subscription channels and event payloads |
- Release assets — attached to every
v*tagged release on GitHub. The release also carriessbom.cyclonedx.json; artifacts are attested, sogh attestation verify <file> --repo syzygyhack/open-foundryconfirms they were built by the release workflow from that tag. - Local generation —
pnpm --filter @openfoundry/api spec:allwrites all three topackages/api/spec/ - Live endpoint —
GET /api/v1/openapi.jsonreturns the OpenAPI spec from the running server
# Build first (CLIs run from dist/)
pnpm run build
# Generate all three
pnpm --filter @openfoundry/api spec:all
# Or individually
pnpm --filter @openfoundry/api spec:openapi spec/openapi.yaml
pnpm --filter @openfoundry/api spec:graphql spec/schema.graphql
pnpm --filter @openfoundry/api spec:asyncapi spec/asyncapi.yamlThe specs reflect whichever domain packs are configured via DOMAIN_PACKS_DIR,
DOMAIN_PACKS, and DOMAIN_PACKS_EXTRA_DIRS. To generate for a specific pack
combination:
DOMAIN_PACKS=core,nhs-acute pnpm --filter @openfoundry/api spec:allThe generated specs cover all loaded packs. If you load packs core +
nhs-acute + my-custom-pack, the OpenAPI spec will contain routes for every
object type and action across all three.
To generate a spec for a subset of packs, set DOMAIN_PACKS before running the
dump CLI.
openapi-generator-cli generate \
-i openapi.yaml \
-g python \
-o ./generated/python \
--additional-properties=packageName=openfoundry# Using openapi-generator
openapi-generator-cli generate \
-i openapi.yaml \
-g rust \
-o ./generated/rust
# Or using progenitor (Oxide's Rust-native generator)
# Add to build.rs — see Phase 1 of the SDK plannpx graphql-codegen \
--schema schema.graphql \
--generates ./generated/types.tsnpx @asyncapi/generator asyncapi.yaml @asyncapi/typescript-template -o ./generated/eventsReleased spec metadata is stamped with the platform version from the root
package.json; it does not have an independent version track. API compatibility
therefore follows the platform's SemVer policy. While the platform is pre-1.0,
breaking contract changes require a minor release and compatible fixes use a
patch release.
The spec round-trip test (src/__tests__/spec-roundtrip.test.ts) validates:
- All OpenAPI
$refpointers resolve to defined component schemas - Every path operation has at least one response defined
- GraphQL SDL parses without errors and contains Query, Mutation, Subscription roots
- AsyncAPI channels have valid payloads with required ChangeEvent fields
- All three specs cover the same set of object types (cross-spec consistency)
Run the validation:
pnpm --filter @openfoundry/api test spec-roundtripThe .github/workflows/release.yml workflow runs on every v* tag push:
- Require the full
CIworkflow to have succeeded for the exact tagged commit as amainbranch push. - Verify the tag, package, Helm chart, default image tag, changelog, and install
example all name the same version, and that the commit remains on
main. - Install frozen dependencies, build, and generate the API contracts via
spec:all. - Build and push the service images and versioned Helm chart, then generate the image-digest list and CycloneDX SBOM.
- Attach the contracts, chart, digests, and SBOM to a draft GitHub release, attest their provenance, and only then publish the release.
Tests are not rerun in the release job; the exact-SHA CI gate is authoritative
and includes the complete test, integration, Helm, image-build, and security
matrix. The maintainer checklist is in
CONTRIBUTING.md.