From fdfda9aa105f4ce6a3c6026aff06d7967e4e61e9 Mon Sep 17 00:00:00 2001 From: Seongjae Date: Thu, 17 Sep 2026 16:52:26 +0900 Subject: [PATCH] Publish security and upstream guides as bilingual pairs. Public titles drop W05 and W13. The registry records security-model, runner-isolation, error-codes, codex-reuse, upstream-lock, and upstream-update. Codex sources and the workspace example stay off the site and remap to repository blob URLs. Co-authored-by: Cursor --- docs/codex-reuse.md | 2 + docs/error-codes.md | 2 + docs/index.md | 6 + docs/ko/architecture.md | 8 +- docs/ko/codex-reuse.md | 362 +++++++++++++++++++++++++++++++++ docs/ko/error-codes.md | 67 ++++++ docs/ko/execution-substrate.md | 8 +- docs/ko/index.md | 6 + docs/ko/operations.md | 4 +- docs/ko/runner-isolation.md | 53 +++++ docs/ko/security-model.md | 126 ++++++++++++ docs/ko/upstream-lock.md | 105 ++++++++++ docs/ko/upstream-update.md | 66 ++++++ docs/runner-isolation.md | 4 +- docs/security-model.md | 2 + docs/translations.json | 172 +++++++++++++++- docs/upstream-lock.md | 2 + docs/upstream-update.md | 4 +- 18 files changed, 982 insertions(+), 17 deletions(-) create mode 100644 docs/ko/codex-reuse.md create mode 100644 docs/ko/error-codes.md create mode 100644 docs/ko/runner-isolation.md create mode 100644 docs/ko/security-model.md create mode 100644 docs/ko/upstream-lock.md create mode 100644 docs/ko/upstream-update.md diff --git a/docs/codex-reuse.md b/docs/codex-reuse.md index 08e1eec..a7902c3 100644 --- a/docs/codex-reuse.md +++ b/docs/codex-reuse.md @@ -1,5 +1,7 @@ # Codex reuse: product vs primitive +[English](codex-reuse.md) | [한국어](ko/codex-reuse.md) + CodeSpace does **not** embed the Codex agent. It also does **not** reimplement every execution mechanism from scratch. diff --git a/docs/error-codes.md b/docs/error-codes.md index 5a614d3..daa1695 100644 --- a/docs/error-codes.md +++ b/docs/error-codes.md @@ -1,5 +1,7 @@ # Error codes and transport vs execution +[English](error-codes.md) | [한국어](ko/error-codes.md) + HTTP/JSON-RPC **request id**, `operation_id`, and `process_id` are three different identifiers. A lost HTTP response is not an execution failure. Clients call `operation_status` (W08) instead of replaying a mutating tool. diff --git a/docs/index.md b/docs/index.md index 1ceb862..3dc913b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,4 +16,10 @@ workspace. - [Execution substrate](execution-substrate.md) — no-model execution invariant - [Protocol compatibility](protocol-compatibility.md) — MCP 2025-11-25 baseline - [Behavior differences](behavior-differences.md) — product policy vs crate defaults +- [Security model](security-model.md) — gateway policy and trust boundaries +- [Runner isolation](runner-isolation.md) — current host exec and target Linux container +- [Error codes](error-codes.md) — transport failure vs execution error +- [Codex reuse](codex-reuse.md) — product vs primitive +- [Upstream lock](upstream-lock.md) — pinned Codex submodule +- [Upstream pin update](upstream-update.md) — deliberate release checklist - [Documentation site](documentation.md) — bilingual registry and Pages diff --git a/docs/ko/architecture.md b/docs/ko/architecture.md index 1c15547..c20bf7f 100644 --- a/docs/ko/architecture.md +++ b/docs/ko/architecture.md @@ -27,7 +27,7 @@ Codex V4A 패치를 적용하며, 등록된 워크스페이스에서 관리형 이후 Runner 뒤에 격리된 응집력 있는 **실행 서브그래프**(hardening, PTY, UDS, path, filesystem, Linux sandbox, network). Codex는 구현 의존성이며 제어 평면이 아닙니다 - ([codex-reuse.md](../codex-reuse.md)). + ([codex-reuse.md](codex-reuse.md)). 가져오지 않은 것: Electron, Chrome 확장, ChatGPT DOM, agents spawn, Desktop, 플러그인 마켓플레이스, TypeScript `apply-patch` 포트, @@ -197,9 +197,9 @@ Bearer 미들웨어로 남고, 디스패치는 `/mcp` → rmcp 도구입니다. 재정렬합니다. 의도 본문은 지시이지 능력이 아닙니다. 내부 모델 호출 도구는 없습니다. `git_apply_patch`는 MVP 밖입니다. -오류 코드와 전송 대 실행 규칙: [error-codes.md](../error-codes.md). -Linux 격리 픽스처: [runner-isolation.md](../runner-isolation.md). -Codex 제품 대 프리미티브: [codex-reuse.md](../codex-reuse.md). +오류 코드와 전송 대 실행 규칙: [error-codes.md](error-codes.md). +Linux 격리 픽스처: [runner-isolation.md](runner-isolation.md). +Codex 제품 대 프리미티브: [codex-reuse.md](codex-reuse.md). 실행 전용 기반: [execution-substrate.md](execution-substrate.md). ## ID diff --git a/docs/ko/codex-reuse.md b/docs/ko/codex-reuse.md new file mode 100644 index 0000000..b5e609c --- /dev/null +++ b/docs/ko/codex-reuse.md @@ -0,0 +1,362 @@ +# Codex 재사용: 제품과 프리미티브 + +[English](../codex-reuse.md) | [한국어](codex-reuse.md) + +CodeSpace는 Codex 에이전트를 넣지 **않습니다**. 모든 실행 메커니즘을 +처음부터 재구현하지도 **않습니다**. + +> CodeSpace는 Codex 실행 코드를 피하지 않습니다. Codex 에이전트/제품 +> 소유권이 CodeSpace 핵심에 들어오는 것을 막습니다. 의미와 인가는 여기에 +> 남고, 저수준 실행은 핀된 Codex 서브그래프에서 옵니다. + +요점은 “코드를 덜 쓰는 것”이 아닙니다. 핀 범프가 PTY, 샌드박스, +hardening, 경로 버그 수정을 물려받아야 합니다. 그다음 CodeSpace는 MCP, +인가, 작업 신원, Runner 계약에 힘을 씁니다. + +이 프로세스는 실행 전용입니다. 모델 없음, Responses API 없음 +([execution-substrate.md](execution-substrate.md)). App Server +**프로토콜**은 MCP 번역 대상이 아닙니다. `command/exec` **형태** +(독립 argv, 핸들, 이후 TTY)는 Runner DTO에 올 수 있습니다. +`codex-exec`, `codex-core`, App Server는 금지된 채로 남습니다. + +```text +WHO MAY → CodeSpace Gateway + MCP contract, workspace, profile meaning, + operation/idempotency, audit, Runner trait + +HOW SAFE → pinned Codex execution subgraph + patch engine, PTY, spawn/reap, Landlock/seccomp, + process hardening, filesystem mechanics, + network enforcement +``` + +서브그래프를 재사용해도 Codex가 인가자가 되지는 **않습니다**. +게이트웨이가 여전히 허용하고, 어댑터가 여전히 실행합니다. + +```text +ChatGPT / Cursor / other MCP host + │ MCP + ▼ +CodeSpace Core ← only authorization authority + ├─ MCP / workspace / profile meaning + ├─ operation_key / operation_id / persist + └─ Runner contract (CodeSpace DTOs; no Codex types) + │ + ▼ + isolated adapter workspace + │ crates/patch today (codespace-patch) + │ crates/codex-runtime later + │ crate name: codespace-codex-runtime + │ (documented only; not created in this WP) + ▼ + Codex execution subgraph (pinned) → OS +``` + +Codex는 어댑터 뒤의 **구현** 의존성이며 Gateway의 아키텍처 의존성이 +아닙니다. `InProcessRunner`, `ContainerRunner`, 이후 원격 러너, 또는 +다른 샌드박스 백엔드는 Codex 타입이 어댑터를 떠나지 않으면 바뀔 수 +있습니다. + +## 재사용 단위는 서브그래프 + +“`codex-apply-patch`만큼 좁아야 한다”를 요구하지 마세요. 물으세요. + +1. 이 서브그래프가 **응집력 있는 실행**인가? +2. **에이전트 / 모델 / 제품** 타입이 Runner 경계를 넘는가? +3. **Gateway 허용을 우회**할 수 있는가? + +넓은 Cargo 그래프 자체는 거절이 아닙니다. PTY fd 처리, 시그널 레이스, +Landlock, 마운트 탈출, 또는 프로세스 hardening을 재구현하면 Codex 버그 +수정이 손으로만 옵니다. 선호: + +```text +Codex bugfix → candidate pin → adapter compile / security / parity → promotion +``` + +그것은 **“`main`을 추적”이 아닙니다.** 릴리스 수락은 +[upstream-update.md](upstream-update.md)에 남습니다. 핀 범프에서 +hardening / PTY / sandbox / filesystem / network 크레이트의 diff는 +실행/보안 변경 로그이지 조용한 의존성 범프가 아닙니다. + +컨테이너 격리와 호스트 샌드박스는 **대체물이 아닙니다**. 컨테이너에 +no-new-privs / seccomp / Landlock / 네트워크 한도를 더하는 것은 +심층 방어입니다. 이후 Environment(로컬 컨테이너, 원격 Linux, 베어 +Linux)는 같은 Linux 샌드박스 서브그래프를 공유할 수 있습니다. + +## 핵심 대 어댑터 + +```text +CodeSpace core + crates/domain, policy, store, server, runner + ────────────────────────────────────────── + NO Codex types (including codex-protocol) + NO Codex crate path dependency + + +isolated adapter (crates/patch today; +crates/codex-runtime later) + ────────────────────────────────────────── + approved execution subgraph allowed + including transitive codex-protocol + + +adapter boundary + ────────────────────────────────────────── + CodeSpace DTO ↔ Codex DTO +``` + +공개 MCP는 `workspace_id` + 상대 경로로 남습니다. 내부에서 어댑터는 +해석할 수 있습니다. + +```text +MCP virtual path + ↓ +CodeSpace WorkspaceResolver / path scope + ↓ +Codex AbsolutePath / PathUri (adapter only) + ↓ +Runner helper +``` + +## 정책 대 메커니즘 + +| CodeSpace가 소유 (정책) | Codex를 선호 (메커니즘) | +| --- | --- | +| workspace / profile allow | PTY, UDS transport primitive | +| path permission meaning | filesystem walk / symlink mechanics | +| network permission meaning | seccomp / Landlock / hardening | +| operation approval | network enforcement (when needed) | +| Runner RPC contract | shell parse / argv construction | + +`codex-execpolicy`는 어댑터에서 파싱하거나 분류할 수 있습니다. 최종 +`allow(command)`가 **아닙니다**. + +## `apply_patch` 패턴 (격리이지 크레이트 너비가 아님) + +엔진을 재사용하세요. 그 주변 서비스는 소유하세요. 이후 런타임 어댑터도 +같은 패턴입니다. + +- 핀은 [upstream-lock.md](upstream-lock.md)에 남습니다 + (`6b9826e3aa83b1a5947db50f4332cb9c65f1b340`). +- **격리된** Cargo 워크스페이스에서의 경로 의존성이며 저장소 루트가 + 아닙니다. 오늘: `crates/patch`. 이후: `crates/codex-runtime` + (`codespace-codex-runtime`. 문서만. **이 작업 패키지에서 만들지 + 않음**). +- NOTICE + Apache-2.0 귀속. +- 제품 정책은 서브그래프 앞과 뒤에 남습니다. +- Codex 워크스페이스에서 크레이트를 파일 복사하지 마세요. + +```text +Gateway → Runner trait → (later) ContainerRunner + → codespace-codex-runtime helper → Codex execution crates +``` + +루트 워크스페이스에 Codex 경로 의존성이 생기면 안 됩니다. + +정책 스캔(`scripts/check-no-model-deps.sh`)은 Codex 서브모듈 **없이** +돌아가는 싼 병렬 CI job입니다. 비용은 이 grep이 아니라 서브모듈 +checkout과 cargo가 지배합니다. + +| 구역 | 경로 | 비용 | 때 | +| --- | --- | --- | --- | +| core manifests | root + `crates/{domain,policy,runner,store,server}/Cargo.toml` | tiny | crate in the update range | +| core sources | those crates’ trees | low | same | +| server tests | `tests/` | low | `crates/server` or `tests/` changed | +| adapter manifests | `crates/patch/Cargo.toml`; later `crates/codex-runtime` | tiny | adapter in the update range; allowlist only | +| upstream | `third_party/codex` | huge / false positives | never | + +갱신 범위는 `SCAN_BASE`(PR base / 이전 `main`)입니다. 범위를 모르면 +**모든** 핵심 크레이트와 어댑터 매니페스트를 스캔합니다(diff 실패로 +건너뛰지 않음). 문서만 바뀌면 이 job은 exit 0으로 건너뛰고, rust job은 +여전히 실행됩니다. + +핵심 매니페스트는 어떤 `codex-` 의존성 키도 금지합니다. 어댑터 +매니페스트는 승인된 서브그래프만 허용합니다(오늘 `crates/patch`: +`codex-apply-patch`, apply-patch 워크스페이스 그래프로서 +`codex-exec-server`, `codex-utils-path-uri`). 소스는 에이전트/모델 +패턴을 유지합니다(`api.openai.com`, Responses, `codex-login`, +`codex-core`, `codex-app-server`, `async-openai`). 크레이트 이름을 +언급하는 주석은 cargo 의존성이 아닙니다. + +독립 `apply_patch` 바이너리를 보안 경계로 감싸지 **마세요**. Codex App +Server를 내부 백엔드로 감싸지 **마세요**. + +## 감독 코드가 아직 있는 이유 + +`process_id`, stdin, terminate, timeout이 모이는 이유는 요청 수명이 +프로세스 수명이 아니기 때문입니다. 프로세스 내부 감독은 Runner 전송이 +생길 때까지 CodeSpace에 남습니다. `operation_key` / `operation_status`는 +잃어버린 **원격 MCP 변경 RPC**를 복구하며, Codex 스레드를 복구하지 +않습니다. + +spawn+PTY를 얻으려고 `codex-core` / `codex-exec` / App Server를 끌어오면 +login, models, plugins, rollout도 따라옵니다. 그 폭발 반경은 여전히 +거절입니다. + +## 단계적 가져오기 (그 WP가 생길 때) + +문서화된 순서입니다. **이 작업 패키지에서 크레이트를 추가하지 않습니다.** + +```text +process-hardening → PTY → UDS / path → filesystem → linux-sandbox → network +``` + +복잡도와 잠금은 그 순서로 커집니다. 핀은 가져가는 모든 서브시스템을 +한 번에 정의합니다. + +## 핀 `6b9826e`의 후보 + +Codex `main`이 아니라 핀의 `Cargo.toml` 파일로 판단합니다. + +### 지금 재사용 (코드에서) + +**`codex-apply-patch`** via `crates/patch`. 파싱, 헝크 검증, 적용, +패리티 부분집합. + +### 재사용 선호 (그 WP가 올 때) + +**`codex-process-hardening`** +([`codex-rs/process-hardening/Cargo.toml`](../../third_party/codex/codex-rs/process-hardening/Cargo.toml)) + +런타임 의존성은 `libc`입니다. 코어 덤프, `PR_SET_DUMPABLE`, macOS +디버거 연결, `LD_*` / `DYLD_*` 제거. 첫 재사용 후보: 다시 짜도 +CodeSpace가 얻는 독립은 거의 없습니다. + +**`codex-utils-pty`** +([`codex-rs/utils/pty/Cargo.toml`](../../third_party/codex/codex-rs/utils/pty/Cargo.toml)) + +Unix: `portable-pty`, `tokio`, `libc`. CodeSpace PTY보다 업스트림을 +선호하세요. 연결해도 PTY MCP 도구가 추가되지는 **않습니다**. +게이트웨이가 여전히 `process_id`를 발급합니다. + +**`codex-uds`** +([`codex-rs/uds/Cargo.toml`](../../third_party/codex/codex-rs/uds/Cargo.toml)) + +Unix: Tokio `fs` / `net` / `rt`. 다음 Runner Unix 소켓 전송에 맞습니다. +**RPC 프로토콜은 CodeSpace 소유로 남습니다.** 이 크레이트는 전송 +프리미티브입니다. + +**`codex-utils-absolute-path` / `codex-utils-path-uri`** + +작은 경로/URI 층(`dirs`, `dunce`, URL). 패치가 이미 필요합니다. MCP는 +여전히 워크스페이스 상대 경로만 노출합니다. + +**`codex-file-search`** +([`codex-rs/file-search/Cargo.toml`](../../third_party/codex/codex-rs/file-search/Cargo.toml)) + +`ignore`, `nucleo`, Tokio. `codex-core` 없음. MCP는 +`find(query, workspace_id)`로 남고, 엔진은 어댑터 뒤로 옮길 수 있습니다. + +### 조건부 / 적극 평가 + +**`codex-file-system`** +([`codex-rs/file-system/Cargo.toml`](../../third_party/codex/codex-rs/file-system/Cargo.toml)) + +제한된 탐색, 심링크 제어, executor FS 타입. `codex-protocol`에 +의존합니다. `PathSandbox`를 지우지 **마세요**. 목표: + +```text +CodeSpace path scope / authorization + ↓ +Codex ExecutorFileSystem (adapter) +``` + +**`codex-shell-command`** + +Tree-sitter Bash/PowerShell, shlex, `which`. 파싱 / 인용 / 실행 파일 +해석만. 허용 엔진이 아닙니다. + +**`codex-linux-sandbox`** +([`codex-rs/linux-sandbox/Cargo.toml`](../../third_party/codex/codex-rs/linux-sandbox/Cargo.toml)) + +Landlock, seccomp, process-hardening, network-proxy, protocol, +sandboxing. 너비는 응집력 있는 Linux 샌드박스입니다. **컨테이너**가 +이를 대체하지 않습니다. 런타임 의존성에는 `codex-core`가 없습니다. +**dev-dependencies에는 있습니다** — 어댑터 시험이 그 그래프를 제품 +바이너리로 끌어오면 안 됩니다. + +**전이(서브그래프를 가져가면 어댑터에서 허용):** +`codex-sandboxing`, `codex-network-proxy`. 프록시의 직접 사용은 +PermissionProfile **네트워크** 축이 있을 때입니다. 허용 엔진이 +아닙니다. 루트 워크스페이스 의존성이 아닙니다. + +### 내부 프로토콜 후보 + +**`codex-exec-server-protocol`** +([`codex-rs/exec-server-protocol/Cargo.toml`](../../third_party/codex/codex-rs/exec-server-protocol/Cargo.toml)) + +file-system, network-proxy, protocol, shell-command, path-uri. 이후 +워커 DTO / 어댑터 기반. MCP나 `crates/domain` 타입이 **아닙니다**. + +### 격리 층 전이: `codex-protocol` + +무거움: execpolicy, http-client, network-proxy, extension items, +Linux에서 Landlock/seccompiler. **핵심에서 금지.** 어댑터에서는 +허용합니다. 금지하면 file-system, sandbox, shell-command를 다시 짜야 +합니다. `codex_protocol::PermissionProfile`은 MCP나 `crates/domain`에 +나타나면 안 됩니다. + +### 실험적 백엔드 (지금은 아님) + +**`codex-exec-server`** +([`codex-rs/exec-server/Cargo.toml`](../../third_party/codex/codex-rs/exec-server/Cargo.toml)) + +HTTP/WS plus `codex-api`, `codex-config`, OTel, protocol, sandboxing, +PTY. 오늘의 Runner 백엔드로는 너무 무겁습니다. 영구 거절은 아닙니다. +나중에 ContainerRunner + 저수준 크레이트 대 Gateway 어댑터 → +exec-server를 비교하세요. 컴파일 그래프와 업그레이드 비용을 재세요. + +### 이후 Environment (P0 아님) + +**`codex-git-utils` / `codex-worktree`** — Environment 프로비저닝이 +필요하면 격리된 checkout / worktree 수명주기. file-system, protocol, +PTY, `gix`를 끌어옵니다. 그 WP까지 빼 두세요. + +### 코드는 허용, 권한은 금지 + +**`codex-execpolicy`** — Starlark 접두 규칙. 어댑터의 분류/파싱은 +괜찮습니다. 최종 허용은 Gateway에 남습니다. + +### 거절 + +**`codex-exec`** — App Server 클라이언트, `codex-core`, login, config, +rollout, history. 제품 exec 흐름이지 `spawn`이 아닙니다. + +**`codex-core`** — 에이전트 루프, 도구, 세션. + +**App Server embed** (`ChatGPT → MCP adapter → Codex App Server`) — +에이전트 인프라를 다시 가져오고 인가를 나눕니다. + +**login / model / Responses** — 실행 전용 위반. + +**Codex 세션 `permissionProfile` / 사용자 샌드박스 설정을 허용으로** — +두 번째 인가자. + +## CodeSpace에 남는 것 + +- MCP 도구 스키마와 도메인 타입(runner/domain에 `rmcp` 없음. 핵심에 + Codex 타입 없음). +- 워크스페이스 레지스트리, 프로필의 **의미**, 경로 정책. +- 쓰기 잠금, 셸 점유, `WORKSPACE_BUSY`(스케줄러 WP까지). +- `operation_key` 재실행, `operation_id`, `operation_status`. +- Runner 전송이 생길 때까지 호스트/프로세스 내부 프로세스 감독. +- 컨테이너 수명주기와 워크스페이스 바인드 마운트 **정책**. +- 격리된 어댑터 워크스페이스(`crates/patch`, 이후 + `crates/codex-runtime` / `codespace-codex-runtime`). + +## 다음 구현 WP + +다음 **코드** 작업 패키지는 여전히 기존 `Runner` 트레이트 뒤의 Runner +**전송**(Unix 소켓 / `ContainerRunner`)입니다. 그 WP는 `apply_patch`를 +게이트웨이가 구동하는 여러 RPC로 쪼개면 안 됩니다. + +기본으로 자체 PTY / Landlock / seccomp / UDS 스택을 두지 마세요. +위 표 이후 격리된 워크스페이스를 통해 실행 서브그래프를 가져오세요. +핀 범프는 의도적 릴리스입니다 +([upstream-update.md](upstream-update.md)): 지금은 SHA + 패치 패리티. +그 워크스페이스가 생기면 런타임 어댑터 빌드와 PTY / sandbox / process +회귀를 더합니다. + +도메인 확장(PermissionProfile 축, Environment, 스케줄러, 승인 도구)은 +[execution-substrate.md](execution-substrate.md)에서 순서를 정합니다. +이 작업 패키지에서 실제 MCP 스키마는 바뀌지 않습니다. diff --git a/docs/ko/error-codes.md b/docs/ko/error-codes.md new file mode 100644 index 0000000..ff98f0d --- /dev/null +++ b/docs/ko/error-codes.md @@ -0,0 +1,67 @@ +# 오류 코드와 전송 대 실행 + +[English](../error-codes.md) | [한국어](error-codes.md) + +HTTP/JSON-RPC **요청 id**, `operation_id`, `process_id`는 세 개의 서로 +다른 식별자입니다. 잃어버린 HTTP 응답은 실행 실패가 아닙니다. +클라이언트는 변경 도구를 재실행하는 대신 `operation_status`(W08)를 +호출합니다. + +## 전송 실패 (작업 없음) + +이들은 `operation_id`를 절대 발급하지 않으며 작업으로 저장되면 안 +됩니다. + +| 신호 | 의미 | +| --- | --- | +| TCP reset / client disconnect | Wire died. The process or patch may still be running. | +| HTTP 401 / 403 from Bearer middleware | Auth failed **before** any tool handler. | +| HTTP 404 at `/mcp` | Wrong path. | +| HTTP 408 / 502 / 503 / 504 | Transport or proxy. | + +`codespace_domain::classify_http_status`는 이를 +`FailureClass::Transport`로 매핑합니다. `TRANSPORT_FAILURE_IS_NOT_OPERATION`은 +참입니다. + +## 실행 오류 코드 (도구 결과) + +JSON에서 `SCREAMING_SNAKE_CASE`로 직렬화됩니다. + +| 코드 | 때 | +| --- | --- | +| `UNAUTHORIZED` | Tool-layer refusal after a valid transport (not Bearer 401) | +| `WORKSPACE_NOT_FOUND` | Unknown `workspace_id` (W04) | +| `WORKSPACE_BUSY` | Write lock held by a live shell (W08 / W10) | +| `INVALID_PATCH` | Codex parse failure (W06 / W09) | +| `PATH_ESCAPE` | `..` or absolute path outside the workspace | +| `SYMLINK_REJECTED` | Symlink file or escape | +| `SPECIAL_FILE_REJECTED` | Device, socket, fifo | +| `ADD_FILE_EXISTS` | Add File destination already exists | +| `MOVE_DESTINATION_EXISTS` | Move destination already exists | +| `VERSION_CONFLICT` | `expected_versions` mismatch | +| `OPERATION_KEY_CONFLICT` | Same key, different request (W08) | +| `OPERATION_NOT_FOUND` | Unknown `operation_id` / `operation_key`, or `operation_status` did not receive exactly one of them | +| `PROCESS_NOT_FOUND` | Unknown `process_id` | +| `OUTPUT_LIMIT` | Reserved; live `read_process` drops oldest bytes instead of storing unbounded output | +| `TIMEOUT` | Managed process time limit (default 30s; `CODESPACE_PROCESS_TIMEOUT_SECS`) | +| `WORK_NOT_FOUND` | Unknown `work_id` | +| `WORK_CLOSED` | Mutating steer on a closed work | +| `INTENT_NOT_FOUND` | Unknown `intent_id` | +| `INTENT_ALREADY_CLAIMED` | Edit/cancel after the model claimed the item | +| `INTENT_NOT_EDITABLE` | State is not draft/queued | +| `INTENT_REVISION_CONFLICT` | Optimistic `revision` mismatch | +| `QUEUE_NOT_EMPTY` | Reserved; `work_finish` returns `closed: false` instead of this error | + +적용 결과는 `status`를 사용합니다(`applied`, `checked`, `rejected`, +`failed_rolled_back`, `failed_partial`, `unknown`). `checked`는 성공한 +`check_only` 미리보기입니다. `rejected`는 실제 거절입니다. 실패한 적용은 +절대 `applied`를 보고하지 않습니다. `applied`는 디스크 해시가 헬퍼가 +주장한 `after_version`과 일치해야 합니다. 재시작은 미완료 행을 +`unknown`으로 남기고 자동 적용하지 않습니다. + +`begin`이 `operation_id`를 발급한 뒤, 도구 오류는 그 id를 +`ErrorBody.operation_id`에 포함합니다. `begin` 전의 정책 / 잠금 / +키 충돌 거절은 포함하지 않습니다. + +대기 중인 사용자 입력이 있는 `work_finish`는 **전송 실패가 아닙니다**. +`{ "closed": false, "reason": "pending_user_input" }`를 반환합니다. diff --git a/docs/ko/execution-substrate.md b/docs/ko/execution-substrate.md index 8e827a5..fe588d8 100644 --- a/docs/ko/execution-substrate.md +++ b/docs/ko/execution-substrate.md @@ -33,8 +33,8 @@ CodeSpace 도구로 다시 노출하세요. (구현 의존성이지 아키텍처 의존성이 아님). 핵심 크레이트는 `codex-protocol`을 포함해 Codex 타입을 가져오면 안 됩니다. 어댑터는 가져도 됩니다. 가져오기/빼기 표: -[codex-reuse.md](../codex-reuse.md). 핀: -[upstream-lock.md](../upstream-lock.md) (`6b9826e`, `rust-v0.154.0`). +[codex-reuse.md](codex-reuse.md). 핀: +[upstream-lock.md](upstream-lock.md) (`6b9826e`, `rust-v0.154.0`). Codex `main` `4701aa4b`를 언급하는 조사 노트는 핀 범프가 **아닙니다**. 의도적인 W13 갱신 뒤에 그래프를 다시 확인하세요. @@ -118,7 +118,7 @@ exec_command / write_stdin / read_process / terminate_process `codex-exec-server-protocol`은 내부 워커 DTO 후보입니다. `codex-exec-server`는 실험적 백엔드(`codex-api` / `codex-config`)이며 영구 거절은 아닙니다 -([codex-reuse.md](../codex-reuse.md)). 샌드박스 정책을 “Codex 사용자 +([codex-reuse.md](codex-reuse.md)). 샌드박스 정책을 “Codex 사용자 설정”에서 기본값으로 두지 **마세요**. 게이트웨이는 이미 허용된 요청을 러너 DTO로 매핑합니다. `codex-process-hardening`, `codex-utils-pty`, `codex-uds`(전송 프리미티브, RPC는 CodeSpace)를 선호하세요. PathSandbox @@ -228,4 +228,4 @@ network). 다음 **코드** WP는 기존 트레이트 뒤의 Runner **전송**으로 남으며, `apply_patch`를 게이트웨이 RPC로 쪼개지 않습니다. Sandbox / PTY / network는 기본 자체 OS 스택이 아닙니다 -([codex-reuse.md](../codex-reuse.md)). +([codex-reuse.md](codex-reuse.md)). diff --git a/docs/ko/index.md b/docs/ko/index.md index c6fe1f5..56e9083 100644 --- a/docs/ko/index.md +++ b/docs/ko/index.md @@ -16,4 +16,10 @@ Codex 형식 패치를 적용하며, 등록된 워크스페이스에서 관리 - [실행 기반](execution-substrate.md) — 모델 없는 실행 불변식 - [프로토콜 호환성](protocol-compatibility.md) — MCP 2025-11-25 기준 - [동작 차이](behavior-differences.md) — 제품 정책 대 크레이트 기본값 +- [보안 모델](security-model.md) — 게이트웨이 정책과 신뢰 경계 +- [러너 격리](runner-isolation.md) — 현재 호스트 exec와 목표 Linux 컨테이너 +- [오류 코드](error-codes.md) — 전송 실패 대 실행 오류 +- [Codex 재사용](codex-reuse.md) — 제품 대 프리미티브 +- [업스트림 고정](upstream-lock.md) — 핀된 Codex 서브모듈 +- [업스트림 핀 갱신](upstream-update.md) — 의도적 릴리스 절차 - [문서 사이트](documentation.md) — 영·한 레지스트리와 Pages diff --git a/docs/ko/operations.md b/docs/ko/operations.md index cc6323a..0d797e3 100644 --- a/docs/ko/operations.md +++ b/docs/ko/operations.md @@ -21,10 +21,10 @@ cd CodeSpace # git submodule update --init --recursive ``` -Codex 핀은 [upstream-lock.md](../upstream-lock.md)의 커밋에 있는 +Codex 핀은 [upstream-lock.md](upstream-lock.md)의 커밋에 있는 `third_party/codex`입니다. Codex `main`으로 `git submodule update --remote`를 하지 마세요. 제품 런타임은 게이트웨이 밖에 둡니다. -[codex-reuse.md](../codex-reuse.md)와 +[codex-reuse.md](codex-reuse.md)와 [execution-substrate.md](execution-substrate.md)를 보세요. 게이트웨이가 패치 헬퍼를 자기 옆에서 찾을 수 있도록 두 바이너리를 diff --git a/docs/ko/runner-isolation.md b/docs/ko/runner-isolation.md new file mode 100644 index 0000000..41ff2e3 --- /dev/null +++ b/docs/ko/runner-isolation.md @@ -0,0 +1,53 @@ +# 러너 격리 + +[English](../runner-isolation.md) | [한국어](runner-isolation.md) + +**목표** 실행 격리 OS는 Linux 컨테이너입니다. **현재** `exec_command`는 +호스트 프로세스입니다(`tokio::process::Command`, 워크스페이스 cwd, +`env_clear`). 게이트웨이 단위 시험은 macOS에서 실행할 수 있습니다. 그것은 +개발 노트북에서 Linux 격리를 검증했다는 주장이 아닙니다. + +## compose 픽스처가 하는 일 + +[`deploy/compose.yml`](../../deploy/compose.yml)은 **격리 픽스처**입니다. +비특권 사용자(`uid 10001`)로 실행하고, 워크스페이스만 `/workspace`에 +바인드 마운트한 뒤 sleep합니다. `codespace-mcp` / `codespace-patch`를 +실어 보내지 않으며 `exec_command`에 **연결되어 있지 않습니다**. + +마운트하지 않는 것: + +- host `$HOME` +- SSH agent socket +- `/var/run/docker.sock` +- gateway `.env`, Bearer files, or SQLite + +지금은 러너 제어 소켓이 없습니다. 이 픽스처에 호스트 Docker 소켓이나 +이후 제어 소켓을 실수로 추가하지 마세요. + +## macOS / Docker 없음 + +`codespace-runner::PathSandbox`는 단위 시험과 `read` / `find` / versions에 +같은 상대 경로 + 심링크 + 특수 파일 규칙을 적용합니다. Docker를 쓰지 +않으면 **Linux 컨테이너 격리는 검증되지 않습니다**. 호스트 +seccomp/AppArmor와 Docker Desktop 대 Linux 엔진 차이도 검증되지 않습니다. + +## 이후 프로세스 분리 + +오늘은 `codespace-mcp`가 한 프로세스입니다. `crates/runner`가 프로세스 +내부 `Runner`를 호스팅합니다(`PathSandbox`, `apply_patch` 트랜잭션 하나, +호스트 감독). 이후 Unix 소켓 / `ContainerRunner` 워커는 같은 크레이트에 +살며, 양쪽 모두 Rust로 남습니다. 그 **전송** 분리가 다음 구현 WP이며 +이 문서가 아닙니다. 소켓 프리미티브로 `codex-uds`를 선호하세요. Runner +RPC는 CodeSpace 계약으로 남습니다. + +Linux 격리는 여전히 목표 OS입니다. Landlock, seccomp, PTY 헬퍼, UDS, +파일시스템 역학, 네트워크 격리는 **기본 자체 스택이 아닙니다**. 업스트림 +실행 서브그래프를 선호하세요 +([codex-reuse.md](codex-reuse.md)). 단계: +process-hardening → PTY → UDS/path → filesystem → linux-sandbox → +network. `codex-linux-sandbox`는 컨테이너 옆에 둘 수 있습니다. 그 +`codex-core` **dev-dep**는 제품 그래프에서 빼 두세요. `codex-exec`는 +거절된 채로 남습니다. `codex-exec-server`는 참고 / 이후 백엔드이며 +영구 거절은 아닙니다. 게이트웨이 정책이 유일한 허용 경로입니다. compose +픽스처에 호스트 Docker 소켓이나 이후 제어 소켓을 실수로 마운트하지 +마세요. diff --git a/docs/ko/security-model.md b/docs/ko/security-model.md new file mode 100644 index 0000000..b828b89 --- /dev/null +++ b/docs/ko/security-model.md @@ -0,0 +1,126 @@ +# 보안 모델 + +[English](../security-model.md) | [한국어](security-model.md) + +CodeSpace는 커널 샌드박스가 아닙니다. CoS와 cokacremote도 아닙니다. +인가는 **게이트웨이 정책**입니다. Linux 컨테이너 격리가 **목표** 실행 +OS입니다. 현재 `exec_command`는 워크스페이스 cwd를 가진 호스트 +프로세스입니다. Codex 패치 크레이트는 제품 경계를 공급하지 않습니다. +Codex 세션 설정과 `permissionProfile`은 허용 경로가 아닙니다. 게이트웨이와 +러너는 둘 다 Rust입니다. 언어를 나눠도 신뢰 경계가 추가되지 않습니다. +프리미티브 대 제품: +[codex-reuse.md](codex-reuse.md). 실행 전용 기반: +[execution-substrate.md](execution-substrate.md). + +## 신뢰 경계 + +1. **MCP client** — 인가에 대해 신뢰하지 않음. `workspace_id`, + `approved: true`, 절대 경로를 포함해 어떤 도구 인자도 보낼 수 + 있습니다. 그 인자는 권리를 부여하지 않습니다. +2. **Gateway (`crates/server` + `crates/policy`)** — 전송을 인증하고 + (HTTP 실험의 선택적 정적 Bearer), 등록된 워크스페이스를 고르며, + 프로필이 허용하지 않는 작업을 거절하도록 신뢰합니다. +3. **Runner (`crates/runner`, 오늘은 프로세스 내부)** — 경로 정책 + (`PathSandbox`)을 강제하고 이미 인가된 동작의 **호스트** 프로세스를 + 감독하도록 신뢰합니다. 게이트웨이 비밀을 보도록 신뢰하지 않습니다. + 이후 Unix 소켓 / 컨테이너 분리는 같은 Rust 워크스페이스를 유지합니다. + 프로세스 경계이지 언어 경계가 아닙니다. `deploy/` 아래 compose는 + 격리 픽스처이지 이 프로세스가 아닙니다. +4. **Patch helper (`codespace-patch` + `crates/patch`)** — 헬퍼 자식 + **안에서 프로세스 내부로** Codex V4A를 파싱/검증/적용하도록 + 신뢰합니다. 게이트웨이는 JSON stdin/stdout으로 그 자식과 대화합니다. + 샌드박스로는 신뢰하지 않습니다(업스트림 독립 apply는 sandbox `None`을 + 쓰고 심링크를 따를 수 있음). 폐기된 `native/patch-worker`가 아닙니다. + +## 인증 대 선택 + +- 선택적 정적 Bearer는 **HTTP 실험 전용**입니다. OAuth 서버가 아닙니다. + 토큰은 로그나 오류 페이로드에 절대 나타나면 안 됩니다. +- `workspace_id`는 선택자입니다. id를 아는 것이 인증이 아닙니다. +- `work_id`와 `intent_id`는 선택자입니다. 아는 것이 인증이 아닙니다. +- 사용자 의도 본문은 지시입니다. 워크스페이스 프로필을 올리거나 경로 + 정책을 우회하지 않습니다. +- ChatGPT 대화 id는 신뢰 기반이 아닙니다. + +## 워크스페이스 레지스트리 + +워크스페이스는 모델이 아니라 **서버 설정**에 등록됩니다. + +각 항목은 `workspace_id` → `{ root, profile }`을 매핑합니다. + +알 수 없는 id는 거절됩니다. 경로는 엔진에 넘기기 **전에** 해석됩니다. +상대 경로만. 해석 후 그 워크스페이스 루트 안에 남아 있어야 합니다. + +## 프로필 (MVP) + +| 프로필 | 의미 | +| --- | --- | +| `read-only` | Default. `read` / `find` / `workspace_info` / `operation_status`. No patch, no shell. | +| `workspace-write` | Explicit. Mutating patch and shell **inside** the workspace. A live shell can delete workspace files; the product says so honestly. | +| `host-admin` | **Excluded from MVP.** | + +바쁜 셸은 워크스페이스 쓰기 잠금을 잡습니다. 다른 변경 작업은 기다리거나 +`WORKSPACE_BUSY`로 실패합니다. + +## 제품 경로 정책 (크레이트가 허용해도 항상) + +- 상대 경로만. +- 심링크 대상과 특수 파일(디바이스, 소켓, fifo)을 거절. +- 목적지가 이미 있으면 Add File을 거절. +- 목적지가 이미 있으면 Move를 거절. +- 워크스페이스 밖으로 `..`를 따르지 않음. +- 모델의 호스트 절대 경로를 엔진에 넘기지 않음. + +[behavior-differences.md](behavior-differences.md)를 보세요. + +## 러너 격리 (Linux) + +**현재:** `exec_command`는 argv + 워크스페이스 cwd + `env_clear`로 +호스트에서 실행됩니다. 경로 샌드박스는 `read` / `find` / versions / +rollback에 적용되며 Linux 네임스페이스가 아닙니다. + +**목표 / 픽스처:** 비특권 컨테이너 사용자. 워크스페이스를 `/workspace` +(또는 동등한 전용 볼륨)에 마운트합니다. 다음을 마운트하지 **마세요**. + +- host home +- SSH agent socket +- `/var/run/docker.sock` +- gateway `.env`, Bearer files, SQLite + +[`deploy/compose.yml`](../../deploy/compose.yml)은 `sleep infinity`로 그 +속성을 보여줍니다. `exec_command`에 연결되어 있지 않습니다. 지금은 러너 +제어 소켓이 없습니다. + +게이트웨이 단위 시험은 macOS에서 실행할 수 있습니다. 개발 노트북에서 +Linux 격리를 검증했다는 주장이 아닙니다. + +## 패치 정직성 + +상태: `applied`, `checked`, `rejected`, `failed_rolled_back`, +`failed_partial`, `unknown`. + +- 성공한 `check_only` 미리보기 → 파일 변경 없음 (`checked`). +- 프리플라이트 / 정책 실패 → 파일 변경 없음 (`rejected`). +- 스냅샷을 복원한 적용 실패 → `failed_rolled_back`. +- 남은 드리프트가 있는 적용 실패 → `failed_partial` 또는 `unknown`. +- 디스크 해시가 헬퍼가 주장한 `after_version`과 일치하지 않으면 + `applied`를 보고하지 마세요(삭제는 없어야 함). +- `git reset --hard`를 쓰지 마세요. +- HTTP 타임아웃을 롤백이나 성공으로 취급하지 마세요. + +`Store::begin`이 `operation_id`를 발급한 뒤, 실행 오류는 그 id를 +`ErrorBody`에 포함합니다. 전송과 `begin` 전 거절은 포함하지 않습니다. + +## 프로세스 정직성 + +`process_id` 값은 서버가 발급합니다. 클라이언트가 핸들을 만들어 낼 수 +없습니다. 출력은 커서로 읽고 제한됩니다(프로세스당 256 KiB). 시간, 살아있는 +프로세스 수, **완료 핸들 보존**(15분 또는 완료 슬롯 64개)이 제한됩니다. +연결 끊김이 프로세스가 죽었다는 뜻은 아닙니다. 프로세스 상태는 휘발성입니다. +SQLite에 저장되지 않습니다. + +## 로깅 + +Authorization 헤더, Bearer 토큰, `.env` 값을 가리세요. 원본 요청을 +덤프하기보다 구조화 필드(`workspace_id`, `operation_id`)를 선호하세요. +별도 감사 서브시스템은 없습니다. diff --git a/docs/ko/upstream-lock.md b/docs/ko/upstream-lock.md new file mode 100644 index 0000000..56322e0 --- /dev/null +++ b/docs/ko/upstream-lock.md @@ -0,0 +1,105 @@ +# 업스트림 고정 + +[English](../upstream-lock.md) | [한국어](upstream-lock.md) + +CodeSpace는 OpenAI Codex를 **핀된** git 서브모듈로 재사용합니다. 단일 +소스 파일을 벤더하지 않고, 독립 `apply_patch` 바이너리를 보안 경계로 +감싸지 않으며, `main`을 따라가지 않습니다. + +**현재 코드 재사용**은 `crates/patch`를 통한 `codex-apply-patch`(V4A의 +파싱 / 검증 / 적용)입니다. 그 핀은 실행 구현 공급이며, 그만큼 좁은 +크레이트만 따라온다는 서약이 아닙니다. 제품 런타임(App Server, +`codex-core`, `codex-exec`, login, models)은 **핵심** 밖에 둡니다. +응집력 있는 **실행 서브그래프**는 격리된 어댑터에서 가져올 수 있습니다 +([codex-reuse.md](codex-reuse.md)). Codex 타입은 `crates/domain`이나 +MCP 표면으로 새면 안 됩니다. 실행 전용 규칙: +[execution-substrate.md](execution-substrate.md). 오늘은 그래프에 추가 +Codex 크레이트가 없습니다. + +## 배포 핀 (W06) + +| 필드 | 값 | +| --- | --- | +| Project | [openai/codex](https://github.com/openai/codex) | +| License | Apache-2.0 (see root `NOTICE`) | +| Tag | `rust-v0.154.0` | +| Commit | `6b9826e3aa83b1a5947db50f4332cb9c65f1b340` | +| Path | `third_party/codex` git submodule | +| Crate | `codex-apply-patch` via Cargo path dependency from `crates/patch` | +| Apply options | `PreserveLineEndings`, `follow_symlinks: false` | +| Parity | subset in `tests/parity/` and `crates/patch` tests; not the full upstream suite | + +`crates/patch`는 **격리된 Cargo 워크스페이스**입니다(저장소 루트 +워크스페이스에서 제외). Codex 크레이트가 자체 `workspace.dependencies`를 +유지하게 합니다. 그 `Cargo.lock`은 핀된 Codex lockfile에서 시작해 +전이 크레이트(예를 들어 맞는 `rama-*` 알파)가 떠다니지 않게 합니다. +Codex `[patch.crates-io]` git 포크는 `crates/patch/Cargo.toml`에 +복사됩니다. + +어댑터는 `parse_patch`, 그다음 제품 경로 정책(심링크 조상 거절 포함), +그다음 같은 프로세스에서 `LOCAL_FS`로 `apply_patch_with_options`를 +호출합니다. `git apply`나 독립 `apply_patch` 바이너리를 호출하지 +않습니다. 라이브러리에 `sandbox: None`을 넘기는 것은 제품 샌드박스가 +**아닙니다**. 정책 + no-follow I/O + Linux 러너입니다. + +macOS에서 `/var`는 `/private/var`의 심링크입니다. 어댑터는 `PathUri` +cwd를 만들기 전에 워크스페이스 루트를 정규화해, no-follow 탐색이 그 +호스트 별칭에서 실패하지 않게 합니다. + +## 파일 복사 벤더가 금지인 이유 + +`codex-apply-patch` 0.154.0은 워크스페이스 크레이트입니다. 같은 저장소의 +다른 크레이트에 의존합니다. 포함: + +- `codex-exec-server` +- `codex-utils-absolute-path` +- `codex-utils-path-uri` +- tree-sitter 관련 워크스페이스 크레이트 + +`apply-patch` 소스를 `crates/patch`에 복사하면 빌드가 실패하거나 엔진을 +조용히 포크합니다. 그래서 CodeSpace는 다음을 사용합니다. + +```text +git submodule add https://github.com/openai/codex.git third_party/codex +git -C third_party/codex checkout 6b9826e3aa83b1a5947db50f4332cb9c65f1b340 +``` + +경로 의존성이며 crates.io의 움직이는 버전이 아닙니다. + +## 재사용하는 것과 거절하는 것 + +**이 핀에서, 코드로:** 파싱, 헝크 검증, 적용 API, 그리고 패리티용으로 +고른 업스트림 픽스처(`crates/patch` → `codex-apply-patch`). + +**그 크레이트가 허용해도 제품 기본값으로 거절:** 심링크 follow, +sandbox `None` 독립 CLI, 모델의 호스트 절대 경로, 조용한 `git apply`. + +**CodeSpace *핵심* 의존성으로 거절:** `codex-protocol` 타입을 포함한 +어떤 Codex 크레이트 경로 의존성. 제품 런타임은 어디에나 빼 둡니다. +App Server, `codex-core`, `codex-exec`, login, models. +[codex-reuse.md](codex-reuse.md)를 보세요. 이 SHA에서 재사용 선호 +(아직 연결 안 함): `codex-process-hardening`, `codex-utils-pty`, +`codex-uds`, path/URI utils, `codex-file-search`. 적극 평가: +`codex-file-system`, `codex-shell-command`, `codex-linux-sandbox` +(전이 `codex-sandboxing`, `codex-network-proxy`; `codex-protocol`은 +어댑터에서만 허용). `codex-exec-server-protocol`은 내부 DTO 후보입니다. +`codex-exec-server`는 참고 / 이후 백엔드이며 영구 거절은 아닙니다. + +`codex-rs` 독립 `apply_patch`를 감싸고 그것을 샌드박스라고 부르지 +마세요. Preview / `check_only`는 라이브러리 파싱과 CodeSpace +프리플라이트로 구현하며, `apply_patch --check`가 있다고 가정하지 +않습니다. + +Codex 세션 `permissionProfile`을 허용 경로로 취급하지 마세요. +게이트웨이 정책이 유일한 인가 권한입니다. + +## 승격 규칙 + +1. 후보를 기록합니다 (W01). +2. W06: 서브모듈 + 어댑터 + 패리티 부분집합 (이 핀). +3. 패리티가 실패하면 **출하하지 마세요**. 어댑터 옵션을 바꾸거나 다른 + 리비전을 고르세요. 불일치를 덮지 마세요. +4. W13: [upstream-update.md](upstream-update.md)를 따르세요. 배포 + 단계로 최신 Codex `main`에 `git submodule update --remote`를 하지 + 마세요. SHA나 패치 시험이 실패하면 `scripts/check-upstream-pin.sh`는 + 빨간 상태로 남아야 합니다. diff --git a/docs/ko/upstream-update.md b/docs/ko/upstream-update.md new file mode 100644 index 0000000..923acf9 --- /dev/null +++ b/docs/ko/upstream-update.md @@ -0,0 +1,66 @@ +# 업스트림 핀 갱신 + +[English](../upstream-update.md) | [한국어](upstream-update.md) + +Codex 리비전을 바꾸는 것은 **의도적 릴리스**이며, `main`으로 +`git submodule update --remote`가 아닙니다. 패리티 부분집합이 실패하면 +**출하하지 마세요**. 워크스페이스 의존성을 덮으려고 `apply-patch` 소스를 +`crates/patch`에 복사하지 마세요. + +현재 핀: [upstream-lock.md](upstream-lock.md). +제품 대 크레이트 기본값: [behavior-differences.md](behavior-differences.md). +apply-patch 외에 재사용할 수 있는 것: [codex-reuse.md](codex-reuse.md). +NOTICE는 Apache-2.0 Codex 귀속을 유지해야 합니다. + +## 점검 목록 + +1. **태그 또는 커밋**을 고르세요(떠 있는 `main` 아님). 이유를 기록하세요. +2. `git submodule update --init third_party/codex` +3. `git -C third_party/codex fetch --tags` +4. `git -C third_party/codex checkout ` +5. 격리된 어댑터를 다시 빌드하세요: + `cargo test --manifest-path crates/patch/Cargo.toml` + `cargo clippy --manifest-path crates/patch/Cargo.toml --all-targets -- -D warnings` +6. `docs/upstream-lock.md`의 Commit 칸을 새 SHA로 갱신한 뒤 + `scripts/check-upstream-pin.sh`를 실행하세요(서브모듈 HEAD ≠ lock + 파일이면 스크립트가 실패합니다). +7. 적용 옵션, 심링크 정책, 또는 파싱 오류가 바뀌면 + [behavior-differences.md](behavior-differences.md)를 갱신하세요. +8. 재사용 설명이나 핀 문자열이 바뀌면 [NOTICE](../../NOTICE)를 갱신하세요. +9. 핀의 **실행 서브그래프**를 [codex-reuse.md](codex-reuse.md)에 비춰 + 판단하세요: 응집력 있는 실행 대 에이전트 / 모델 의미 대 Gateway 허용 + 우회. process-hardening, PTY, UDS, filesystem, linux-sandbox, + network-proxy의 diff는 실행/보안 변경 로그로 취급하세요. 후보 표를 + 갱신하세요. 루트 워크스페이스에 Codex 경로 의존성을 추가하지 마세요. + 격리는 `crates/patch`와, 생기면 `crates/codex-runtime` + (`codespace-codex-runtime`)에 남습니다. +10. 그 런타임 워크스페이스가 생기기 전까지 게이트는 SHA + 패치 패리티 + 뿐입니다. 생기면 추가로: 런타임 어댑터 컴파일, 그리고 PTY / + sandbox / process 회귀. 이 작업 패키지는 그 스위트를 추가하지 + 않습니다. +11. PR을 여세요. CI는 핀 검사 **와** `crates/patch` 시험을 실행해야 + 합니다. 빨간 패치 job은 경고가 아니라 실패한 배포입니다. + +실패한 패리티 실행을 성공으로 표시하는 경로는 **없습니다**. + +## 로컬 게이트 + +```bash +./scripts/check-upstream-pin.sh +``` + +서브모듈 SHA가 lock 파일과 다르거나 +`cargo test --manifest-path crates/patch/Cargo.toml`이 실패하면 +종료 코드가 0이 아닙니다. + +`PIN_ONLY=1 ./scripts/check-upstream-pin.sh`는 SHA만 검사합니다. +CI는 그것을 fmt/clippy **전에** 실행한 뒤, SHA를 다시 검사하지 않고 +패치 시험을 실행합니다. 로컬에서 접두 없는 스크립트는 여전히 SHA + +`crates/patch` 시험을 합니다. + +## 금지 + +- 워크스페이스 크레이트 없이 `codex-rs/apply-patch`를 파일 복사 벤더 +- 독립 `apply_patch` 바이너리를 보안 경계로 감싸기 +- 조용한 `git apply` 폴백 +- 패치 시험이 실패하는데 출하하기 diff --git a/docs/runner-isolation.md b/docs/runner-isolation.md index 3ab4f98..594f2a8 100644 --- a/docs/runner-isolation.md +++ b/docs/runner-isolation.md @@ -1,4 +1,6 @@ -# Runner isolation (W05) +# Runner isolation + +[English](runner-isolation.md) | [한국어](ko/runner-isolation.md) **Target** execution isolation OS is a Linux container. **Current** `exec_command` is a host process (`tokio::process::Command`, workspace diff --git a/docs/security-model.md b/docs/security-model.md index f4ed50e..821b572 100644 --- a/docs/security-model.md +++ b/docs/security-model.md @@ -1,5 +1,7 @@ # Security model +[English](security-model.md) | [한국어](ko/security-model.md) + CodeSpace is not a kernel sandbox. CoS and cokacremote are not either. Authorization is **gateway policy**. Linux container isolation is the **target** execution OS; current `exec_command` is a host process with diff --git a/docs/translations.json b/docs/translations.json index b673ada..07c6107 100644 --- a/docs/translations.json +++ b/docs/translations.json @@ -42,8 +42,8 @@ "find-your-next-step", "다음-단계" ], - "source_sha256": "227dd4a8988a24e87ca6fd883c54bf3b27ed1950318793752db8310ed27ec7f6", - "translation_sha256": "d85cece608050fb734a47eeb5f605bb83589ffb58241cac8e240fc41cce18b8f" + "source_sha256": "aab2117e9bc7b9181de82b470378177d99c0d893da21666852d3656bde23ee7d", + "translation_sha256": "fa275f3ee817600988401c80761fb8749e77abd84a7165f54fe22da4c477dc09" }, { "id": "getting-started", @@ -92,7 +92,7 @@ "이-문서가-검증하지-않는-것" ], "source_sha256": "0a31118f3079f05527613e22a57455e5c5ba0159026aa5bbcc3d7b1186461640", - "translation_sha256": "b3ff9c3f35400dde8c21f3ad523457990c879baf78fd141179b1de158a6ebd9e" + "translation_sha256": "f839d595db274cccfb2790379410062fdb8ccb90f9dc9f3811f1f942774e693f" }, { "id": "chatgpt-connector", @@ -146,7 +146,7 @@ "현재-배치" ], "source_sha256": "812858a1a21d31d06f7223e198527442ad8f3c50a635ec6ce96f1cf62a90f24d", - "translation_sha256": "cbfabb564943fac7982bc8fe7401ef8271555eec615dbfda964d069fca1ab608" + "translation_sha256": "e1d82ce7a1231df987c4bdcba4bd01612810b746f3b605e5fe6073cc844e83da" }, { "id": "execution-substrate", @@ -178,7 +178,7 @@ "훅과-스킬" ], "source_sha256": "497c710bdb17ebbfcdad4cca8002f0551fe45af02d929b0520b0861069dc6278", - "translation_sha256": "1b950ea6cd7d1155e3c310e536f3dee3a4a0b74a7179e651b7e7924cd4be0d66" + "translation_sha256": "a7499a65adaf2e1b6fc93aaa0bf4ed41555535b1f0da906ca1cd4449c252c003" }, { "id": "protocol-compatibility", @@ -223,6 +223,168 @@ "source_sha256": "23f9a96282eee32750388bcb05cdae7ce9ad2b461d637cc67fcf4a6f1c39aa30", "translation_sha256": "2862a4c4839b8fce67edd2ed40b1ba9e3b0f996e4f26b4dd3bb454d865fc1941" }, + { + "id": "security-model", + "section": "security", + "order": 0, + "route": "/guide/security-model", + "source": "docs/security-model.md", + "translation": "docs/ko/security-model.md", + "anchors": [ + "authentication-vs-selection", + "logging", + "patch-honesty", + "process-honesty", + "product-path-policy-always-even-if-the-crate-would-allow-it", + "profiles-mvp", + "runner-isolation-linux", + "security-model", + "trust-boundaries", + "workspace-registry", + "러너-격리-linux", + "로깅", + "보안-모델", + "신뢰-경계", + "워크스페이스-레지스트리", + "인증-대-선택", + "제품-경로-정책-크레이트가-허용해도-항상", + "패치-정직성", + "프로세스-정직성", + "프로필-mvp" + ], + "source_sha256": "3e551ed0eb1575787d0d5ea631ca306a7843869397a96e4a04c78ce02a3cbdd6", + "translation_sha256": "616620b6f6aca2f279f9f265ae275a7a45097af31394db582c1c8b02f7cd0693" + }, + { + "id": "runner-isolation", + "section": "security", + "order": 1, + "route": "/guide/runner-isolation", + "source": "docs/runner-isolation.md", + "translation": "docs/ko/runner-isolation.md", + "anchors": [ + "compose-픽스처가-하는-일", + "later-process-split", + "macos-docker-없음", + "macos-no-docker", + "runner-isolation", + "what-the-compose-fixture-does", + "러너-격리", + "이후-프로세스-분리" + ], + "source_sha256": "39464d076b856527d363c2031b04eb9228ecc0abbefac4416035fbff807e67f0", + "translation_sha256": "80b1342ab219fcc4dfd501f156fe86e8078cb5d107f884314f9c3a0e271d616a" + }, + { + "id": "error-codes", + "section": "security", + "order": 2, + "route": "/guide/error-codes", + "source": "docs/error-codes.md", + "translation": "docs/ko/error-codes.md", + "anchors": [ + "error-codes-and-transport-vs-execution", + "execution-error-codes-tool-results", + "transport-failures-no-operation", + "실행-오류-코드-도구-결과", + "오류-코드와-전송-대-실행", + "전송-실패-작업-없음" + ], + "source_sha256": "e5c6d7e5d6c0fc1d07a6f0e16832b2c62cafed465b2f7cd69eb524f0fdc2a029", + "translation_sha256": "966d153e562f2cadd83b105063c39b269bef44b13972466a82f93eb7a4f055c0" + }, + { + "id": "codex-reuse", + "section": "implementation", + "order": 0, + "route": "/guide/codex-reuse", + "source": "docs/codex-reuse.md", + "translation": "docs/ko/codex-reuse.md", + "anchors": [ + "apply_patch-패턴-격리이지-크레이트-너비가-아님", + "candidates-at-pin-6b9826e", + "code-allowed-authority-forbidden", + "codespace에-남는-것", + "codex-reuse-product-vs-primitive", + "codex-재사용-제품과-프리미티브", + "conditional-active-evaluation", + "core-vs-adapter", + "experimental-backend-not-now", + "future-environment-not-p0", + "internal-protocol-candidate", + "isolated-layer-transitive-codex-protocol", + "next-implementation-wp", + "policy-vs-mechanism", + "prefer-reuse-when-that-wp", + "reject", + "reuse-now-in-code", + "staged-take-when-those-wps-exist", + "the-apply_patch-pattern-isolation-not-crate-width", + "unit-of-reuse-is-a-subgraph", + "what-stays-codespace", + "why-supervisor-code-still-exists", + "감독-코드가-아직-있는-이유", + "거절", + "격리-층-전이-codex-protocol", + "내부-프로토콜-후보", + "다음-구현-wp", + "단계적-가져오기-그-wp가-생길-때", + "실험적-백엔드-지금은-아님", + "이후-environment-p0-아님", + "재사용-단위는-서브그래프", + "재사용-선호-그-wp가-올-때", + "정책-대-메커니즘", + "조건부-적극-평가", + "지금-재사용-코드에서", + "코드는-허용-권한은-금지", + "핀-6b9826e의-후보", + "핵심-대-어댑터" + ], + "source_sha256": "309d465d5a4b5e09ab34097a6415dc2a1e833e2fd26cf721611d3031580d6feb", + "translation_sha256": "f0717d1d40fa67a5117cf5eb0f5d8601d205979c1513d27545a1e1179c35c68b" + }, + { + "id": "upstream-lock", + "section": "implementation", + "order": 1, + "route": "/guide/upstream-lock", + "source": "docs/upstream-lock.md", + "translation": "docs/ko/upstream-lock.md", + "anchors": [ + "deployment-pin-w06", + "promotion-rule", + "upstream-lock", + "what-is-reused-vs-rejected", + "why-file-copy-vendor-is-forbidden", + "배포-핀-w06", + "승격-규칙", + "업스트림-고정", + "재사용하는-것과-거절하는-것", + "파일-복사-벤더가-금지인-이유" + ], + "source_sha256": "bf539fbb2d8a34af688e99c7fb2db6a748627990d9c95bd65fad9506af28a088", + "translation_sha256": "cae3e0c2f07b4a9942afd0f58a0dddefe790784c29dd21ac5dcbff55e74261ab" + }, + { + "id": "upstream-update", + "section": "implementation", + "order": 2, + "route": "/guide/upstream-update", + "source": "docs/upstream-update.md", + "translation": "docs/ko/upstream-update.md", + "anchors": [ + "checklist", + "forbidden", + "local-gate", + "upstream-pin-update", + "금지", + "로컬-게이트", + "업스트림-핀-갱신", + "점검-목록" + ], + "source_sha256": "4eb34720223aff91a19cc8c9c4ab7b67a8cf9261795ee4e151cdb838250f68be", + "translation_sha256": "c0dbe1f6ab4f3d7a8ec3ba5605c061a70b605adca505fe0f54a5b7fee7d7ab58" + }, { "id": "documentation", "section": "project", diff --git a/docs/upstream-lock.md b/docs/upstream-lock.md index b7c9848..0190ef3 100644 --- a/docs/upstream-lock.md +++ b/docs/upstream-lock.md @@ -1,5 +1,7 @@ # Upstream lock +[English](upstream-lock.md) | [한국어](ko/upstream-lock.md) + CodeSpace reuses OpenAI Codex as a **pinned** git submodule. It does not vendor a single source file, wrap the standalone `apply_patch` binary as the security boundary, or follow `main`. diff --git a/docs/upstream-update.md b/docs/upstream-update.md index 7ae2612..c94943e 100644 --- a/docs/upstream-update.md +++ b/docs/upstream-update.md @@ -1,4 +1,6 @@ -# Upstream pin update (W13) +# Upstream pin update + +[English](upstream-update.md) | [한국어](ko/upstream-update.md) Changing the Codex revision is a **deliberate release**, not `git submodule update --remote` to `main`. If the parity subset fails, **do