Skip to content

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

  1. 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.
  2. Owner project is source-of-truth — Specs live in the owning service repository. The registry holds provenance references, not copies.
  3. Specification-driven — Implementation and clients generate from the contract, never the reverse.
  4. 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