You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/consuming/contract.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -121,7 +121,7 @@ SRI 속성을 직접 걸 수 없으므로, 이 검증은 spawn 전 preflight다.
121
121
122
122
**가상 오리진 경계 (정직한 벽)**: SW 합성 응답이라 진짜 오리진과 다르다. `tests/attempts/runtimeParity/virtualOriginBoundaryProbe.html`이 이 경계를 브라우저에서 계속 실측한다. (1) `Set-Cookie`는 응답 header로 노출되지 않고 저장되지 않는다. 쿠키 세션에 의존하지 말고 `Authorization` header, bearer token, signed URL 같은 명시 토큰을 쓴다. (2) WebSocket upgrade는 Service Worker fetch 이벤트가 가로채지 않으므로 ASGI dispatch로 들어오지 않는다. 양방향 스트림은 별도 relay나 SocketBridge 계열로 설계한다. (3) 스트리밍/SSE는 `AsgiServer`가 `http.response.body` 조각을 축적한 뒤 일괄 `Response`로 돌려준다. 청크 단위 UI 갱신이 필요한 제품은 이 경로에 의존하지 않는다. (4) 엔드포인트는 `async def` 강제(동기 dispatch 없음).
123
123
124
-
부활(저널/세션/openMachine) 후에는 파일 핸들·DB 커넥션 같은 프로세스 자원이 힙 델타만으로 보장되지 않는다: `.pymachine`은 파이썬 힙과 `/home/web` 파일 바이트를 복원하지만 열린 fd, 소켓, DB 커넥션은 다시 열어야 하므로, 소비자는 `Init.resume(reason)`으로 `/home/web/resume.py`를 실행해 그런 자원을 재개설한다. signature는 출처 검증이지 sandbox 권한 허가가 아니므로, 제품은 공개키 배포와 권한 UI를 별도로 관리한다.
124
+
부활(저널/세션/openMachine) 후에는 파일 핸들·DB 커넥션 같은 프로세스 자원이 힙 델타만으로 보장되지 않는다: `.pymachine`은 파이썬 힙과 `/home/web` 파일 바이트를 복원하지만 열린 fd, 소켓, DB 커넥션은 다시 열어야 하므로, 소비자는 `Init.resume(reason)`으로 `/home/web/resume.py`를 실행해 그런 자원을 재개설한다. 제품별 정책은 [resumeCatalog.md](resumeCatalog.md)가 정본이다. signature는 출처 검증이지 sandbox 권한 허가가 아니므로, 제품은 공개키 배포와 권한 UI를 별도로 관리한다.
125
125
126
126
subpath export: `pyproc/assets`, `pyproc/runtime`, `pyproc/reactive`, `pyproc/syscall-bridge`, `pyproc/process-os`, `pyproc/worker`. **src 내부 경로 deep import 금지** (내부 파일 배치는 릴리즈 간 바뀔 수 있다. 실제로 v0.0.3에서 레이어 폴더로 재배치됐고 subpath 이름은 불변이었다).
`Session.load`, `MachineJournal.recover`, `openMachine`은 파이썬 힙과 `/home/web` 파일 바이트를 되살린다. 그러나 열린 파일 핸들, SQLite connection, WebSocket/relay connection, 브라우저 장치 권한, DOM callback 같은 프로세스 바깥 자원은 힙 델타만으로 보장하지 않는다. 이 문서는 제품이 `/home/web/resume.py`에 무엇을 넣어야 하는지의 카탈로그다.
4
+
5
+
## 공통 계약
6
+
7
+
- 기본 위치는 `/home/web/resume.py`다. 다른 경로가 필요하면 `rt.enableInit({ resumePath })`로 명시한다.
8
+
- 부활 뒤 소비자가 `rt.enableInit().resume(reason)`을 호출한다. `reason`은 `resume.py` 안에서 전역 `pyprocResumeReason`으로 읽는다.
9
+
- 같은 파일은 여러 번 실행될 수 있으므로 idempotent여야 한다. 테이블 생성, 디렉터리 생성, 캐시 재구성은 `if not exists`와 재시도 가능 구조로 쓴다.
10
+
- 다시 열 대상은 "힙에 객체가 남아 보여도 플랫폼 상태가 사라질 수 있는 것"이다: SQLite connection, 열린 파일 핸들, SocketBridge/relay 세션, ASGI 앱 전역 DB connection, 브라우저 장치 handle, 외부 권한 토큰의 메모리 캐시.
11
+
-`/home/web`에 영속된 파일과 명시 설정을 정본으로 삼고, stale Python object는 신뢰하지 않는다.
12
+
- 권한 요청은 제품 UI가 소유한다. `resume.py`가 카메라, 네트워크 relay, clipboard 같은 권한을 조용히 다시 열면 안 된다.
13
+
- 장시간 package install이나 네트워크 fetch를 `resume.py`에 넣지 않는다. 부활 경로는 빠르게 수렴해야 한다.
14
+
15
+
권장 reason 값:
16
+
17
+
| reason | 언제 |
18
+
|---|---|
19
+
|`fresh.boot`| 제품이 첫 부팅에서도 같은 hook으로 자원을 여는 경우 |
20
+
|`session.load`|`Session.load(dir, name)` 뒤 |
21
+
|`journal.recover`|`MachineJournal.recover()` 뒤 |
22
+
|`openMachine`|`openMachine(blob, trustOptions)` 뒤 |
23
+
|`kernel.failover`| 탭 리더 교체 뒤 follower가 저널에서 되살아난 경우 |
24
+
25
+
## 현재 고정된 표면
26
+
27
+
| 표면 | 상태 | resume.py 정책 | 검증 |
28
+
|---|---|---|---|
29
+
|`tests/attempts/pythonMachine/resumeHookProbe.html`| 계약 probe | sqlite connection을 `resumeConn`으로 다시 열고 reason/value를 기록한다. `Session.load`, `MachineJournal.recover`, `openMachine` 세 경로와 파일 없음 no-op을 검증한다 |`node tests/browser/run.mjs tests/attempts/pythonMachine/resumeHookProbe.html`|
30
+
|`examples/machine.html`| 실제 데모 표면 | 첫 부팅 또는 부활 뒤 `/home/web/resume.py`가 `appDb` SQLite connection을 열고 `resumeEvent`에 reason을 남긴다. signed `.pymachine` cast 후 `openMachine`에서도 같은 hook을 실행한다 |`npm run test:examples`, 또는 `node tests/browser/run.mjs examples/machine.html?gate=1`|
31
+
32
+
## 제품별 적용 정책
33
+
34
+
| 제품 | 재개설 대상 | resume.py에 둬야 할 것 | pyproc 쪽 판정 |
35
+
|---|---|---|---|
36
+
| codaro | 셀 실행 기록, `/home/web/codaro` 산출물 index, ASGI 개발 서버가 잡는 DB/file connection |`/home/web/codaro` 파일 트리를 정본으로 삼고, SQLite/index connection과 ASGI app 전역 connection을 다시 연다. 셀별 PyProxy, DOM handle, editor callback은 저장하지 않는다 | 다음 제품 소비 축에서 `.pymachine` 또는 `VirtualOrigin` 채택 시 gate로 고정 |
37
+
| dartlab | notebook worker의 ASGI `/pyapi`, sqlite/파일 connection, 패키지 캐시 index | 자체 부팅 Pyodide를 `Runtime`으로 채택한 뒤, DB connection과 app state adapter를 `/home/web` 기준으로 다시 연결한다. FastAPI route 함수 자체보다 외부 connection 재개설이 핵심이다 | pyproc 계약은 준비됨. dartlab 채택 시 제품 gate 필요 |
38
+
| xlpod | 스프레드시트 UDF 캐시, formula bridge callback, 취소 SAB, workbook별 산출물 | workbook 식별자와 `/home/web/xlpod` 산출물을 정본으로 삼고, callback/SAB/worksheet bridge는 힙에서 재사용하지 않고 호스트에서 다시 주입한다 | UDF 동기 브리지 채택 시 별도 gate 필요 |
39
+
| 일반 외부 제품 | 사용자 파일, 로컬 DB, relay/session token, device permission |`/home/web/<app>` 아래 manifest를 두고 resume.py는 그 manifest만 읽어 connection을 다시 만든다. 권한이 필요한 자원은 먼저 UI 승인 상태를 확인한다 | 소비 계약으로 공개. 제품별 증거는 각 제품 gate에서 요구 |
40
+
41
+
## 최소 템플릿
42
+
43
+
```python
44
+
import os, sqlite3
45
+
46
+
os.makedirs("/home/web/myApp", exist_ok=True)
47
+
resumeReasonSeen = pyprocResumeReason
48
+
appDbPath ="/home/web/myApp/app.db"
49
+
appDb = sqlite3.connect(appDbPath)
50
+
appDb.execute("create table if not exists resumeEvent(reason text)")
51
+
appDb.execute("insert into resumeEvent(reason) values (?)", (resumeReasonSeen,))
52
+
appDb.commit()
53
+
```
54
+
55
+
제품은 이 템플릿을 그대로 복사하지 말고, 자기 자원 목록을 기준으로 얇게 유지한다. 핵심은 "힙에 남은 객체를 믿지 않고 `/home/web`의 파일과 명시 권한으로 다시 연다"는 점이다.
| 부팅/영속 |`bootEnv`, `freeze`, `MachineJournal`, `MachineJournal.pack/prune/autoPack`, `Init.resume`, `KernelElection`, `SharedKernel`, `resumeCatalog`| SharedKernel과 hibernate/resume 결합, 외부 제품 resume.py gate|
30
30
| 개발 표면 |`Terminal`, `%pip`, `%undo`, signed machine cast demo, Server Dev demo, Speed Lab demo | 제품 소비 배선, completion/history polish, compatibility lab |
31
31
| 성능 | WebGPU, CPU sharding, snapshot fork, Speed Lab public benchmark | WebVM/JupyterLite/marimo 대비 정면 벤치 |
32
32
@@ -42,6 +42,6 @@ pyproc이 소유하는 것은 제품 UI가 아니라 OS API와 커널 프리미
42
42
43
43
1. OS 판정표 v2에서 현재 점수는 몇 점인가.
44
44
2. 공개키 배포와 권한 UI를 소비 제품에 어떤 계약으로 맡길 것인가.
45
-
3.제품별`resume.py`는 어떤 fd, socket, DB connection을 다시 여는가.
45
+
3.codaro/dartlab/xlpod의`resume.py` 정책을 어떤 제품 gate로 고정할 것인가.
46
46
4. 외부 소비 제품은 VirtualOrigin을 어떤 URL namespace와 인증 방식으로 채택할 것인가.
0 commit comments