-
Notifications
You must be signed in to change notification settings - Fork 2.9k
docs(acp): update permission mediator status #9866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9fa40d6
ee77198
04d0284
2d83335
cb93f83
6b14972
04d0da5
05146bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,13 +5,13 @@ and remote-control adapters. Lives in the monorepo, not published to npm. | |
|
|
||
| Lift history (#4175 Mode B daemon roadmap): | ||
|
|
||
| | Slice | Scope | Status | | ||
| | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | ||
| | **PR 22a** (#4295) | Skeleton + `EventBus` + `inMemoryChannel` + `AcpChannel` types + `PermissionMediator` type-only stub | ✅ merged | | ||
| | **PR 22b/1** (#4298) | Lift `status` + `workspacePaths` + `bridgeErrors` + `bridgeTypes` | ✅ merged | | ||
| | **PR 22b/2** (#4304) | Lift `BridgeOptions` + new `DaemonStatusProvider` injection seam | ✅ merged | | ||
| | **F1** (this PR) | Lift `defaultSpawnChannelFactory` + `BridgeClient` + `createHttpAcpBridge` factory closure + new `BridgeFileSystem` injection seam (22b' scope) | ✅ in this PR | | ||
| | **F3 PR 24** | Implement the four `PermissionMediator` strategies (`first-responder`, `designated`, `consensus`, `local-only`) + pair-token revocation + audit log | F3 in the feature-cohesive plan | | ||
| | Slice | Scope | Status | | ||
| | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | | ||
| | **PR 22a** (#4295) | Skeleton + `EventBus` + `inMemoryChannel` + `AcpChannel` types + `PermissionMediator` type-only stub | ✅ merged | | ||
| | **PR 22b/1** (#4298) | Lift `status` + `workspacePaths` + `bridgeErrors` + `bridgeTypes` | ✅ merged | | ||
| | **PR 22b/2** (#4304) | Lift `BridgeOptions` + new `DaemonStatusProvider` injection seam | ✅ merged | | ||
| | **F1** (#4490) | Lift `defaultSpawnChannelFactory` + `BridgeClient` + `createHttpAcpBridge` factory closure + new `BridgeFileSystem` injection seam (22b' scope) | ✅ merged | | ||
| | **F3 PR 24** | Implement the four `PermissionMediator` policies (`first-responder`, `designated`, `consensus`, `local-only`) plus audit/emit fan-out; pair-token binding and revocation stay future scope | ✅ implemented | | ||
|
|
||
| ## What's here today | ||
|
|
||
|
|
@@ -25,13 +25,12 @@ Lift history (#4175 Mode B daemon roadmap): | |
| type contract that `createHttpAcpBridge` (now in this package) plus | ||
| the channels / VSCode IDE companion's own-spawn paths consume via | ||
| `BridgeOptions.channelFactory`. | ||
| - `permission` — type-only `PermissionMediator` interface, | ||
| - `permission` — `PermissionMediator` interface, | ||
| `PermissionPolicy` literal union (4 strategies), and | ||
| `PermissionResolution` discriminated union. **No implementation | ||
| yet** — first-responder voting still lives in | ||
| `BridgeClient.requestPermission` (in `bridgeClient.ts` after F1). | ||
| F3 PR 24 will move that and add the other three policies behind | ||
| this interface. | ||
| `PermissionResolution` discriminated union. `MultiClientPermissionMediator` | ||
| implements the four policies, owns pending/resolved permission state, and | ||
| handles strategy dispatch plus audit/emit fan-out; `BridgeClient` only | ||
| plumbs `requestPermission` into `mediator.request`. | ||
|
Comment on lines
+30
to
+33
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The unchanged 中文说明未改动的 — qwen3.8-max via Qwen Code /review (v0.22.0) |
||
| - `status` (PR 22b/1) — wire-contract status types for | ||
| `/workspace/{mcp,skills,providers,env,preflight}` and | ||
| `/session/:id/{context,supported-commands,tasks}` routes, the | ||
|
|
@@ -75,20 +74,20 @@ Lift history (#4175 Mode B daemon roadmap): | |
| companion consume this directly instead of each reimplementing the | ||
| child lifecycle. | ||
| - `bridgeClient` (F1) — `BridgeClient` class implementing the ACP | ||
| `Client` surface: first-responder permission flow, session-update | ||
| fan-out into `EventBus`, child-side `extNotification` routing, | ||
| early-event buffer + tombstone bookkeeping, inline fs proxy for | ||
| `writeTextFile` / `readTextFile`. Exports the supporting | ||
| `PendingPermission` / `PermissionResolutionRecord` / | ||
| `BridgeClientSessionEntry` types + `MAX_RESOLVED_PERMISSION_RECORDS` | ||
| cap that the factory's bookkeeping maps consume. | ||
| `Client` surface: permission requests delegated to | ||
| `PermissionMediator`, session-update fan-out into `EventBus`, | ||
| child-side `extNotification` routing, early-event buffer + tombstone | ||
| bookkeeping, inline fs proxy for `writeTextFile` / `readTextFile`. | ||
| Exports the supporting `BridgeClientSessionEntry` type consumed by | ||
| the session-entry lookup passed in by the factory. | ||
| - `bridge` (F1) — `createHttpAcpBridge` factory closure (~3000 LOC) | ||
| - `ChannelInfo` / `SessionEntry` interfaces + factory-only | ||
| helpers (`withTimeout`, `canonicalizeExistingAncestor`, | ||
| `verifyParentWithinWorkspace`, debug log helpers, | ||
| `hasControlCharacter`) + factory constants. Builds the | ||
| bookkeeping closures (`resolveEntry`, `registerPending`, etc.) | ||
| and wires them into `BridgeClient`. | ||
| `hasControlCharacter`) + factory constants. Owns session | ||
| bookkeeping, constructs the `MultiClientPermissionMediator` that | ||
| owns permission state, and passes the session-entry lookup into | ||
| `BridgeClient`. | ||
| - `bridgeFileSystem` (F1) — `BridgeFileSystem` interface for the | ||
| ACP fs proxy. When wired through `BridgeOptions.fileSystem`, | ||
| `BridgeClient.readTextFile` / `BridgeClient.writeTextFile` | ||
|
|
@@ -135,6 +134,6 @@ exported symbols (`createHttpAcpBridge`, `defaultSpawnChannelFactory`, | |
| - #4175 Mode B daemon roadmap (feature-cohesive F1-F5 plan targeting | ||
| `daemon_mode_b_main`) | ||
| - #3803 `Stage 1.5-prereq AcpChannel lift` (chiga0's original framing) | ||
| - F3 PR 24 will replace the inline first-responder logic in | ||
| `BridgeClient.requestPermission` with the four `PermissionMediator` | ||
| strategies declared in `permission.ts`. | ||
| - `permissionMediator.ts` implements the four `PermissionMediator` | ||
| strategies declared in `permission.ts`; `BridgeClient.requestPermission` | ||
| delegates to that mediator. | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,36 +5,32 @@ | |||||||
| */ | ||||||||
|
|
||||||||
| /** | ||||||||
| * `PermissionMediator` — type-only interface contract for daemon | ||||||||
| * permission flow. **No implementation lives here.** Permission voting | ||||||||
| * still runs inside `BridgeClient.requestPermission` | ||||||||
| * (`@qwen-code/acp-bridge/bridgeClient`) and | ||||||||
| * `respondToPermission` (inside `createHttpAcpBridge` factory closure | ||||||||
| * at `@qwen-code/acp-bridge/bridge` after F1 step 3), hard-coded to | ||||||||
| * `first-responder`. A future change will move that code behind this | ||||||||
| * interface and add the other three policies. | ||||||||
| * `PermissionMediator` — interface contract for daemon permission flow. | ||||||||
| * `MultiClientPermissionMediator` in `permissionMediator.ts` owns the | ||||||||
| * policy dispatch and pending/resolved permission state used by | ||||||||
|
Comment on lines
+9
to
+10
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] This header rewrite presents the four policy bullets below it as the implemented semantics of 中文说明这段头部重写使其下方的四条策略条目成为 — qwen3.8-max via Qwen Code /review (v0.22.0) |
||||||||
| * `BridgeClient.requestPermission` plus the `respondToPermission` route | ||||||||
| * in `createHttpAcpBridge`. | ||||||||
| * | ||||||||
| * The four policies are ordered from cheapest to strongest: | ||||||||
| * The four policy contracts are ordered from cheapest to strongest: | ||||||||
| * | ||||||||
| * - `first-responder` — first valid `POST /permission/:requestId` | ||||||||
| * wins; later voters get `permission_already_resolved`. Today's | ||||||||
| * default; preserves the live-collaboration UX. | ||||||||
| * - `designated` — only the `originatorClientId` that started the | ||||||||
| * prompt may answer; other clients see `permission_forbidden`. | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] R3-3: The header rewrite presents the four policy bullets below it as the implemented semantics of
Suggested change
中文说明头部重写使其下方的四条策略条目成为 — qwen3.8-max via Qwen Code /review (v0.22.0) |
||||||||
| * Use case: per-tenant SaaS where a UI surface must own its own | ||||||||
| * approvals. | ||||||||
| * - `consensus` — N-of-M quorum across pair-token-authenticated | ||||||||
| * clients before resolving; intermediate `permission_partial_vote` | ||||||||
| * events let UIs render progress. Use case: enterprise change | ||||||||
| * review where two operators must agree. | ||||||||
| * Prompts with no originator fall back to first-responder. Use case: | ||||||||
| * per-tenant SaaS where a UI surface must own its own approvals. | ||||||||
| * - `consensus` — N-of-M quorum across the session client IDs | ||||||||
| * captured when the permission request is issued. Client identity is | ||||||||
| * self-declared until pair-token authentication lands; intermediate | ||||||||
| * `permission_partial_vote` events let UIs render progress. Use case: | ||||||||
| * enterprise change review where two operators must agree. | ||||||||
| * - `local-only` — refuses any HTTP voter; the prompt blocks until | ||||||||
| * a loopback client (the local TUI super-client) resolves it. | ||||||||
| * Use case: workstations where remote control should never grant | ||||||||
| * privilege escalation. | ||||||||
| * | ||||||||
| * See `bridgeClient.ts BridgeClient.requestPermission` for the | ||||||||
| * current first-responder implementation; the `FIXME(stage-1.5)` | ||||||||
| * block above that method scoped this contract. | ||||||||
| * See `permissionMediator.ts` for the implementation details. | ||||||||
| */ | ||||||||
| export type PermissionPolicy = | ||||||||
| | 'first-responder' | ||||||||
|
|
@@ -43,10 +39,7 @@ export type PermissionPolicy = | |||||||
| | 'local-only'; | ||||||||
|
|
||||||||
| /** | ||||||||
| * One pending permission tracked by a `PermissionMediator`. The | ||||||||
| * shape mirrors the current `PendingPermission` record in | ||||||||
| * `@qwen-code/acp-bridge/bridgeClient` | ||||||||
| * so the mediation implementation's lift is a structural rename rather than a redesign. | ||||||||
| * One pending permission tracked by a `PermissionMediator`. | ||||||||
| */ | ||||||||
| export interface PermissionRequestRecord { | ||||||||
| /** ACP `RequestPermission` request id, unique per session. */ | ||||||||
|
|
@@ -148,9 +141,7 @@ export type PermissionResolution = | |||||||
|
|
||||||||
| /** | ||||||||
| * The contract `qwen serve`'s permission route layer talks to. | ||||||||
| * Today there is one implementation (first-responder) wired | ||||||||
| * inline in `BridgeClient`; The implementation will provide all four behind | ||||||||
| * this surface plus pair-token authentication and an audit log. | ||||||||
| * `MultiClientPermissionMediator` provides the implementation. | ||||||||
| */ | ||||||||
| export interface PermissionMediator { | ||||||||
| /** Active policy. May be reconfigured per session in future | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] This rewritten bullet contradicts a sibling bullet the diff left stale: the unchanged
bridgeClientbullet in the same section (lines 76-84) still says BridgeClient implements the "first-responder permission flow" and "Exports the supportingPendingPermission/PermissionResolutionRecord/BridgeClientSessionEntrytypes +MAX_RESOLVED_PERMISSION_RECORDScap". At this commitbridgeClient.tsexports onlyKNOWN_APPROVAL_MODES,BridgeClientSessionEntry,BridgeClient, and the a2ui helpers —PendingPermissionexists nowhere in the package, andPermissionResolutionRecord/MAX_RESOLVED_PERMISSION_RECORDSare module-private inpermissionMediator.ts. A reader following that bullet imports the three symbols and gets compile errors, and the same section now tells two opposite stories about where permission state lives — the exact staleness this PR exists to remove survives in its own file. Updating the sibling bullet in the same pass keeps the section self-consistent, e.g. drop the three vanished exports (keepBridgeClientSessionEntry) and replace "first-responder permission flow" with "permission requests plumbed into the injectedPermissionMediator(mediator.request)"; the pending/resolved state and cap live inpermissionMediator.ts.中文说明
这条重写后的条目与 diff 未更新的一条相邻条目矛盾:同一节中未改动的
bridgeClient条目(第 76-84 行)仍声称 BridgeClient 实现 "first-responder permission flow" 并 "Exports the supportingPendingPermission/PermissionResolutionRecord/BridgeClientSessionEntrytypes +MAX_RESOLVED_PERMISSION_RECORDScap"。在当前提交,bridgeClient.ts只导出KNOWN_APPROVAL_MODES、BridgeClientSessionEntry、BridgeClient和 a2ui 辅助函数——PendingPermission在整个包中不存在,PermissionResolutionRecord/MAX_RESOLVED_PERMISSION_RECORDS是permissionMediator.ts的模块私有符号。读者按该条目导入这三个符号会得到编译错误,同一节因此对 permission 状态归属给出两种相反说法——本 PR 要消除的过期内容恰好残留在它自己改动的文件里。建议顺手更新该条目保持一致:删掉三个已不存在的导出(保留BridgeClientSessionEntry),把 "first-responder permission flow" 改为 "permission requests plumbed into the injectedPermissionMediator(mediator.request)";pending/resolved 状态与上限在permissionMediator.ts。— qwen3.8-max via Qwen Code /review (v0.22.0)