API-First Standard¶
Model¶
OWNER PROJECTS
│
OpenAPI / AsyncAPI
JSON Schema
│
▼
API SCHEMA REGISTRY
│
┌────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
VALIDATE ENRICH VERSION
│
Overlays
│
▼
COMPILE
│
┌────────┬───────┼────────┬────────────┐
▼ ▼ ▼ ▼ ▼
Catalog Types Arazzo MCP Control
│
│
┌──────────┼───────────┐
▼ ▼ ▼
Cedar Orbit Gas City
│ │ │
└──────────┼───────────┘
▼
AGENTS
Axioms¶
Registry ≠ runtime
Registry ≠ policy engine
Registry ≠ orchestrator
Registry ≠ source-code authority
Registry = CONTRACT COMPILER + DISCOVERY PLANE
Owners own contracts. The registry validates, enriches, versions, and compiles. It does not hold the authoritative source for service specs — owner projects do.
Do not make api-schema-registry the place humans maintain every service's OpenAPI source. That violates: Reuse the owner. Fix the owner. Extend the owner. Do not duplicate the owner.
Contract-First Design¶
- OpenAPI 3.1 → 3.2 — All HTTP APIs declare contracts via OpenAPI 3.1. Migrate to 3.2 when value is gained (nested tags,
$self, Arazzo 1.1 interop) — not as a mass rewrite. - Owner project is source-of-truth — Specs live in the owning service repository. The registry holds provenance references, not copies.
- Specification-driven — Implementation and clients generate from the contract, never the reverse.
- Versioning — Breaking changes increment the API version in the contract before deployment. CI gates on breaking-change detection.
Contract Family¶
The registry accepts five contract types:
| Type | Version | Role |
|---|---|---|
| OpenAPI | 3.1.0 (→ 3.2 targeted) | HTTP operation surface |
| AsyncAPI | 3.x | Event / SSE / webhook surface |
| Arazzo | 1.0.1 | Machine-readable multi-step workflows |
| JSON Schema | Draft 2020-12 | Canonical payload definitions |
| Overlay | 1.1 | Non-invasive enrichment (Cedar, MCP, agent views) |
Do not add a second spec format without updating this table and the registry compiler.
Maturity Buckets¶
Every registered spec is classified:
| Bucket | Meaning |
|---|---|
OWNER-AUTHORITATIVE |
Spec lives in service owner's repo; registry holds provenance reference |
REGISTRY-COPIED |
Spec authored inside registry; must migrate to owner project |
GENERATED |
Compiler / export output (Drupal JSON:API, bundle artifacts) |
EXTERNAL/UPSTREAM |
Third-party or vendor spec |
LEGACY/UNKNOWN |
Origin unclear — open a bead and investigate |
Target state: all Bluefly-owned services are OWNER-AUTHORITATIVE. REGISTRY-COPIED is debt.
x-bluefly-control Vocabulary¶
Every OpenAPI spec registered in the registry carries a top-level x-bluefly-control block:
x-bluefly-control:
serviceId: <stable-slug>
tier: platform | contrib-ready | demo | legacy
maturityBucket: OWNER-AUTHORITATIVE | REGISTRY-COPIED | GENERATED | EXTERNAL/UPSTREAM | LEGACY/UNKNOWN
provenance:
project: <gitlab-group/project>
path: <path/to/openapi.yaml>
ref: release/v0.1.x
capabilities: # controlled vocabulary — see api-schema-registry openapi/vocabulary/capabilities.yaml
- capability: <vocab-term>
action: provide | consume | depend
provides:
- event: <event.name> # async events this service produces
dependsOn:
- serviceId: <other-service>
cedarNamespace: <Namespace>
overlays:
- context: cedar | mcp | agent | internal | public
path: openapi/<service>/overlays/<context>.overlay.yaml
status: active | todo
Per-operation Cedar binding (required on every operation):
x-bluefly-cedar:
action: "<Namespace>::Action::\"<ActionName>\""
resource: "<Namespace>::<ResourceType>"
principalTypes: [BluAgent, BetaUser, Admin]
x-bluefly-mcp:
exposure: allowed | forbidden | internal
Capability Vocabulary¶
Capability terms are controlled. All capabilities[] values must appear in openapi/vocabulary/capabilities.yaml in the api-schema-registry repo. Do not add freeform strings to specs.
MCP Exposure Policy¶
Not every operation is exposed as an MCP tool. Hard rule.
x-bluefly-mcp.exposure controls visibility per operation:
- allowed — may appear in agent toolsets
- forbidden — never in toolsets (admin, webhook, destructive)
- internal — registry/CI use only
Dynamic agent toolset generation: query capability graph → filter allowed → filter by Cedar principalTypes → score by relevance → return ≤25 operations. Never 8,000.
Endpoint Discovery¶
Endpoints are discovered through:
- OpenAPI contract metadata (servers[])
- Service registry (service-catalog.json — compiler output, never hand-edited)
- Gas City service protocol
Never hardcoded in client implementations or documentation.
Generated Clients¶
From each published spec, generate:
| Output | Tool |
|---|---|
| TypeScript types | openapi-typescript |
| PHP types | openapi-generator (php-nextgen) |
| Zod schemas | openapi-zod-client |
| MCP tool schema | redocly introspect-mcp + mcp Overlay |
Generated artifacts are published to the GitLab Package Registry. They are not committed to source trees.
Stable Contract URIs¶
Published contracts resolve at:
https://api.blueflyagents.com/contracts/openapi/<service-id>/<version>/openapi.yaml
https://api.blueflyagents.com/contracts/asyncapi/<service-id>/<version>/asyncapi.yaml
https://api.blueflyagents.com/contracts/arazzo/<workflow-id>/<version>/workflow.arazzo.yaml
https://api.blueflyagents.com/schemas/<schema-id>/<version>/schema.json
CI Contract Lifecycle¶
Every MR touching openapi/ must pass:
LINT_ERRORS=0 redocly lint --format=github-actions
BUNDLE_ERRORS=0 redocly bundle (no $ref cycles)
AGGREGATE_ERRORS=0 npm run aggregate → 0 failures
TEST_PASS=all repo test suite
NO_WORKSTATION_PATHS=0 GOV-PATH-PRIV-001
CEDAR_BINDINGS_VALID every operation has x-bluefly-cedar OR is internal
ARAZZO_VALID redocly lint on all workflows/
CONTRACT_SCORE>=50 maturity score (contrib-ready minimum)
BREAKING_CHANGE_GATE=PASS redocly diff — breaking change requires label + version bump
All CI jobs live in gitlab_components. No per-repo duplication.
No Hardcoded Paths or Local Dependencies¶
Forbidden:
- ~ workstation paths in committed source (GOV-PATH-PRIV-001)
- Relative symlinks as deployment dependencies
- npm link or file: dependencies in deployed packages
Permitted:
- [PROJECT-ROOT] placeholder in generated metadata
- Environment variables for configuration discovery
- Repository-relative documentation paths