kisenon
Agent-Safe Change Control

Sandboxes & promote

安全地将 AI 编码智能体对准你的生产数据库——被捕获、被观测、通过一道闸门提升,且可逆。

Agent-Safe Change Control 的一部分。本文所述的 keon sandboxkeon ledger 命令以及控制台 Sandboxes 视图都 已上线——需要较新的 keon(cli-v0.1.46+)。

Kisenon 让你把一个数据库交给编码智能体(Claude Code、Cursor 或你自己的), 任其自由更改——而不必冒险危及生产环境。沙箱是 你分支的一份每次运行的 fork,配有受限凭据、一份实时操作日志, 以及一个服务端的提升步骤。本页覆盖完整的循环:捕获 → 工作 → 提升 → 落地(可逆地)→ 证明

Why it's safe

两项保证,二者皆为确定性的——信任路径中没有 LLM 介入:

  • 智能体无法触及生产环境。 它以受限的、 非超级用户的凭据连接到一份 fork。它绝不持有能 写入 main 的凭据。提升在服务端运行,并且只应用那些 已在沙箱中通过验证的更改。
  • 你能看清它究竟做了什么。 每一条语句都被归因并 流式推送到一个只读控制台——是真实的 SQL,而非摘要。

The loop

keon sandbox run \
  --migrate "alembic upgrade head" \
  --verify  "pytest tests/db"
# → green/red verdict + schema diff + a sandbox you can inspect

keon sandbox promote <id>   # cp applies the validated changes to main

智能体始终掌控着这个循环;正是那道边界使其变得安全。

Durable capture

操作日志是提升的事实来源,因此它必须完整。 每个沙箱携带一个 capture_state —— oklost。如果捕获曾经 受损,状态会翻转为 lost保持 在那里:一个 lost 沙箱 无法提升(409 sandbox_capture_lost),并且绝不会悄悄应用 部分变更。没有自动修复——丢弃它,并在一个 全新的沙箱中重新运行该工作。keon sandbox get / list 会显示捕获健康状况。

Promote: self-serve or human-approved

每个项目选择一种 promote_mode

模式由谁提交到 main
self(默认)智能体在其检查通过后自行提升——在其边界之内。
human智能体提议;由 owner/admin 审查 diff + 操作日志后点击 Approve

Blast-radius dry-run

在你提升之前,你可以请求平台 测量 提升会做什么 ——真实的锁级别、真实的持锁时长、真实的行数—— 而不是从语句文本去猜测:

keon sandbox dry-run <id>

平台将沙箱的确切语句集对父分支的两个短期存活的 一次性 fork 进行重放——一个在父分支的当前 HEAD(在那里测量锁、 时长和行数),一个在沙箱的 fork 点(分歧 基线)——然后销毁两者。它绝不触及 main,且 智能体绝不收到对任一 fork 的凭据。该试运行是 建议性的: 它产出报告,绝不阻断提升。

它还回答了一个静态 diff 无法回答的问题:现实是否在 智能体脚下移动了? 任何在父分支 HEAD 处报错、或影响与 fork 点不同行数的语句都会被暴露为一个 冲突 —— 例如 一条 UPDATE ... WHERE id = 2,其目标行在 fork 之后已在 main 上被删除。

已完成的报告携带:

字段含义
statements[].lock_level该语句在提升事务中新获取的最强锁(例如表重写时的 AccessExclusiveLock)。
statements[].lock_wait_est_ms在 head fork 上测量到的执行时间——该锁在 main 上被持有时长的下限。
statements[].rows_measured在 head fork 上受影响的行数(DDL 为 0)。
statements[].divergence当语句在 HEAD 处的行为与 fork 时不同时,为 {kind:"error"}{kind:"row_count"}
rollup.conflicts每一处分歧,外加一个 baseline_unavailable 标记(如果基线通道无法运行)——因此一道以"无冲突"为条件的闸门在测量降级时会 失败即关闭
rollup.max_lock_level / rollup.duration_ms_total聚合的锁强度与总重放时间。
capture_advanced / parent_head_lsn陈旧性信号:该报告是一个快照,重新运行成本很低。

端点是 POST /v1/sandboxes/{id}/dry-run(启动一次异步运行,202) 和 GET /v1/sandboxes/{id}/dry-run(最新记录)。一次失败的试运行 携带一个机器可读的 error_codecapture_fence_failedincomplete_capturefork_failedcompute_unreachablereplay_infra_failedtimeout)。沙箱详情页上的 Blast radius 面板在控制台中渲染同一份报告。

Undo a promote

提升是可逆的。在 cp 将验证过的语句应用到 main 之前,它锚定父分支提升前的确切状态(一个 LSN)。一条 命令即可将分支回滚到那个锚点:

keon sandbox undo <id>   # restore the parent branch to its pre-promote state

父分支的连接字符串不变——客户端重新连接到同一 端点。撤销是一个 owner/admin 操作;智能体能力密钥会被拒绝 (403 scope_insufficient),因为一次撤销会丢弃锚点之后落到分支上的 任何内容。

keon sandbox get <id> 携带一个 undo 对象——undoablerestored_lsnundone_at,以及在它无法运行时的 blocked_reasonsuperseded_by_later_promotealready_undone)。撤销只针对 最近的 一次提升,并在锚点消失后以 409 拒绝(sandbox_not_promotedundo_anchor_missingundo_anchor_invalidated)。 只要锚点有效且在你的存储保留期内,它就保持可用 ——没有单独的倒计时。

撤销按 LSN 恢复:它回滚锚点之后的 一切,而 不只是被提升的变更——包括直接写入和该分支上后来的 智能体会话。参见 Common pitfalls

Emitted migrations

每一次落地的提升都会发出一份确定性的 up/down SQL 迁移——没有 LLM, 从捕获的模式变更生成,并在提供之前于一次性 fork 上经过 往返验证。获取它:

keon sandbox migration <id> --out ./migrations --wait

该制品携带 up 和 down SQL(files[],每个带一个 role)、一个 coverage 标志(fullpartial)、down_fidelity、任何 uncovered_seqs、 一个 validation 结果,以及一个 sha256。终态是 validatedvalidation_failedemission_failedno_schema_changes。v1 发出 sqlGET /v1/sandboxes/{id}/migration(以及 .../migration/files/{role}) 提供它。发出在提升落地之后运行,绝不阻断或回滚 它——一次纯数据的提升只会报告 no_schema_changes

Signed ledger

每一次提升和撤销都会向一个每项目的账本追加一条签名的、哈希链接的 记录——一份对所变更内容的可离线验证的证明。验证不需要 网络,且不信任 Kisenon:

keon ledger list --project <id>          # the chain (reports chain_ok)
keon ledger export <id> --out att.json   # one attestation document
keon ledger verify att.json              # offline; exit 0 iff valid
keon ledger keys --save                  # pin the signing keys you trust

keon ledger verify 检查 Ed25519 签名和哈希链,并 报告精确的失败(signature_invalidstatement_chain_mismatchseq_gapkey_untrustedchain_broken、…);信任是三态的 (trusted / untrusted / unverified)。路由:GET /v1/sandboxes/{id}/ledgerGET /v1/projects/{projectId}/ledgerGET /v1/ledger/keys

如果 cp 未配置签名密钥,提升仍会成功但是 未签名的ledger_enabled: false)——签名不是无条件的。

What a sandbox is not

  • 不是代码沙箱——它限定的是你的数据库,而非智能体的进程。
  • 不是 LLM 评审——捕获、重放与审查都是逐字节确定性的。

Try it

kisenon.com 试用,并查看 快速开始