# ADR-0009: DTI action бүр explicit REST path тодорхойлох

## Status

Accepted

## Context

DTI action contract-ийн `name` нь action-ийг таних identifier бөгөөд logging, debugging болон diagnostic мэдээлэлд ашиглагдана. Одоогийн contract дээр `path` optional тул adapter бүр fallback route-ийг өөрөөр тодорхойлох боломжтой байна.

Тухайлбал server `path` байхгүй үед `/${action.name}` route ашиглаж болох боловч client хоосон path ашиглавал нэг contract client болон server дээр өөр URL заана. Энэ нь shared contract-ийн deterministic behavior-ийг алдагдуулж, REST endpoint-ийг action identifier-ээс далд хамааралтай болгоно.

Napp DTI server-ийг `@napp/dti-client` ашиглахгүй raw HTTP client-аар дуудах боломжтой байлгахын тулд HTTP route contract дээр ил тод, тогтвортой байх шаардлагатай.

## Decision

DTI action бүр `path`-ийг заавал explicit тодорхойлно.

```ts
createAction("getTenant", schemas, {
    method: "GET",
    path: "/tenants/:tenantId",
});
```

Дараах үндсэн дүрэм үйлчилнэ:

1. `path` нь `createAction` options болон `DTIAction` contract дээр required байна.
2. `action.name` нь contract identifier бөгөөд URL эсвэл route тодорхойлох fallback болохгүй.
3. `path` нь хоосон string байж болохгүй.
4. `path` нь `/` тэмдэгтээр эхэлнэ.
5. Root endpoint шаардлагатай үед `path: "/"` гэж explicit тодорхойлно.
6. Relative path-ийг автоматаар normalize хийхгүй.
7. Client болон server contract дээр өгсөн ижил `path`-ийг ашиглана.
8. Typed path params байгаа үед client зөвхөн placeholder value-г resolve болон encode хийнэ. Base route-ийг өөрчлөхгүй.

Дараах contract-ууд invalid байна:

```ts
createAction("getTenant", schemas, {
    method: "GET",
    path: "",
});

createAction("getTenant", schemas, {
    method: "GET",
    path: "tenants/:tenantId",
});
```

Contract construction үед missing, empty эсвэл `/`-ээр эхлээгүй `path`-ийг reject хийнэ. Client болон server adapter нь action name-аас route үүсгэхгүй.

Invalid action path contract дараах public error code ашиглана:

```text
DTI_ACTION_PATH_ERROR
```

Энэ нь HTTP response биш, action contract construction үед гарах configuration error байна.

### Interoperability acceptance

Implementation дараах нөхцөлийг test-ээр батална:

1. DTI client contract дээрх explicit path-аар server endpoint-ийг дуудна.
2. Raw HTTP client ижил method болон resolved path-аар тухайн endpoint-ийг дуудна.
3. Client болон server ижил contract path ашиглана.
4. `action.name`-ийг өөрчилсөн ч explicit `path` өөрчлөгдөхгүй бол HTTP route өөрчлөгдөхгүй.
5. Missing, empty болон relative path contract validation дээр reject хийгдэнэ.
6. `path: "/"` root endpoint байдлаар зөвшөөрөгдөнө.

Test implementation нь TypeScript дээр `node:test`, `node:assert/strict` ашиглана.

## Consequences

- REST route action contract дээр ил тод, deterministic болно.
- DTI client болон server adapter хооронд route fallback зөрөх боломжгүй болно.
- Raw HTTP client contract documentation-оос endpoint URL-ийг шууд тодорхойлж чадна.
- `action.name`-ийг logging/debugging зориулалтаар HTTP route-оос хамааралгүй өөрчлөх боломжтой болно.
- `path` өгөөгүй existing action contract-ууд compile эсвэл runtime validation дээр fail болно.
- Энэ нь public contract-ийн breaking change тул release хийхдээ major version эсвэл project-ийн мөрдөж буй breaking-change policy-г дагана.
- Existing action бүр explicit `path`-тай эсэхийг migration үед шалгах шаардлагатай.

## Alternatives Considered

### `action.name`-ийг default path болгох

Boilerplate багасах боловч contract identifier болон public REST route хооронд далд coupling үүснэ. Action rename хийхэд API route санамсаргүй өөрчлөгдөх эрсдэлтэй.

### `path`-ийг optional хэвээр үлдээж client/server дээр ижил fallback хэрэглэх

Одоогийн зөрүүг арилгах боловч REST route contract дээр ил тод болохгүй. Fallback behavior нь public wire contract-ийн далд хэсэг хэвээр үлдэнэ.

### Relative path-ийг автоматаар `/` prefix-тэй болгох

Хэрэглэхэд хялбар боловч буруу contract-ийг чимээгүй засна. Route declaration-ийн canonical form нэг утгатай байх шаардлагатай тул relative path-ийг reject хийнэ.

### Empty string-ийг root endpoint гэж үзэх

Client implementation-д боломжтой боловч route intent тодорхой бус байна. Root endpoint-ийг `path: "/"` гэж explicit тодорхойлох нь REST route contract-ийг ойлгомжтой байлгана.
