# rawp 1.0.2 변경 사항 1.0.1와 비교 ## 개요 | 항목 | 값 | | --- | --- | | 원본 파일 | `rawp.md` | | 추가된 섹션 | 2 | | 삭제된 섹션 | 0 | | 수정된 섹션 | 11 | | 문서 변경 여부 | 예 | ## 추가된 섹션 - 10. 로컬 세션 관리 (Local Session Management) - 11. 게이트웨이 생명주기 (Gateway Lifecycle) ## 삭제된 섹션 - 없음 ## 수정된 섹션 - Document Overview - 1. 개요 (Introduction) - 2. Discovery 및 엔드포인트 라우팅 - 3. Phase 1: 등록, 페어링 및 키 교환 (Registration & Lifecycle) - 4. Phase 2: 제어 및 모니터링 인터페이스 (Master → Client HTTP) - 5. Phase 3: 세션 라이프사이클 및 연결 (Session & I/O) - 6. 데이터 평면 스트리밍 규격 (Data Plane WSS Protocol) - 7. 보안 및 예외 처리 (Security & Errors) - 8. 클라이언트 UI/UX 구현 지침 (Client UI Implementer Notes) - 9. Edge Node API (사용자 접점 통신 규약) - 부록: 관련 규격 문서 ## 섹션별 변경 상세 ### Document Overview - 이전 앵커: `#document-overview` - 현재 앵커: `#document-overview` - 추가된 줄: 6 - 삭제된 줄: 6 ```diff # RAWP 1.0: Remote Agent Wire Protocol -| 항목 | 값 | -| ---------------------- | ---------------- | -| 상태 | Stable | -| 버전 | 1.0 | -| 데이터 평면 규격 | **RAWP-DPS 1.0** | -| 클라이언트 렌더링 규격 | **RAWP-CRS 1.0** | +| 항목 | 값 | +| ---------------------- | ------------------ | +| 상태 | Stable | +| 버전 | 1.0.2 | +| 데이터 평면 규격 | **RAWP-DPS 1.0.1** | +| 클라이언트 렌더링 규격 | **RAWP-CRS 1.0.1** | --- ``` ### 1. 개요 (Introduction) - 이전 앵커: `#1-introduction` - 현재 앵커: `#1-introduction` - 추가된 줄: 11 - 삭제된 줄: 8 ```diff ### 1.2. 용어 정의 (Terminology) -| 용어 | 정의 | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| Master Server | 클라이언트 노드를 관리하고 제어 명령을 하달하는 중앙 서버 (Control Plane). | -| Local Client | 마스터 서버의 명령을 수신하는 HTTP 엔드포인트를 소유하며, 로컬 프로세스(Agent)의 실행 및 I/O를 담당하는 에지 게이트웨이 (Execution Plane). | -| Agent | 클라이언트 환경에서 실행되는 실제 단위 작업 프로세스 (예: LLM, 스크립트 등). | -| Session | 특정 에이전트의 실행부터 종료까지의 라이프사이클 및 I/O 스트림의 논리적 단위. | -| Config Scope | 클라이언트 설정의 논리적 분류 단위. 각 스코프는 독립된 엔드포인트, 독립된 `config_version`, 독립된 갱신 주기를 갖는다. | -| Session-Pinned Config | 세션 초기화 시점에 바인딩된 설정 스냅샷. 해당 세션의 전체 라이프사이클 동안 불변이다. | +| 용어 | 정의 | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Master Server | 클라이언트 노드를 관리하고 제어 명령을 하달하는 중앙 서버 (Control Plane). | +| Local Client | 마스터 서버의 명령을 수신하는 HTTP 엔드포인트를 소유하며, 로컬 프로세스(Agent)의 실행 및 I/O를 담당하는 에지 게이트웨이 (Execution Plane). | +| Agent | 클라이언트 환경에서 실행되는 실제 단위 작업 프로세스 (예: LLM, 스크립트 등). | +| Agent Session | 특정 에이전트의 실행부터 종료까지의 라이프사이클 및 I/O 스트림의 논리적 단위. `session_id`(UUID v4)로 식별한다. 상태 머신: `INIT → RUNNING → DETACHED → TERMINATED`. 하나의 Agent Session에 복수의 WSS Connection이 바인딩될 수 있다. 본 문서에서 "세션"은 별도 명시가 없는 한 Agent Session을 의미한다. | +| WSS Connection | Agent Session에 바인딩된 WebSocket 전송 채널. 티켓(§5.3)을 통해 수립되며, 네트워크 단절 시 소멸하고 재연결(reattach)으로 재수립할 수 있다. 동일 Agent Session에 여러 WSS Connection이 동시에 존재할 수 있다 (예: 마스터 연결 + 로컬 UI 연결, 또는 다중 엣지 연결). | +| Config Scope | 클라이언트 설정의 논리적 분류 단위. 각 스코프는 독립된 엔드포인트, 독립된 `config_version`, 독립된 갱신 주기를 갖는다. | +| Session-Pinned Config | 세션 초기화 시점에 바인딩된 설정 스냅샷. 해당 세션의 전체 라이프사이클 동안 불변이다. | +**Agent Session과 WSS Connection의 관계**: Agent Session은 에이전트의 논리적 생명주기이고, WSS Connection은 그 세션의 데이터를 전달하는 전송 채널이다. Agent Session이 `RUNNING` 상태에서 WSS Connection이 단절되면 Agent Session은 `DETACHED`로 전이하지만 에이전트 프로세스는 계속 실행된다. WSS Connection이 재수립(reattach)되면 Agent Session은 `RUNNING`으로 복귀한다. Agent Session이 `TERMINATED`되면 모든 WSS Connection이 종료된다. + ### 1.3. 호환성 및 파싱 규약 (Forward Compatibility) ``` ### 2. Discovery 및 엔드포인트 라우팅 - 이전 앵커: `#2-discovery-` - 현재 앵커: `#2-discovery-` - 추가된 줄: 0 - 삭제된 줄: 2 ```diff ``` -> **변경 사항**: RAWP-DPS 1.0 적용 시 `data_plane_protocol` 필드가 추가되었다. 이 필드는 서버가 지원하는 데이터 평면 규격을 명시하며, 클라이언트는 이를 확인하여 호환되는 데이터 평면 규격을 선택해야 한다 (MUST). 필드가 없으면 RAWP-DPS-0.1-Legacy로 간주한다. - --- ``` ### 3. Phase 1: 등록, 페어링 및 키 교환 (Registration & Lifecycle) - 이전 앵커: `#3-phase-1-registration-lifecycle` - 현재 앵커: `#3-phase-1-registration-lifecycle` - 추가된 줄: 38 - 삭제된 줄: 2 ```diff 양측은 타 API 호출 시 `401 Unauthorized`를 받으면, 발급 주체의 갱신 엔드포인트를 호출하여 토큰을 갱신하고 원래 요청을 재시도해야 한다 (MUST). -### 3.4.1. 클라이언트의 마스터 토큰 갱신 (Client → Master) +#### 3.4.1. 클라이언트의 마스터 토큰 갱신 (Client → Master) - **Endpoint**: `POST /v1/auth/refresh` (Master Server 제공) ... - **Response**: §3.3의 Master → Client 응답 포맷과 동일. -### 3.4.2. 마스터의 클라이언트 토큰 갱신 (Master → Client) +#### 3.4.2. 마스터의 클라이언트 토큰 갱신 (Master → Client) - **Endpoint**: `POST /v1/auth/refresh` (Local Client 제공) ... ``` +#### 3.4.3. 토큰 갱신 상세 규칙 + +**Refresh Token Rotation**: 토큰 갱신 응답에는 항상 새로운 `refresh_token`이 포함되어야 한다 (MUST). 갱신에 사용된 기존 `refresh_token`은 즉시 무효화해야 한다 (MUST). 이를 통해 탈취된 토큰의 재사용을 방지한다. + +**Replay 감지**: 이미 사용(무효화)된 `refresh_token`으로 갱신이 시도되면, 토큰 발급 주체는 해당 클라이언트(또는 사용자)에게 발급된 모든 토큰(access + refresh)을 즉시 무효화해야 한다 (MUST). 이는 토큰 탈취 후 공격자와 정당한 사용자가 경쟁적으로 갱신하는 시나리오를 차단한다. 무효화 후 `401 Unauthorized`를 반환한다. + +**갱신 실패 복구**: `refresh_token` 자체가 만료되었거나 무효화되어 갱신이 불가능한 경우(`401 Unauthorized` 수신), 클라이언트는 재페어링(§3.3) 절차를 개시해야 한다 (MUST). + +#### 3.4.4. Edge → Master 토큰 관리 + +엣지 노드(§9)가 마스터 서버에 접속할 때 사용하는 사용자 토큰의 갱신 및 폐기 절차이다. + +**토큰 갱신 — Endpoint**: `POST /v1/edge/auth/refresh` (Master Server 제공) + +**Request**: `{"refresh_token": "String (필수)"}` + +**Response (200 OK):** + +```json +{ + "access_token": "String (필수)", + "refresh_token": "String (필수, 새로 발급된 토큰)", + "expires_in": "Number (필수, 초 단위)" +} +``` + +§3.4.3의 Refresh Token Rotation 및 Replay 감지 규칙이 동일하게 적용된다 (MUST). + +**토큰 폐기 (로그아웃) — Endpoint**: `POST /v1/edge/auth/revoke` (Master Server 제공) + +**Request**: `{"refresh_token": "String (필수)"}` + +**Response**: `204 No Content` + +마스터는 해당 `refresh_token`과 연관된 모든 `access_token`을 즉시 무효화해야 한다 (MUST). 폐기 후 해당 토큰으로의 모든 API 호출은 `401 Unauthorized`를 반환한다. + ### 3.5. 등록 해제 (Unregister) ``` ### 4. Phase 2: 제어 및 모니터링 인터페이스 (Master → Client HTTP) - 이전 앵커: `#4-phase-2-master-client-http` - 현재 앵커: `#4-phase-2-master-client-http` - 추가된 줄: 99 - 삭제된 줄: 36 ```diff 클라이언트는 시스템 한계치와 지원 능력을 서버에 동기화한다. 설정은 의미적 성격에 따라 독립된 Config Scope로 분리되며, 각 스코프는 전용 엔드포인트를 통해 전체 교체(Full Replacement) 방식으로 동기화된다. 마스터 서버는 수신한 설정 값으로 요청을 스로틀링하며, 보고되지 않은 기능을 요구해서는 안 된다 (MUST). -### 4.1.1. Config Scope 분리 원칙 +#### 4.1.1. Config Scope 분리 원칙 클라이언트 설정은 다음 두 개의 Config Scope로 분리된다: ... 각 스코프는 독립된 `config_version`을 가지며, 한 스코프의 갱신이 다른 스코프의 버전에 영향을 주지 않는다 (MUST). 클라이언트는 변경이 발생한 스코프의 엔드포인트만 호출하면 되고, 변경되지 않은 스코프를 함께 재전송할 필요가 없다. -### 4.1.2. 초기 동기화 (Initial Synchronization) +#### 4.1.2. 초기 동기화 (Initial Synchronization) 클라이언트는 페어링 완료(§3.3) 직후 그리고 재기동 직후, **양쪽 Config Scope를 모두** 동기화해야 한다 (MUST). 초기 동기화 시 `config_version`은 `1`로 시작한다. 서버는 양쪽 스코프의 초기 동기화가 완료되기 전까지 해당 클라이언트에 대한 세션 초기화(§5.1) 요청을 보류해야 한다 (MUST). 초기 동기화 미완료 상태에서 세션 초기화가 시도되면 서버는 `503 Service Unavailable`을 반환해야 한다 (MUST). ... 마스터 서버가 특정 스코프에 대한 설정을 보유하지 않은 상태에서 해당 클라이언트의 헬스 체크(§4.2) 또는 에이전트 탐색(§4.3)을 수행하는 것은 허용된다. 설정 동기화 보류 규칙은 세션 초기화에만 적용된다. -### 4.1.3. 런타임 설정 갱신 (Runtime Configuration Update) +#### 4.1.3. 런타임 설정 갱신 (Runtime Configuration Update) 클라이언트는 런타임 중 설정 변경이 발생할 때마다 해당 스코프의 엔드포인트를 호출하여 서버에 변경 사항을 동기화해야 한다 (MUST). 각 호출은 해당 스코프의 **전체 필드를 포함하는 완전한 스냅샷**이어야 하며, 부분 필드만 포함하는 것은 허용되지 않는다 (MUST NOT). 서버는 수신한 스냅샷으로 해당 스코프의 기존 상태를 전체 교체한다. -### 4.1.4. 설정 버전 관리 및 순서 보장 (Config Versioning) +#### 4.1.4. 설정 버전 관리 및 순서 보장 (Config Versioning) 모든 Config Scope 요청에는 `config_version` 필드가 포함되어야 한다 (MUST). 이 값은 각 스코프별로 독립적이며, 클라이언트가 해당 스코프의 설정을 변경할 때마다 반드시 1씩 단조 증가시켜야 한다 (MUST). ... **클라이언트 재기동 시 버전 처리**: 클라이언트가 재기동될 때 이전 `config_version`을 영속적으로 보관하지 못하는 경우를 위해, 다음의 특수 규칙을 적용한다: `config_version`이 `1`인 요청은 서버가 보유한 버전과 무관하게 항상 수락해야 한다 (MUST). 이는 재기동 후 초기 동기화를 보장하기 위한 것이며, 서버는 `config_version: 1` 수신 시 내부 버전 카운터를 `1`로 리셋해야 한다. 단, 활성 세션이 존재하는 상태에서 `config_version: 1`이 수신되면, 서버는 이를 클라이언트 재기동 시그널로 해석하여 시스템 로그에 기록해야 한다 (MUST). -### 4.1.5. Resource Limits 동기화 +#### 4.1.5. Resource Limits 동기화 클라이언트의 수량적 운영 제약을 서버에 동기화한다. ... ``` -### 4.1.6. Capabilities 동기화 +#### 4.1.6. Capabilities 동기화 클라이언트가 지원하는 기능 목록을 서버에 동기화한다. ... ``` -### 4.1.7. 설정 갱신 에러 응답 (Config Update Errors) +#### 4.1.7. 설정 갱신 에러 응답 (Config Update Errors) 설정 갱신 요청이 검증에 실패한 경우, 서버는 §7.1의 에러 응답 표준 규격을 확장한 다음 포맷으로 응답해야 한다 (MUST). ... `current_config_version`을 통해 클라이언트는 자신의 `config_version`을 서버 값 이상으로 재조정한 후 재시도할 수 있다. -### 4.1.8. 설정 적용 범위: Session-Pinned Config +#### 4.1.8. 설정 적용 범위: Session-Pinned Config 런타임 설정 갱신은 **새로 초기화되는 세션에만 적용**되며, 이미 `RUNNING` 또는 `DETACHED` 상태인 세션에는 소급 적용되지 않는다 (MUST NOT). 이를 Session-Pinned Config라 한다. ... - 갱신 후 제거된 capability가 활성 세션에 바인딩되어 있는 경우, 해당 세션은 정상적으로 계속 동작한다. 서버가 해당 세션을 강제 종료하거나 기능을 제한해서는 안 된다 (MUST NOT). -### 4.1.9. 레거시 호환: POST /v1/nodes/config (Deprecated) - -> **본 엔드포인트는 단종 예고(Deprecated) 상태이다.** 새로운 클라이언트 구현은 §4.1.5 및 §4.1.6의 분리된 PUT 엔드포인트를 사용해야 한다 (MUST). - -**Endpoint**: `POST /v1/nodes/config` (Master Server 제공) - -기존 클라이언트와의 하위 호환을 위해 서버는 이 엔드포인트를 계속 수락할 수 있다 (MAY). 수신된 요청은 서버 내부에서 limits와 capabilities 스코프로 분리 저장한다. 이 경우 `config_version`은 양쪽 스코프 모두 `1`로 초기화한다. - -서버는 이 엔드포인트로의 응답에 반드시 `Warning: 299 - "Deprecated: Use PUT /v1/nodes/config/limits and PUT /v1/nodes/config/capabilities"` HTTP 헤더를 포함해야 한다 (MUST). - -**Request** (Client → Master): +#### 4.1.9. 레거시 호환: POST /v1/nodes/config (지원 종료) -```json -{ - "rate_limit": "Number (필수, 초당 처리 가능한 최대 HTTP 요청 수)", - "max_frame_size": "Number (필수, WSS 단일 프레임 최대 바이트)", - "reattach_window": "Number (필수, WSS 단절 시 대기 시간 초)", - "max_buffer_size": "Number (필수, 최대 메모리 버퍼 바이트)", - "buffer_overflow_policy": "String (필수, 'RING' 또는 'DROP')", - "capabilities": ["String (선택, e.g., 'vision_v1', 'tool_call_v2')"] -} -``` +`POST /v1/nodes/config` 엔드포인트는 지원이 종료되었다. 모든 클라이언트는 §4.1.5 및 §4.1.6의 분리된 PUT 엔드포인트를 사용해야 한다 (MUST). ... diff truncated ... ``` ### 5. Phase 3: 세션 라이프사이클 및 연결 (Session & I/O) - 이전 앵커: `#5-phase-3-session-io` - 현재 앵커: `#5-phase-3-session-io` - 추가된 줄: 48 - 삭제된 줄: 2 ```diff **제약 조건**: 클라이언트는 자식 프로세스에 `SIGTERM`을 전송하고, 5초 내 종료되지 않으면 `SIGKILL`로 강제 종료 후 메모리 버퍼 및 소켓을 파기해야 한다 (MUST). +**WSS 알림 의무**: 세션 종료 처리 후 WSS 연결을 닫기 전에, 해당 세션에 바인딩된 모든 WSS Connection에 RAWP-DPS 1.0.1 §7.7의 `session.deleted` 이벤트를 발송해야 한다 (MUST). 발송 순서는 RAWP-DPS 1.0.1 §7.5.3(진행 중 항목 정리) → `session.deleted` → WSS 종료이다. + ### 5.3. WebSocket 연결 수립 (WebSocket Upgrade) ... **인가 절차** (MUST): -1. 클라이언트는 HTTP Upgrade 요청 수신 시 HTTP 헤더의 `Sec-WebSocket-Protocol`을 확인해야 한다. RAWP-DPS 1.0 적용 시 `rawp-dps-1.0`을 우선 수락하고, 미지원 시 `rawp-1.0`으로 폴백한다. 양측 모두 미지원 시 `426` 또는 `400`을 반환해야 한다. +1. 클라이언트는 HTTP Upgrade 요청 수신 시 HTTP 헤더의 `Sec-WebSocket-Protocol`을 확인해야 한다. RAWP-DPS 1.0.1 적용 시 `rawp-dps-1.0`을 우선 수락하고, 미지원 시 `rawp-1.0`으로 폴백한다. 양측 모두 미지원 시 `426` 또는 `400`을 반환해야 한다. 2. Query Parameter의 `ticket`과 `session_id`를 검증하고, 만료되거나 불일치 시 `401 Unauthorized`를 반환 후 연결을 거절한다. 3. 사용된 티켓은 1회 사용 시 즉시 무효화(Burn)해야 한다. -> **변경 사항**: RAWP-DPS 1.0 적용에 따라 `Sec-WebSocket-Protocol` 협상 절차가 확장되었다. `rawp-dps-1.0`이 우선이며, 레거시 호환을 위해 `rawp-1.0`도 수락 가능하다. 자세한 프로토콜 협상 규칙은 RAWP-DPS 1.0 §1.3을 참조한다. +### 5.4. 세션 이름 변경 (Session Rename) +세션에 사용자 친화적 이름을 부여하고, 변경 사항을 모든 참여자에게 전파한다. + +#### 5.4.1. 마스터 → 클라이언트 이름 변경 + +**Endpoint**: `PATCH /v1/session/{session_id}` (Local Client 제공) + +**Request**: + +```json +{ + "name": "String (필수, 새 세션 이름. 최대 200자)" +} +``` + +**Response (200 OK)**: + +```json +{ + "session_id": "String (필수)", + "name": "String (필수, 변경된 이름)", + "updated_at": "String (필수, ISO 8601)" +} +``` + +**제약 조건**: 존재하지 않거나 `TERMINATED` 상태인 세션에 대한 요청은 `404 Not Found`를 반환한다 (MUST). + +**WSS 알림 의무**: HTTP 응답 후, 클라이언트는 해당 세션에 바인딩된 모든 WSS Connection에 RAWP-DPS 1.0.1 §7.6의 `session.renamed` 이벤트를 발송해야 한다 (MUST). 이는 로컬 UI WSS(§10.6)와 마스터 WSS를 모두 포함한다. + +#### 5.4.2. 엣지 → 마스터 이름 변경 + +**Endpoint**: `PATCH /v1/edge/sessions/{session_id}` (Master Server 제공) + +**Request/Response**: §5.4.1과 동일한 스키마. + +마스터는 이름 변경 수신 시 대상 로컬 클라이언트의 `PATCH /v1/session/{session_id}`를 호출하여 전파하고, 해당 세션에 연결된 모든 엣지 WSS에 RAWP-DPS 1.0.1 §7.6의 `session.renamed` 이벤트를 브로드캐스트해야 한다 (MUST). + +#### 5.4.3. 로컬 세션 이름 변경 + +**Endpoint**: `PATCH /local/v1/sessions/{session_id}` (Local Client 제공) + +**Request/Response**: §5.4.1과 동일한 스키마. + +HTTP 응답 후, 클라이언트는 해당 세션에 바인딩된 모든 WSS Connection에 `session.renamed` 이벤트를 발송해야 한다 (MUST). + --- ``` ### 6. 데이터 평면 스트리밍 규격 (Data Plane WSS Protocol) - 이전 앵커: `#6-data-plane-wss-protocol` - 현재 앵커: `#6-data-plane-wss-protocol` - 추가된 줄: 3 - 삭제된 줄: 5 ```diff > **본 절은 별도 규격으로 분리되었다.** > -> WSS 연결 수립(§5.3) 이후 교환되는 데이터 프레임의 Envelope 구조, 이벤트 타입 및 페이로드 정의는 **RAWP-DPS 1.0** 규격을 따른다. +> WSS 연결 수립(§5.3) 이후 교환되는 데이터 프레임의 Envelope 구조, 이벤트 타입 및 페이로드 정의는 **RAWP-DPS 1.0.1** 규격을 따른다. > -> RAWP-DPS 1.0은 다음을 정의한다: +> RAWP-DPS 1.0.1은 다음을 정의한다: > > - **Envelope 구조**: 버전 필드(`v`), 네임스페이스 기반 이벤트 타입, Turn 추적(`turn_id`), 요청-응답 상관(`parent_id`)을 포함하는 확장된 프레임 구조 (RAWP-DPS §2) ... > - **파일 참조** (RAWP-DPS §16): 인라인 파일 참조 토큰 포맷, 실시간 퍼지 파일 검색, 토큰 이스케이프 규칙, 어댑터별 변환 규칙 > -> 구현자는 RAWP-DPS 1.0 규격 문서를 참조하여 데이터 평면을 구현해야 한다 (MUST). -> -> **레거시 호환**: RAWP-DPS-0.1-Legacy만 지원하는 피어와의 통신이 필요한 경우, RAWP-DPS 1.0 §14의 하위 호환성 가이드라인 및 브릿지 변환 규칙을 따른다. +> 구현자는 RAWP-DPS 1.0.1 규격 문서를 참조하여 데이터 평면을 구현해야 한다 (MUST). --- ``` ### 7. 보안 및 예외 처리 (Security & Errors) - 이전 앵커: `#7-security-errors` - 현재 앵커: `#7-security-errors` - 추가된 줄: 21 - 삭제된 줄: 1 ```diff - **명령어 및 에이전트 보호 (Whitelisting)**: 활성화된 `agent_name`에 매핑된 명령어만 실행 가능해야 하며, 임의의 쉘 스크립트나 바이너리를 원격으로 주입받아 실행하는 시도는 차단해야 한다 (RCE 방어). - **버퍼 관리 및 OOM 방어**: WSS 단절 중 자식 프로세스를 유지할 때 발생하는 출력은 버퍼에 저장하되, `max_buffer_size`에 도달하면 반드시 사전에 합의된 `buffer_overflow_policy`(RING/DROP)에 따라 강제로 메모리를 관리하여 게이트웨이 다운을 방지해야 한다. -- **도구 호출 보안**: RAWP-DPS 1.0 적용 시, `tool.catalog.publish`에서 고지된 도구만 `tool.invoke.request`에 사용 가능하며, 고지되지 않은 도구의 호출 요청은 클라이언트가 거부해야 한다 (MUST). 자세한 도구 보안 규칙은 RAWP-DPS 1.0 §15를 참조한다. +- **도구 호출 보안**: RAWP-DPS 1.0.1 적용 시, `tool.catalog.publish`에서 고지된 도구만 `tool.invoke.request`에 사용 가능하며, 고지되지 않은 도구의 호출 요청은 클라이언트가 거부해야 한다 (MUST). 자세한 도구 보안 규칙은 RAWP-DPS 1.0.1 §15를 참조한다. +### 7.3. Rate Limiting + +**적용 대상**: Rate Limiting은 HTTP 엔드포인트에 대한 요청에 적용된다. WSS 프레임은 Rate Limit 대상이 아니다. WSS는 이미 세션당 단일 연결이므로 별도의 프레임 수준 제한을 두지 않는다. + +**`limits.rate_limit` 필드의 의미**: §4.1.5에서 클라이언트가 보고하는 `limits.rate_limit`은 해당 클라이언트가 초당 처리 가능한 최대 HTTP 요청 수를 의미한다. 마스터 서버는 이 값을 초과하는 빈도로 해당 클라이언트에 HTTP 요청을 보내서는 안 된다 (MUST NOT). + +**429 응답 형식**: Rate Limit을 초과한 요청에 대해 `429 Too Many Requests`를 반환할 때, 다음을 포함해야 한다 (MUST): + +```json +{ + "error_code": "RATE_LIMITED", + "message": "String (휴먼 리더블 디버깅 메시지)", + "retry_after": "Number (필수, 초 단위, 다음 요청까지 대기해야 할 최소 시간)" +} +``` + +`Retry-After` HTTP 헤더에도 동일한 값을 초 단위로 포함해야 한다 (MUST). + +**양방향 적용**: 마스터가 클라이언트의 `rate_limit`을 초과하면 클라이언트가 429를 반환하고, 클라이언트가 마스터의 내부 Rate Limit을 초과하면 마스터가 429를 반환한다. 양측 모두 본 절의 응답 형식을 따른다 (MUST). + --- ``` ### 8. 클라이언트 UI/UX 구현 지침 (Client UI Implementer Notes) - 이전 앵커: `#8-uiux-client-ui-implementer-notes` - 현재 앵커: `#8-uiux-client-ui-implementer-notes` - 추가된 줄: 3 - 삭제된 줄: 3 ```diff > **본 절은 별도 규격으로 분리되었다.** > -> RAWP 프로토콜의 제어 평면 이벤트와 RAWP-DPS 1.0의 데이터 평면 이벤트를 사용자에게 시각적으로 전달하는 클라이언트 렌더링 규격은 **RAWP-CRS 1.0** 규격을 따른다. +> RAWP 프로토콜의 제어 평면 이벤트와 RAWP-DPS 1.0.1의 데이터 평면 이벤트를 사용자에게 시각적으로 전달하는 클라이언트 렌더링 규격은 **RAWP-CRS 1.0.1** 규격을 따른다. > -> RAWP-CRS 1.0은 다음을 정의한다: +> RAWP-CRS 1.0.1은 다음을 정의한다: > > - **메시지 아키텍처**: User(우측 버블), Agent(좌측 버블리스), System(중앙 정렬) 세 행위자의 시각적 정체성 및 레이아웃 규칙 (RAWP-CRS §2) ... > - **비스트리밍 환경 적응**: Discord, Slack 등 완성형 플랫폼의 Typing Indicator 활용, 버퍼링, 사고 과정 우회 처리 (RAWP-CRS §6) > -> 구현자는 RAWP-CRS 1.0 규격 문서를 참조하여 클라이언트 UI를 구현해야 한다 (MUST). +> 구현자는 RAWP-CRS 1.0.1 규격 문서를 참조하여 클라이언트 UI를 구현해야 한다 (MUST). --- ``` ### 9. Edge Node API (사용자 접점 통신 규약) - 이전 앵커: `#9-edge-node-api-` - 현재 앵커: `#9-edge-node-api-` - 추가된 줄: 124 - 삭제된 줄: 17 ```diff ### 9.1. Edge Node 인증 및 권한 (Authentication) -엣지 노드는 마스터 서버의 로컬 클라이언트 인증 방식(Pairing Token)과 분리된 사용자 단위의 인증 체계(예: OIDC 기반 JWT)를 사용해야 한다. 모든 Edge API 요청은 `Authorization: Bearer {user_access_token}` 헤더를 포함해야 한다 (MUST). +엣지 노드는 마스터 서버의 로컬 클라이언트 인증 방식(Pairing Token)과 분리된 **OIDC(OpenID Connect) 기반** 사용자 인증 체계를 사용한다. 세부 로그인 방법(지원 프로바이더, 허용 흐름 등)은 마스터 서버가 Discovery 엔드포인트를 통해 공개하고, 엣지 노드가 이를 조회하여 협상한다. 모든 Edge API 요청은 `Authorization: Bearer {access_token}` 헤더를 포함해야 한다 (MUST). +#### 9.1.1. 인증 구성 Discovery + +엣지 노드는 로그인 UI를 구성하기 전에 마스터 서버의 인증 구성을 조회해야 한다 (MUST). + +**Endpoint**: `GET /v1/edge/auth/configuration` (Master Server 제공, 인증 불필요) + +**Response (200 OK)**: + +```json +{ + "issuer": "String (필수, OIDC Issuer URL. 예: 'https://auth.example.com')", + "authorization_endpoint": "String (필수, OIDC Authorization Endpoint URL)", + "token_endpoint": "String (필수, OIDC Token Endpoint URL)", + "userinfo_endpoint": "String (선택, OIDC UserInfo Endpoint URL)", + "end_session_endpoint": "String (선택, OIDC End Session Endpoint URL)", + "supported_flows": [ + "String (필수, 지원하는 OIDC 인증 흐름 목록. 아래 열거 값)" + ], + "supported_scopes": [ + "String (필수, 허용하는 OIDC Scope 목록. 최소 'openid' 포함)" + ], + "client_id": "String (필수, 엣지 노드가 사용할 OIDC Client ID)", + "redirect_uris": ["String (필수, 허용되는 Redirect URI 패턴 목록)"] +} +``` + +**`supported_flows` 열거 값:** + +| 값 | 설명 | +| -------------------------------- | ------------------------------------------------------------------------- | +| `authorization_code` | Authorization Code Flow (PKCE 필수). 브라우저 기반 엣지 노드의 기본 흐름. | +| `authorization_code_with_device` | Device Authorization Grant (RFC 8628). 브라우저가 없는 환경(TV, CLI 등). | + +마스터 서버는 최소 `authorization_code`를 지원해야 한다 (MUST). + +#### 9.1.2. Authorization Code Flow (PKCE) + +브라우저 기반 엣지 노드의 표준 인증 흐름이다. RFC 7636(PKCE)을 필수 적용한다 (MUST). + +**흐름:** + +1. 엣지 노드가 `code_verifier`(최소 43자 랜덤 문자열)를 생성하고, SHA-256 해시하여 `code_challenge`를 만든다. +2. 엣지 노드가 사용자를 `authorization_endpoint`로 리디렉트한다: + +``` +{authorization_endpoint}? + response_type=code + &client_id={client_id} + &redirect_uri={redirect_uri} + &scope=openid {추가_scope} + &state={csrf_state} + &code_challenge={code_challenge} + &code_challenge_method=S256 +``` + +3. 사용자가 인증을 완료하면, OIDC 프로바이더가 `redirect_uri`로 `code`와 `state`를 반환한다. +4. 엣지 노드가 `state`를 검증한 후, 마스터 서버의 토큰 교환 엔드포인트를 호출한다. + +#### 9.1.3. 토큰 교환 + +엣지 노드가 OIDC Authorization Code를 마스터 서버의 Access/Refresh Token으로 교환한다. 마스터 서버는 OIDC 프로바이더에 코드를 검증하고, 자체 토큰을 발급한다. + +**Endpoint**: `POST /v1/edge/auth/token` (Master Server 제공) + +**Request**: + +```json +{ + "grant_type": "String (필수, 'authorization_code')", + "code": "String (필수, OIDC Authorization Code)", + "redirect_uri": "String (필수, 인증 요청 시 사용한 redirect_uri와 동일해야 함)", + "code_verifier": "String (필수, PKCE code_verifier)" +} +``` + ... diff truncated ... ``` ### 부록: 관련 규격 문서 - 이전 앵커: `#-` - 현재 앵커: `#-` - 추가된 줄: 5 - 삭제된 줄: 5 ```diff ## 부록: 관련 규격 문서 -| 문서 | 설명 | -| ----------------------- | ----------------------------------------------------- | -| **RAWP-DPS 1.0** | 데이터 평면 스트리밍 규격 (현행). 본 문서 §6이 참조. | -| **RAWP-CRS 1.0** | 클라이언트 렌더링 규격 (현행). 본 문서 §8이 참조. | -| **RAWP-DPS-0.1-Legacy** | 데이터 평면 스트리밍 규격 (단종 예고). 레거시 호환용. | +| 문서 | 설명 | +| ----------------------- | ---------------------------------------------------- | +| **RAWP-DPS 1.0.1** | 데이터 평면 스트리밍 규격 (현행). 본 문서 §6이 참조. | +| **RAWP-CRS 1.0.1** | 클라이언트 렌더링 규격 (현행). 본 문서 §8이 참조. | +| **RAWP-DPS-0.1-Legacy** | 데이터 평면 스트리밍 규격 (지원 종료). | ```