ADR-0001. Publish a type-only-ish ./contracts subpath instead of mounting pricing as a component
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-03 |
| Deciders | pricing-team, sale-team |
| Supersedes | — |
Context
- Sale must price carts at checkout, but pricing is a separate runtime service with its own DB schema, Kafka consumer, and calculators.
- Mounting pricing as an embeddable IGNIS component inside sale would drag pricing's repositories, Kafka component, and DB coupling into the sale process.
- Sale still needs strongly-typed request/response shapes, and a few runtime constants (e.g.
TransactionDirections.SALE,PartyRoleskeys) to build requests and read the snapshot'sbyBearerledger.
Decision
Pricing exposes a dedicated @nx/pricing/contracts subpath export (src/contracts/index.ts) that is mostly export type declarations, plus a small set of frozen runtime const containers (AppliedRuleSourceTypes, FareSourceTypes, FeeScopes, PartyRoles, RuleBasises, Snapshot{Discount,Fee,Tax}Types, TransactionDirections). Sale calls pricing over HTTP (PricingNetworkService, BASIC auth) and imports only from this subpath. Sale never mounts pricing as a component.
Consequences
| Pros | Cons |
|---|---|
| Sale ships only erasable types + tiny const tables — no pricing runtime in its bundle | Two services must stay reachable at checkout (network hop) |
| Clean service boundary; pricing can evolve internals freely | Const containers are a real (small) runtime dependency to version-manage |
| Type safety across the HTTP boundary without a shared schema package | Contract drift only caught at type-check time, not at the wire |
Alternatives Considered
| Option | Pros | Cons | Why rejected |
|---|---|---|---|
| Mount pricing as an embeddable component in sale | No network hop | Drags DB/Kafka/repo coupling into sale; breaks service isolation | Defeats the standalone-service design |
Share all types via @nx/core only | One place for types | Pricing-internal snapshot shapes don't belong in core | Pollutes core with engine-specific contracts |
| Pure-type contracts (no runtime consts) | Zero runtime dependency | Sale would re-declare TransactionDirections / PartyRoles values, risking divergence | Duplication is worse than a frozen const export |
References
pricing/src/contracts/index.tssale/src/services/pricing-network.service.tssale/src/services/checkout.service.ts