AIDAWORK / SEQUENCE

Schema identity 迁移部署序

独立图页 ↗

先看「视图」里的主路径;每条失败链都有同名成功对偶(fail-x ↔ ok-x)。

机制说明(SoT)图是辅读 · 结论以说明与证据为准

Config 平面:同一 Postgres(CONFIG_DB_URL)上的 config_schema_identity 与 CURRENT_CONFIG_SCHEMA_ID(tip:aida-config-dev-2026-10-28-conversation-turn-queue(定义在 schema-metadata.ts),链为 177 → 178 → 179 → 181 → 183 → 184 → 185 → 186 background-open-roots-index → 187 llm-credits → 188 desktop-execution → 189 `local-t…

本页可直接往下读完整机制说明,不需要「演示 / 播放故事」。术语不熟先看 术语表。

先读机制说明,结论以说明与证据为准 · 基于固定代码版本核验 · 部署状态另行确认

机制说明(全文)

存储平面:Config / 运行业务表 / Desktop 本地

三层不要混

Config 平面:同一 Postgres(CONFIG_DB_URL)上的 config_schema_identity 与 CURRENT_CONFIG_SCHEMA_ID(tip:aida-config-dev-2026-10-28-conversation-turn-queue(定义在 schema-metadata.ts),链为 177 → 178 → 179 → 181 → 183 → 184 → 185 → 186 background-open-roots-index → 187 llm-credits → 188 desktop-execution → 189 local-tenant-admin → 190 document-conversion → 191 conversation-turn-queue;180 / 182 不改 identity;迁移 165 新增 runtime_work_provider_attempts 与 provider attempt ↔ run_checkpoints checkpoint guard 约束触发器,166 新增 local_file_operations.original_content,167 Work side query,168 为配置数据迁移且因与 165–167 撞号顺延);启动 assertCurrentConfigSchema 校验 identity、messages 必须是普通表(relkind=r)、关系/列/触发器/CHECK(含 PG11 compact fingerprint);缺迁移 fail fast;租户密钥与 Provider 凭据用 CONFIG_ENC_KEY AES-GCM。Admin/配置对象写这里。

运行 / 业务表平面:仍在 Config DB 内,但职责是 Run、Interaction、LF Operation、通知、runtime_work_(model rebuild/rejection/material)、conversation_compact_ pins、offer_approval_cycle_bindings 等执行事实。外部 VMS/ATS 等源系统才是业务实体 SoR。部署:审阅 migration(117–151)→ 应用 → bump schema identity → 启动断言;共享库禁止 silent DDL / reset(assertConfigDbSafeToInitialize 拒非空库)。

Desktop 本地平面:Main 持有授权文件夹、LF 写状态(write-state-v4.json,版本 3;legacy 1/2 条目解析时丢弃不可迁移的)及对话级 Interaction 草稿。钉点 8eecd12081db(e2fdc7c7)起,授权文件夹、写状态、已选文件句柄、本地 artifact 索引与原生路径 message-overlay 改存账号作用域的加密信封 LocalSecureEnvelope(根目录 <config>.native-private;随机 profile key 由 safeStorage 包裹,正文 AES-256-GCM,AAD 绑定 OS profile / installation / endpoint / tenant / user);底层文件仍由 AtomicJsonStore 原子写。旧明文 write-state-v4.json 只作迁移来源:仅 POSIX、journal 归当前账号、无待用确认 / 另存目标且能完整往返时才迁入信封并删除明文;不能无损导入、但每条写都已完成送达且确认 / 另存目标都已消费或过期的旧 journal(desktop ca745377 起,Desktop #428)改为「移到一边、不导入」:原样改名 write-state-v4.legacy-retired.json,迁移回执记下 retiredOperationIds 继续拒绝重放(回执读不出即报错)。其余情况仍 LOCAL_FILE_WRITE_STATE_LEGACY_UNAVAILABLE,明文还在期间写状态一直不可用(LEGACY_UNSCOPED);win32 上有残留明文即不可迁移。旧明文 authorized-folders-v4.json 本钉点源码不再读取,未见迁移代码(静态推断:升级后需重新授权文件夹)。这些升级路径实际是否会发生、如何处置未核实。证据:aida-desktop · apps/desktop/electron/security/local-secure-envelope.ts L48–61 · LocalSecureEnvelope · 4346d79eb364;aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L794–798 · LOCAL_FILE_WRITE_STATE_LEGACY_UNAVAILABLE · 4346d79eb364;aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L886–950 · LOCAL_FILE_WRITE_STATE_RETIRED_FILE · 4346d79eb364;aida-desktop · apps/desktop/electron/local-files-v4/authorized-folder-authority.ts L31–71 · LocalSecureEnvelope · 4346d79eb364。绝对路径不出 Main;本地仓不授权服务端工作,也不随用户跨设备。

失败 / 耦合

  • schema_id 不匹配或缺 REQUIRED 关系/列 → 进程拒绝启动,不静默降级。
  • 已有对象上跑 initialize → 明确拒绝,要求走审阅迁移链。
  • Desktop 本地文件损坏只影响本机投影,不污染 Config DB。

迁移 169–173(钉点 e2adc9a3c325)

  • 原来同号的两个 169 已拆开:取消操作约束改名为 170_employee_lifecycle_cancellation_operations.sql,db:migrate 仍接受旧名并提示改名;SQL 主体不变,可以重复执行。
  • 169_restore_config_structure.sql 现在同时接受取消前、取消后两种约束定义:健康环境只执行 170;需要修复的环境先 169 再 170,顺序反了也不再 REPAIR_OBJECT_CONFLICT。
  • 171:从在线 Skill vms-employee-lifecycle 移除离项个人应付来源工具;173:给 payroll-work-command 追加只读 list_payroll_book_members。都是纯数据、可重放,README 写明未在任何环境执行。
  • 以上都不改 schema identity(当时为 aida-config-dev-2026-10-10-work-side-queries,之后由 177 推进)。
  • 编号(钉点 e2adc9a3c325,!219 合入后):170 已被取消约束占用;角色按租户迁移改为预留 172(文件尚未提交、尚未执行),171 / 173 文件头与 README 已一致。两份草案(170-role-capability-answer-DOWN-DRAFT.sql、tenant-resource-tiers-DRAFT.sql)仍写「170」,README 说正式提交时随之改为 172;资源档位草案写明执行前需 Max 确认。

迁移 174 / 176 / 177(钉点 e2adc9a3c325)

  • 174:给 audit_events 补 2026-11 到 2028-12 的月分区,不加 DEFAULT,不改 identity。README 记载审阅版已在 150、202 执行;截止 2026-11-01 前两库都要有分区。
  • 176:放宽 desktop_distribution_releases 平台 CHECK,加入 linux-x64(Linux 发布链路见 desktop-client),不改 identity。
  • 177:给分区父表 audit_events 加可空 state / failure_class 两列,不加 CHECK、不改旧行;identity 推进到 aida-config-dev-2026-10-16-audit-state-contract。启动断言要求目标 identity 和这两列都在。
  • 三条都不随启动执行。README 177 段仍写「未在 150、202 或任何共享库执行」,但同一 README 记载 202 已处在 179 identity、150 已依次执行 178 / 179 / 181 / 182——都以 177 为前置,177 段这句已过时。175 预留已取消,messages 去分区改由 181 完成。
  • 证据:aida-agent · packages/agent/migrations/README.md L163–167 · 177_audit_state_failure_class.sql · e2adc9a3c325;packages/agent/migrations/177_audit_state_failure_class.sql L125–128 · aida-config-dev-2026-10-16-audit-state-contract · e2adc9a3c325

迁移 180–185 与 ADR-0094 / 0095(钉点 e2adc9a3c325)

  • identity 链:179 → 181_messages_unpartition(aida-config-dev-2026-10-21-messages-unpartitioned)→ 183_conversation_seq_quota_bucket(…-conversation-seq-quota-bucket)→ 184_quota_bucket_kind_assignment(…-quota-bucket-kind-assignment)→ 185_background_runs_outside_conversation_slot(…-background-outside-conversation-slot)→ 186_background_open_roots_index(…-background-open-roots-index,即 tip;部分索引 idx_agent_runs_background_open_roots)。每步前置只接受上一步或本步目标值,目标重放只核对、不写;均 PG11/12 单事务、lock_timeout=5s、表属主 SET LOCAL ROLE,开头按 ADR-0094 一次取齐业务表锁、之后不升级。
  • messages 普通表(180 / 181 / 182,STA-84):180 给当时的分区表补 26 个月分区(只在 202 执行过,已被 181 取代);181 把 messages 收敛为普通表(202 走复制路径、保留 messages_partitioned_old;150 本已是普通表,只核对结构),启动校验要求 relkind=r;182 在核对归档每行都在 messages 后删除归档表,不改 identity。
  • 会话序号(183,ADR-0095 2a-1 / 2a-2):conversations.next_message_seq + BEFORE INSERT 触发器串行分配 messages.conversation_seq(覆盖调用方值,允许空洞,不可改,存量 NULL 不回填)。读路径统一按 conversation_seq ASC NULLS FIRST, created_at, id(session/message-order.ts);前台上下文快照以本轮原始输入消息的序号为截止,晚到的外部推送 / 后台汇报下一轮才可见;旧摘要在新顺序下不是完整前缀时改用无摘要窗口并告警。ADR 禁止以 INSERT 恢复历史消息。已知例外:附件来源截止仍按 (created_at, id)。
  • 配额分桶与后台写入(183 / 184 / 185):agent_runs.quota_bucket 由触发器推导(conversation turn → foreground;background_work.v1 及其 child → background;其余 uncounted),184 修复「先 NULL kind 建行、受理时再赋 kind」两阶段路径的首次推导,之后不可改桶、不可把非 NULL kind 清回 NULL;后台 root 只能写 assistant / background_report 消息,后台 child 不得写消息;origin_run_id 可空、不可变、无外键。185 让一会话一活跃 run 的唯一索引排除 background_work.v1。领取侧见 scaling-roles。
  • 锁层级(ADR-0094,Proposed,代码已落地):L1 原 root → L2 carrier/child → L3 run 附属行 → L4 消息 id advisory → L5 conversations → L6 sessions → L7 已有 messages;持有 conversations 行锁后不得再阻塞等待已有 run 行锁。受理据此删掉旧 runtimeExecution 分支与对已有 root 的 FOR UPDATE,挂起本机执行改为逐表显式加锁,过期卡收敛改为非阻塞锁整棵树(见 state-authority)。ADR 自述不是全库无死锁证明。
  • 执行记录(README,2026-10-21):150(PG 12.22)依次执行 178、179、181、182;202(PG 11.16)在 179 identity 上执行 181(首次锁超时整体回滚,修正后重跑)、182,并已执行 183。184 / 185 两库都只有执行说明、没有执行记录,150 尚未执行 183。按 README,183 / 184 / 185 每步执行后都要立刻发布匹配镜像,旧镜像过不了新 identity。README 181 段末尾仍留有「150:未执行」旧句,与 182 段矛盾。
  • 证据:aida-agent · packages/agent/src/config/schema-metadata.ts L6–8 · aida-config-dev-2026-10-28-conversation-turn-queue · e2adc9a3c325;aida-agent · packages/agent/src/config/schema-identity.ts L691–699 · relkind · e2adc9a3c325;aida-agent · packages/agent/src/config/ddl.ts L4812–4828 · assign_conversation_message_seq · e2adc9a3c325;aida-agent · packages/agent/src/config/ddl.ts L1348–1355 · idx_agent_runs_one_active_per_conversation · e2adc9a3c325;aida-agent · packages/agent/src/session/message-order.ts L7–12 · messageOrderSql · e2adc9a3c325;aida-agent · docs/adr/0094-config-db-transaction-lock-hierarchy.md L27–41 · 持有 conversations 行锁 · e2adc9a3c325;aida-agent · docs/adr/0095-conversation-seq-quota-bucket-background-write.md L13–24 · next_message_seq · e2adc9a3c325;aida-agent · packages/agent/migrations/README.md L198–203 · 182_drop_messages_partitioned_old.sql · e2adc9a3c325

迁移 187–191(钉点 e2adc9a3c325)

  • 187 llm_credits → identity aida-config-dev-2026-10-26-llm-credits:租户/用户 Credits 配额与用量表;chat 受理 admitChatCredits,耗尽返回专用拒绝。共享部署需单独授权。
  • 188 desktop_execution_devices → …-desktop-execution:设备登记 / online lease / runtime_invocations_remote_desktop;为远程 Desktop 执行就绪(设计稿 docs/design/remote-desktop-readiness.md)。代码已合入;共享库执行与真机远程验收未核实。
  • 189 local_tenant_admin → …-local-tenant-admin:本地操作员角色扩到 tenant_admin 且强制具体租户作用域。
  • 190 document_conversion → …-document-conversion:guard_local_file_original_content 增加 convert_pdf_to_xlsx / document_conversion 消费方。
  • 191 conversation_turn_queue → tip …-conversation-turn-queue:会话仍在执行时,新 chat turn 服务端 FIFO 排队(加密载荷),不改一会话一活跃 run 唯一索引;ChatSubmissionStore 经 insertConversationTurnQueue / claimNext… / mark…Admitted 驱动。
  • README 没有 150/202 对 187–191 的执行记录;未升到 tip identity 的库上本钉点 Agent 会拒绝启动。旧债 184/185/186 共享库执行状态仍未核实。
  • 证据:见本轮 evidence storage-planes 新增 claim。

迁移 179(钉点 e2adc9a3c325)

  • 179_local_file_transient_expiry.sql(Config DB):前置 identity 只接受 aida-config-dev-2026-10-18-desktop-protocol-v3 或目标值(可重放),并按 md5 校验现有守卫函数体与触发器形状,否则 TRANSIENT_EXPIRY_*_PRECONDITION_FAILED / TRANSIENT_EXPIRY_GUARD_DRIFT;事务内只 CREATE OR REPLACE guard_local_file_original_content,新增写入者 runtime_work.original_file_writer = 'transient-expiry':只允许 UPDATE 把已过期的 transient_result / transient_result_expires_at 置空,行其余字段(含原件)不变;不改表结构;identity 推进到 aida-config-dev-2026-10-20-local-file-transient-expiry。带 DOWN 草稿 docs/migration-drafts/rollback/179-local-file-transient-expiry-DOWN.sql。
  • 运行时写入者:createLocalFileMaintenance.runOnce 在事务里设置该写入者后调 expireUnconsumedTransientResults。
  • SQL 头注释写明共享环境部署需单独授权。179 现为 181 的唯一前置;执行记录见下文「迁移 180–185」。
  • 证据:aida-agent · packages/agent/migrations/179_local_file_transient_expiry.sql L1–30 · TRANSIENT_EXPIRY_SCHEMA_PRECONDITION_FAILED · e2adc9a3c325;aida-agent · packages/agent/migrations/179_local_file_transient_expiry.sql L324–337 · transient-expiry · e2adc9a3c325;aida-agent · packages/agent/migrations/181_messages_unpartition.sql L23–24 · aida-config-dev-2026-10-20-local-file-transient-expiry · e2adc9a3c325;aida-agent · packages/agent/src/runtime/local/local-file-maintenance.ts L29–34 · transient-expiry · e2adc9a3c325

Work 展示账本(钉点 e2adc9a3c325)

  • 生产 Chat Work 在 common-control 事务里把公开事实投影写入 run_projection_events(producer chat-sse-work,dense 序号复用 producer_revision,推进 agent_runs.projection_next_sequence);每 Root 上限 10000 条 / 16 MiB,超限写 chat_sse_truncated。投影在 savepoint 内执行:失败只回滚展示写入,在 savepoint 外写截断标记,Work 核心状态照常提交。供只读 GET /api/runs/:runId/stream 重放(见 observability-map)。未改 DDL / 迁移 / identity;ER-09 静态写入者清单已把它登记为受审 Run 写入者(只分配展示序号,不碰 status / attempt / checkpoint)。
  • 证据:aida-agent · packages/agent/src/runtime/stream/work-chat-sse-ledger.ts L24–50 · WORK_CHAT_SSE_MAX_EVENTS · e2adc9a3c325;aida-agent · packages/agent/src/runtime/stream/work-chat-sse-ledger.ts L192–206 · savepoint · e2adc9a3c325

迁移 178(钉点 e2adc9a3c325;现为 179 的前置)

  • 178_desktop_protocol_v3.sql(Config DB):前置 identity 必须是 aida-config-dev-2026-10-16-audit-state-contract(已是目标时可重放),否则 DESKTOP_PROTOCOL_V3_PREDECESSOR_MISMATCH;事务内只 CREATE OR REPLACE 两个守卫函数——guard_local_file_original_content 去掉对 request->'features' token 的判断,local_file_operations_assert_work_identity 改看 localFileCapability 是否存在而不是 localFileProtocolVersions——不改行与约束形状;identity 推进到 aida-config-dev-2026-10-18-desktop-protocol-v3(本钉点已被 179 继续推进)。
  • 启动必需清单同时不再要求 chat_submission_idempotency.original_inline_inputs。
  • 运行时只做 identity 检查,从不执行此 SQL。ADR-0090 D5 要求部署到 202 等远程环境前先应用 178。README 没有单独的 178 段落;执行情况记在 181 / 182 段(150 于 2026-10-21 先执行 178、179;202 执行 181 时已处在 179 identity)。
  • 遗留:business_task_agent_turn_outbox 仍在必需清单里,但源码已无写入方(见 harness)。
  • 证据:aida-agent · packages/agent/migrations/178_desktop_protocol_v3.sql L1–16 · aida-config-dev-2026-10-18-desktop-protocol-v3 · e2adc9a3c325;aida-agent · packages/agent/migrations/178_desktop_protocol_v3.sql L39–43 · DESKTOP_PROTOCOL_V3_PREDECESSOR_MISMATCH · e2adc9a3c325;aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L255–270 · protocolFeatures · 4346d79eb364

归属边与非目标

  • Owner:Config DB schema 与 Agent 运行表;Desktop 本地状态(LocalSecureEnvelope 加密信封 + AtomicJsonStore 原子写)仅本机。
  • 非目标:不讨论对象存储字节面(S3 协议元数据另册);不写 RustFS。
  • 相关:state-authority、ledger-authority、local-file-v5、overview。

视图

  • main — 三平面架构。

  • migrate — schema identity 迁移/部署耦合序(图里的迁移号是示意;现行 identity 链见上文「迁移 180–185」)。

  • fail-schema — 启动 schema 断言 fail-fast。

  • fail-atomic — AtomicJsonStore corrupt / LEGACY_DROPPED。

  • ok-schema — schema identity 断言通过(对偶 fail-schema)。

  • ok-atomic — AtomicJson 读写干净(对偶 fail-atomic)。

成功对偶(与失败链入口相同)

  1. ok-schema:assertCurrentConfigSchema 匹配 schema_id 且关系/列完备 → 启动继续。
  2. ok-atomic:AtomicJsonStore.read status=ok;原子写;legacy drop=0。

失败链(深挖)

  1. fail-schema:assertCurrentConfigSchema mismatch/缺列 → throw;进程拒启;恢复=审阅迁移+bump+重启。
  2. fail-atomic:corrupt 不覆写空态;unmigratable legacy → LOCAL_FILE_WRITE_STATE_LEGACY_DROPPED;仅本机。

证据与范围

  • aida-agent · packages/agent/src/config/schema-identity.ts L4–42 · CURRENT_CONFIG_SCHEMA_ID · e2adc9a3c325

  • aida-agent · packages/agent/src/config/schema-identity.ts L633–663 · config_schema_identity · e2adc9a3c325

  • aida-agent · packages/agent/src/config/schema-identity.ts L661–701 · assertCurrentConfigSchema · e2adc9a3c325

  • aida-agent · packages/agent/src/config/db-init.ts L176–206 · assertConfigDbSafeToInitialize · e2adc9a3c325

  • aida-agent · packages/agent/src/config/crypto.ts L15–45 · initEncryption · e2adc9a3c325

  • aida-agent · docs/architecture/backend-admin.md L76–98 · Config DB · e2adc9a3c325(历史引用:该文件在上一钉点与当前钉点均不存在,未能复核;见 ATLAS-DEBT)

  • aida-desktop · apps/desktop/electron/local-files-v4/authorized-folder-authority.ts L119–159 · V4AuthorizedFolderStore · 4346d79eb364

  • aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L36–67 · LOCAL_FILE_WRITE_STATE_FILE · 4346d79eb364

  • aida-desktop · apps/desktop/electron/atomic-json-store.ts L68–97 · AtomicJsonStore · 4346d79eb364

  • aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L730–746 · LOCAL_FILE_WRITE_STATE_LEGACY_DROPPED · 4346d79eb364

  • aida-agent · packages/agent/src/config/schema-identity.ts L661–701 · assertCurrentConfigSchema · e2adc9a3c325

  • aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L459–469 · read status=ok · 4346d79eb364

结论来自固定版本的静态源码与合同阅读;实现存在、默认开关和生产启用分别判断。本站代码证据面板列出声明状态与具体限制。

  • aida-agent · packages/agent/migrations/README.md L133–141 · 170_employee_lifecycle_cancellation_operations.sql · e2adc9a3c325

  • aida-agent · packages/agent/migrations/171_remove_offboarding_payable_skill_tool.sql L1–4 · schema identity · e2adc9a3c325

  • aida-agent · packages/agent/migrations/173_add_payroll_book_members_skill_tool.sql L1–3 · schema identity · e2adc9a3c325

  • 本轮 186:aida-agent · packages/agent/migrations/186_background_open_roots_index.sql L56–70 · idx_agent_runs_background_open_roots · e2adc9a3c325;aida-agent · packages/agent/src/config/schema-metadata.ts L6–8 · aida-config-dev-2026-10-28-conversation-turn-queue · e2adc9a3c325;aida-agent · packages/agent/src/config/schema-identity.ts L19 · idx_agent_runs_background_open_roots · e2adc9a3c325。共享库是否已执行未核。

数据生命周期:字节、引用、凭据与观察记录

本页补充 存储平面,不另建主题。基线:Agent 7f2e519936b53035646a70f152e734298abed2fb、Desktop 4346d79eb364b502ef87c0869a494dfed7964419。这是固定快照的静态事实,不代表线上配置、实际清理任务运行或备份删除已核验。

D01 数据从哪里来、经过哪里、在哪里结束

图中「登记/读取/保留/清理」是概念阶段,不是数据库状态枚举;附件投影的真实类型是 available | unavailable | revoked,也不等于文件本体生命周期。

附件与产物的数据生命周期及宿主边界

图形正在加载;下方源代码始终可读。

Mermaid 源代码
flowchart TB
  accTitle: 附件与产物的数据生命周期及宿主边界
  accDescr: 本地文件经 Main 授权形成无绝对路径的附件关系,按请求读取后正文可进入 Agent 临时材料;消费或无活跃引用的过期清理仅删除临时材料,不删除原文件。已安装插件的用户级文件与网络访问属于独立执行边界。
  File["用户本地文件"] --> Main["Main:locator 与原生授权"]
  Main -->|"ID、显示名、相对路径"| Relation["Agent:附件关系与原 Work 范围"]
  Relation -->|"绑定原请求读取"| Main
  Main -->|"获准结果正文"| Material["Agent:transient_result"]
  Material --> Read["Work / 模型材料消费"]
  Material -->|"过期但 paired 引用仍活跃"| Retain["保留原材料"]
  Retain --> Material
  Material -->|"消费或满足过期清理条件"| Clear["清空临时字段,不删除用户文件"]
  Plugin["已安装 Plugin:用户级执行"] -->|"os_user 文件权限"| File
  Plugin -->|"network true"| External["外部服务:保留策略另核"]
  Plugin --> Artifact["产物与执行事实"]
  Artifact -->|"原 producer 与产物读取事实"| Completion["Work owner:完成判定"]
  Read -->|"源材料读取事实"| Completion

证据:附件关系与冻结范围;Local File path-free 合同;临时正文读取、消费与引用保留;Plugin 原请求授权与宿主访问;产物事实与完成判定。

数据分类与责任矩阵

数据 写入 owner / 存储 谁可读取、如何传输 清理与保留边界
用户文件及附件 locator 用户文件仍在本机;Main 的授权与 locator 存储使用带 scope 的安全信封 Local File wire 发送 ID、显示名、相对路径;原 Work 依账号、设备、附件范围读取;获准正文仍可传给 Agent 撤销关系不等于删除文件;此处未核实原文件、备份或系统回收站的统一删除政策
附件关系 Agent local_file_message_attachments;引用 conversation、installation、identity scope 等 原始历史与 upToMessageId 等约束不能被后续轮次扩大;显示投影不是访问授权本身 未确认全局 TTL;不能把附件关系删除当成所有正文副本删除
Local File 临时正文 Agent local_file_operations.transient_result,与回执事实分开 受 tenant / operation 或 run 查询范围约束;供后续材料消费 consume 清空两个 transient 字段;过期维护只释放无活跃 paired 引用者,保留 operation 行与事实,不删除源文件
产物 Plugin/本机 effect owner 产生实际结果;Work owner 核验 producer、原范围及真实结果/读取事实 条件产物目标冻结 plugin/version/digest/runtime revision/tool/outputKey;不是模型一句“已生成”即完成 未确认所有 Plugin 产物目录或外部对象的统一 TTL;完成、释放材料、删除产物是三件不同的事
Desktop 凭据 SafeStorageCredentialVault:safeStorage 密文文件,或进程内 sessionSecrets Main 经 ref 读取;密文在使用时解密。无加密能力时写入返回 session-only,不是明文落盘 显式 delete 删除对应记录或内存项;不据此宣称远端 token 已撤销或所有凭据自动随退出删除
Connector 凭据 Agent provider 委托 TokenProvider 的缓存/持久源 按显式 connector 与 tenant/user principal 解析;不支持 connector fail closed 缓存 TTL、持久记录、远端撤销须分别复核,provider 接口本身不证明统一保留期限
会话 / 排队输入 Agent 消息、Run 与 queue 各有存储合同;queue snapshot 使用 Config AES-GCM queue 消费者解密原受理快照;不能据 queue 加密推断所有会话列都加密 queue admitted / failed / cancelled 写路径清空 ciphertext/nonce/tag;状态与摘要仍在,不等于整段会话删除
展示账本 / 诊断日志 run_projection_events 的 Work 展示写入;进程日志是另一存储面 展示从受控公开事实投影,不是原始 prompt dump;诊断应仅记必要元数据 Work 每 Root 10000 事件 / 16 MiB 上限;SSE 定义 24h TTL 常量,不证明线上准时物理删除;日志汇聚、轮转、备份保留未核实

逐项证据:Main locator 加密与 scope;附件关系与冻结范围;临时正文读取、消费与引用保留;条件产物冻结合同;产物事实与完成判定;凭据读写、session-only 与删除;Connector 显式 principal;排队快照加密写入;Config AES-GCM 实现;队列终态清空载荷;展示账本界限;SSE TTL 常量。

两个不能混用的安全边界

  1. Local File path-free 是协议边界:绝对路径的 locator 留在 Main;并不意味着文件正文永远不离开机器,也不意味着绝对路径字符串不可能出现在用户正文中。
  2. installedPlugin 是另一条执行边界:请求明确呈现 files: 'os_user'、network: true、workingDirectoryIsSandbox: false。获准 Plugin 不是被工作目录困住的沙箱;不得把 Local File 的路径保证外推到 Plugin 的任意文件或网络行为。证据:Plugin 原请求授权与宿主访问。

清理变更的验收条件

  • 用两个 tenant、两个 installation、晚到消息验证原 Work 材料范围不扩张;同名文件不能替代原 attachment 身份。
  • 同时覆盖消费、普通 TTL 到期、paired 引用仍活跃、解除引用后到期四种情形;检查清空的是临时字段,不是回执或用户原文件。
  • 维护是独立有界事务,不领取 Run、不恢复模型、不结算 effect;日志失败不得推翻已提交清理。证据:有界维护事务。
  • safeStorage 不可用、账号切换、撤权、密文损坏分别验证;不能为方便恢复而降级明文或重绑旧 locator。
  • “全部删除”需另有数据库、文件、外部服务及备份的删除证据。本页未证明该能力,也不提供线上删库命令。

继续阅读:Local File · 信任边界 · 观测 · 开发者改动导航。

机制说明

存储平面:Config / 运行业务表 / Desktop 本地

三层不要混

Config 平面:同一 Postgres(CONFIG_DB_URL)上的 config_schema_identity 与 CURRENT_CONFIG_SCHEMA_ID(tip:aida-config-dev-2026-10-28-conversation-turn-queue(定义在 schema-metadata.ts),链为 177 → 178 → 179 → 181 → 183 → 184 → 185 → 186 background-open-roots-index → 187 llm-credits → 188 desktop-execution → 189 local-tenant-admin → 190 document-conversion → 191 conversation-turn-queue;180 / 182 不改 identity;迁移 165 新增 runtime_work_provider_attempts 与 provider attempt ↔ run_checkpoints checkpoint guard 约束触发器,166 新增 local_file_operations.original_content,167 Work side query,168 为配置数据迁移且因与 165–167 撞号顺延);启动 assertCurrentConfigSchema 校验 identity、messages 必须是普通表(relkind=r)、关系/列/触发器/CHECK(含 PG11 compact fingerprint);缺迁移 fail fast;租户密钥与 Provider 凭据用 CONFIG_ENC_KEY AES-GCM。Admin/配置对象写这里。

运行 / 业务表平面:仍在 Config DB 内,但职责是 Run、Interaction、LF Operation、通知、runtime_work_(model rebuild/rejection/material)、conversation_compact_ pins、offer_approval_cycle_bindings 等执行事实。外部 VMS/ATS 等源系统才是业务实体 SoR。部署:审阅 migration(117–151)→ 应用 → bump schema identity → 启动断言;共享库禁止 silent DDL / reset(assertConfigDbSafeToInitialize 拒非空库)。

Desktop 本地平面:Main 持有授权文件夹、LF 写状态(write-state-v4.json,版本 3;legacy 1/2 条目解析时丢弃不可迁移的)及对话级 Interaction 草稿。钉点 8eecd12081db(e2fdc7c7)起,授权文件夹、写状态、已选文件句柄、本地 artifact 索引与原生路径 message-overlay 改存账号作用域的加密信封 LocalSecureEnvelope(根目录 <config>.native-private;随机 profile key 由 safeStorage 包裹,正文 AES-256-GCM,AAD 绑定 OS profile / installation / endpoint / tenant / user);底层文件仍由 AtomicJsonStore 原子写。旧明文 write-state-v4.json 只作迁移来源:仅 POSIX、journal 归当前账号、无待用确认 / 另存目标且能完整往返时才迁入信封并删除明文;不能无损导入、但每条写都已完成送达且确认 / 另存目标都已消费或过期的旧 journal(desktop ca745377 起,Desktop #428)改为「移到一边、不导入」:原样改名 write-state-v4.legacy-retired.json,迁移回执记下 retiredOperationIds 继续拒绝重放(回执读不出即报错)。其余情况仍 LOCAL_FILE_WRITE_STATE_LEGACY_UNAVAILABLE,明文还在期间写状态一直不可用(LEGACY_UNSCOPED);win32 上有残留明文即不可迁移。旧明文 authorized-folders-v4.json 本钉点源码不再读取,未见迁移代码(静态推断:升级后需重新授权文件夹)。这些升级路径实际是否会发生、如何处置未核实。证据:aida-desktop · apps/desktop/electron/security/local-secure-envelope.ts L48–61 · LocalSecureEnvelope · 4346d79eb364;aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L794–798 · LOCAL_FILE_WRITE_STATE_LEGACY_UNAVAILABLE · 4346d79eb364;aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L886–950 · LOCAL_FILE_WRITE_STATE_RETIRED_FILE · 4346d79eb364;aida-desktop · apps/desktop/electron/local-files-v4/authorized-folder-authority.ts L31–71 · LocalSecureEnvelope · 4346d79eb364。绝对路径不出 Main;本地仓不授权服务端工作,也不随用户跨设备。

失败 / 耦合

  • schema_id 不匹配或缺 REQUIRED 关系/列 → 进程拒绝启动,不静默降级。
  • 已有对象上跑 initialize → 明确拒绝,要求走审阅迁移链。
  • Desktop 本地文件损坏只影响本机投影,不污染 Config DB。

迁移 169–173(钉点 e2adc9a3c325)

  • 原来同号的两个 169 已拆开:取消操作约束改名为 170_employee_lifecycle_cancellation_operations.sql,db:migrate 仍接受旧名并提示改名;SQL 主体不变,可以重复执行。
  • 169_restore_config_structure.sql 现在同时接受取消前、取消后两种约束定义:健康环境只执行 170;需要修复的环境先 169 再 170,顺序反了也不再 REPAIR_OBJECT_CONFLICT。
  • 171:从在线 Skill vms-employee-lifecycle 移除离项个人应付来源工具;173:给 payroll-work-command 追加只读 list_payroll_book_members。都是纯数据、可重放,README 写明未在任何环境执行。
  • 以上都不改 schema identity(当时为 aida-config-dev-2026-10-10-work-side-queries,之后由 177 推进)。
  • 编号(钉点 e2adc9a3c325,!219 合入后):170 已被取消约束占用;角色按租户迁移改为预留 172(文件尚未提交、尚未执行),171 / 173 文件头与 README 已一致。两份草案(170-role-capability-answer-DOWN-DRAFT.sql、tenant-resource-tiers-DRAFT.sql)仍写「170」,README 说正式提交时随之改为 172;资源档位草案写明执行前需 Max 确认。

迁移 174 / 176 / 177(钉点 e2adc9a3c325)

  • 174:给 audit_events 补 2026-11 到 2028-12 的月分区,不加 DEFAULT,不改 identity。README 记载审阅版已在 150、202 执行;截止 2026-11-01 前两库都要有分区。
  • 176:放宽 desktop_distribution_releases 平台 CHECK,加入 linux-x64(Linux 发布链路见 desktop-client),不改 identity。
  • 177:给分区父表 audit_events 加可空 state / failure_class 两列,不加 CHECK、不改旧行;identity 推进到 aida-config-dev-2026-10-16-audit-state-contract。启动断言要求目标 identity 和这两列都在。
  • 三条都不随启动执行。README 177 段仍写「未在 150、202 或任何共享库执行」,但同一 README 记载 202 已处在 179 identity、150 已依次执行 178 / 179 / 181 / 182——都以 177 为前置,177 段这句已过时。175 预留已取消,messages 去分区改由 181 完成。
  • 证据:aida-agent · packages/agent/migrations/README.md L163–167 · 177_audit_state_failure_class.sql · e2adc9a3c325;packages/agent/migrations/177_audit_state_failure_class.sql L125–128 · aida-config-dev-2026-10-16-audit-state-contract · e2adc9a3c325

迁移 180–185 与 ADR-0094 / 0095(钉点 e2adc9a3c325)

  • identity 链:179 → 181_messages_unpartition(aida-config-dev-2026-10-21-messages-unpartitioned)→ 183_conversation_seq_quota_bucket(…-conversation-seq-quota-bucket)→ 184_quota_bucket_kind_assignment(…-quota-bucket-kind-assignment)→ 185_background_runs_outside_conversation_slot(…-background-outside-conversation-slot)→ 186_background_open_roots_index(…-background-open-roots-index,即 tip;部分索引 idx_agent_runs_background_open_roots)。每步前置只接受上一步或本步目标值,目标重放只核对、不写;均 PG11/12 单事务、lock_timeout=5s、表属主 SET LOCAL ROLE,开头按 ADR-0094 一次取齐业务表锁、之后不升级。
  • messages 普通表(180 / 181 / 182,STA-84):180 给当时的分区表补 26 个月分区(只在 202 执行过,已被 181 取代);181 把 messages 收敛为普通表(202 走复制路径、保留 messages_partitioned_old;150 本已是普通表,只核对结构),启动校验要求 relkind=r;182 在核对归档每行都在 messages 后删除归档表,不改 identity。
  • 会话序号(183,ADR-0095 2a-1 / 2a-2):conversations.next_message_seq + BEFORE INSERT 触发器串行分配 messages.conversation_seq(覆盖调用方值,允许空洞,不可改,存量 NULL 不回填)。读路径统一按 conversation_seq ASC NULLS FIRST, created_at, id(session/message-order.ts);前台上下文快照以本轮原始输入消息的序号为截止,晚到的外部推送 / 后台汇报下一轮才可见;旧摘要在新顺序下不是完整前缀时改用无摘要窗口并告警。ADR 禁止以 INSERT 恢复历史消息。已知例外:附件来源截止仍按 (created_at, id)。
  • 配额分桶与后台写入(183 / 184 / 185):agent_runs.quota_bucket 由触发器推导(conversation turn → foreground;background_work.v1 及其 child → background;其余 uncounted),184 修复「先 NULL kind 建行、受理时再赋 kind」两阶段路径的首次推导,之后不可改桶、不可把非 NULL kind 清回 NULL;后台 root 只能写 assistant / background_report 消息,后台 child 不得写消息;origin_run_id 可空、不可变、无外键。185 让一会话一活跃 run 的唯一索引排除 background_work.v1。领取侧见 scaling-roles。
  • 锁层级(ADR-0094,Proposed,代码已落地):L1 原 root → L2 carrier/child → L3 run 附属行 → L4 消息 id advisory → L5 conversations → L6 sessions → L7 已有 messages;持有 conversations 行锁后不得再阻塞等待已有 run 行锁。受理据此删掉旧 runtimeExecution 分支与对已有 root 的 FOR UPDATE,挂起本机执行改为逐表显式加锁,过期卡收敛改为非阻塞锁整棵树(见 state-authority)。ADR 自述不是全库无死锁证明。
  • 执行记录(README,2026-10-21):150(PG 12.22)依次执行 178、179、181、182;202(PG 11.16)在 179 identity 上执行 181(首次锁超时整体回滚,修正后重跑)、182,并已执行 183。184 / 185 两库都只有执行说明、没有执行记录,150 尚未执行 183。按 README,183 / 184 / 185 每步执行后都要立刻发布匹配镜像,旧镜像过不了新 identity。README 181 段末尾仍留有「150:未执行」旧句,与 182 段矛盾。
  • 证据:aida-agent · packages/agent/src/config/schema-metadata.ts L6–8 · aida-config-dev-2026-10-28-conversation-turn-queue · e2adc9a3c325;aida-agent · packages/agent/src/config/schema-identity.ts L691–699 · relkind · e2adc9a3c325;aida-agent · packages/agent/src/config/ddl.ts L4812–4828 · assign_conversation_message_seq · e2adc9a3c325;aida-agent · packages/agent/src/config/ddl.ts L1348–1355 · idx_agent_runs_one_active_per_conversation · e2adc9a3c325;aida-agent · packages/agent/src/session/message-order.ts L7–12 · messageOrderSql · e2adc9a3c325;aida-agent · docs/adr/0094-config-db-transaction-lock-hierarchy.md L27–41 · 持有 conversations 行锁 · e2adc9a3c325;aida-agent · docs/adr/0095-conversation-seq-quota-bucket-background-write.md L13–24 · next_message_seq · e2adc9a3c325;aida-agent · packages/agent/migrations/README.md L198–203 · 182_drop_messages_partitioned_old.sql · e2adc9a3c325

迁移 187–191(钉点 e2adc9a3c325)

  • 187 llm_credits → identity aida-config-dev-2026-10-26-llm-credits:租户/用户 Credits 配额与用量表;chat 受理 admitChatCredits,耗尽返回专用拒绝。共享部署需单独授权。
  • 188 desktop_execution_devices → …-desktop-execution:设备登记 / online lease / runtime_invocations_remote_desktop;为远程 Desktop 执行就绪(设计稿 docs/design/remote-desktop-readiness.md)。代码已合入;共享库执行与真机远程验收未核实。
  • 189 local_tenant_admin → …-local-tenant-admin:本地操作员角色扩到 tenant_admin 且强制具体租户作用域。
  • 190 document_conversion → …-document-conversion:guard_local_file_original_content 增加 convert_pdf_to_xlsx / document_conversion 消费方。
  • 191 conversation_turn_queue → tip …-conversation-turn-queue:会话仍在执行时,新 chat turn 服务端 FIFO 排队(加密载荷),不改一会话一活跃 run 唯一索引;ChatSubmissionStore 经 insertConversationTurnQueue / claimNext… / mark…Admitted 驱动。
  • README 没有 150/202 对 187–191 的执行记录;未升到 tip identity 的库上本钉点 Agent 会拒绝启动。旧债 184/185/186 共享库执行状态仍未核实。
  • 证据:见本轮 evidence storage-planes 新增 claim。

迁移 179(钉点 e2adc9a3c325)

  • 179_local_file_transient_expiry.sql(Config DB):前置 identity 只接受 aida-config-dev-2026-10-18-desktop-protocol-v3 或目标值(可重放),并按 md5 校验现有守卫函数体与触发器形状,否则 TRANSIENT_EXPIRY_*_PRECONDITION_FAILED / TRANSIENT_EXPIRY_GUARD_DRIFT;事务内只 CREATE OR REPLACE guard_local_file_original_content,新增写入者 runtime_work.original_file_writer = 'transient-expiry':只允许 UPDATE 把已过期的 transient_result / transient_result_expires_at 置空,行其余字段(含原件)不变;不改表结构;identity 推进到 aida-config-dev-2026-10-20-local-file-transient-expiry。带 DOWN 草稿 docs/migration-drafts/rollback/179-local-file-transient-expiry-DOWN.sql。
  • 运行时写入者:createLocalFileMaintenance.runOnce 在事务里设置该写入者后调 expireUnconsumedTransientResults。
  • SQL 头注释写明共享环境部署需单独授权。179 现为 181 的唯一前置;执行记录见下文「迁移 180–185」。
  • 证据:aida-agent · packages/agent/migrations/179_local_file_transient_expiry.sql L1–30 · TRANSIENT_EXPIRY_SCHEMA_PRECONDITION_FAILED · e2adc9a3c325;aida-agent · packages/agent/migrations/179_local_file_transient_expiry.sql L324–337 · transient-expiry · e2adc9a3c325;aida-agent · packages/agent/migrations/181_messages_unpartition.sql L23–24 · aida-config-dev-2026-10-20-local-file-transient-expiry · e2adc9a3c325;aida-agent · packages/agent/src/runtime/local/local-file-maintenance.ts L29–34 · transient-expiry · e2adc9a3c325

Work 展示账本(钉点 e2adc9a3c325)

  • 生产 Chat Work 在 common-control 事务里把公开事实投影写入 run_projection_events(producer chat-sse-work,dense 序号复用 producer_revision,推进 agent_runs.projection_next_sequence);每 Root 上限 10000 条 / 16 MiB,超限写 chat_sse_truncated。投影在 savepoint 内执行:失败只回滚展示写入,在 savepoint 外写截断标记,Work 核心状态照常提交。供只读 GET /api/runs/:runId/stream 重放(见 observability-map)。未改 DDL / 迁移 / identity;ER-09 静态写入者清单已把它登记为受审 Run 写入者(只分配展示序号,不碰 status / attempt / checkpoint)。
  • 证据:aida-agent · packages/agent/src/runtime/stream/work-chat-sse-ledger.ts L24–50 · WORK_CHAT_SSE_MAX_EVENTS · e2adc9a3c325;aida-agent · packages/agent/src/runtime/stream/work-chat-sse-ledger.ts L192–206 · savepoint · e2adc9a3c325

迁移 178(钉点 e2adc9a3c325;现为 179 的前置)

  • 178_desktop_protocol_v3.sql(Config DB):前置 identity 必须是 aida-config-dev-2026-10-16-audit-state-contract(已是目标时可重放),否则 DESKTOP_PROTOCOL_V3_PREDECESSOR_MISMATCH;事务内只 CREATE OR REPLACE 两个守卫函数——guard_local_file_original_content 去掉对 request->'features' token 的判断,local_file_operations_assert_work_identity 改看 localFileCapability 是否存在而不是 localFileProtocolVersions——不改行与约束形状;identity 推进到 aida-config-dev-2026-10-18-desktop-protocol-v3(本钉点已被 179 继续推进)。
  • 启动必需清单同时不再要求 chat_submission_idempotency.original_inline_inputs。
  • 运行时只做 identity 检查,从不执行此 SQL。ADR-0090 D5 要求部署到 202 等远程环境前先应用 178。README 没有单独的 178 段落;执行情况记在 181 / 182 段(150 于 2026-10-21 先执行 178、179;202 执行 181 时已处在 179 identity)。
  • 遗留:business_task_agent_turn_outbox 仍在必需清单里,但源码已无写入方(见 harness)。
  • 证据:aida-agent · packages/agent/migrations/178_desktop_protocol_v3.sql L1–16 · aida-config-dev-2026-10-18-desktop-protocol-v3 · e2adc9a3c325;aida-agent · packages/agent/migrations/178_desktop_protocol_v3.sql L39–43 · DESKTOP_PROTOCOL_V3_PREDECESSOR_MISMATCH · e2adc9a3c325;aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L255–270 · protocolFeatures · 4346d79eb364

归属边与非目标

  • Owner:Config DB schema 与 Agent 运行表;Desktop 本地状态(LocalSecureEnvelope 加密信封 + AtomicJsonStore 原子写)仅本机。
  • 非目标:不讨论对象存储字节面(S3 协议元数据另册);不写 RustFS。
  • 相关:state-authority、ledger-authority、local-file-v5、overview。

视图

  • main — 三平面架构。

  • migrate — schema identity 迁移/部署耦合序(图里的迁移号是示意;现行 identity 链见上文「迁移 180–185」)。

  • fail-schema — 启动 schema 断言 fail-fast。

  • fail-atomic — AtomicJsonStore corrupt / LEGACY_DROPPED。

  • ok-schema — schema identity 断言通过(对偶 fail-schema)。

  • ok-atomic — AtomicJson 读写干净(对偶 fail-atomic)。

成功对偶(与失败链入口相同)

  1. ok-schema:assertCurrentConfigSchema 匹配 schema_id 且关系/列完备 → 启动继续。
  2. ok-atomic:AtomicJsonStore.read status=ok;原子写;legacy drop=0。

失败链(深挖)

  1. fail-schema:assertCurrentConfigSchema mismatch/缺列 → throw;进程拒启;恢复=审阅迁移+bump+重启。
  2. fail-atomic:corrupt 不覆写空态;unmigratable legacy → LOCAL_FILE_WRITE_STATE_LEGACY_DROPPED;仅本机。

证据与范围

  • aida-agent · packages/agent/src/config/schema-identity.ts L4–42 · CURRENT_CONFIG_SCHEMA_ID · e2adc9a3c325

  • aida-agent · packages/agent/src/config/schema-identity.ts L633–663 · config_schema_identity · e2adc9a3c325

  • aida-agent · packages/agent/src/config/schema-identity.ts L661–701 · assertCurrentConfigSchema · e2adc9a3c325

  • aida-agent · packages/agent/src/config/db-init.ts L176–206 · assertConfigDbSafeToInitialize · e2adc9a3c325

  • aida-agent · packages/agent/src/config/crypto.ts L15–45 · initEncryption · e2adc9a3c325

  • aida-agent · docs/architecture/backend-admin.md L76–98 · Config DB · e2adc9a3c325(历史引用:该文件在上一钉点与当前钉点均不存在,未能复核;见 ATLAS-DEBT)

  • aida-desktop · apps/desktop/electron/local-files-v4/authorized-folder-authority.ts L119–159 · V4AuthorizedFolderStore · 4346d79eb364

  • aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L36–67 · LOCAL_FILE_WRITE_STATE_FILE · 4346d79eb364

  • aida-desktop · apps/desktop/electron/atomic-json-store.ts L68–97 · AtomicJsonStore · 4346d79eb364

  • aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L730–746 · LOCAL_FILE_WRITE_STATE_LEGACY_DROPPED · 4346d79eb364

  • aida-agent · packages/agent/src/config/schema-identity.ts L661–701 · assertCurrentConfigSchema · e2adc9a3c325

  • aida-desktop · apps/desktop/electron/local-files-v4/write-state-persistence.ts L459–469 · read status=ok · 4346d79eb364

结论来自固定版本的静态源码与合同阅读;实现存在、默认开关和生产启用分别判断。本站代码证据面板列出声明状态与具体限制。

  • aida-agent · packages/agent/migrations/README.md L133–141 · 170_employee_lifecycle_cancellation_operations.sql · e2adc9a3c325

  • aida-agent · packages/agent/migrations/171_remove_offboarding_payable_skill_tool.sql L1–4 · schema identity · e2adc9a3c325

  • aida-agent · packages/agent/migrations/173_add_payroll_book_members_skill_tool.sql L1–3 · schema identity · e2adc9a3c325

  • 本轮 186:aida-agent · packages/agent/migrations/186_background_open_roots_index.sql L56–70 · idx_agent_runs_background_open_roots · e2adc9a3c325;aida-agent · packages/agent/src/config/schema-metadata.ts L6–8 · aida-config-dev-2026-10-28-conversation-turn-queue · e2adc9a3c325;aida-agent · packages/agent/src/config/schema-identity.ts L19 · idx_agent_runs_background_open_roots · e2adc9a3c325。共享库是否已执行未核。

数据生命周期:字节、引用、凭据与观察记录

本页补充 存储平面,不另建主题。基线:Agent 7f2e519936b53035646a70f152e734298abed2fb、Desktop 4346d79eb364b502ef87c0869a494dfed7964419。这是固定快照的静态事实,不代表线上配置、实际清理任务运行或备份删除已核验。

D01 数据从哪里来、经过哪里、在哪里结束

图中「登记/读取/保留/清理」是概念阶段,不是数据库状态枚举;附件投影的真实类型是 available | unavailable | revoked,也不等于文件本体生命周期。

flowchart TB
  accTitle: 附件与产物的数据生命周期及宿主边界
  accDescr: 本地文件经 Main 授权形成无绝对路径的附件关系,按请求读取后正文可进入 Agent 临时材料;消费或无活跃引用的过期清理仅删除临时材料,不删除原文件。已安装插件的用户级文件与网络访问属于独立执行边界。
  File["用户本地文件"] --> Main["Main:locator 与原生授权"]
  Main -->|"ID、显示名、相对路径"| Relation["Agent:附件关系与原 Work 范围"]
  Relation -->|"绑定原请求读取"| Main
  Main -->|"获准结果正文"| Material["Agent:transient_result"]
  Material --> Read["Work / 模型材料消费"]
  Material -->|"过期但 paired 引用仍活跃"| Retain["保留原材料"]
  Retain --> Material
  Material -->|"消费或满足过期清理条件"| Clear["清空临时字段,不删除用户文件"]
  Plugin["已安装 Plugin:用户级执行"] -->|"os_user 文件权限"| File
  Plugin -->|"network true"| External["外部服务:保留策略另核"]
  Plugin --> Artifact["产物与执行事实"]
  Artifact -->|"原 producer 与产物读取事实"| Completion["Work owner:完成判定"]
  Read -->|"源材料读取事实"| Completion

证据:附件关系与冻结范围;Local File path-free 合同;临时正文读取、消费与引用保留;Plugin 原请求授权与宿主访问;产物事实与完成判定。

数据分类与责任矩阵

数据 写入 owner / 存储 谁可读取、如何传输 清理与保留边界
用户文件及附件 locator 用户文件仍在本机;Main 的授权与 locator 存储使用带 scope 的安全信封 Local File wire 发送 ID、显示名、相对路径;原 Work 依账号、设备、附件范围读取;获准正文仍可传给 Agent 撤销关系不等于删除文件;此处未核实原文件、备份或系统回收站的统一删除政策
附件关系 Agent local_file_message_attachments;引用 conversation、installation、identity scope 等 原始历史与 upToMessageId 等约束不能被后续轮次扩大;显示投影不是访问授权本身 未确认全局 TTL;不能把附件关系删除当成所有正文副本删除
Local File 临时正文 Agent local_file_operations.transient_result,与回执事实分开 受 tenant / operation 或 run 查询范围约束;供后续材料消费 consume 清空两个 transient 字段;过期维护只释放无活跃 paired 引用者,保留 operation 行与事实,不删除源文件
产物 Plugin/本机 effect owner 产生实际结果;Work owner 核验 producer、原范围及真实结果/读取事实 条件产物目标冻结 plugin/version/digest/runtime revision/tool/outputKey;不是模型一句“已生成”即完成 未确认所有 Plugin 产物目录或外部对象的统一 TTL;完成、释放材料、删除产物是三件不同的事
Desktop 凭据 SafeStorageCredentialVault:safeStorage 密文文件,或进程内 sessionSecrets Main 经 ref 读取;密文在使用时解密。无加密能力时写入返回 session-only,不是明文落盘 显式 delete 删除对应记录或内存项;不据此宣称远端 token 已撤销或所有凭据自动随退出删除
Connector 凭据 Agent provider 委托 TokenProvider 的缓存/持久源 按显式 connector 与 tenant/user principal 解析;不支持 connector fail closed 缓存 TTL、持久记录、远端撤销须分别复核,provider 接口本身不证明统一保留期限
会话 / 排队输入 Agent 消息、Run 与 queue 各有存储合同;queue snapshot 使用 Config AES-GCM queue 消费者解密原受理快照;不能据 queue 加密推断所有会话列都加密 queue admitted / failed / cancelled 写路径清空 ciphertext/nonce/tag;状态与摘要仍在,不等于整段会话删除
展示账本 / 诊断日志 run_projection_events 的 Work 展示写入;进程日志是另一存储面 展示从受控公开事实投影,不是原始 prompt dump;诊断应仅记必要元数据 Work 每 Root 10000 事件 / 16 MiB 上限;SSE 定义 24h TTL 常量,不证明线上准时物理删除;日志汇聚、轮转、备份保留未核实

逐项证据:Main locator 加密与 scope;附件关系与冻结范围;临时正文读取、消费与引用保留;条件产物冻结合同;产物事实与完成判定;凭据读写、session-only 与删除;Connector 显式 principal;排队快照加密写入;Config AES-GCM 实现;队列终态清空载荷;展示账本界限;SSE TTL 常量。

两个不能混用的安全边界

  1. Local File path-free 是协议边界:绝对路径的 locator 留在 Main;并不意味着文件正文永远不离开机器,也不意味着绝对路径字符串不可能出现在用户正文中。
  2. installedPlugin 是另一条执行边界:请求明确呈现 files: 'os_user'、network: true、workingDirectoryIsSandbox: false。获准 Plugin 不是被工作目录困住的沙箱;不得把 Local File 的路径保证外推到 Plugin 的任意文件或网络行为。证据:Plugin 原请求授权与宿主访问。

清理变更的验收条件

  • 用两个 tenant、两个 installation、晚到消息验证原 Work 材料范围不扩张;同名文件不能替代原 attachment 身份。
  • 同时覆盖消费、普通 TTL 到期、paired 引用仍活跃、解除引用后到期四种情形;检查清空的是临时字段,不是回执或用户原文件。
  • 维护是独立有界事务,不领取 Run、不恢复模型、不结算 effect;日志失败不得推翻已提交清理。证据:有界维护事务。
  • safeStorage 不可用、账号切换、撤权、密文损坏分别验证;不能为方便恢复而降级明文或重绑旧 locator。
  • “全部删除”需另有数据库、文件、外部服务及备份的删除证据。本页未证明该能力,也不提供线上删库命令。

继续阅读:Local File · 信任边界 · 观测 · 开发者改动导航。

代码证据

引用核验检查固定 commit 的文件与范围;实现结论来自代码阅读。自动检查不证明生产环境已启用。

已核验实现

Config DB 以 CURRENT_CONFIG_SCHEMA_ID 与 config_schema_identity 做启动身份校验;REQUIRED_CONFIG_SCHEMA_RELATIONS 缺失则 fail fast,禁止静默 DDL。

aida-agentpackages/agent/src/config/schema-identity.ts:1–397f2e519936b57902d4907ed8026fe1ecdd146e82符号:CURRENT_CONFIG_SCHEMA_ID
aida-agentpackages/agent/src/config/schema-identity.ts:729–7597f2e519936b57902d4907ed8026fe1ecdd146e82符号:config_schema_identity
已核验实现

assertCurrentConfigSchema 在 schema_id 不匹配或缺必需关系时抛错并拒绝启动,要求显式审阅迁移而非 reset。

aida-agentpackages/agent/src/config/schema-identity.ts:720–7607f2e519936b57902d4907ed8026fe1ecdd146e82符号:assertCurrentConfigSchema
已核验实现

assertConfigDbSafeToInitialize 拒绝非空 aida_config 或遗留 public AIDA 关系上的 initialize,强制走审阅迁移路径。

aida-agentpackages/agent/src/config/db-init.ts:176–2067f2e519936b57902d4907ed8026fe1ecdd146e82符号:assertConfigDbSafeToInitialize
已核验实现

CONFIG_ENC_KEY 初始化 AES-GCM;Config DB 同时承载配置与运行业务表(Run/Interaction/LF/通知),外部 VMS/ATS 仍是源系统 SoR。

aida-agentpackages/agent/src/config/crypto.ts:15–457f2e519936b57902d4907ed8026fe1ecdd146e82符号:initEncryption
aida-agentpackages/agent/src/config/db.ts:28–597f2e519936b57902d4907ed8026fe1ecdd146e82符号:Config DB
已核验实现

Desktop 本地授权文件夹与 LF 写状态由 Main 持有,desktop e2fdc7c7 起改存账号作用域的加密信封 LocalSecureEnvelope(根目录 `<config>.native-private`,namespace authorized-folders / local-file-write-state;写状态文件名仍为 write-state-v4.json、版本 3);未提供 privateStorage 时授权文件夹只在内存(session-only)。

aida-desktopapps/desktop/electron/local-files-v4/authorized-folder-authority.ts:38–784346d79eb36402355e51118df0edf1f98586880c符号:LocalSecureEnvelope
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:43–474346d79eb36402355e51118df0edf1f98586880c符号:LOCAL_FILE_WRITE_STATE_FILE
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:842–8804346d79eb36402355e51118df0edf1f98586880c符号:local-file-write-state
aida-desktopapps/desktop/electron/main.ts:1242–12434346d79eb36402355e51118df0edf1f98586880c符号:native-private
aida-desktopapps/desktop/electron/main.ts:1421–14614346d79eb36402355e51118df0edf1f98586880c符号:privateStorage
已核验实现

AtomicJsonStore.read 对损坏/超限文件返回 status=corrupt(或 unsupported_version),不静默改写为空文档。

aida-desktopapps/desktop/electron/atomic-json-store.ts:66–954346d79eb36402355e51118df0edf1f98586880c符号:AtomicJsonStore
已核验实现

LocalFileWriteStatePersistence 解析加密信封内的 write-state 时丢弃不可迁移的 legacy 条目并诊断 LOCAL_FILE_WRITE_STATE_LEGACY_DROPPED。

aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:860–8764346d79eb36402355e51118df0edf1f98586880c符号:LOCAL_FILE_WRITE_STATE_LEGACY_DROPPED
已核验实现

assertCurrentConfigSchema 在 schema_id 匹配且必需关系/列完备、无 forbidden legacy 时通过,启动继续。

aida-agentpackages/agent/src/config/schema-identity.ts:720–7607f2e519936b57902d4907ed8026fe1ecdd146e82符号:assertCurrentConfigSchema
已核验实现

LocalFileWriteStatePersistence.read 先校验作用域与代际、迁移旧明文 journal,再从加密信封读出 write-state;信封里没有文件但 profile key 与目录已存在时抛 LOCAL_FILE_WRITE_STATE_JOURNAL_MISSING,不把丢失当空态;作用域在读写中途变化抛 LOCAL_FILE_WRITE_STATE_CONTEXT_CHANGED。

aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:1176–11924346d79eb36402355e51118df0edf1f98586880c符号:JOURNAL_MISSING
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:905–9354346d79eb36402355e51118df0edf1f98586880c符号:LOCAL_FILE_WRITE_STATE_CONTEXT_CHANGED
已核验实现

迁移 179(历史,已被 181 起的链取代为前置):把 identity 从 178 的 desktop-protocol-v3 推进到 aida-config-dev-2026-10-20-local-file-transient-expiry(前置只接受 178 或 179 目标值并校验守卫函数体 md5,可重放);只 CREATE OR REPLACE guard_local_file_original_content,新增写入者 runtime_work.original_file_writer=transient-expiry:只允许 UPDATE 把已过期的 transient_result / transient_result_expires_at 置空、行其余字段不变,不改表结构。179 现为 181 的唯一前置。

aida-agentpackages/agent/migrations/179_local_file_transient_expiry.sql:1–307f2e519936b57902d4907ed8026fe1ecdd146e82符号:TRANSIENT_EXPIRY_SCHEMA_PRECONDITION_FAILED
aida-agentpackages/agent/migrations/179_local_file_transient_expiry.sql:324–3377f2e519936b57902d4907ed8026fe1ecdd146e82符号:transient-expiry
aida-agentpackages/agent/migrations/179_local_file_transient_expiry.sql:363–3647f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-20-local-file-transient-expiry
aida-agentpackages/agent/src/runtime/local/local-file-maintenance.ts:34–397f2e519936b57902d4907ed8026fe1ecdd146e82符号:transient-expiry
aida-agentpackages/agent/src/config/schema-identity.ts:360–4027f2e519936b57902d4907ed8026fe1ecdd146e82符号:original_content
aida-agentpackages/agent/migrations/178_desktop_protocol_v3.sql:1–167f2e519936b57902d4907ed8026fe1ecdd146e82符号:guard_local_file_original_content
aida-agentpackages/agent/src/config/required-schema-triggers.ts:33–477f2e519936b57902d4907ed8026fe1ecdd146e82符号:trg_local_file_original_content
aida-agentpackages/agent/migrations/181_messages_unpartition.sql:23–247f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-20-local-file-transient-expiry
已核验实现

CURRENT_CONFIG_SCHEMA_ID tip 为 aida-config-dev-2026-10-28-conversation-turn-queue(schema-metadata.ts);链在 186 background-open-roots-index 之后继续 187 llm-credits → 188 desktop-execution → 189 local-tenant-admin → 190 document-conversion → 191 conversation-turn-queue。REQUIRED 清单含 desktop_execution_devices*、llm credits 表、conversation_turn_queue*。共享库是否已执行 187–191 未核实。

aida-agentpackages/agent/src/config/schema-metadata.ts:6–87f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-28-conversation-turn-queue
aida-agentpackages/agent/src/config/schema-identity.ts:44–687f2e519936b57902d4907ed8026fe1ecdd146e82符号:conversation_turn_queue
aida-agentpackages/agent/migrations/191_conversation_turn_queue.sql:1–507f2e519936b57902d4907ed8026fe1ecdd146e82符号:conversation_turn_queue
已核验实现

messages 统一为普通表(迁移 181,STA-84):启动校验要求 messages 的 relkind=r,否则提示先执行 181 并拒绝启动;三个触发器直接挂在 messages 上(逐分区触发器常量已删)。202 走路径 A(分区表单事务复制全部行与指纹、旧表改名 messages_partitioned_old),150 走路径 B(已是普通表,只核对结构);182 随后删除归档表,删除前校验每行都在 messages 中。

aida-agentpackages/agent/src/config/schema-identity.ts:750–7587f2e519936b57902d4907ed8026fe1ecdd146e82符号:relkind
aida-agentpackages/agent/migrations/181_messages_unpartition.sql:1–57f2e519936b57902d4907ed8026fe1ecdd146e82符号:Retain messages_partitioned_old
aida-agentpackages/agent/migrations/README.md:177–1867f2e519936b57902d4907ed8026fe1ecdd146e82符号:181_messages_unpartition.sql
已核验实现

会话消息序号(迁移 183 / ADR-0095 2a-1):conversations.next_message_seq 由 BEFORE INSERT 触发器以同一会话行的 UPDATE … +1 RETURNING 串行分配 messages.conversation_seq(总是覆盖调用方传值,允许空洞,写入后不可改);存量 NULL 不回填。读路径(2a-2)统一按 conversation_seq ASC NULLS FIRST, created_at, id 排序(共享 message-order.ts),前台上下文快照以本轮原始输入消息的序号为截止,晚提交的外部推送 / 后台汇报从下一轮才可见。ADR 明确禁止以 INSERT 恢复历史消息(会排到末尾);附件来源截止仍按 (created_at, id),是已知例外。

aida-agentpackages/agent/src/config/ddl.ts:4881–48977f2e519936b57902d4907ed8026fe1ecdd146e82符号:assign_conversation_message_seq
aida-agentpackages/agent/src/session/message-order.ts:25–307f2e519936b57902d4907ed8026fe1ecdd146e82符号:NULLS
aida-agentdocs/adr/0095-conversation-seq-quota-bucket-background-write.md:13–247f2e519936b57902d4907ed8026fe1ecdd146e82符号:next_message_seq
aida-agentdocs/adr/0095-conversation-seq-quota-bucket-background-write.md:112–1167f2e519936b57902d4907ed8026fe1ecdd146e82符号:conversation_seq ASC NULLS FIRST
已核验实现

配额分桶与后台写入规则(迁移 183 / 184 / 185):agent_runs.quota_bucket 由触发器按 run_kind 与 original root 推导(conversation_turn → foreground;background_work 及其 child → background;其余 uncounted),184 让 PgRunStore.create 先 NULL kind、bindAdmittedWork 再赋 kind 的两阶段路径在首次赋值时重新推导,之后不可改桶;后台 root 只能写 assistant/background_report 消息,后台 child 不得写消息;可空且不可变的 origin_run_id 指向同租户同会话来源 run(无外键)。185 让 idx_agent_runs_one_active_per_conversation 排除 background_work.v1,后台 root 可与前台活跃 run 共存,前台仍一会话一个。

aida-agentpackages/agent/src/config/ddl.ts:4912–49297f2e519936b57902d4907ed8026fe1ecdd146e82符号:derive_run_quota_bucket
aida-agentpackages/agent/src/config/ddl.ts:4959–49747f2e519936b57902d4907ed8026fe1ecdd146e82符号:background_report
aida-agentpackages/agent/src/config/ddl.ts:1383–13907f2e519936b57902d4907ed8026fe1ecdd146e82符号:idx_agent_runs_one_active_per_conversation
aida-agentdocs/adr/0095-conversation-seq-quota-bucket-background-write.md:27–377f2e519936b57902d4907ed8026fe1ecdd146e82符号:quota_bucket
已核验实现

Config DB 事务锁层级(ADR-0094,Proposed,代码已落地 9a3e49ec1):L1 原 root agent_runs → L2 carrier/child → L3 run 附属行(invocation、interaction、checkpoint 等)→ L4 消息 id advisory → L5 conversations → L6 sessions → L7 已有 messages;同一事务首次可能阻塞的锁只能自上而下,持有 conversations 行锁的事务不得再阻塞等待任何已有 run 行锁(只能 SKIP LOCKED / NOWAIT / 重入)。受理因此删除了旧 runtimeExecution 分支、不再 FOR UPDATE 已有 root;挂起本机执行改为 ar → ri → run_checkpoints → c → s 逐表加锁;过期卡收敛改为非阻塞锁住整棵成员树。ADR 自述不是全库无死锁证明。

aida-agentdocs/adr/0094-config-db-transaction-lock-hierarchy.md:27–417f2e519936b57902d4907ed8026fe1ecdd146e82符号:持有 conversations 行锁
aida-agentpackages/agent/src/session/chat-submission-store.ts:985–10087f2e519936b57902d4907ed8026fe1ecdd146e82符号:background_work.v1
aida-agentpackages/agent/src/session/expired-interaction-closure.ts:4–557f2e519936b57902d4907ed8026fe1ecdd146e82符号:Fail-closed
已核验实现

迁移执行记录(migrations/README,2026-10-21):150(PG 12.22)先依次执行 178、179、181(普通表核对路径)再执行 182;202(PG 11.16)在已核实的 179 identity 上执行 181(首次因锁超时整体回滚,修正后重跑成功)、182,并已执行 183。184 / 185 在两库均只有执行说明、没有执行记录;150 尚未执行 183。README 181 段末尾仍留有「150:未执行」的旧句,与 182 段的 150 执行记录矛盾。

aida-agentpackages/agent/migrations/README.md:183–1867f2e519936b57902d4907ed8026fe1ecdd146e82符号:150
aida-agentpackages/agent/migrations/README.md:202–2037f2e519936b57902d4907ed8026fe1ecdd146e82符号:150
aida-agentpackages/agent/migrations/README.md:274–2777f2e519936b57902d4907ed8026fe1ecdd146e82符号:183 已执行
已核验实现

迁移 163–168:163 VMS business task spine、164 入项材料 CHECK(均不改 schema identity);165 runtime_work_provider_attempts + checkpoint 约束触发器;166 local_file_operations.original_content(≤40MiB jsonb CHECK);167 Work 只读 side query;168 为 advance_candidate 执行方式的配置数据迁移,因与 165–167 撞号顺延为 168,不改 CURRENT_CONFIG_SCHEMA_ID。

aida-agentpackages/agent/migrations/165_runtime_work_provider_attempts_and_child_rebuild.sql:68–727f2e519936b57902d4907ed8026fe1ecdd146e82符号:CREATE TABLE IF NOT EXISTS runtime_work_provider_attempts
aida-agentpackages/agent/migrations/165_runtime_work_provider_attempts_and_child_rebuild.sql:293–2957f2e519936b57902d4907ed8026fe1ecdd146e82符号:runtime_work_provider_attempt_checkpoint_guard
aida-agentpackages/agent/migrations/166_runtime_work_original_file_content.sql:31–397f2e519936b57902d4907ed8026fe1ecdd146e82符号:original_content
aida-agentpackages/agent/migrations/167_runtime_work_side_queries.sql:1–17f2e519936b57902d4907ed8026fe1ecdd146e82符号:side queries
aida-agentpackages/agent/migrations/168_advance_candidate_agent_executor.sql:1–57f2e519936b57902d4907ed8026fe1ecdd146e82符号:CURRENT_CONFIG_SCHEMA_ID is unchanged
aida-agentpackages/agent/migrations/163_vms_business_task_spine.sql:1–37f2e519936b57902d4907ed8026fe1ecdd146e82符号:does NOT change config_schema_identity
已核验实现

原两个 169 迁移已拆号:取消操作约束改名为 170_employee_lifecycle_cancellation_operations(db:migrate 仍接受旧名别名,可重放);169_restore_config_structure 同时接受取消前与取消后的约束定义,需修复的环境先 169 再 170。171(移除离项个人应付来源工具)与 173(追加 list_payroll_book_members)为纯数据迁移;四者都不改 schema identity(当时为 aida-config-dev-2026-10-10-work-side-queries;之后迁移 177 把它推进到 audit-state-contract)。

各环境是否已执行 169/170/171/173 未核实(README 写明 171、173 未在任何环境执行)。

aida-agentpackages/agent/migrations/README.md:133–1417f2e519936b57902d4907ed8026fe1ecdd146e82符号:170_employee_lifecycle_cancellation_operations.sql
aida-agentpackages/agent/migrations/170_employee_lifecycle_cancellation_operations.sql:1–37f2e519936b57902d4907ed8026fe1ecdd146e82符号:Renamed from 169
aida-agentpackages/agent/migrations/171_remove_offboarding_payable_skill_tool.sql:1–47f2e519936b57902d4907ed8026fe1ecdd146e82符号:schema identity
aida-agentpackages/agent/migrations/173_add_payroll_book_members_skill_tool.sql:1–37f2e519936b57902d4907ed8026fe1ecdd146e82符号:schema identity
aida-agentpackages/agent/migrations/177_audit_state_failure_class.sql:5–67f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-10-work-side-queries
已核验实现

迁移编号已统一:170 由取消约束迁移占用;角色按租户迁移(原拟 170)改为预留 172,迁移文件尚未提交、尚未执行;171、173 文件头与 README 一致写明这一点。两份草案(170-role-capability-answer-DOWN-DRAFT.sql、tenant-resource-tiers-DRAFT.sql)仍写“170”,README 说明正式提交时随之改为 172;tenant-resource-tiers 草案写明执行前需 Max 确认。

172 迁移本身尚不存在;最终编号以正式提交为准。

aida-agentpackages/agent/migrations/README.md:161–1617f2e519936b57902d4907ed8026fe1ecdd146e82符号:172 号预留给角色按租户迁移
aida-agentpackages/agent/migrations/171_remove_offboarding_payable_skill_tool.sql:4–47f2e519936b57902d4907ed8026fe1ecdd146e82符号:预留 172
aida-agentpackages/agent/migrations/173_add_payroll_book_members_skill_tool.sql:3–37f2e519936b57902d4907ed8026fe1ecdd146e82符号:172
aida-agentdocs/migration-drafts/rollback/170-role-capability-answer-DOWN-DRAFT.sql:1–17f2e519936b57902d4907ed8026fe1ecdd146e82符号:170
aida-agentdocs/migration-drafts/tenant-resource-tiers-DRAFT.sql:2–27f2e519936b57902d4907ed8026fe1ecdd146e82符号:Max 确认
已核验实现

Config DB 迁移 174 / 176 / 177:174 给 audit_events 补 2026-11~2028-12 月分区(不改 identity);176 放宽 desktop_distribution_releases 平台 CHECK 加入 linux-x64(不改 identity);177 给分区父表 audit_events 加可空 state / failure_class 列并把 identity 推进到 aida-config-dev-2026-10-16-audit-state-contract(现为 178 的前置)。迁移都不自动执行;175 预留已取消(README:messages 去分区改由 181 完成)。

README 177 段仍写「未在 150、202 或任何共享库执行」,但同一 README 记载 202 在 179 identity 上执行 181、150 依次执行 178/179/181/182——两处都要求 177 已执行,177 段这句已过时(以执行记录为准)。174 的审阅版已在 150、202 执行;176 各环境执行情况未核实。

aida-agentpackages/agent/migrations/README.md:163–1677f2e519936b57902d4907ed8026fe1ecdd146e82符号:177_audit_state_failure_class.sql
aida-agentpackages/agent/migrations/177_audit_state_failure_class.sql:56–607f2e519936b57902d4907ed8026fe1ecdd146e82符号:failure_class
aida-agentpackages/agent/migrations/177_audit_state_failure_class.sql:125–1287f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-16-audit-state-contract
aida-agentpackages/agent/migrations/176_desktop_distribution_linux_x64.sql:1–87f2e519936b57902d4907ed8026fe1ecdd146e82符号:linux-x64
aida-agentpackages/agent/src/config/schema-identity.ts:359–3687f2e519936b57902d4907ed8026fe1ecdd146e82符号:failure_class
已核验实现

迁移 178_desktop_protocol_v3(Config DB):前置 identity 必须是 aida-config-dev-2026-10-16-audit-state-contract(已是目标时可重放),否则 DESKTOP_PROTOCOL_V3_PREDECESSOR_MISMATCH;事务内只替换两个守卫函数体,不改行与约束形状,目标 identity 为 aida-config-dev-2026-10-18-desktop-protocol-v3;运行时启动只做 identity 检查,从不执行此 SQL。

README 没有单独的 178 段落,执行情况记在 181 / 182 段:150 于 2026-10-21 先执行 178、179 再执行 181、182;202 执行 181 时已处在 179 identity(178 的执行时间未单独记载)。

aida-agentpackages/agent/migrations/178_desktop_protocol_v3.sql:1–167f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-18-desktop-protocol-v3
aida-agentpackages/agent/migrations/178_desktop_protocol_v3.sql:39–437f2e519936b57902d4907ed8026fe1ecdd146e82符号:DESKTOP_PROTOCOL_V3_PREDECESSOR_MISMATCH
aida-agentdocs/adr/0090-desktop-protocol-v3-and-retired-local-primitives.md:37–397f2e519936b57902d4907ed8026fe1ecdd146e82符号:178
已核验实现

Desktop write-state 升级路径(desktop ca745377 起):明文 write-state-v4.json 只作迁移来源。能无损导入的(POSIX、信封可用、journal 归当前账号、无待用确认、可完整往返)写入加密信封并删除明文;不能无损导入但已全部结束的旧 journal(每条写都已完成并送达、确认与另存目标都已消费或过期、全属当前账号,≤64 条)改为「移到一边、不导入」:原文件原样改名为 write-state-v4.legacy-retired.json,迁移回执记下 retiredOperationIds 继续拒绝重放(回执读不出则报错不放行)。其余情况(win32、含待用确认、非本账号、已有 retired 文件等)仍抛 LOCAL_FILE_WRITE_STATE_LEGACY_UNAVAILABLE,且只要明文文件还在 store() 就抛 LEGACY_UNSCOPED。这些分支在真机上的命中情况未核实。

静态读码;未在真机或 Desktop E2E 上运行,旧明文文件在各用户机器上的实际形态未知。

aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:671–7314346d79eb36402355e51118df0edf1f98586880c符号:legacyRetirement
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:929–9334346d79eb36402355e51118df0edf1f98586880c符号:LOCAL_FILE_WRITE_STATE_LEGACY_UNAVAILABLE
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:972–9824346d79eb36402355e51118df0edf1f98586880c符号:this.retireLegacy
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:1089–11534346d79eb36402355e51118df0edf1f98586880c符号:LOCAL_FILE_WRITE_STATE_RETIRED_FILE
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:1152–11564346d79eb36402355e51118df0edf1f98586880c符号:LOCAL_FILE_WRITE_STATE_LEGACY_UNSCOPED
已核验实现

Desktop 本机私有存储加密信封 LocalSecureEnvelope(desktop e2fdc7c7 新增):随机 profile key 由 Electron safeStorage 包裹,正文以 AES-256-GCM 加密,AAD 绑定 OS profile、installationId、endpoint、tenant、user 等作用域轴;作用域缺任一轴即 LOCAL_SECURE_ENVELOPE_UNAVAILABLE,查找时不创建 key。Main 用它存 LF 写状态、授权文件夹、已选文件句柄、本地 artifact 索引与原生路径 message-overlay,账号切换(clearIdentity)会让排队中的变更失效。

aida-desktopapps/desktop/electron/security/local-secure-envelope.ts:9–244346d79eb36402355e51118df0edf1f98586880c符号:LocalSecureScope
aida-desktopapps/desktop/electron/security/local-secure-envelope.ts:106–1194346d79eb36402355e51118df0edf1f98586880c符号:LocalSecureEnvelope
aida-desktopapps/desktop/electron/main.ts:1297–13094346d79eb36402355e51118df0edf1f98586880c符号:LocalSecureEnvelope
aida-desktopapps/desktop/electron/local-files-v4/write-state-persistence.ts:884–8884346d79eb36402355e51118df0edf1f98586880c符号:clearIdentity
已核验实现

Work 展示账本(agent 3d61c4903 / f3b517c5b / da594270b):生产 Chat Work 在 common-control 事务中把公开事实投影写入 run_projection_events(producer chat-sse-work,dense 序号复用 producer_revision,并推进 agent_runs.projection_next_sequence),每个 Root 上限 10000 条、16 MiB,超限写 chat_sse_truncated 标记;投影在 savepoint 内执行,失败只回滚展示写入、在 savepoint 外写截断标记,Work 核心状态照常提交。未改 DDL / 迁移 / schema identity。

aida-agentpackages/agent/src/runtime/stream/work-chat-sse-ledger.ts:21–477f2e519936b57902d4907ed8026fe1ecdd146e82符号:WORK_CHAT_SSE_MAX_EVENTS
aida-agentpackages/agent/src/runtime/stream/work-chat-sse-ledger.ts:112–1357f2e519936b57902d4907ed8026fe1ecdd146e82符号:run_projection_events
aida-agentpackages/agent/src/runtime/stream/work-chat-sse-ledger.ts:155–1697f2e519936b57902d4907ed8026fe1ecdd146e82符号:savepoint
条件路径

迁移 186(agent 728dbceee):agent_runs 部分索引 idx_agent_runs_background_open_roots(execution_scope, created_at, id)WHERE 未完成的 background_work.v1 root;PG11/12 单事务、ADR-0094 锁序;identity → aida-config-dev-2026-10-22-background-open-roots-index。共享库是否已执行本站岗未核。

共享 Config DB 实际 schema_id 本站岗只读代码与迁移文件,未连库核验。

aida-agentpackages/agent/migrations/186_background_open_roots_index.sql:56–707f2e519936b57902d4907ed8026fe1ecdd146e82符号:idx_agent_runs_background_open_roots
aida-agentpackages/agent/src/config/schema-metadata.ts:6–87f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-28-conversation-turn-queue
条件路径

迁移 187–191 分别推进 identity 至 llm-credits → desktop-execution → local-tenant-admin → document-conversion → conversation-turn-queue;均要求维护窗口与单独授权,README 无 150/202 执行记录。

共享库是否已执行 187–191 未核实;未升到 tip identity 的库上本钉点 Agent 拒绝启动。

aida-agentpackages/agent/migrations/187_llm_credits.sql:57–617f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-26-llm-credits
aida-agentpackages/agent/migrations/188_desktop_execution_devices.sql:28–887f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-26-desktop-execution
aida-agentpackages/agent/migrations/191_conversation_turn_queue.sql:47–937f2e519936b57902d4907ed8026fe1ecdd146e82符号:aida-config-dev-2026-10-28-conversation-turn-queue
已核验实现

conversation_turn_queue:会话执行中新 chat turn 的服务端 FIFO(加密载荷、queued/admitted/failed);ChatSubmissionStore 经 insert/claim/markAdmitted 驱动,不放宽一会话一活跃 run 唯一索引。

aida-agentpackages/agent/src/session/conversation-turn-queue.ts:318–3357f2e519936b57902d4907ed8026fe1ecdd146e82符号:insertConversationTurnQueue
aida-agentpackages/agent/src/session/conversation-turn-queue.ts:547–5647f2e519936b57902d4907ed8026fe1ecdd146e82符号:markConversationTurnQueueAdmitted
aida-agentpackages/agent/src/session/chat-submission-store.ts:2278–22887f2e519936b57902d4907ed8026fe1ecdd146e82符号:insertConversationTurnQueue
已核验实现

开发者指南 data:查数据去向,按当前固定源码与关联主题定位责任和边界;建议操作与验收计划不是已执行结果。

只核对当前代码与文档结构;生产配置、所有真实客户端、清理作业及原生/浏览器验收另行举证。PR状态仅为读取时快照。

aida-agentpackages/agent/src/session/local-file-message-attachment.ts:11–457f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentdocs/adr/0079-local-file-v5-conversation-attachments.md:21–367f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/session/local-file-operation-store.ts:545–6747f2e519936b57902d4907ed8026fe1ecdd146e82
aida-desktopapps/desktop/electron/plugin-host/plugin-host.ts:1452–15574346d79eb36402355e51118df0edf1f98586880c
aida-agentpackages/agent/src/runtime/work/run-work-conditional-artifact.ts:89–3657f2e519936b57902d4907ed8026fe1ecdd146e82
aida-desktopapps/desktop/electron/security/local-secure-envelope.ts:79–1394346d79eb36402355e51118df0edf1f98586880c
aida-agentpackages/agent/src/routing/conditional-artifact-contract.ts:15–1037f2e519936b57902d4907ed8026fe1ecdd146e82
aida-desktopapps/desktop/electron/auth/credential-vault.ts:87–1634346d79eb36402355e51118df0edf1f98586880c
aida-agentpackages/agent/src/connectors/credential-provider.ts:55–1447f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/session/conversation-turn-queue.ts:307–3597f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/config/crypto.ts:3–567f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/session/conversation-turn-queue.ts:539–5967f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/runtime/stream/work-chat-sse-ledger.ts:21–497f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/runtime/stream/chat-sse-ledger.ts:8–157f2e519936b57902d4907ed8026fe1ecdd146e82
aida-agentpackages/agent/src/runtime/local/local-file-maintenance.ts:9–557f2e519936b57902d4907ed8026fe1ecdd146e82