# rawp 1.0.3 변경 사항 1.0.2와 비교 ## 개요 | 항목 | 값 | | --- | --- | | 원본 파일 | `rawp.md` | | 추가된 섹션 | 0 | | 삭제된 섹션 | 0 | | 수정된 섹션 | 6 | | 문서 변경 여부 | 예 | ## 추가된 섹션 - 없음 ## 삭제된 섹션 - 없음 ## 수정된 섹션 - Document Overview - 4. Phase 2: 제어 및 모니터링 인터페이스 (Master → Client HTTP) - 5. Phase 3: 세션 라이프사이클 및 연결 (Session & I/O) - 7. 보안 및 예외 처리 (Security & Errors) - 9. Edge Node API (사용자 접점 통신 규약) - 10. 로컬 세션 관리 (Local Session Management) ## 섹션별 변경 상세 ### Document Overview - 이전 앵커: `#document-overview` - 현재 앵커: `#document-overview` - 추가된 줄: 2 - 삭제된 줄: 2 ```diff | ---------------------- | ------------------ | | 상태 | Stable | -| 버전 | 1.0.2 | +| 버전 | 1.0.3 | | 데이터 평면 규격 | **RAWP-DPS 1.0.1** | -| 클라이언트 렌더링 규격 | **RAWP-CRS 1.0.1** | +| 클라이언트 렌더링 규격 | **RAWP-CRS 1.0.2** | --- ``` ### 4. Phase 2: 제어 및 모니터링 인터페이스 (Master → Client HTTP) - 이전 앵커: `#4-phase-2-master-client-http` - 현재 앵커: `#4-phase-2-master-client-http` - 추가된 줄: 132 - 삭제된 줄: 9 ```diff ], "single_turn_process": "Boolean (선택, 기본값 false. RAWP-DPS 1.0.1 §18 참조)", - "description": "String (선택, 에이전트 설명)" + "description": "String (선택, 에이전트 설명)", + "allowed_directories": [ + "String (선택, 에이전트가 실행 가능한 디렉토리 경로 목록)" + ], + "extensions": "Object (선택, 구현체별 확장 메타데이터를 위한 열린 객체)" } ] ... `type: "builtin"`은 클라이언트에 사전 탑재된 에이전트, `type: "custom"`은 사용자가 등록한 커스텀 에이전트를 의미한다. `models` 배열이 비어 있으면 에이전트가 모델 선택을 지원하지 않음을 의미한다. -#### 4.3.1. 에이전트 상세 조회 +`allowed_directories`는 에이전트가 작업 가능한 디렉토리 경로의 목록이다. 미지정 시 디렉토리 제한이 없음을 의미한다. `extensions`는 프로토콜에 정의되지 않은 구현체별 메타데이터를 전달하기 위한 열린 객체이며, §1.3의 필드 무시 원칙을 따른다. +#### 4.3.1. 에이전트 동기화 프로토콜 (Agent Synchronization) + +클라이언트가 보유한 에이전트 목록을 마스터 서버에 체계적으로 동기화하기 위한 프로토콜이다. + +##### A) 클라이언트 → 마스터 에이전트 보고 (Push) + +클라이언트가 자신의 에이전트 목록을 마스터 서버에 전체 교체(Full Replacement) 방식으로 푸시한다. + +**Endpoint**: `PUT /v1/nodes/agents` (Master Server 제공) + +**Request** (Client → Master): + +```json +{ + "agents": ["Object (§4.3의 에이전트 스키마 배열)"] +} +``` + +**Response**: `204 No Content` + +**트리거 조건**: 클라이언트는 다음 시점에 에이전트 목록을 보고해야 한다 (MUST): + +- 페어링 완료(§3.3) 직후 초기 보고 +- 에이전트 추가, 수정, 삭제 시 +- 구현체가 정의한 주기적 갱신 시점 + +**버전 관리**: 에이전트 동기화는 §4.1의 Config Scope와 달리 `config_version` 기반 버전 관리를 사용하지 않는다. 매 요청이 전체 교체이며, 마스터는 수신한 목록으로 기존 캐시를 덮어쓴다. + +##### B) 마스터 → 클라이언트 에이전트 요청 (Pull) + +마스터 서버가 최신 에이전트 목록이 필요할 때, 기존 `GET /v1/agents`(§4.3) 엔드포인트를 온디맨드로 호출하여 클라이언트로부터 직접 조회한다. + +**트리거 조건**: 세션 생성(§5.1) 시 에이전트 캐시 미스, 엣지의 에이전트 목록 요청(§9.2 하위) 수신 시 등 마스터가 최신 정보를 확보해야 하는 시점에 호출한다. + +##### C) 에이전트 삭제 시 세션 전파 (MUST) + +클라이언트에서 에이전트가 삭제(§4.3.5)되면, 클라이언트는 해당 에이전트로 생성된 모든 활성 세션(`INIT`, `RUNNING`, `DETACHED` 상태)을 종료하고, 연결된 모든 마스터 서버에 해당 세션들이 삭제되었음을 전파해야 한다 (MUST). 세션 종료는 §5.2의 절차를 따르며, `session.deleted` WSS 알림 의무도 동일하게 적용된다. 클라이언트는 모든 관련 세션의 삭제 전파가 완료된 후에만 에이전트 삭제를 확정해야 한다 (MUST). 즉, 에이전트 레코드 제거는 세션 전파 완료 이후에 수행되어야 하며, 세션 전파가 실패한 경우 에이전트 삭제를 중단해야 한다. + +#### 4.3.2. 에이전트 상세 조회 + **Endpoint**: `GET /v1/agents/{agent_id}` (Local Client 제공) ... **에러**: 존재하지 않는 `agent_id` 시 `404 Not Found`. -#### 4.3.2. 커스텀 에이전트 등록 +#### 4.3.3. 커스텀 에이전트 등록 **Endpoint**: `POST /v1/agents` (Local Client 제공) ... **제약 조건**: `name`이 기존 에이전트와 중복되면 `409 Conflict`를 반환한다 (MUST). -#### 4.3.3. 커스텀 에이전트 수정 +#### 4.3.4. 커스텀 에이전트 수정 **Endpoint**: `PATCH /v1/agents/{agent_id}` (Local Client 제공) -**Request**: §4.3.2의 필드 중 변경할 필드만 포함. `type: "builtin"` 에이전트는 수정할 수 없다 (MUST NOT). 시도 시 `403 Forbidden`. +**Request**: §4.3.3의 필드 중 변경할 필드만 포함. `type: "builtin"` 에이전트는 수정할 수 없다 (MUST NOT). 시도 시 `403 Forbidden`. **Response (200 OK)**: 수정된 에이전트 객체. -#### 4.3.4. 커스텀 에이전트 삭제 +#### 4.3.5. 커스텀 에이전트 삭제 ... diff truncated ... ``` ### 5. Phase 3: 세션 라이프사이클 및 연결 (Session & I/O) - 이전 앵커: `#5-phase-3-session-io` - 현재 앵커: `#5-phase-3-session-io` - 추가된 줄: 57 - 삭제된 줄: 1 ```diff { "session_id": "String (필수, UUID v4)", - "agent_name": "String (reattach: false 시 필수)", + "agent_id": "String (reattach: false 시 필수)", "workspace_path": "String (reattach: false 시 필수)", "ticket": "String (필수, WSS 연결 인증용 난수 티켓)", ... HTTP 응답 후, 클라이언트는 해당 세션에 바인딩된 모든 WSS Connection에 `session.renamed` 이벤트를 발송해야 한다 (MUST). +### 5.5. 세션 동기화 프로토콜 (Session Synchronization) + +클라이언트가 보유한 열려있는 세션 목록을 마스터 서버에 체계적으로 동기화하기 위한 프로토콜이다. §4.3.1의 에이전트 동기화와 동일한 Push/Pull 패턴을 적용한다. + +#### A) 클라이언트 → 마스터 세션 보고 (Push) + +클라이언트가 자신의 활성 세션 목록을 마스터 서버에 전체 교체(Full Replacement) 방식으로 푸시한다. + +**Endpoint**: `PUT /v1/nodes/sessions` (Master Server 제공) + +**Request** (Client → Master): + +```json +{ + "sessions": [ + { + "session_id": "String (필수, UUID v4)", + "session_name": "String (필수)", + "agent_id": "String (필수)", + "workspace_path": "String (필수)", + "status": "String (필수, 'INIT' | 'RUNNING' | 'DETACHED')", + "origin": "String (필수, §10.3 참조)", + "created_at": "String (필수, ISO 8601)", + "last_activity_at": "String (필수, ISO 8601)", + "total_turns": "Number (필수)" + } + ] +} +``` + +**Response**: `204 No Content` + +**트리거 조건**: 클라이언트는 다음 시점에 세션 목록을 보고해야 한다 (MUST): + +- 페어링 완료(§3.3) 직후 초기 보고 +- 세션 생성, 종료, 상태 변경 시 +- 구현체가 정의한 주기적 갱신 시점 + +**디렉토리 필터링 (MUST)**: 클라이언트가 복수의 마스터에 연결된 경우, 각 마스터의 관할 디렉토리 범위에 해당하는 세션(`workspace_path` 기준)만 필터링하여 전달해야 한다. 관할 디렉토리 설정 방식은 프로토콜 범위 밖이다. + +**버전 관리**: 세션 동기화는 §4.1의 Config Scope와 달리 `config_version` 기반 버전 관리를 사용하지 않는다. 매 요청이 전체 교체이며, 마스터는 수신한 목록으로 기존 캐시를 덮어쓴다. + +`TERMINATED` 상태의 세션은 목록에 포함하지 않는다 (MUST NOT). + +#### B) 마스터 → 클라이언트 세션 요청 (Pull) + +마스터 서버가 최신 세션 목록이 필요할 때 온디맨드로 호출한다. + +**Endpoint**: `GET /v1/sessions` (Local Client 제공) + +**트리거 조건**: 엣지의 노드별 세션 조회 요청(§9.2.5) 수신 시 캐시 미스, 마스터가 최신 정보를 확보해야 하는 시점에 호출한다. + +**Response (200 OK)**: Push의 `sessions` 스키마와 동일한 배열을 반환한다. + +이 엔드포인트는 마스터 전용이며, 마스터의 관할 디렉토리에 따른 필터링은 클라이언트가 수행한다. + --- ``` ### 7. 보안 및 예외 처리 (Security & Errors) - 이전 앵커: `#7-security-errors` - 현재 앵커: `#7-security-errors` - 추가된 줄: 2 - 삭제된 줄: 2 ```diff ### 7.2. 보안 제약 및 필수 보호 장치 (MUST) -- **경로 검증 (Path Normalization)**: 클라이언트는 모든 파일/디렉토리 조회 요청 시 경로 내 `../` 등을 정규화하고 인가된 `workspace_path` 범위 내인지 반드시 검증해야 한다 (Directory Traversal 방어). -- **명령어 및 에이전트 보호 (Whitelisting)**: 활성화된 `agent_name`에 매핑된 명령어만 실행 가능해야 하며, 임의의 쉘 스크립트나 바이너리를 원격으로 주입받아 실행하는 시도는 차단해야 한다 (RCE 방어). +- **경로 검증 (Path Normalization)**: 클라이언트는 모든 파일/디렉토리 조회 요청 시 경로 내 `../` 등을 정규화하고 인가된 `workspace_path` 범위 내인지 반드시 검증해야 한다 (Directory Traversal 방어). 세션 외 파일시스템 브라우징(§4.5) 시에도 `allowed_directories` 범위를 동일하게 적용해야 한다 (MUST). +- **명령어 및 에이전트 보호 (Whitelisting)**: 활성화된 `agent_id`에 매핑된 명령어만 실행 가능해야 하며, 임의의 쉘 스크립트나 바이너리를 원격으로 주입받아 실행하는 시도는 차단해야 한다 (RCE 방어). - **버퍼 관리 및 OOM 방어**: WSS 단절 중 자식 프로세스를 유지할 때 발생하는 출력은 버퍼에 저장하되, `max_buffer_size`에 도달하면 반드시 사전에 합의된 `buffer_overflow_policy`(RING/DROP)에 따라 강제로 메모리를 관리하여 게이트웨이 다운을 방지해야 한다. - **도구 호출 보안**: RAWP-DPS 1.0.1 적용 시, `tool.catalog.publish`에서 고지된 도구만 `tool.invoke.request`에 사용 가능하며, 고지되지 않은 도구의 호출 요청은 클라이언트가 거부해야 한다 (MUST). 자세한 도구 보안 규칙은 RAWP-DPS 1.0.1 §15를 참조한다. ``` ### 9. Edge Node API (사용자 접점 통신 규약) - 이전 앵커: `#9-edge-node-api-` - 현재 앵커: `#9-edge-node-api-` - 추가된 줄: 77 - 삭제된 줄: 3 ```diff 이 엔드포인트는 Pull 방식으로 최신 설정을 확인하기 위한 것이다. 실시간 Push 알림은 §9.4.4를 참조한다. +#### 9.2.4. 노드 에이전트 목록 조회 (Node Agent List) + +엣지 노드가 특정 로컬 머신의 에이전트 목록을 마스터 서버를 통해 조회한다. + +**Endpoint:** `GET /v1/edge/nodes/{node_id}/agents` (Master Server 제공) + +**Response (200 OK):** + +```json +{ + "node_id": "String (필수)", + "agents": ["Object (§4.3의 에이전트 스키마와 동일)"] +} +``` + +마스터 서버는 §4.3.1의 에이전트 동기화 프로토콜을 통해 캐시한 에이전트 목록을 반환한다. 캐시가 존재하지 않거나 마스터가 최신 정보를 확보해야 한다고 판단하면, 대상 클라이언트의 `GET /v1/agents`(§4.3)를 호출하여 갱신한 후 응답해야 한다 (MUST). + +**에러**: 해당 `node_id`의 노드가 존재하지 않거나 `offline` 상태이면 `404 Not Found`를 반환한다. + +#### 9.2.5. 노드 세션 목록 조회 (Node Session List) + +엣지 노드가 특정 로컬 머신의 세션 목록을 마스터 서버를 통해 조회한다. + +**Endpoint:** `GET /v1/edge/nodes/{node_id}/sessions` (Master Server 제공) + +**Response (200 OK):** + +```json +{ + "node_id": "String (필수)", + "sessions": ["Object (§5.5의 세션 스키마와 동일)"] +} +``` + +마스터 서버는 §5.5의 세션 동기화 프로토콜을 통해 캐시한 해당 노드의 세션 목록을 반환한다. 캐시가 존재하지 않거나 마스터가 최신 정보를 확보해야 한다고 판단하면, 대상 클라이언트의 `GET /v1/sessions`(§5.5)를 호출하여 갱신한 후 응답해야 한다 (MUST). + +**§9.3.2와의 차이**: §9.3.2(`GET /v1/edge/sessions`)는 사용자 계정 기준으로 모든 노드에 걸친 전체 세션을 조회하는 반면, 본 엔드포인트는 특정 노드 기준으로 해당 머신의 세션(로컬 세션 포함)을 조회한다. + +**에러**: 해당 `node_id`의 노드가 존재하지 않거나 `offline` 상태이면 `404 Not Found`를 반환한다. + +#### 9.2.6. 노드 파일시스템 브라우징 (Node Filesystem Browsing) + +엣지 노드가 특정 로컬 머신의 파일시스템을 마스터 서버를 통해 탐색한다. 세션 생성(§9.3.1) 전 `workspace_path` 선택에 사용한다. + +**Endpoint:** `POST /v1/edge/nodes/{node_id}/fs/browse` (Master Server 제공) + +**Request:** §4.5의 Request 스키마와 동일하다. + +**Response (200 OK):** + +```json +{ + "node_id": "String (필수)", + "agent_id": "String (필수)", + "base_path": "String (필수, 루트 모드 시 빈 문자열)", + "os_type": "String (필수, 'unix' | 'windows')", + "entries": ["Entry (§4.5의 Entry 스키마와 동일)"], + "truncated": "Boolean (필수)", + "total_entries_count": "Number (선택)" +} +``` + +마스터 서버는 대상 클라이언트의 `POST /v1/fs/browse`(§4.5)로 요청을 투명하게 프록시한다. 클라이언트가 반환한 4xx 에러는 그대로 패스스루한다. + +**에러:** + +| HTTP 상태 | error_code | 조건 | +| ----------- | ---------------- | ------------------------ | +| 400/403/404 | (§4.5 동일) | 클라이언트 에러 패스스루 | +| 404 | `NODE_NOT_FOUND` | 노드 미존재 | +| 404 | `NODE_OFFLINE` | 노드 오프라인 | +| 502 | `CLIENT_ERROR` | 클라이언트 5xx 에러 | +| 504 | `CLIENT_TIMEOUT` | 클라이언트 응답 타임아웃 | + ### 9.3. 엣지 세션(Edge Session) 라이프사이클 관리 ... #### 9.3.1. 원격 세션 생성 (Edge → Master) ... diff truncated ... ``` ### 10. 로컬 세션 관리 (Local Session Management) - 이전 앵커: `#10-local-session-management` - 현재 앵커: `#10-local-session-management` - 추가된 줄: 3 - 삭제된 줄: 3 ```diff ```json { - "agent_name": "String (필수, 실행할 에이전트 이름. §4.3의 에이전트 목록 참조)", + "agent_id": "String (필수, 실행할 에이전트 식별자. §4.3의 에이전트 목록 참조)", "workspace_path": "String (필수, 작업 디렉토리 절대 경로)", - "session_name": "String (선택, 세션 표시명. 생략 시 agent_name + 생성 시각으로 자동 생성)" + "session_name": "String (선택, 세션 표시명. 생략 시 agent_id + 생성 시각으로 자동 생성)" } ``` ... { "session_id": "String (필수)", - "agent_name": "String (필수)", + "agent_id": "String (필수)", "workspace_path": "String (필수)", "session_name": "String (필수)", ```