# ADR-0010: Default HTTP method-ийг GET болгож GET body хориглох

## Status

Accepted

## Context

DTI action contract дээр `method` optional бөгөөд omitted үед adapter default method сонгоно. Default method client болон server дээр өөр байвал нэг shared contract өөр HTTP operation болж ажиллах эрсдэлтэй.

Өмнөх behavior default `POST` байсан. Гэхдээ body-гүй resource read болон collection query нь энгийн REST API-ийн нийтлэг хэрэглээ тул omitted method-ийг `GET` гэж resolve хийхээр тогтоох шаардлагатай.

HTTP `GET` request дээр body ашиглах нь client, proxy, cache болон server implementation хооронд тогтвортой interoperability өгөхгүй. DTI client `GET` body илгээхгүй атлаа server body schema validate хийвэл нэг contract-ийн client/server behavior зөрнө.

## Decision

DTI action-ийн `method` optional хэвээр байна. `method` өгөөгүй үед client болон server хоёул `GET` гэж resolve хийнэ.

DTI action contract нь `GET`, `POST`, `PUT`, `PATCH`, `DELETE` method дэмжинэ. `HEAD` болон `OPTIONS`-ийг typed DTI action method хэлбэрээр дэмжихгүй. Эдгээрийг шаардлагатай үед HTTP server framework, middleware, gateway эсвэл proxy layer хариуцна.

```ts
const tenantList = createAction("tenantList", {
    query: tenantListQuery,
    result: tenantListResult,
}, {
    path: "/tenants",
});
```

Дээрх contract дараах HTTP operation болно:

```text
GET /tenants
```

Public API contract-ийг уншихад method ил тод байх шаардлагатай project болон integration дээр `method: "GET"`-ийг explicit бичиж болно. Explicit болон default `GET` ижил behavior-тэй байна.

### GET body rule

Resolved method `GET` бол action contract дээр `body` schema тодорхойлохыг хориглоно.

Дараах contract invalid байна:

```ts
createAction("tenantSearch", {
    body: tenantSearchBody,
}, {
    path: "/tenants/search",
});
```

```ts
createAction("tenantSearch", {
    body: tenantSearchBody,
}, {
    path: "/tenants/search",
    method: "GET",
});
```

GET operation-д input шаардлагатай бол `params` эсвэл `query` schema ашиглана. Request body шаардлагатай operation нь `POST`, `PUT` эсвэл `PATCH` method-ийг explicit тодорхойлно.

Contract construction үед resolved `GET` болон `body` schema зэрэг байвал reject хийнэ. Client body-г чимээгүй хаяхгүй, server GET body parse хийх тусдаа behavior үүсгэхгүй.

### DELETE body rule

Explicit `method: "DELETE"` action дээр `body` schema зөвшөөрнө.

```ts
createAction("tenantBatchDelete", {
    body: tenantBatchDeleteBody,
}, {
    path: "/tenants",
    method: "DELETE",
});
```

DTI client contract-ийн `contentType` дүрмээр body serialize хийж илгээнэ. Server ижил body schema-аар parse болон validate хийнэ.

DELETE request body-ийн semantics нь тухайн application endpoint-ийн ownership байна. Proxy, gateway эсвэл external HTTP client DELETE body-г дэмжихгүй орчинд application body-гүй resource path ашиглах эсвэл тусдаа `POST` operation сонгоно. Library DELETE body-г автоматаар query болгох, хаях эсвэл өөр method рүү шилжүүлэхгүй.

### Method resolution

Client, server, request signing болон route uniqueness validation бүгд дараах нэг resolved method ашиглана:

```ts
const resolvedMethod = action.method ?? "GET";
```

Request signing enabled үед canonical payload-д resolved uppercase method орно.

### Acceptance criteria

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

1. `method` omitted body-гүй action client болон server дээр `GET` болж resolve хийгдэнэ.
2. Raw HTTP `GET` болон DTI client ижил explicit path дээр ижил action дуудна.
3. Explicit `method: "GET"` өмнөхтэй ижил ажиллана.
4. Omitted method болон `body` schema хосолсон contract reject хийгдэнэ.
5. Explicit `GET` болон `body` schema хосолсон contract reject хийгдэнэ.
6. `POST`, `PUT`, `PATCH` дээр body schema ашиглах боломж хэвээр байна.
7. Explicit `DELETE` action дээр body schema client/server хооронд дамжина.
8. Signing canonical payload client/server дээр resolved `GET` method ашиглана.
9. TypeScript test-ийг `node:test`, `node:assert/strict` ашиглан нэмнэ.

## Consequences

- Body-гүй энгийн read action бага configuration-тай байна.
- Client болон server method default нэг утгатай болно.
- GET request body-тэй холбоотой browser, proxy, cache болон adapter interoperability зөрүү арилна.
- DELETE body ашиглах эсэх болон external infrastructure compatibility application-ийн ownership байна.
- `method` өгөөгүй existing action өмнөх `POST` route-оос `GET` route руу өөрчлөгдөнө.
- `method` өгөөгүй body schema-тай existing action contract invalid болно.
- Migration үед existing action бүрийн method-ийг шалгаж, write operation дээр `POST`, `PUT` эсвэл `PATCH`-ийг explicit нэмнэ.
- Энэ нь public wire behavior-ийн breaking change тул major version эсвэл project-ийн мөрдөж буй breaking-change policy-г дагана.

## Alternatives Considered

### `method`-ийг required болгох

HTTP operation contract дээр бүрэн explicit болно. Гэхдээ body-гүй нийтлэг read action бүр дээр `GET` давтан бичих шаардлагатай тул optional method болон default `GET` сонгов.

### Default method-ийг POST хэвээр үлдээх

Existing behavior backward-compatible байна. Гэхдээ method omitted энгийн resource read action POST болж, REST resource semantics-тэй нийцэл буурна.

### GET body-г зөвшөөрөх

Complex filter object-ийг body-аар дамжуулах боломжтой. Гэхдээ browser, proxy, cache болон HTTP client behavior тогтвортой биш бөгөөд DTI client/server contract drift үүсэх эрсдэлтэй тул хориглоно.

### GET body-г client дээр чимээгүй хаях

Request илгээхэд алдаа гарахгүй боловч contract дээр зарласан input server-д очихгүй. Ийм silent behavior-ийг зөвшөөрөхгүй.

### DELETE body-г хориглох

Proxy болон HTTP client interoperability илүү predictably body-гүй байна. Гэхдээ batch delete болон application-specific delete command-д тусдаа endpoint/method шаардана. Иймээс DELETE body-г зөвшөөрч, infrastructure compatibility болон endpoint semantics-ийг application хариуцна.
