# API Domain Authoring Model v1

## Decision

API contracts remain published and generated as one canonical artifact per protocol:

- REST: `doc/api/openapi.draft.yaml`
- Events: `doc/api/asyncapi.draft.yaml`

Domain teams should not create externally versioned API files. Instead, domain-owned source fragments will be authored under:

- `doc/api/openapi/`
- `doc/api/asyncapi/`

The bundling tool validates those fragments and preserves the canonical artifacts consumed by codegen, CI, docs, and external consumers.

## Why

The platform is now large enough that a single contract file creates review noise across unrelated teams. We still need one generated contract because:

- client/server codegen is simpler and already wired to one input,
- API consumers should not have to understand internal service/domain boundaries,
- compatibility and lint gates are easier to enforce once per artifact,
- runtime deployment remains a single `cmd/api` BFF for now.

This model separates authoring ownership without splitting the public API surface.

For the broader team/resource ownership model behind this split, see `doc/architecture/AI_Factory_Team_Domain_Operating_Model_v1.md`.

## Authoring Layout

Each protocol directory has a `manifest.yaml`.

```text
doc/api/
  openapi.draft.yaml
  asyncapi.draft.yaml
  openapi/
    manifest.yaml
    domains/
      <domain>.yaml
  asyncapi/
    manifest.yaml
    domains/
      <domain>.yaml
```

The current manifests run in `canonical` mode. That means the canonical artifact remains the editable source while the toolchain and review model are introduced.

When a domain migrates to fragments, switch the manifest to `fragments` mode and provide:

- a root file containing shared metadata/security,
- domain fragments containing only owned `paths`/`components` or event channels/schemas,
- ownership metadata for each fragment.

## Ownership Rules

- One domain owns a path prefix or event subject family.
- Cross-domain shared schemas live in a shared fragment and are reviewed by platform maintainers.
- A fragment must not redefine a path, operation, component, channel, or message already owned by another fragment.
- Generated artifacts must be committed so CI and reviews can detect bundling drift.
- Codegen and contract validation continue to consume only the canonical generated artifacts.

## Route Code Layout

The BFF remains one binary, but route registration and handlers should be split by domain file:

- `cmd/api/routes.go`: top-level server wiring, public/bootstrap route registration, and legacy handlers not yet migrated.
- `cmd/api/routes_core_api.go`: authenticated core `/api/v1` public contract route registration. New product work should still move into owning domain route files rather than expanding this catch-all registrar.
- `cmd/api/routes_v3_readmodels.go`: v3 product read-model coordinator and shared helper/handler code not yet extracted.
- `cmd/api/routes_v3_readmodels_*.go`: v3 product read-model registration split by shell group or domain.
- Future domain files should follow `routes_<domain>.go`.

This is a code organization boundary, not a service extraction boundary.

For the v1 freeze and route modularization policy, see `doc/architecture/API_Route_Modularization_and_V1_Freeze_v1.md`.

## Migration Order

1. Add manifest and bundling checks while retaining canonical mode.
2. Split large route groups into domain files without behavior changes.
3. Move one low-risk OpenAPI domain to fragments and verify generated artifact drift checks.
4. Repeat per domain as ownership stabilizes.
5. Apply the same pattern to AsyncAPI event subject families.

## Validation

Run:

```bash
ruby scripts/api/bundle_contracts.rb --check
make codegen
bash scripts/ci/contracts_validate.sh
```
