# @concordia/orchestrator

Fastify (TypeScript) gateway for the Concordia cooperative mediation and
negotiation stack (Phase 179).

## Stack decision — Fastify over Python

Phase 179 `179.2.4.5` requires an explicit choice between a TypeScript Fastify
service and a Python FastAPI service for `apps/concordia/orchestrator/`. We
chose Fastify for this gateway.

Rationale:

- **Repo convention.** Every existing gateway-style service in this monorepo
  (`apps/hestia/api`, `apps/arete/api`, `apps/lilith/svc-*`) runs on Fastify.
  Adding a new Python gateway here would fragment the operational surface
  (logging, deployments, docker, middleware) without corresponding benefit.
- **Contract alignment.** The Concordia OpenAPI contract is generated into
  TypeScript clients under `libs/openapi/src/generated/concordia.ts` via
  `@oshun/codegen`. The orchestrator can consume the same types without a
  cross-language boundary.
- **Streaming RPC homogeneity.** `libs/proto/src/concordia/concordia.proto` is
  generated for `grpc-js` via ts-proto. Hosting the orchestrator on Node keeps
  the gRPC server and REST gateway in the same runtime.
- **Python lives in workers, not the gateway.** Phase 179 explicitly splits
  preference learning, evaluation, agent simulation, and ML experimentation into
  Python (≈30%). Those run as separate workers (future) that the orchestrator
  calls via HTTP/gRPC. Keeping the gateway in TypeScript does not close the door
  on Python — it keeps the Python footprint concentrated where it's actually
  justified.
- **Solver sidecars.** CP-SAT / MILP kernels (tasks 179.4.2.4+) and NSGA-II /
  MAP-Elites search kernels (179.4.2.2+) will live as Rust or Python sidecar
  services. The orchestrator is the coordinating layer, not the numerics engine.

## Repo-convention surfaces wired up

| Surface           | Path                                      | Notes                                                                                      |
| ----------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------ |
| Liveness          | `GET /health`                             | Always 200 while the process is running.                                                   |
| Readiness         | `GET /health/ready`                       | Runs dependency checks (OpenAPI spec availability today; DB / Redis / workers later).      |
| Startup           | `GET /health/startup`                     | Readiness cached for 30s to avoid boot storms.                                             |
| OpenAPI (raw)     | `GET /openapi.yaml`                       | Serves `libs/openapi/src/specs/concordia/concordia-api.yaml` directly.                     |
| OpenAPI (parsed)  | `GET /openapi.json`                       | Parsed JSON form of the same spec.                                                         |
| OpenAPI metadata  | `GET /openapi/metadata`                   | Title / version / description / path count for service registries.                         |
| Service discovery | `GET /.well-known/concordia-orchestrator` | Registration payload — serviceId, advertised base URL, tags, capabilities.                 |
| Discovery alias   | `GET /service/discovery`                  | Same payload at a convention path for internal registries.                                 |
| Register upstream | `POST /service/discovery/register`        | POSTs the registration to `SERVICE_REGISTRY_URL` when configured; no-op in local dev / CI. |

## Nx / project integration

- `project.json` declares `build`, `dev`, `start`, `lint`, `test`, and
  `typecheck` targets using `nx:run-commands` — aligned with `apps/hestia/api`
  and `apps/arete/api`.
- `tsconfig.json` uses `NodeNext` module resolution with `strict: true`,
  matching every other gateway service.
- `vitest.config.ts` runs Node environment tests from `__tests__/` and `src/`.

## Configuration

Environment variables (all optional, sane defaults for local dev):

| Variable                        | Default                                                           | Purpose                                                   |
| ------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------- |
| `HOST`                          | `0.0.0.0`                                                         | Bind address.                                             |
| `PORT`                          | `8090`                                                            | Listen port.                                              |
| `NODE_ENV`                      | `development`                                                     | Enables pino-pretty in development.                       |
| `LOG_LEVEL`                     | `info`                                                            | Pino log level.                                           |
| `CONCORDIA_OPENAPI_PATH`        | Resolves to `libs/openapi/src/specs/concordia/concordia-api.yaml` | Path to the spec that `/openapi.*` serves.                |
| `CONCORDIA_SERVICE_ID`          | `concordia-orchestrator-primary`                                  | Service identity advertised to discovery registries.      |
| `CONCORDIA_ADVERTISED_BASE_URL` | `http://${HOST}:${PORT}`                                          | URL that other services should use to reach the gateway.  |
| `CONCORDIA_DISCOVERY_TAGS`      | `mediation,negotiation,orchestrator`                              | Comma-separated tags stamped onto the discovery document. |
| `SERVICE_REGISTRY_URL`          | _(unset)_                                                         | Optional registry to POST registrations to on boot.       |

## Docker

`Dockerfile` builds a minimal Node 20 Alpine image, adds `tini` for signal
handling, and exposes `8090`. The `HEALTHCHECK` hits `/health` so container
orchestrators can detect stalled processes without depending on external probes.

## Next steps

`179.3`–`179.4` add case / intake / preference / search routes behind this
gateway. `179.5.5.3` adds the kill-switch and feature flags. `179.7` wires the
domain integrations. The scaffold in this directory is the substrate those tasks
plug into.
