API · WebSocket · 웹훅 계약 (IR-*)
이 페이지는 LogiNippon의 유선(wire) 계약을 단일 버전 진실원으로 고정한다 — REST(OpenAPI 3.1) · WebSocket(AsyncAPI) · 웹훅의 정확한 형상, 인증 스코프, 페이지네이션·레이트리밋·에러 규약, 그리고 외부 인터페이스(EDI·텔레매틱스·맵/기상)다. 계약은 @loginippon/contract 패키지로 추출되어 server·console·Flutter가 단일 소비하고, CI drift-gate가 불일치를 빌드 실패로 막는다. 본 페이지의 모든 엔드포인트는 as-built 구현 상태(DONE/STUB/ABSENT)를 정직하게 표기한다 — 계약은 고정되었으나 구현은 진입 단계로, 다수가 STUB/ABSENT다. 수치는 마스터 정규화 표(§4)에서 글자 그대로 인용하며 모두 "운영 데이터 없는 진입 단계의 초기 확정 목표(설계), 베이스라인으로 조정"임을 전제한다.
1. 단일 계약 원칙 — IR-API-001
요구. 시스템은 REST 표면을 OpenAPI 3.1 문서로, 실시간 표면을 AsyncAPI 문서로 기술하고, 이 둘을 단일 패키지 @loginippon/contract로 추출하여 server·console·Flutter app이 단일 소비하도록 반드시 한다(MUST). 생성된 타입·클라이언트가 손으로 쓴 모델과 어긋나면 CI의 drift-gate가 빌드를 실패시켜야 한다(MUST).
문제(현재 3중 손중복). as-built에서 같은 계약이 세 곳에서 손으로 중복된다 — ① server interfaces(server/src/types/index.ts), ② console console/src/lib/types.ts(server 타입 수기 복제, 코드 내 TODO: @loginippon/contract 추출), ③ Flutter 수기 모델(app/lib/core/models/job.dart·tracking_snapshot.dart·canonical_code.dart). 단일 추출이 없어 필드 추가 시 3곳 동기화에 의존하며, console·Flutter의 서버 의존 기능 전부가 계약 동결을 unblock 산출물로 대기한다(app: ShipmentWsClient/JobsRepository stub).
수용기준
- Given
@loginippon/contract가 OpenAPI 3.1 + AsyncAPI에서 타입/클라이언트를 생성 When server·console·Flutter 빌드가 이 패키지를 임포트 Then 세 레포에 동일 계약 버전이 단일 소스로 주입된다(중복 정의 0). - Given 누군가
server/src/types/index.ts의 응답 형상을 변경하고 OpenAPI 문서를 갱신하지 않음 When CI drift-gate 실행 Then 빌드가 실패한다(생성물 ≠ 선언물). - Given 클라이언트가
LogiNippon-Api-Version응답 헤더를 읽음 When 비파괴적 필드 추가가/v1내에서 배포 Then 날짜 버전이 증가하고 기존 클라이언트는 깨지지 않는다.
2. REST 엔드포인트 카탈로그 — IR-REST-catalog
전 /v1 엔드포인트(techspec 21개 + as-built 누락분 GET /v1/shipments/tracking 배치 라이브 추가). 구현상태 열은 마스터 §7 as-built에 정합한다(DONE=구현+테스트 / PARTIAL=부분 / STUB=껍데기·501·500·ack-only / ABSENT=미존재). Auth scope는 보안 문서(SR-AUTHZ-001 scope→endpoint 매트릭스)를 따르며, 모든 호출은 API Key의 tenant_id로 자동 필터링되고 타 테넌트 리소스는 404(존재 비노출)다.
| Method | Path | 목적 | Auth scope | 구현상태 |
|---|---|---|---|---|
POST | /v1/auth/token | API Key/자격→단기 토큰 교환(grant=password / refresh_token) | (public, 키/자격 필요) | DONE |
POST | /v1/auth/ingest-token | 장수명 ingest 전용 토큰 발급(백그라운드 GPS) | (인증 후, positions:write 한정 발급) | DONE |
GET | /v1/shipments | 화물 목록(필터·커서 페이지) | shipments:read | DONE |
POST | /v1/shipments | 화물 등록(외부 TMS→우리) | shipments:write | STUB·500 |
GET | /v1/shipments/tracking | 배치 라이브 스냅샷(N+1 회피, console FleetMap 6s 폴링 하드의존) | shipments:read | DONE |
GET | /v1/shipments/{id} | 화물 상세(상태+최신 위치+ETA+stops) | shipments:read | PARTIAL |
GET | /v1/shipments/{id}/tracking | 현재 상태 1건(라이브 DO 우선·D1 폴백) — 추적 링크·위젯용 | shipments:read | DONE |
GET | /v1/shipments/{id}/events | 이벤트 타임라인(canonical) | shipments:read | DONE |
GET | /v1/shipments/{id}/positions | GPS 경로(샘플링·페이지) | positions:read | STUB·빈배열 |
GET | /v1/jobs | 드라이버 案件 목록(커서 페이지) | shipments:read | DONE |
GET | /v1/jobs/{id} | 案件 상세 | shipments:read | DONE |
POST | /v1/jobs/{id}/accept | 案件 수락(캐리어/드라이버/차량 배정+상태 전이) | shipments:read | DONE |
POST | /v1/jobs/{id}/complete | 案件 완료(→ DELIVERED) | shipments:read | DONE |
POST | /v1/ingest/positions | GPS 배치 인제스트(오프라인 버퍼 flush) | positions:write | DONE |
GET | /v1/vehicles/{id}/position | 차량 현재 위치(운송사 스코프) | vehicles:read | ABSENT |
GET | /v1/geofences | 지오펜스 목록(거점) | geofences:read | ABSENT |
GET | /v1/geofences/{id} | 지오펜스 상세(GeoJSON·임계) | geofences:read | ABSENT |
POST | /v1/webhooks | 웹훅 구독 등록(이벤트 타입 선택) | webhooks:write | STUB·501 |
GET | /v1/webhooks | 구독 목록(+최근 전달 상태) | webhooks:read | STUB·빈배열 |
DELETE | /v1/webhooks/{id} | 구독 해지 | webhooks:write | STUB·204 |
POST | /v1/webhooks/{id}/test | 테스트 이벤트 발송(서명 검증 점검) | webhooks:write | STUB·501 |
GET | /v1/analytics/carriers/{id} | 캐리어 성능 지표(OTD·dwell·tracking rate) | analytics:read | ABSENT |
GET | /v1/reports/nimachi?from=&to= | 荷待ち 기록(규제) — 메타+다운로드 URL | reports:read | DONE |
GET | /v1/reports/jitsuunso?from=&to= | 実運送体制管理簿 — 메타+다운로드 URL | reports:read | STUB·501 |
GET | /v1/reports/{report_id}/download | R2 산출물 다운로드(테넌트 스코프·egress 무료) | reports:read | DONE |
POST /v1/shipments(화물 등록)는 현재 500 stub(shipments.ts "shipment registration not implemented", Phase 1 후반 예정). 웹훅 CRUD(webhooks.ts)는 501(구독 테이블·endpoint_secret 미생성). GET /v1/reports/jitsuunso(実運送体制管理簿)는 501(다단계 캐리어 체인 carrier.parent_carrier_id + GPS 검증 실운송 차량 결합 후속 의존). 부재(ABSENT): /v1/vehicles/{id}/position·/v1/geofences[/:id]·/v1/analytics/carriers/{id}(라우터에 TODO만, POST /v1/admin/drivers도 부재). {id}/positions·GET /webhooks는 라우트는 살아 있으나 빈 배열을 반환한다. GET /v1/shipments/tracking은 스펙 미기재 as-built 추가로, console FleetMap의 6s 폴링이 하드 의존하므로 계약에 반드시 편입한다.
3. 공통 규약 — 버전 · 페이지네이션 · 레이트리밋 · 에러
3.1 버전
경로 프리픽스 /v1. 파괴적 변경은 /v2로, 비파괴적 필드 추가는 /v1 내에서. 모든 응답에 날짜 기반 마이너 버전 헤더 LogiNippon-Api-Version: 2026-05-31을 실어 클라이언트가 동작 변화를 감지하게 한다(server API_VERSION var와 정합; 웹훅 페이로드 api_version 필드와 동일 값).
3.2 커서 페이지네이션
커서 기반(offset 아님 — D1 대용량 스캔 회피). 요청 ?limit=50&cursor=…. 응답은 data[] + page 객체(next_cursor, has_more). 커서는 (occurred_at, id) 복합 키를 불투명 base64로 인코딩한다. as-built 정합: GET /v1/shipments·/v1/jobs 모두 { data, page:{ next_cursor, has_more } } 형상을 반환하며 has_more = (next_cursor != null)이다(shipments.ts·jobs.ts). 배치 GET /v1/shipments/tracking은 위치 있는 화물만 필터링한 { data }(page 없음, 지도 스냅샷 용도)를 반환한다.
3.3 레이트리밋
테넌트별(API Key 단위). 표준 헤더로 노출하고, 한도 수치는 NFR-SEC-RL-001(보안 문서가 권위)을 따른다. 모두 진입 단계 초기 확정 목표(설계), 운영 베이스라인으로 조정한다.
| 헤더 | 의미 |
|---|---|
RateLimit-Limit | 윈도 내 허용 요청 수 |
RateLimit-Remaining | 남은 요청 수 |
RateLimit-Reset | 윈도 리셋까지 초 |
Retry-After | 429 시 재시도 대기 초 |
RATE_LIMITED/429 코드가 존재하나 실제 미들웨어가 없어 한도가 강제되지 않는다(마스터 §7). 위 헤더·수치는 계약상 확정 목표이며 Phase 1 내 미들웨어 배선이 필요하다.
3.4 에러 엔벨로프
일관 형식(HTTP 상태 + 머신리더블 code + request_id + details). request_id는 로그·관측성(slo-catalog.html)과 상관(correlate)된다.
{
"error": {
"code": "SHIPMENT_NOT_FOUND",
"message": "shipment SHP-2025-00456 not found in this tenant",
"request_id": "req_01HF...",
"details": []
}
}
code | HTTP | 의미 |
|---|---|---|
UNAUTHENTICATED | 401 | 토큰/자격 없음·무효 |
PERMISSION_DENIED | 403 | 스코프 부족 |
SHIPMENT_NOT_FOUND | 404 | 부재 또는 타 테넌트(존재 비노출) |
VALIDATION_FAILED | 422 | 본문/쿼리 검증 실패(예: 리포트 범위 위반) |
RATE_LIMITED | 429 | 레이트리밋 초과(+ Retry-After) |
NOT_IMPLEMENTED | 501 | 계약 고정·미구현(웹훅 CRUD·jitsuunso 등 STUB) |
INTERNAL | 500 | 내부 오류(현재 POST /v1/shipments stub 포함) |
4. JSON 예시 — 직렬화 계약
형상은 데이터 모델(data-model.html)의 3계층(Shipment→Stop→Event)·canonical_code와 1:1 정합한다. 캐리어 개인정보(드라이버 실명·番号板)는 화주 스코프에서 마스킹된다(SR-PII-001). eta_is_estimate는 D1의 0/1 정수를 API 계약에서 JSON boolean으로 정규화한다(shipmentJson).
4.1 Shipment 객체 — GET /v1/shipments/{id}
actual_carrier는 다단계 하청(元請→下請→孫請)에서 실시간 위치로 검증된 실운송 차량의 캐리어다(carrier.tier=PRIME/SUB1/SUB2/SUB3 + parent_carrier_id 체인). dwell_minutes: 143은 임계 120분 초과 → 荷待ち 예외(FR-ENG-EXC-002)로 잡힌다.
{
"shipment_id": "SHP-2025-00456",
"tenant_id": "TN-SHIPPER-KAO",
"shipper_ref": "PO-98765",
"mode": "TRUCK",
"current_status": "IN_TRANSIT",
"carrier": { "carrier_id": "CR-PRIME-001", "name": "○○運輸 (元請)", "tier": "PRIME" },
"actual_carrier": { "carrier_id": "CR-SUB2-077", "name": "△△急配 (孫請·실운송)", "tier": "SUB2" },
"vehicle": { "vehicle_id": "VH-0231", "class": "MEDIUM", "plate": "品川 1*-**" },
"driver": { "driver_id": "DR-1180", "display_name": "佐**" },
"planned_pickup_at": "2025-05-15T09:00:00+09:00",
"planned_delivery_at": "2025-05-15T17:00:00+09:00",
"predicted_delivery_eta":"2025-05-15T18:45:00+09:00",
"eta_is_estimate": true,
"stops": [
{ "stop_id": "ST-0456-1", "sequence": 1, "type": "PICKUP",
"geofence_id": "GF-KOTO-DC-001", "address": "東京都江東区辰巳3-2-1",
"planned_arrival_at": "2025-05-15T09:00:00+09:00",
"actual_arrival_at": "2025-05-15T09:12:00+09:00",
"actual_departure_at":"2025-05-15T11:35:00+09:00",
"dwell_minutes": 143 },
{ "stop_id": "ST-0456-2", "sequence": 2, "type": "DROPOFF",
"geofence_id": "GF-OSAKA-CUST-014", "address": "大阪府吹田市...",
"planned_arrival_at": "2025-05-15T17:00:00+09:00",
"actual_arrival_at": null, "actual_departure_at": null, "dwell_minutes": null }
],
"created_at": "2025-05-14T20:10:00+09:00"
}
4.2 Tracking 스냅샷 — GET /v1/shipments/{id}/tracking
추적 링크·외부 위젯이 폴링하는 "지금 한 장면". 라이브 DO 우선, 콜드/부재 시 D1 투영 + ETA(공용 빌더 buildSnapshot; 배치 /tracking과 공유). staleness_seconds(마지막 핑 경과)·tracking_rate(추적 커버리지)를 정직하게 노출한다 — 스마트폰 GPS 한계를 숨기지 않는 원칙(KPI-TRACK-001).
{
"shipment_id": "SHP-2025-00456",
"status": "IN_TRANSIT",
"as_of": "2025-05-15T14:30:05+09:00",
"position": {
"lat": 35.1702, "lon": 136.8816, "h3_r10": "8a4f1d2a3b07fff",
"heading_deg": 248, "speed_kmh": 82,
"captured_at": "2025-05-15T14:29:50+09:00",
"staleness_seconds": 15
},
"next_stop": {
"stop_id": "ST-0456-2", "type": "DROPOFF",
"eta": "2025-05-15T18:45:00+09:00", "eta_is_estimate": true,
"promised": "2025-05-15T17:00:00+09:00", "delay_minutes": 105
},
"current_dwell": null,
"tracking_rate": 0.93
}
position이 생략되고 ETA만 노출된다(個人情報保護法 — SR-PII-001; Phase 1엔 consignee 역할 미존재). staleness_seconds는 console 폴링 예산(핀 >60s = stale 표시, >300s = drop — NFR-PERF-003b)을 구동한다. 주의: tracking_rate는 계약 필드이나 Phase 1 미산출(정직한 unknown — 기대 대비 수신 핑 cadence 계산은 후속, buildSnapshot 주석). current_dwell도 현재 항상 null이다.
5. WebSocket 실시간 프로토콜 — IR-WS-001
요구. 시스템은 단일 화물 실시간 뷰를 위해 채널 /v1/shipments/{id}/ws(Durable Object 백엔드)를 AsyncAPI 문서로 기술하고, 메시지 타입·인증 핸드셰이크·heartbeat·reconnect·화주 스코프 마스킹을 계약으로 고정해야 한다(MUST). 이 채널은 UI 레이어 전용이며 외부 시스템 연동으로 노출하지 않는다(외부는 REST/웹훅).
형상. 서버→클라이언트 메시지 타입: position_update(좌표·heading·speed·captured_at·staleness_seconds; Tracking 스냅샷의 position 형상과 동형) · status_change(canonical current_status 전이). 인증은 핸드셰이크 시 토큰(?token= 또는 첫 프레임)으로 검증 후 테넌트/스코프 스코핑. heartbeat(주기 ping/pong)와 reconnect(끊김 시 클라 재접속) 규약 포함. 화주 스코프에서 position 마스킹 규칙(受取人=ETA만)은 REST와 동일하게 적용.
수용기준
- Given 유효 토큰으로
/v1/shipments/{id}/ws핸드셰이크 When 차량 위치 핑이 인제스트 Then 대시보드 broadcast까지 p95 ≤ 1.5s, p99 ≤ 3s(NFR-PERF-003) 내position_update가 푸시된다. - Given 무효/만료 토큰 When 핸드셰이크 Then 연결이 거부된다(401 동등).
- Given 受取人(consignee) 스코프 When
position_update발생 Thenposition이 마스킹되고 ETA만 전달된다. - Given 연결 끊김 When reconnect Then heartbeat로 생존을 확인하고 마지막 상태를 재동기화한다.
6. 웹훅 카탈로그 — IR-WH-001
요구. 이벤트 발생 시 화주 시스템에 HTTP POST하고(발송·재시도는 Queues notify가 담당), 각 POST에 표준 전달 헤더를 붙이며, 수신자가 서명을 검증하고 Event-Id로 멱등 처리할 수 있도록 계약을 고정해야 한다(MUST). 구독 모델(webhook_subscription·webhook_delivery)을 위한 0004 마이그레이션 신설을 요구한다.
구독 가능한 type(7종). canonical 이벤트(DM-EVT-ENUM-001)와 정합: SHIPMENT_ARRIVED_PICKUP · PICKUP_COMPLETED · SHIPMENT_ARRIVED_DELIVERY · SHIPMENT_DELIVERED · SHIPMENT_EXCEPTION(지연·荷待ち 초과·추적 손실 등 data.canonical_code로 세분) · DWELL_THRESHOLD_EXCEEDED · TEST(POST /v1/webhooks/{id}/test 발송).
수용기준
- Given 구독한
type의 이벤트 발생 When notify 큐가 전달 Then 첫 시도 또는 재시도 내 2xx 비율 ≥ 99.0% / 28일(NFR-RELY-001), 발신 타임아웃 5s hard. - Given 수신자가
signed = "{X-LogiNippon-Timestamp}." + raw_body로 HMAC-SHA256 계산 WhenX-LogiNippon-Signature의v1과 상수시간 비교 Then 일치 시 수락, 타임스탬프 윈도 ±300s 초과 시 거부(replay 방지). - Given 같은
X-LogiNippon-Event-Id가 두 번 도착(at-least-once) When 수신자가 처리한 id 기록 Then 중복은 무시된다(멱등). - Given 전달 실패 When 재시도 래더 소진(8회) Then 구독을
disabled로 표시하고 대시보드 알림 + 재활성 경로 제공. - Given 이벤트가 순서 뒤바뀜 When 수신자 처리 Then
occurred_at기준 정렬(더 오래된 status로 덮어쓰지 않음).
6.1 웹훅 페이로드
{
"id": "evt_01HF8Z9Q3K7M2N",
"type": "SHIPMENT_EXCEPTION",
"api_version": "2026-05-31",
"occurred_at": "2025-05-15T14:30:00+09:00",
"shipment_id": "SHP-2025-00456",
"data": {
"canonical_code": "LATE_DELIVERY_PREDICTED",
"severity": "HIGH",
"predicted_eta": "2025-05-15T18:45:00+09:00",
"promised_eta": "2025-05-15T17:00:00+09:00",
"delay_minutes": 105,
"current_location": { "lat": 35.1702, "lon": 136.8816 }
}
}
6.2 전달 헤더
| 헤더 | 예 | 용도 |
|---|---|---|
X-LogiNippon-Signature | t=1747287000,v1=5d41402a... | HMAC-SHA256({timestamp}.{raw_body}, endpoint_secret) |
X-LogiNippon-Timestamp | 1747287000 | 서명 대상 타임스탬프(replay 방지, 허용 윈도 ±300s) |
X-LogiNippon-Event-Id | evt_01HF8Z9Q3K7M2N | 멱등성 키(data.id와 동일) |
X-LogiNippon-Delivery | dlv_01HF... | 이 전달 시도의 고유 ID(재시도마다 다름) |
X-LogiNippon-Webhook-Id | wh_01HF... | 구독 ID |
Content-Type | application/json | — |
6.3 재시도 래더 · 멱등 · 순서
지수 백오프 래더(초): [0, 60, 300, 1800, 7200, 21600, 43200, 86400] — 8회, 최대 전달수명 24h, 8연속 실패 시 auto-disable + 대시보드 재활성(FR-DLV-WH-001의 notify max_retries=8과 정합). 전달은 at-least-once(같은 id가 두 번 올 수 있음, 재시도는 같은 id·다른 X-LogiNippon-Delivery). 성공 조건: 수신자 2xx를 5초 내; 그 외(타임아웃·5xx·연결 실패)는 실패로 재시도. 순서 보장 없음 — 수신자는 occurred_at 기준으로 정렬·판단한다.
webhook_subscription: 구독별 endpoint_secret·구독 type·상태; webhook_delivery: 시도/상태 succeeded/failed/disabled)이 신설되어야 한다(현재 마이그레이션은 0001_init·0002_auth·0003_geofence_membership까지만 존재). 전진전용 expand-first 마이그레이션 거버넌스는 pipeline-ops.html을 따른다.
7. 외부 인터페이스 — IR-EDI-001 · IR-TELE-001 · IR-EXT-001
요구. 대형 화주 연동을 위해 EDI 214(Transportation Carrier Shipment Status Message) 어댑터를 권장(SHOULD)한다 — 인바운드 상태를 source_type=EDI_X12(또는 EDIFACT) 이벤트로 정규화하고, 아웃바운드로 화주 시스템에 상태를 반환한다. 소스 정밀도는 EDI_X12(HIGH)(DM-EVT-PREC-001)로 위치 기반(GEOFENCE/APP_GPS=MED)보다 우선.
수용기준
- Given EDI 214 메시지 수신 When 어댑터 정규화 Then
canonical_code로 매핑되어 이벤트 타임라인에 정합 삽입(미매핑 <1%/일, KPI-NORM-001).
요구. 차재 텔레매틱스(디지털 타코그래프·차재 단말)에서 위치/주행 데이터를 source_type=TELEMATICS(정밀도 MED)로 수집하는 인터페이스를 권장(SHOULD)한다 — 스마트폰 GPS 미보유 차량의 tracking rate(KPI-TRACK-001 ≥85%) 보강 경로.
수용기준
- Given 텔레매틱스 위치 스트림 When 인제스트 Then
PositionPing계약으로 정규화되어 동일 dedup·지오펜스 파이프라인을 탄다.
7.1 외부 IF 요약 — IR-EXT-001
우리가 소비하는 외부 인터페이스(아웃바운드 의존). 인증 시크릿은 server에 바인딩되어 있다(MAPS_API_KEY·JMA_API_KEY·LINE_CHANNEL_TOKEN).
| 외부 IF | 용도 | 시크릿/바인딩 | 구현상태 | 신뢰도 |
|---|---|---|---|---|
| Google Maps Platform | 거리·교통(룰 ETA FR-ENG-ETA-001), 지도 렌더(일본 도로·일본어 우선) | MAPS_API_KEY | ABSENT(시크릿만, 호출 미배선) | 설계 |
| 国土地理院 타일 | 지도 대안(무료·고정밀 국내 타일) | —(공개 타일) | ABSENT | 추정 |
| JMA(気象庁) | 기상 데이터(ETA·예외 보정 입력) | JMA_API_KEY | ABSENT(시크릿만) | 설계 |
| LINE / LINE Works | 운영팀 실시간 예외 알림(1순위 채널 — 일본 B2B 현장 지배적) | LINE_CHANNEL_TOKEN | STUB(notify kind:'line' 큐 자리, 발송 미구현) | 확인 |
IR-EDI-001·jitsuunso 계약의 필드 매핑은 잠정이며, 법무 서명 플래그 RR-LEGAL-001을 따른다. CSV 인코딩(Shift_JIS vs UTF-8) 법무 결정은 OD-004.
근거·상호참조
- techspec(설계): 05-delivery-layer/delivery.md — REST 엔드포인트 표·공통 규약·JSON 예시·웹훅 시맨틱스·외부 IF·규제 출력
- techspec: 02-data-model/model.md(형상 정합) · 03-data-acquisition/acquisition.md(인제스트·텔레매틱스) · 07-security/security-privacy.md(스코프·서명·마스킹)
- ADR: ADR-0003 · ADR-0010(대시보드 채널 분리·단일 contract 소비처; 요약 OD-001)
- code(as-built):
server/src/routes/shipments.ts(배치/tracking·스냅샷 빌더·POST 500 stub) ·server/src/routes/webhooks.ts(CRUD 501) ·server/src/routes/reports.ts(nimachi DONE·jitsuunso 501) ·server/src/routes/jobs.ts·server/src/routes/auth.ts(token·ingest-token) ·server/src/routes/index.ts(부재 라우트 TODO) ·server/src/types/index.ts(TrackingSnapshotDto·ErrorCode·NotifyJob·SourceType등 계약 형상) - Research(시장·구현): Research/delivery-layer(WS=UI 전용·웹훅 형식·LINE 1순위) · Research/implications-for-us·landscape-map(규제 킬러앱)
- 상호참조(TRD 내부): FR-DLV-WH-001 · FR-ENG-ETA-001 · FR-ENG-EXC-002 · DM-TS-001 · DM-EVT-ENUM-001 · DM-EVT-PREC-001 · NFR-SEC-RL-001 · NFR-RELY-001 · NFR-PERF-003 · NFR-PERF-003b · SR-PII-001 · SR-AUTHZ-001 · RR-LEGAL-001 · KPI-TRACK-001 · KPI-NORM-001 · OD-001 · OD-004 · OD-008 · pipeline-ops.html