Skip to content

feat(managed-agent): Archive, delete and unarchive Workspace-bound Sessions #13164

Description

@wenshao

What would you like to be added?

Archive, delete and unarchive for Workspace-bound Hosted Sessions, on the public and WebShell lifecycle routes. D4 (#12881) made close, archive and delete durable operations, but only for Sessions without a Workspace binding. #13135 adds close for idle hosted-workspace-files/1 Sessions. A bound Session still cannot be archived, unarchived or deleted.

Where main is today

Proposed slices

Slice Deliverable Exit check
L1: archive and unarchive For a closed bound Session, archive completes in the admission transaction as in D4, and unarchive restores closed without lifting the close fence of #13135. Admission follows #13135: the creator with current read access, 404 without read access, 403 for a readable non-creator. History, Artifacts, file-history backups and publications stay. A replayed key returns the original result on both surfaces. Another actor's key is a separate request. A Session that is not closed answers 409 session_state_conflict. An unarchived Session still refuses input and warm.
L2: delete a closed or archived Session The D4 tombstone for bound Sessions: Session reads answer 404 and its operations stay readable. The delete commits the O4-1 retirement of private recovery and publication access together with the tombstone. Shared Workspace files and other Sessions' holders stay. Tombstone and operation reads on both surfaces. Retirement and tombstone commit together or not at all.
L3: delete an active Session Delete through the Harness's explicit deletion, so SessionEnd and SessionDelete run once, then the settlement of #13135, then L2. Close moves to a Harness call that does not run SessionDelete. A running, cancelling or approval-waiting Turn answers 409 turn_active. An unknown Hook or execution outcome leaves the Session deleting with recovery_blocked; nothing is replayed or provisioned again. Lost replies and a crash at each step, with claim takeover on a second server. ACL or mount revoked after admission. Each Hook runs once, and a close runs no SessionDelete. Real MySQL concurrency, and Linux identity checks where available.
L4: Shell and MCP profiles Close and delete for hosted-workspace-shell/1, which settles capture and publications before the O4 retirement, and for hosted-workspace-mcp/1, which detaches and releases its connections through the H1 release receipts. The L3 matrix for each profile, plus an API delete of a Shell Session followed by O4-2 collection without a seam.

L1 and L2 can start on top of #13135 now and land after it. L3 needs L2, and its Hook part needs #13129. L4 depends on question 1.

Out of scope

Questions before implementation

  1. @doudouOUC Will feat(managed-agent): reliably close workspace-bound sessions #13135 grow to cover close for the Shell and MCP profiles, or should L4 here take it?
  2. @doudouOUC Should bound delete land after feat(managed-agent): Protect Session-owned tool output retirement #13084 and call its retirement inside the tombstone transaction, or land first with a retirement step that O4-1 fills in?
  3. Capability shape: per-operation flags like session_close in feat(managed-agent): reliably close workspace-bound sessions #13135, or session_lifecycle turning true for a Session once all four operations work for its profile?
  4. Who may delete: only the creator, as for close, or also a Workspace administrator who did not create the Session?

Why is this needed?

Workspace-bound Sessions are the only Sessions that run tools. Once #13135 lands they can be closed on the files profile, and nothing else. A tenant cannot archive or delete them, so their records, backups and publications can never be retired, and O4 collection has no real trigger. The D4 lifecycle contract should hold for bound Sessions as it does for the others: close, archive, and a delete that leaves a tombstone and keeps the shared Workspace.

Part of #12380, under Stage D (#12867). Follows D4 (#12881) and #13135.

中文说明

希望增加什么?

在公开与 WebShell 生命周期路由上,为绑定了 Workspace 的 Hosted 会话提供 archive、delete 与 unarchive。D4(#12881)把 close、archive、delete 做成了持久操作,但只覆盖没有 Workspace 绑定的会话。#13135 为空闲的 hosted-workspace-files/1 会话补上了 close。绑定会话目前仍不能归档、取消归档或删除。

main 上的现状

拆分

切片 交付 验收
L1:archive 与 unarchive 对已关闭的绑定会话,archive 与 D4 一样在准入事务内完成;unarchive 恢复为 closed,不解除 #13135 的关闭围栏。准入沿用 #13135:当前有读权限的创建者可以执行,无读权限返回 404,有读权限的非创建者返回 403。历史、Artifact、文件历史备份与发布都保留。 两个入口重放同一个键都返回原结果。其他 actor 的键是另一个请求。非 closed 的会话返回 409 session_state_conflict。取消归档后的会话仍拒绝输入与 warm。
L2:删除已关闭或已归档的会话 为绑定会话提供 D4 的墓碑:会话读取返回 404,其操作仍可读取。删除与墓碑一起提交 O4-1 对私有恢复与发布访问的退役。共享的 Workspace 文件与其他会话的持有保留。 两个入口上的墓碑与操作读取。退役与墓碑要么一起提交,要么都不提交。
L3:删除活跃会话 经由 Harness 的显式删除执行,使 SessionEnd 与 SessionDelete 各运行一次,再执行 #13135 的结算,然后是 L2。close 改用不运行 SessionDelete 的 Harness 调用。运行中、取消中或等待审批的 Turn 返回 409 turn_active。Hook 或执行结果未知时,会话保持 deleting 并标记 recovery_blocked,不重放、不重新供给。 每一步的应答丢失与崩溃,以及第二台服务器接管 claim。准入之后 ACL 或挂载被撤销。每个 Hook 只运行一次,close 不运行 SessionDelete。真实 MySQL 并发,以及条件具备时的 Linux 身份检查。
L4:Shell 与 MCP 配置 为 hosted-workspace-shell/1 提供 close 与 delete,在 O4 退役之前结算捕获与发布;为 hosted-workspace-mcp/1 提供 close 与 delete,通过 H1 的释放回执 detach 并释放连接。 每种配置都跑 L3 的矩阵,再加上经 API 删除 Shell 会话后、不借助测试接缝的 O4-2 回收。

L1 与 L2 现在就能在 #13135 之上开始,在它之后合入。L3 依赖 L2,其中的 Hook 部分依赖 #13129。L4 取决于问题 1。

不在范围内

实现前需要确认的问题

  1. @doudouOUC feat(managed-agent): reliably close workspace-bound sessions #13135 是否会扩展到 Shell 与 MCP 配置的 close,还是由这里的 L4 来做?
  2. @doudouOUC 绑定会话的 delete 应该在 feat(managed-agent): Protect Session-owned tool output retirement #13084 之后合入、并在墓碑事务内调用它的退役,还是先合入、留一个由 O4-1 填充的退役步骤?
  3. 能力字段的形式:像 feat(managed-agent): reliably close workspace-bound sessions #13135 的 session_close 那样按操作分别给出,还是某个会话的配置支持全部四种操作后,把它的 session_lifecycle 置为 true?
  4. 谁可以删除:与 close 一样只限创建者,还是 Workspace 管理员也可以删除不是自己创建的会话?

为什么需要?

绑定 Workspace 的会话是唯一会运行工具的会话。#13135 合入后,它们只能在 files 配置下被关闭,别的都做不了。租户无法归档或删除它们,它们的记录、备份与发布永远无法退役,O4 的回收也没有真实的触发入口。D4 的生命周期契约应当像对其他会话一样适用于绑定会话:close、archive,以及留下墓碑并保留共享 Workspace 的 delete。

属于 #12380 的 D 阶段(#12867)。接续 D4(#12881)与 #13135。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions