fix: install bounded Browser RPC stream leases
R-04: install the RPC contract bindings as exact immutable snapshots. Registry and row data are copied from own data descriptors into frozen null-prototype maps before validation, so a getter is never invoked, extra and symbol keys and malformed descriptors are composition-time TypeErrors, and the runtime reads only the snapshot. A post-validation mutation can no longer change replay policy, deadlines, byte ceilings or transport selection. R-01: bound transport stream cleanup. The generation is fenced and listeners released immediately, and iterator.return() is awaited only within a cleanup bound, so a non-cooperative iterator cannot keep the application generator, its listeners or the total deadline alive. Unresolved cleanup stays observed. R-05: reject oversized WebSocket text frames before allocating an encoded copy and count UTF-8 bytes incrementally with an early exit, matching TextEncoder for surrogate pairs and lone surrogates. R-06: canonicalise clock and generation-fence failures into the closed Result taxonomy instead of letting them escape as native rejections, with listener and timer cleanup on every exit path. Browser RPC remains AVAILABLE_NOT_COMPOSED; R-07 transport evidence is still required before composition. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2f29ccbf1a
commit
8f67974f68
@@ -19,6 +19,37 @@
|
||||
- 운영 절차:
|
||||
[API contract와 server-state recovery](../operations/api-contract-and-server-state-recovery.md)
|
||||
|
||||
|
||||
## Installed binding snapshot과 stream cleanup bound (R-01, R-04, R-05, R-06)
|
||||
|
||||
- `installBrowserRpcContractBindings()`가 registry를 **parse → validate →
|
||||
install** 순서로 처리한다. own data descriptor만 읽어 exact key set으로
|
||||
null-prototype frozen snapshot을 만들고, 그 snapshot을 검증한 뒤 설치한다.
|
||||
getter/accessor, extra key, symbol key, malformed descriptor, revoked proxy는
|
||||
composition-time `TypeError`이며 getter는 호출조차 되지 않는다. runtime과
|
||||
transport call은 이후 snapshot만 읽으므로 validation 이후 registry mutation이
|
||||
replay policy·deadline·byte ceiling·transport selection을 바꿀 수 없다.
|
||||
- server stream 종료는 transport iterator에 lifecycle authority를 위임하지
|
||||
않는다. commit/admission generation은 즉시 fence하고 listener는 바로 해제하며,
|
||||
`iterator.return()`은 cleanup **요청**으로서 bound 안에서만 기다린다. 끝나지
|
||||
않은 cleanup은 관찰만 유지되고(unhandled rejection 없음) application generator는
|
||||
bound 안에 종료된다. cleanup rejection은 이미 선택된 application failure를
|
||||
덮지 않는다.
|
||||
- WebSocket text frame은 allocation 전에 admission한다. UTF-16 code unit 길이가
|
||||
이미 cap을 넘으면 encoder를 만들지 않고 거절하고, 나머지는 early exit하는
|
||||
code-point 누적으로 센다. valid surrogate pair는 4 bytes, lone surrogate는
|
||||
`TextEncoder`와 동일하게 replacement 3 bytes다.
|
||||
- clock/fence collaborator 예외는 Result 경계를 벗어나지 않는다. clock 실패는
|
||||
`SERVER_FAILURE/RPC_RUNTIME_DEPENDENCY_FAILED`, capture 실패는
|
||||
`SCOPE_GENERATION_CHANGED/RPC_SCOPE_GENERATION_UNAVAILABLE`, `isCurrent` 실패는
|
||||
fail-closed로 canonicalize하며 listener/timer는 단일 exit path에서 정확히 한 번
|
||||
해제한다.
|
||||
|
||||
Browser RPC는 여전히 `AVAILABLE_NOT_COMPOSED`다. 선택된 Connect/gRPC-Web
|
||||
transport는 enqueue-time `maxBufferedBytes`, raw/decompressed ceiling,
|
||||
cancel/closed receipt, terminal framing, target browser와 load behavior를
|
||||
별도로 증명해야 조립할 수 있다 (R-07).
|
||||
|
||||
## 1. 먼저 축을 분리한다
|
||||
|
||||
네 이름은 같은 종류의 대안이 아니다.
|
||||
|
||||
@@ -104,12 +104,12 @@ Rollout state starts at `NOT_STARTED`; documented-unimplemented items start at
|
||||
|
||||
| ID | Activation | Red test command | Fix commit/PR | Rollout state | Rollback trigger | Evidence |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| R-01 | Browser RPC `AVAILABLE_NOT_COMPOSED` | `corepack pnpm exec vitest run tests/unit/browser-rpc/browser-rpc-runtime.test.ts` | — | `NOT_STARTED` | stream lease deadlock | — |
|
||||
| R-01 | Browser RPC `AVAILABLE_NOT_COMPOSED` | `corepack pnpm exec vitest run tests/unit/browser-rpc/browser-rpc-runtime.test.ts` | `fix: install bounded Browser RPC stream leases` | `FIXED_NOT_RELEASED` | stream lease deadlock | Stream cleanup is bounded; the generator no longer waits indefinitely on a non-cooperative `iterator.return()` |
|
||||
| R-02 | Realtime `NOT_SELECTED` | `corepack pnpm exec vitest run tests/unit/realtime/stream-coordinator.test.ts` | `fix: retain realtime work through draining` | `FIXED_NOT_RELEASED` | stream stuck in `DRAINING` | Red never-settling effect and recovery → green 27/27; `close()` returns `IDLE_TIMEOUT` while a task is retained and success only after actual settlement |
|
||||
| R-03 | Realtime `NOT_SELECTED` | `corepack pnpm exec vitest run tests/unit/realtime/live-poll-handoff-coordinator.test.ts` | `fix: retain realtime work through draining` | `FIXED_NOT_RELEASED` | retired-writer set growth | Red overflow fail-close then `close()` → green 11/11; retired writers are waited on and only removed once actually quiesced |
|
||||
| R-04 | Browser RPC `AVAILABLE_NOT_COMPOSED` | `corepack pnpm exec vitest run tests/unit/browser-rpc/browser-rpc-contract.test.ts` | — | `NOT_STARTED` | binding install rejection | — |
|
||||
| R-05 | WebSocket protocol codec | `corepack pnpm exec vitest run tests/unit/realtime/websocket-protocol.test.ts` | — | `NOT_STARTED` | frame rejection regression | — |
|
||||
| R-06 | Browser RPC `AVAILABLE_NOT_COMPOSED` | `corepack pnpm exec vitest run tests/unit/browser-rpc/browser-rpc-runtime.test.ts` | — | `NOT_STARTED` | closed-failure taxonomy drift | — |
|
||||
| R-04 | Browser RPC `AVAILABLE_NOT_COMPOSED` | `corepack pnpm exec vitest run tests/unit/browser-rpc/browser-rpc-contract.test.ts` | `fix: install bounded Browser RPC stream leases` | `FIXED_NOT_RELEASED` | binding install rejection | Red post-validation mutation, accessor and symbol cases → green 19/19; getters are never invoked |
|
||||
| R-05 | WebSocket protocol codec | `corepack pnpm exec vitest run tests/unit/realtime/websocket-protocol.test.ts` | `fix: install bounded Browser RPC stream leases` | `FIXED_NOT_RELEASED` | frame rejection regression | Red oversize frame allocated an encoder copy → green 8/8; byte counts match `TextEncoder` including lone surrogates |
|
||||
| R-06 | Browser RPC `AVAILABLE_NOT_COMPOSED` | `corepack pnpm exec vitest run tests/unit/browser-rpc/browser-rpc-runtime.test.ts` | `fix: install bounded Browser RPC stream leases` | `FIXED_NOT_RELEASED` | closed-failure taxonomy drift | Clock and fence reads are canonicalised into the closed Result taxonomy with single-exit cleanup |
|
||||
| R-07 | Promotion blocker | concrete transport conformance evidence | — | `PROMOTION_BLOCKED` | n/a | — |
|
||||
|
||||
### Browser transfer (`docs/reviews/adapters/04-browser-transfer.md`)
|
||||
|
||||
Reference in New Issue
Block a user