# Openapi — Systems Deep Dive

> The `libs/openapi/` area: a single Nx library, `@oshun/openapi`, that owns the
> platform's OpenAPI surface — loading, validating, generating, and
> drift-checking the REST specs (and the typed clients) for every Oshun domain.

## What this area is

`libs/openapi/` is **one** Nx project — `@oshun/openapi`
(`libs/openapi/project.json`, `sourceRoot` `libs/openapi/src`) — not a cluster.
It is the place where the monorepo's REST contracts stop being scattered
hand-written YAML and become a managed, generated, drift-checked artifact set.
The package is `private`, ESM-only (`package.json` `"type": "module"`, version
`0.1.0`), and its description is authoritative: "OpenAPI specifications for
Oshun REST APIs."

The library has four jobs, all visible in its source. First, **loading**:
`src/utils/loader.ts` reads and parses the canonical YAML specs under
`src/specs/` (and the V2 surface under `v2/`) into `OpenAPIV3_1.Document`
objects, and can `mergeSpecs(...)` several into one. Second, a **registry**:
`src/utils/registry.ts` declares the `ApiDomain` union (tara, arete, veritas,
lilith, yemaya, isis, sophia, hathor, bellona, calliope, nyx, nisaba, metis, v2,
v3, oshun-bff, shared), the `SPEC_PATHS` map of every spec file, and a
`SPEC_REGISTRY` of per-spec `SpecMetadata` (name, version, basePath, tags), plus
`extractEndpoints` / `extractSchemas` helpers that walk a parsed document.
Third, **generation**: `src/oshun-v1/spec-builder.ts` builds OpenAPI 3.1
documents directly from Zod contracts rather than from hand-edited YAML. Fourth,
**drift detection**: `scripts/drift-check.ts` compares each canonical YAML
against the openapi-typescript-generated TS mirror in `src/generated/`.

The generation path is the most domain-specific part.
`buildOshunV1SpecArtifacts()` reads `V1_OBJECT_PERSISTENCE_CONTRACTS` and
`V1_ENUM_PERSISTENCE_CONTRACTS` from `@oshun/persistence` plus the
`DOMAIN_REGISTRY` from `@oshun/domain-registry`, and for each of the six V1 API
domains (`tara`, `arete`, `veritas`, `nyx`, `nisaba`, `metis`) emits a
per-domain service spec, then a consolidated `oshun-bff` spec. Each object
contract is converted to JSON Schema with `z.toJSONSchema(...)` (`$schema`
stripped) and expanded into a uniform CRUD surface — `list` / `create` / `get` /
`upsert` / `tombstone` operations, `bearerAuth` security, cursor pagination
(`LimitParam` / `CursorParam`), and shared `ErrorResponse` / `PageInfo` /
`TombstoneResponse` components. The BFF spec re-uses the same builder with
`componentNameMode: 'prefixed'` and the registry's `bff-base-path`, so the BFF
routes and the per-domain routes describe the same schemas under different
prefixes. This is why a contract change is a single source edit, not an N-place
YAML rewrite.

Alongside the V1 generator there are sibling generators driven from the
`package.json` scripts and Nx targets: `generate-v3-spec.ts` /
`generate-v3-clients.ts` (the V3 `v3.yaml` and the typed clients in
`src/v3-clients/`), `generate-calliope-spec.ts`, `generate-docs.ts` (Redoc HTML
under `docs/`), and the validators `validate.ts` / `validate-v3-spec.ts`. The Nx
project exposes these as `openapi:gen`, `generate:oshun-v1-specs(:check)`,
`generate:oshun-v1-clients(:check)`, `generate:v3(:check)`, `validate:v3`, and
an `openapi:validate` target that lints `src/specs/` with `@redocly/cli`.

## How it fits the wider system

`@oshun/openapi` sits downstream of the contract libraries and upstream of every
REST consumer. Its hard dependency edges (`package.json`) are
`@oshun/contracts`, `@oshun/persistence`, `@oshun/domain-registry`, and
`@calliope/core` — it reads their Zod contracts and domain metadata as the
canonical source and turns them into specs. It does **not** sit on the request
path: nothing here serves HTTP. Instead it produces three kinds of artifact that
others consume. Domain services and the BFF use the generated specs (and the
`:check` targets in CI) to keep their routes honest against the contracts.
TypeScript callers import the typed fetch clients from
`@oshun/openapi/v3-clients` (e.g. `tara-studio`, `saraswati-stage`,
`lilith-platform`, `lilith-commons`) which share the `v3JsonRequest` /
`V3ApiError` transport in `src/v3-clients/base.ts`. And reviewers/docs tooling
read the rendered Redoc pages and `openapi.yaml` files under `docs/`. The drift
checker is the guardrail that ties the three together: when a spec is edited but
its generated mirror is not regenerated, `drift:check` exits non-zero rather
than letting the contract and the client types silently diverge.

## Entity reference

### @oshun/openapi

The single library of this area (`libs/openapi`, project name `@oshun/openapi`,
`sourceRoot` `libs/openapi/src`). It is a real, implemented OpenAPI toolkit —
not a scaffold — with four working surfaces: a YAML **loader/merger**
(`src/utils/loader.ts`), a **spec registry** of domains and metadata
(`src/utils/registry.ts`, including the `ApiDomain` union and `SPEC_REGISTRY`),
a contracts-to-OpenAPI **generator** (`src/oshun-v1/spec-builder.ts`, which
turns `@oshun/persistence` V1 Zod contracts + `@oshun/domain-registry` metadata
into per-domain and BFF OpenAPI 3.1 documents with a uniform
list/create/get/upsert/ tombstone CRUD shape via `z.toJSONSchema`), and a
**drift detector** (`scripts/drift-check.ts`) that diffs canonical YAML in
`src/specs/` against the openapi-typescript mirrors in `src/generated/`. Its
public barrel (`src/index.ts`) re-exports the loader functions, the registry
symbols and `SpecMetadata`/`ApiDomain` types, the `openapi-types` document
types, and the `buildOshunV1SpecArtifacts` / `getOshunV1ClientResources` /
`getOshunV1ApiDomains` builder API. It also ships generated,
dependency-injectable typed fetch clients under `src/v3-clients/` (shared
transport `v3JsonRequest` + `V3ApiError` in `base.ts`) and rendered Redoc docs
under `docs/`. The Nx project wires the generation and validation flows as
targets (`openapi:gen`, `openapi:validate` via `@redocly/cli`,
`generate:oshun-v1-specs(:check)`, `generate:oshun-v1-clients(:check)`,
`generate:v3(:check)`, `validate:v3`); the `test` target is `passWithNoTests`,
though real specs do exist (`src/openapi.spec.ts`,
`scripts/drift-check.spec.ts`, `src/v3-clients/__tests__/client.spec.ts`). The
`libs/openapi/nyx/README.md` note is just a pointer to the canonical Nyx spec at
`docs/nyx/openapi.yaml`, not a separate package.
