Skip to content

Platform Compiler — Contract Model

Document: 2 of 4 Status: Canonical Depends on: Core Object Model (arch_01) Required by: Projection Model, Receipt & Provenance Model


Purpose

This document defines how contracts are structured, stored, versioned, and consumed by the Platform Compiler. It establishes the strict boundary between what is authored (owned by Bluefly), what is imported (owned by external authorities), and what is generated (owned by the compiler). It also retires ai.json as a source of truth.


The Schema / Instance Distinction

Schemas define shape. Objects instantiate schemas.

These are not the same thing and must not live in the same place.

contracts/            ← Schema definitions. Humans author these.
objects/              ← Object instances conforming to those schemas.
providers/            ← External authority contracts. Imported, not authored.
generated/            ← Compiler output. Never authored or edited.

A Capability schema lives in contracts/. A specific capability like platform.capability.compliance is instantiated as an object in objects/capabilities/. The compiler reads the schema to validate the object, then reads the object to generate projections.


Registry Directory Structure

api-schema-registry/
│
├── contracts/
│   ├── schemas/
│   │   ├── authority.schema.yaml
│   │   ├── capability.schema.yaml
│   │   ├── contract.schema.yaml
│   │   ├── deployment.schema.yaml
│   │   ├── provider.schema.yaml
│   │   ├── runtime.schema.yaml
│   │   ├── platform.schema.yaml
│   │   ├── tunnel.schema.yaml
│   │   ├── projection.schema.yaml
│   │   └── receipt.schema.yaml
│   │
│   └── bluefly/                        ← Bluefly-authored interface contracts
│       ├── platform/
│       │   ├── compliance/
│       │   │   └── openapi.yaml
│       │   ├── authentication/
│       │   │   └── oidc.yaml
│       │   ├── agent-ui/
│       │   │   └── ag-ui.yaml          ← AG-UI protocol contract
│       │   ├── tool-access/
│       │   │   └── mcp.yaml            ← MCP protocol contract
│       │   ├── agent-federation/
│       │   │   └── a2a.yaml            ← A2A protocol contract
│       │   └── workflow-engine/
│       │       └── openapi.yaml
│       ├── ossa/
│       │   ├── agent-contract/
│       │   ├── agent-communication/
│       │   └── agent-discovery/
│       ├── portfolio/
│       │   ├── product/
│       │   ├── offering/
│       │   └── pack/
│       └── products/
│           ├── copaw/
│           ├── contractplane/
│           ├── drupl/
│           ├── contextcontrol/
│           ├── agentblu/
│           └── blutown/
│
├── objects/
│   ├── authorities/
│   │   ├── bluefly.yaml
│   │   ├── acquia.yaml
│   │   ├── google.yaml
│   │   ├── anthropic.yaml
│   │   ├── apple.yaml
│   │   └── ...
│   ├── capabilities/
│   │   ├── platform/
│   │   │   ├── compliance.yaml
│   │   │   ├── authentication.yaml
│   │   │   ├── agent-ui.yaml
│   │   │   ├── tool-access.yaml
│   │   │   ├── agent-federation.yaml
│   │   │   ├── workflow-engine.yaml
│   │   │   ├── mesh.yaml
│   │   │   ├── chat.yaml
│   │   │   ├── router.yaml
│   │   │   └── ...
│   │   └── products/
│   │       ├── copaw/
│   │       └── ...
│   ├── deployments/
│   │   ├── oracle/
│   │   │   ├── compliance.yaml
│   │   │   ├── authentication.yaml
│   │   │   ├── mesh.yaml
│   │   │   └── ...
│   │   ├── nas/
│   │   │   ├── storage.yaml
│   │   │   ├── npm-registry.yaml
│   │   │   └── ...
│   │   └── products/
│   │       ├── drupl/
│   │       └── ...
│   ├── runtimes/
│   │   ├── oracle-primary.yaml
│   │   ├── nas-primary.yaml
│   │   └── cloudflare-global.yaml
│   ├── platforms/
│   │   ├── oracle.yaml
│   │   ├── nas.yaml
│   │   └── cloudflare.yaml
│   └── tunnels/
│       ├── oracle-platform.yaml
│       ├── oracle-duadp.yaml
│       └── nas-platform.yaml
│
├── providers/
│   ├── acquia/
│   │   ├── provider.yaml               ← Provider metadata (required)
│   │   └── imports/
│   │       ├── source/
│   │       │   ├── manifest.yaml       ← Import provenance
│   │       │   └── openapi.yaml        ← Imported artifact (never modified)
│   │       └── cms/
│   │           ├── manifest.yaml
│   │           └── jsonapi.yaml
│   ├── anthropic/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── mcp/
│   │           ├── manifest.yaml
│   │           └── specification.yaml
│   ├── google/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── a2a/
│   │           ├── manifest.yaml
│   │           └── specification.yaml
│   ├── apple/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── appintents/
│   │           ├── manifest.yaml
│   │           └── schema.yaml
│   ├── cloudflare/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── openapi/
│   │           ├── manifest.yaml
│   │           └── openapi.yaml
│   ├── drupal/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── jsonapi/
│   │           ├── manifest.yaml
│   │           └── openapi.yaml
│   ├── kubernetes/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── crds/
│   ├── openai/
│   │   ├── provider.yaml
│   │   └── imports/
│   │       └── openapi/
│   └── opentelemetry/
│       ├── provider.yaml
│       └── imports/
│           └── otlp/
│
└── generated/                          ← Compiler output. Never edit.
    ├── catalog/
    │   ├── capabilities.json           ← All capability objects
    │   ├── deployments.json            ← All deployment objects with state
    │   ├── service-catalog.json        ← Service discovery catalog
    │   └── control-plane.json          ← Control plane map
    ├── indexes/
    │   ├── endpoints-index.json        ← Flat endpoint index (existing)
    │   ├── urls.json                   ← All service URLs by env (replaces ai.json)
    │   └── repository-metadata.json   ← Per-repo metadata
    ├── projections/
    │   ├── cloudflare/
    │   │   ├── tunnel-config.yml       ← Generated tunnel ingress
    │   │   └── dns-records.json        ← Generated DNS declarations
    │   ├── terraform/
    │   │   └── cloudflare/
    │   │       ├── tunnels.tf          ← Generated Terraform
    │   │       └── dns.tf
    │   ├── docker/
    │   │   └── oracle-compose.yml
    │   └── tailscale/
    │       ├── acl-policy.hujson
    │       └── nas-tunnel-config.yml
    └── types/
        └── *.types.ts                  ← Generated TypeScript (existing 65 files)

Provider Metadata

Every imported provider must have a provider.yaml at the provider root. The compiler reads this to understand the authority behind the contract.

# providers/acquia/provider.yaml
id: provider.acquia
authority: authority.acquia
name: Acquia
trust: vendor
licensing:
  type: commercial
  url: https://www.acquia.com/legal
contact: https://developers.acquia.com
refresh_cadence: quarterly
version_policy: track-major
imports:
  - name: source
    type: openapi
    source_url: https://...
    description: Acquia Source API
  - name: cms
    type: json-api
    source_url: https://...
    description: Acquia CMS JSON:API

Every imported artifact must have a manifest.yaml beside it:

# providers/acquia/imports/source/manifest.yaml
import: acquia.source
provider: provider.acquia
type: openapi
version: "3.1"
source_url: https://...
imported_at: 2026-07-14T00:00:00Z
imported_by: platform-compiler
hash: sha256:...
status: verified       # imported | verified | outdated | deprecated | removed
notes: >
  Imported from Acquia Developer Portal. Covers all Acquia Source API endpoints.
  Refresh quarterly or when upstream API version is bumped.

The compiler distinguishes imported contracts from authored contracts by reading these manifests. An imported contract whose status is outdated will emit a compiler warning. An imported contract whose hash does not match the file will fail validation.


Contract Types

The type field on a Contract object determines which component of the Compiler (which Reader + Normalizer) processes it.

Type Description Standard
openapi REST API contract OpenAPI 3.x
graphql GraphQL schema GraphQL SDL
asyncapi Event-driven API AsyncAPI 3.x
mcp Model Context Protocol Anthropic MCP
ag-ui Agent-User Interaction AG-UI Protocol
a2a Agent-to-Agent Google A2A
json-schema Data shape contract JSON Schema draft-07+
cedar Authorization policy Cedar Policy Language
opa Authorization / governance policy Rego
kubernetes-crd Kubernetes resource definition k8s CRD
gascity-pack Gas City capability pack Gas City Pack v2
terraform-module Infrastructure module Terraform 1.x
grpc-proto gRPC service definition Protocol Buffers 3
oidc Authentication / identity OpenID Connect

Versioning

Contracts are versioned semantically. The Compiler enforces compatibility:

Change Compatibility policy
Add optional field Backward compatible — no consumer migration
Add required field Breaking — consumer migration required
Remove field Breaking — consumer migration required
Rename path/operation Breaking — consumer migration required
Change field type Breaking — consumer migration required

Deprecated contract versions remain in the registry with stability: deprecated until all consumers have migrated. The Compiler will warn on consumption of a deprecated contract.


Retiring ai.json

ai.json is currently a hand-maintained service map used by config-loader.ts for URL resolution. It has no schema, no validation, and no compiler ownership. It is a fourth source of truth.

Migration:

  1. All services currently in ai.json become Deployment objects in objects/deployments/
  2. The compiler generates generated/indexes/urls.json from the Deployment objects
  3. config-loader.ts reads from generated/indexes/urls.json
  4. ai.json is removed from the repository

After migration, URL resolution flows: objects/deployments/*.yaml → Compiler → generated/indexes/urls.json → consumers.

No consumer reads deployment objects directly. No consumer reads ai.json. Everything reads from the generated index.


Existing OpenAPI Directory Migration

The current openapi/ directory conflates authored Bluefly contracts with imported vendor schemas. Migration is a rename + add manifests — no content changes.

Current path Authority Destination Notes
openapi/acquia-cms/ Acquia providers/acquia/imports/cms/ Add provider.yaml + manifest.yaml
openapi/acquia-source/ Acquia providers/acquia/imports/source/
openapi/drupal-cms-jsonapi/ Drupal providers/drupal/imports/jsonapi/
openapi/drupal-*/ Drupal providers/drupal/imports/*/
openapi/workflow-engine/ Bluefly contracts/bluefly/platform/workflow-engine/
openapi/agent-*/ Bluefly contracts/bluefly/platform/*/
openapi/ossa/ OSSA contracts/bluefly/ossa/
openapi/openstandardagents/ OSSA contracts/bluefly/ossa/
openapi/portfolio/ Bluefly contracts/bluefly/portfolio/
openapi/copaw/ Bluefly contracts/bluefly/products/copaw/
openapi/contractplane-*/ Bluefly contracts/bluefly/products/contractplane/
openapi/duadp/ DUADP (open standard) providers/duadp/
openapi/components/ Bluefly contracts/bluefly/platform/components/ shared $ref components

Migration proceeds only after the new directory structure is committed and CI is updated to read from new paths.


Invariants

  1. Nothing under generated/ is ever edited by a human.
  2. Nothing under providers/ is ever modified — only the manifest.yaml status field is updated.
  3. Every file under providers/*/imports/ has a corresponding manifest.yaml.
  4. Every provider has a provider.yaml.
  5. ai.json does not exist after migration is complete.
  6. objects/ conform to schemas defined in contracts/schemas/.
  7. Adding a Deployment object is the only way to expose a service — there is no other path.