# sales-api Kong routing/policy layer for the **sales** slice of `classic-models-api` (see `/Users/stephanetailland/git/classic-models-api`), split out per the DDD decomposition in `../kong-konnect-deployment-strategy.md`. The backend stays a single monolith — only Kong does the domain split. Structure mirrors `../payments-api`/`../customers-api` — single MCP route, not `../catalog-api`'s original two-route pattern (see `../STATUS.md` section 18). Two resources, both with a REST surface and MCP tools: - **`Order`** (single key `ordernumber`) — full CRUD + an `order-details` sub-resource (`GET /sales/v1/orders/{ordernumber}/order-details/`, mirrors the backend's own `@action` on `OrderViewSet`). - **`Orderdetail`** (**composite key** `ordernumber` + `productcode`, exposed as its own top-level resource — the backend does this too, not just nested under `Order`). | Route | Method | Backend path | |---|---|---| | `/sales/v1/orders/` | GET, POST | `/classic-models/api/v1/orders/` | | `/sales/v1/orders/{ordernumber}/` | GET, PUT, PATCH, DELETE | `/classic-models/api/v1/orders/{ordernumber}/` | | `/sales/v1/orders/{ordernumber}/order-details/` | GET | `/classic-models/api/v1/orders/{ordernumber}/order-details/` | | `/sales/v1/orderdetails/` | GET, POST | `/classic-models/api/v1/orderdetails/` | | `/sales/v1/orderdetails/{ordernumber}/{productcode}/` | GET, PUT, PATCH, DELETE | `/classic-models/api/v1/orderdetails/{ordernumber}/{productcode}/` | | `/sales-mcp` | GET, POST, DELETE | MCP streamable-http (tools call into the REST routes above) | ## Auth & MCP tool ACLs `openid-connect` on both surfaces (`sales-api` REST audience, `mcp-sales` MCP audience), RFC 8693 exchange chain MCP → `sales-api` → `classic-models-api`, same shape as every other domain. IdP: local Keycloak (`https://keycloak.sttlab.local/realms/classic-models`). MCP write-tool ACLs (`create-order`, `create-orderdetail`) are **admin + customer + support** — deliberately different from `customers-api`'s/ `payments-api`'s admin-only write tools, because it's what the real backend permission classes actually allow, verified directly against `authentication/permissions.py` rather than assumed by analogy: `OrderPermission.check()`/`OrderScopedPermission.check()` give `support` an unconditional pass at the class-level (`has_permission`) check — the "status-only" restriction usually associated with `support` is enforced at the *object* level (`has_object_permission`), which only applies to existing records (update/delete), not `create`. `read_only`/ `product_manager` are excluded (both classes only pass those roles for `SAFE_METHODS`). **Correction to note**: `payments-api`'s `create-payment` tool (built earlier this session) restricted writes to `admin` only, described at the time as "verified against `PaymentPermission`'s actual logic" — but `PaymentPermission` extends this same `OrderScopedPermission` base class, so by the same reasoning above, `customer` and `support` should also have been included there. Not fixed as part of this domain's build (out of scope, and it's *more* restrictive than the backend rather than less, so not a safety issue) — flagged here and in `../STATUS.md` for whoever revisits `payments-api`'s MCP tool ACLs. ## Structure Same `dev/` + `kong/rest/` + `kong/mcp/` layout as `payments-api`. Deploy key and broker secret follow the same reused/mirrored pattern (`catalog-api`'s deploy key, broker's real secret pulled live from Keycloak and copied to `kong-v2/sales-api/*` in Vault).