@tencent-ai/agent-harness 0.2.0-beta.1 → 0.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/cli/CHANGELOG.md +71 -0
  4. package/cli/dist-server/shared.cjs +318 -314
  5. package/cli/dist-server/types/node/acp/acp-protocol.d.ts +40 -12
  6. package/cli/dist-server/types/node/acp/usage-by-category-calculator.d.ts +21 -0
  7. package/cli/dist-server/types/node/cli/stream-json-protocol.d.ts +15 -1
  8. package/cli/dist-server/types/node/data-fs/index.d.ts +13 -1
  9. package/cli/dist-server/types/node/hooks/hook-protocol.d.ts +2 -2
  10. package/cli/dist-server/types/node/server/sessions.d.ts +24 -0
  11. package/cli/dist-server/types/node/server/types.d.ts +6 -0
  12. package/cli/dist-server/types/node/settings/settings-protocol.d.ts +5 -0
  13. package/cli/dist-server/types/node/tools/tool-protocol.d.ts +112 -2
  14. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +29 -0
  15. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +2 -0
  16. package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +1 -0
  17. package/cli/dist-server/types/vendor/cbc-core/node/agent/interceptors/input-interceptors.d.ts +1 -6
  18. package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +31 -11
  19. package/cli/dist-server/types/vendor/cbc-core/node/agent/speaker-label.d.ts +44 -0
  20. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-detector-service.d.ts +5 -4
  21. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  22. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-pattern.d.ts +15 -4
  23. package/cli/dist-server/types/vendor/cbc-core/node/hooks/agent-trigger.d.ts +6 -22
  24. package/cli/dist-server/types/vendor/cbc-core/node/hooks/hook-protocol.d.ts +4 -1
  25. package/cli/dist-server/types/vendor/cbc-core/node/session/idle-queue-drain-service.d.ts +4 -56
  26. package/cli/dist-server/types/vendor/cbc-core/node/session/index.d.ts +3 -0
  27. package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +55 -9
  28. package/cli/dist-server/types/vendor/cbc-core/node/session/model-response-interceptors.d.ts +18 -0
  29. package/cli/dist-server/types/vendor/cbc-core/node/session/recovery-budget.d.ts +55 -0
  30. package/cli/dist-server/types/vendor/cbc-core/node/session/session-hook-manager.d.ts +15 -0
  31. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +10 -1
  32. package/cli/dist-server/types/vendor/cbc-core/node/session/session-persistence-error.d.ts +43 -0
  33. package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +63 -4
  34. package/cli/dist-server/types/vendor/cbc-core/node/session/session-run-state-machine-protocol.d.ts +1 -0
  35. package/cli/dist-server/types/vendor/cbc-core/node/session/session-runtime-lifecycle.d.ts +5 -0
  36. package/cli/dist-server/types/vendor/cbc-core/node/session/session-store.d.ts +150 -4
  37. package/cli/dist-server/types/vendor/cbc-core/node/session/stream-timeout-retry-budget.d.ts +13 -1
  38. package/cli/dist-server/types/vendor/cbc-core/node/utils/history-utils.d.ts +23 -0
  39. package/cli/dist-server/types/vendor/cbc-core/node/utils/index.d.ts +1 -0
  40. package/cli/dist-server/types/vendor/cbc-core/node/utils/message-utils.d.ts +12 -0
  41. package/cli/dist-server/types/vendor/cbc-core/node/utils/model-utils.d.ts +7 -0
  42. package/cli/dist-server/types/vendor/cbc-core/node/utils/queue-dispatch-utils.d.ts +24 -2
  43. package/cli/dist-server/types/vendor/cbc-core/node/utils/session-utils.d.ts +4 -1
  44. package/cli/dist-server/types/vendor/cbc-core/node/utils/string-retention-utils.d.ts +4 -0
  45. package/cli/dist-server/types/vendor/cbc-shared/node/hooks/hook-types.d.ts +7 -1
  46. package/cli/dist-server/types/vendor/cbc-shared/node/index.d.ts +2 -0
  47. package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +7 -3
  48. package/cli/dist-server/types/vendor/cbc-shared/node/tools/tool-names.d.ts +1 -0
  49. package/cli/dist-server/types/vendor/cbc-shared/node/utils/retry-backoff.d.ts +30 -0
  50. package/cli/dist-server/types/vendor/cbc-shared/node/utils/retry-policy.d.ts +26 -0
  51. package/cli/dist-server/types/workspace/authentication/lib/common/account-scoped-external-link-authentication-provider.d.ts +2 -2
  52. package/cli/dist-server/types/workspace/authentication/lib/common/account-utils.d.ts +25 -0
  53. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +2 -2
  54. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +19 -2
  55. package/cli/dist-server/types/workspace/authentication/lib/common/external-link-authentication-provider.d.ts +2 -2
  56. package/cli/dist-server/types/workspace/authentication/lib/common/wx-authentication-provider.d.ts +2 -2
  57. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +29 -0
  58. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +2 -0
  59. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +1 -0
  60. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/interceptors/input-interceptors.d.ts +1 -6
  61. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +31 -11
  62. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/speaker-label.d.ts +44 -0
  63. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-detector-service.d.ts +5 -4
  64. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  65. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-pattern.d.ts +15 -4
  66. package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/agent-trigger.d.ts +6 -22
  67. package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/hook-protocol.d.ts +4 -1
  68. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/idle-queue-drain-service.d.ts +4 -56
  69. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/index.d.ts +3 -0
  70. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +55 -9
  71. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-response-interceptors.d.ts +18 -0
  72. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/recovery-budget.d.ts +55 -0
  73. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-hook-manager.d.ts +15 -0
  74. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +10 -1
  75. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-persistence-error.d.ts +43 -0
  76. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +63 -4
  77. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-run-state-machine-protocol.d.ts +1 -0
  78. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-runtime-lifecycle.d.ts +5 -0
  79. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-store.d.ts +150 -4
  80. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/stream-timeout-retry-budget.d.ts +13 -1
  81. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/history-utils.d.ts +23 -0
  82. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/index.d.ts +1 -0
  83. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/message-utils.d.ts +12 -0
  84. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/model-utils.d.ts +7 -0
  85. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/queue-dispatch-utils.d.ts +24 -2
  86. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/session-utils.d.ts +4 -1
  87. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/string-retention-utils.d.ts +4 -0
  88. package/cli/dist-server/types/workspace/cbc-shared/lib/node/hooks/hook-types.d.ts +7 -1
  89. package/cli/dist-server/types/workspace/cbc-shared/lib/node/index.d.ts +2 -0
  90. package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +7 -3
  91. package/cli/dist-server/types/workspace/cbc-shared/lib/node/tools/tool-names.d.ts +1 -0
  92. package/cli/dist-server/types/workspace/cbc-shared/lib/node/utils/retry-backoff.d.ts +30 -0
  93. package/cli/dist-server/types/workspace/cbc-shared/lib/node/utils/retry-policy.d.ts +26 -0
  94. package/cli/dist-server/types/workspace/cbc-workflow/lib/node/workflow/workflow-execution.d.ts +14 -1
  95. package/cli/dist-server/types/workspace/cbc-workflow/lib/node/workflow/workflow-manager.d.ts +7 -0
  96. package/cli/dist-server/types/workspace/cbc-worktree/lib/node/worktree/worktree-session.d.ts +3 -0
  97. package/cli/dist-server/types/workspace/product/lib/common/cloud-product-provider.d.ts +9 -0
  98. package/cli/dist-server/types/workspace/product/lib/common/index.d.ts +1 -0
  99. package/cli/dist-server/types/workspace/product/lib/common/pick-market-skill-id.d.ts +13 -0
  100. package/cli/dist-server/types/workspace/product/lib/common/tool-control-catalog.d.ts +2 -2
  101. package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +62 -2
  102. package/cli/dist-server/types/workspace/product/lib/common/types/language-model.d.ts +66 -0
  103. package/cli/dist-server/types/workspace/product/lib/common/types/product.d.ts +7 -1
  104. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/backup-policy.d.ts +10 -1
  105. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/center-protocol.generated.d.ts +370 -4
  106. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/file-policy.d.ts +1 -1
  107. package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +216 -0
  108. package/cli/package.json +1 -1
  109. package/cli/product.cloudhosted.json +2 -2
  110. package/cli/product.internal.json +259 -40
  111. package/cli/product.ioa.json +333 -148
  112. package/cli/product.json +309 -351
  113. package/cli/product.selfhosted.json +2 -2
  114. package/docs/README.md +1 -0
  115. package/docs/in-process.md +16 -0
  116. package/lib/application/services.d.ts +3 -1
  117. package/lib/application/services.js +1 -1
  118. package/lib/components/sandbox-center.d.mts +2 -0
  119. package/lib/components/sandbox-center.mjs +1 -0
  120. package/lib/components/session-config.d.mts +2 -0
  121. package/lib/components/session-config.mjs +1 -1
  122. package/lib/harness/create-harness.js +1 -1
  123. package/lib/harness/runtime.js +1 -1
  124. package/lib/harness/types.d.ts +3 -0
  125. package/lib/integration/executor-supervisor.js +1 -1
  126. package/lib/public.d.ts +1 -0
  127. package/lib/runtime/sandbox-center.d.ts +21 -0
  128. package/lib/runtime/sandbox-center.js +1 -0
  129. package/lib/server/public.d.ts +1 -0
  130. package/lib/session/agent-backend.d.ts +2 -0
  131. package/lib/session/agent-backend.js +1 -1
  132. package/lib/session/local-fs.js +1 -1
  133. package/lib/session/server-config.js +1 -1
  134. package/lib/session/server-interactions.js +1 -1
  135. package/package.json +25 -15
  136. package/lib/session/local-options.d.ts +0 -50
  137. package/lib/session/local-options.js +0 -1
@@ -55,6 +55,8 @@ export declare const SANDBOX_RULES_COMMANDS: {
55
55
  readonly SET_THREAT_DATABASE: 'sandbox.rules.set_threat_database';
56
56
  readonly CHECK_MALICIOUS_DOMAIN: 'sandbox.rules.check_malicious_domain';
57
57
  readonly GET_REVISION: 'sandbox.rules.get_revision';
58
+ readonly ISSUE_FILE_TOKEN: 'sandbox.rules.issue_file_token';
59
+ readonly DELEGATE_FILE_OPERATION: 'sandbox.rules.delegate_file_operation';
58
60
  };
59
61
  export type SandboxRulesIpcCommandNameValue = (typeof SANDBOX_RULES_COMMANDS)[keyof typeof SANDBOX_RULES_COMMANDS];
60
62
  export declare const SANDBOX_BACKUP_COMMANDS: {
@@ -78,7 +80,7 @@ export declare const SANDBOX_MONITOR_COMMANDS: {
78
80
  };
79
81
  export type SandboxMonitorIpcCommandNameValue = (typeof SANDBOX_MONITOR_COMMANDS)[keyof typeof SANDBOX_MONITOR_COMMANDS];
80
82
  /** 所有合法的 center IPC 命令名(cipher/rules/backup/data 四域全集)。 */
81
- export type SandboxCommandName = 'sandbox.session.close' | 'sandbox.center.shutdown' | 'sandbox.cipher.detect_sensitive_info' | 'sandbox.cipher.notify_encryption_choice' | 'sandbox.cipher.query_entry' | 'sandbox.cipher.query_entry_list' | 'sandbox.cipher.add_entry' | 'sandbox.cipher.delete_entry' | 'sandbox.cipher.update_entry' | 'sandbox.cipher.add_rule' | 'sandbox.cipher.update_rule' | 'sandbox.cipher.delete_rule' | 'sandbox.cipher.query_rule_list' | 'sandbox.cipher.set_rules' | 'sandbox.cipher.set_config' | 'sandbox.cipher.approval.request_sensitive_approval' | 'sandbox.cipher.query_session_entry_list' | 'sandbox.cipher.clear_session_entries' | 'sandbox.rules.add_file_rule' | 'sandbox.rules.remove_file_rule' | 'sandbox.rules.set_file_rules' | 'sandbox.rules.add_network_rule' | 'sandbox.rules.remove_network_rule' | 'sandbox.rules.set_network_rules' | 'sandbox.rules.add_mach_rule' | 'sandbox.rules.remove_mach_rule' | 'sandbox.rules.set_mach_rules' | 'sandbox.rules.add_cmd_rule' | 'sandbox.rules.remove_cmd_rule' | 'sandbox.rules.set_cmd_rules' | 'sandbox.rules.add_forbidden_program' | 'sandbox.rules.remove_forbidden_program' | 'sandbox.rules.set_http_intercept' | 'sandbox.rules.get_rules' | 'sandbox.rules.decide_file' | 'sandbox.rules.decide_network' | 'sandbox.rules.decide_command' | 'sandbox.rules.fetch_profile' | 'sandbox.rules.set_config' | 'sandbox.rules.set_session_workspace' | 'sandbox.rules.set_threat_database' | 'sandbox.rules.check_malicious_domain' | 'sandbox.rules.get_revision' | 'sandbox.backup.enable_modify_backup' | 'sandbox.backup.modify_backup' | 'sandbox.backup.commit_modify_backup' | 'sandbox.backup.query_modify_backup_commits' | 'sandbox.backup.restore_modify_backup' | 'sandbox.data.put_data' | 'sandbox.data.get_data' | 'sandbox.data.remove_data' | 'sandbox.data.clear_business' | 'sandbox.monitor.query' | 'sandbox.monitor.query_session';
83
+ export type SandboxCommandName = 'sandbox.session.close' | 'sandbox.center.shutdown' | 'sandbox.cipher.detect_sensitive_info' | 'sandbox.cipher.notify_encryption_choice' | 'sandbox.cipher.query_entry' | 'sandbox.cipher.query_entry_list' | 'sandbox.cipher.add_entry' | 'sandbox.cipher.delete_entry' | 'sandbox.cipher.update_entry' | 'sandbox.cipher.add_rule' | 'sandbox.cipher.update_rule' | 'sandbox.cipher.delete_rule' | 'sandbox.cipher.query_rule_list' | 'sandbox.cipher.set_rules' | 'sandbox.cipher.set_config' | 'sandbox.cipher.approval.request_sensitive_approval' | 'sandbox.cipher.query_session_entry_list' | 'sandbox.cipher.clear_session_entries' | 'sandbox.rules.add_file_rule' | 'sandbox.rules.remove_file_rule' | 'sandbox.rules.set_file_rules' | 'sandbox.rules.add_network_rule' | 'sandbox.rules.remove_network_rule' | 'sandbox.rules.set_network_rules' | 'sandbox.rules.add_mach_rule' | 'sandbox.rules.remove_mach_rule' | 'sandbox.rules.set_mach_rules' | 'sandbox.rules.add_cmd_rule' | 'sandbox.rules.remove_cmd_rule' | 'sandbox.rules.set_cmd_rules' | 'sandbox.rules.add_forbidden_program' | 'sandbox.rules.remove_forbidden_program' | 'sandbox.rules.set_http_intercept' | 'sandbox.rules.get_rules' | 'sandbox.rules.decide_file' | 'sandbox.rules.decide_network' | 'sandbox.rules.decide_command' | 'sandbox.rules.fetch_profile' | 'sandbox.rules.set_config' | 'sandbox.rules.set_session_workspace' | 'sandbox.rules.set_threat_database' | 'sandbox.rules.check_malicious_domain' | 'sandbox.rules.get_revision' | 'sandbox.rules.issue_file_token' | 'sandbox.rules.delegate_file_operation' | 'sandbox.backup.enable_modify_backup' | 'sandbox.backup.modify_backup' | 'sandbox.backup.commit_modify_backup' | 'sandbox.backup.query_modify_backup_commits' | 'sandbox.backup.restore_modify_backup' | 'sandbox.data.put_data' | 'sandbox.data.get_data' | 'sandbox.data.remove_data' | 'sandbox.data.clear_business' | 'sandbox.monitor.query' | 'sandbox.monitor.query_session';
82
84
  /** 所有合法的 center IPC 命令名(cipher/rules/backup/data 四域全集)。 */
83
85
  export type SandboxCommand = SandboxCommandName;
84
86
  export declare const FileModifier: {
@@ -98,6 +100,9 @@ export type DecisionDomain = 'file' | 'network' | 'cmd';
98
100
  export type DecisionRecordSource = 'center_rule' | 'syslog_deny' | 'cli_synthesized';
99
101
  export type DecisionOperation = 'read' | 'write' | 'delete' | 'rename' | 'execute' | 'connect' | 'dns_resolve' | 'sendto';
100
102
  export type FileOp = 'read' | 'write' | 'delete' | 'rename';
103
+ export type FileOpenOutcome = 'openedExisting' | 'created' | 'overwritten';
104
+ export type FileTokenError = 'alreadyExists' | 'notFound' | 'accessDenied' | 'deliveryFailed' | 'unsupported' | 'openFailed';
105
+ export type FileOpOutcome = 'recycled' | 'deleted' | 'renamed' | 'targetAbsent';
101
106
  export type BackupReason = 'a' | 'm' | 'd';
102
107
  export type RestoreFileStatus = 'staging' | 'staging-failed' | 'applied' | 'apply-failed';
103
108
  /**
@@ -1224,6 +1229,64 @@ export interface DecisionRecord {
1224
1229
  */
1225
1230
  source?: DecisionRecordSource;
1226
1231
  }
1232
+ /**
1233
+ * 打开意图 — 「以什么语义打开」的跨平台表达,代开专用。
1234
+ * **为什么必须有**:center 若只按 op 推导打开参数,会静默破坏调用方语义。
1235
+ * 最典型的是 fopen(path, "w"):它要求**截断**,而按 op=write 推出的
1236
+ * 「不存在则创建、存在则打开」不截断——调用方从头写一遍,旧文件的尾巴
1237
+ * 留在那里,是静默的数据损坏。同理 O_EXCL / FILE_CREATE 要求「已存在即
1238
+ * 失败」,不表达就会把该报冲突的地方开成成功。
1239
+ * 用意图而非某一平台的原生常量,因为三端可互译:
1240
+ * - POSIX:truncate=O_TRUNC,create_if_missing=O_CREAT,
1241
+ * fail_if_exists=O_EXCL;
1242
+ * - Windows CreateDisposition:
1243
+ * FILE_OPEN → 全 false
1244
+ * FILE_CREATE → create_if_missing + fail_if_exists
1245
+ * FILE_OPEN_IF → create_if_missing
1246
+ * FILE_OVERWRITE → truncate
1247
+ * FILE_OVERWRITE_IF → truncate + create_if_missing
1248
+ * FILE_SUPERSEDE → truncate + create_if_missing(**近似**:
1249
+ * SUPERSEDE 语义上是删除重建、丢弃原 ACL 与备用流,代开不复刻这
1250
+ * 一层差异;有此要求的调用方不应走代开)。
1251
+ * 缺省(字段不出现)等价于全 false,即「打开已存在的**文件**,不创建不
1252
+ * 截断」——最保守的一档,不产生任何副作用。
1253
+ *
1254
+ * **directory 与 delete_on_close 为何也必须在这里表达**:这两项与 truncate
1255
+ * 同类——不表达就静默做错事,而且错得比截断更隐蔽:
1256
+ * - 不表达 directory,center 只会用「开文件」那套原语,把一个**普通文件**
1257
+ * 建在目录该在的位置。调用方拿到成功的返回值,之后往里建子项全部失败,
1258
+ * 现场离病根很远。
1259
+ * - 不表达 delete_on_close,代开回来的凭据不带删除权,调用方关闭句柄时
1260
+ * 什么也不会发生:一次删除**静默地没发生**,而调用方已按删成功继续走。
1261
+ * 隔离态下调用方**没有**「不走代开」这个退路(本进程的令牌打不开目标),
1262
+ * 所以「有此要求的调用方不应走代开」对这两项不成立,只能由契约承载。
1263
+ * **wants_* 三位:凭据的权限面按调用方所求给,不由 center 按 op 猜**。
1264
+ * op 是**判定**维度(读/写/删/改名),不是访问面:同一个 op=write 底下,
1265
+ * 调用方可能只要改属性、只要删除权、或真的要写数据。center 若按 op 推
1266
+ * (write → 读写权),会同时犯两个错,且两个错都实测过:
1267
+ * - **该给的没给**:`DeleteFileW` 的 disposition 那条路只要
1268
+ * `DELETE|FILE_READ_ATTRIBUTES`(实测 access=0x00010080),判定收敛成
1269
+ * op=write 后拿到的却是读写权、没有 DELETE。凭据上设不了删除标记,
1270
+ * 隔离态下删除全线失败。
1271
+ * - **不该给的给了**:同一次调用方一位写数据的权都没要,却拿到
1272
+ * `GENERIC_WRITE`。规则许了 write 故不构成提权(调用方本可以直接
1273
+ * 要写权),但凭据的权限面比调用方所求宽,是不必要的暴露面。
1274
+ * 三位都缺省(旧调用方不填)时,center 回落到按 op 推导的老口径,故新增
1275
+ * 本组位不改变既有调用方行为。
1276
+ * 与 delete_on_close 的分工:本组说的是「句柄要带哪些权限」,
1277
+ * delete_on_close 说的是「关闭时做什么」。要删除权但不要关闭即删的调用方
1278
+ * (disposition 那条路)只置 wants_delete。
1279
+ */
1280
+ export interface FileOpenIntent {
1281
+ truncate: boolean;
1282
+ createIfMissing: boolean;
1283
+ failIfExists: boolean;
1284
+ directory: boolean;
1285
+ deleteOnClose: boolean;
1286
+ wantsWriteData: boolean;
1287
+ wantsWriteAttributes: boolean;
1288
+ wantsDelete: boolean;
1289
+ }
1227
1290
  /**
1228
1291
  * DecideFile 请求 data — 单 operation 判定,一次询问一条路径。
1229
1292
  * path 为归一化路径;op 为操作类型(FileOp 枚举),是判定维度映射的
@@ -1242,6 +1305,40 @@ export interface DecisionRecord {
1242
1305
  * 覆盖当新建会给受保护文件登记全维度授权,提权风险);write+存在+
1243
1306
  * backup 开→BACKUP;缺省 fail-closed 当已存在(真新建被当改写仅损失
1244
1307
  * 直通优化,不损失安全)。
1308
+ * **代开 vs 代做(两条不同的路子,勿混)**:沙盒被 OS 层隔离
1309
+ * (Windows 受限令牌 / BaseContainer)后,进程 token 对目标无访问权——
1310
+ * 规则判 allow 它自己也办不成。补救有两条:
1311
+ * - **代开**:center 取得访问权后签发**访问凭据**(fileToken)给沙盒,
1312
+ * 后续读写仍由沙盒自己做。适用于「拿到凭据就能继续」的语义,即
1313
+ * read / write。
1314
+ * 有两个入口,语义完全一致:独立命令 IssueFileToken 是**通用入口**;
1315
+ * 本消息的 need_file_token 是**内联优化**,在本来就要判定的路径上
1316
+ * 顺带把凭据带回,省一次往返。已有判定结论的路径(本地快照命中、
1317
+ * 决策缓存命中)不该为了拿凭据再走一遍判定,走独立命令。
1318
+ * - **代做**:center **直接执行**整个操作,不返回凭据。适用于
1319
+ * rename、删除进回收站、写前备份这类一步到位的复合操作——它们靠
1320
+ * 一个句柄办不成(rename 要目标目录权限与原子性,回收站要 shell
1321
+ * 语义)。故 op=rename/delete **不代开**(详见
1322
+ * DecideFileResponse.file_token 的 op 支持度)。
1323
+ * 代做走 DelegateFileOperation(本域,与 IssueFileToken 并列);写前备份是
1324
+ * 更早就有的另一条代做(backup 域 modify_backup),它早于隔离需求存在。
1325
+ * **历史留档**:RECYCLEBIN 原本只是 FileModifier 的一个位,重定向动作
1326
+ * 由 **tsbx 自己**执行(MoveToRecycleBin → SHFileOperationW)。那在受限
1327
+ * 令牌下会失败,且失败被 fg::Execute 翻成 Deny——放行的删除会变成拒绝。
1328
+ * DelegateFileOperation 就是为补这个洞而加的。
1329
+ * need_file_token 的判据放在请求侧而非 center 侧,是因为 center 不掌握
1330
+ * 会话的隔离臂信息(ProfileExecParams 不含该维度),只有发起方自己知道
1331
+ * 当前 token 打不打得开。
1332
+ * file_token_recipient_pid 同理由请求方自报,且它是**接收方**而非调用方——
1333
+ * 两者会分离(Linux 上发起询问的是 cli 内的 seccomp supervisor 线程、需要 fd 的是被管
1334
+ * 进程),故不命名为 caller。**连接层拿不到真实发起方**:Windows 的
1335
+ * GetNamedPipeClientProcessId 返回创建客户端端点的进程,句柄一旦被继承
1336
+ * 就仍报原创建者;沙盒还能再起子进程、子进程也会发起询问,靠连接身份
1337
+ * 既不准也不完整。
1338
+ * 安全边界因此落在 **session** 上而非进程身份:可代开的文件集合始终由
1339
+ * 本会话规则裁定,file_token_recipient_pid 只决定投递给谁。残余风险是被攻破
1340
+ * 的沙盒谎报 pid,把一个本会话已放行的句柄塞进同用户的其他进程——有界
1341
+ * (对自身无增益,且句柄值攻击方不可见),接受。
1245
1342
  * 历史字段留档:access_mask(字段号 2)已移除(op 语义化后全面冗余:
1246
1343
  * 判定聚合与 modifier 计算均由 op 表达)。
1247
1344
  */
@@ -1251,6 +1348,9 @@ export interface DecideFileRequest {
1251
1348
  dstPath?: string;
1252
1349
  targetExists?: boolean;
1253
1350
  skipSensitiveDetect?: boolean;
1351
+ needFileToken?: boolean;
1352
+ fileTokenRecipientPid?: number;
1353
+ openIntent?: FileOpenIntent;
1254
1354
  }
1255
1355
  /**
1256
1356
  * DecideFile 响应 data — 单 operation 判定的明确结论。
@@ -1263,6 +1363,119 @@ export interface DecideFileRequest {
1263
1363
  * rename 的 BACKUP 按 dstPath 侧 target_exists 分流)。
1264
1364
  * decisionRecord 全态必返(allow 也返回,审计闭环不分态);record.action
1265
1365
  * 与顶层 action 同值(record 内嵌判态,转发后可独立消费)。
1366
+ * file_token 为**代开产物**:请求带 needFileToken 且本次判 allow 时,
1367
+ * center 在响应前取得对目标的访问权,本字段回带一张**访问凭据**。
1368
+ * **凭据对协议不透明,但不对 guest 不透明**——这条边界要拿准:协议层
1369
+ * 不定义内容结构、不解释也不校验,由平台配对的产出方与消费方各自约定
1370
+ * 编码;但消费方必须认得自己平台那一种。Windows 上 guest 非得把十进制
1371
+ * 串解析成 HANDLE 才能用,谈不上「不解析」。故约束是「**跨平台代码**不得
1372
+ * 解析本字段」,不是「任何人都不得解析」。
1373
+ * 三端的凭据实体与投递方向都不同(详见下方平台支持度):
1374
+ * - Windows:DuplicateHandle 进目标进程后的句柄值,十进制无符号。宿主推。
1375
+ * - Linux:经 SCM_RIGHTS + ADDFD 注入被管进程后的 fd 号。宿主推。
1376
+ * - macOS(未落地):sandbox_extension_issue_file 签发的 extension token,
1377
+ * 由 guest 自行 sandbox_extension_consume 兑付。**guest 自取、无投递
1378
+ * 动作**,故 fileTokenRecipientPid 对该形态不适用。
1379
+ * 选 string 而非整数正是为此:整数只装得下前两种。
1380
+ * **与设计稿的关系**:本设计取代 guest-ipc 统一设计稿 §4.1 的
1381
+ * FileTokenRequest。该稿给 Windows 设计的 token 是「center 记账
1382
+ * (session,path,op,nonce)、tsbx 校验后**放行原调用**」,而放行意味着让原始
1383
+ * NtCreateFile 继续走内核——受限令牌下内核直接 ACCESS_DENIED,center 记的
1384
+ * 账内核不认。该稿全文未涉及受限
1385
+ * 令牌/BaseContainer,其前提是「进程持完整权限、hook 只做策略层」。前提
1386
+ * 变了,凭据就必须**携带真实访问权**(Windows 即句柄),而不能只是一条
1387
+ * 放行记录。名字仍沿用 token,因为它不承诺实体形态,能同时容纳 macOS 的
1388
+ * extension token——那一种恰恰是内核认账的真凭据。
1389
+ * 契约要点:
1390
+ * - 本字段是**内联优化**(省一次往返);通用入口是独立命令
1391
+ * IssueFileToken,两者代开语义完全一致。已有判定结论的路径不必为了
1392
+ * 拿句柄再走一遍判定。
1393
+ * - 投递目标由请求的 fileTokenRecipientPid 指定;可代开的**文件集合**由
1394
+ * 本会话规则裁定(安全边界在 session,理由见 DecideFileRequest)。
1395
+ * - 仅 action=allow 代开;deny/ask 不代开(键不出现)。ask 的授权闭环
1396
+ * 走宿主审批,此时代开等于绕过审批放行。
1397
+ * - **op 支持度**:只有 read/write 代开。delete/rename 属「代做」语义
1398
+ * (见 DecideFileRequest),靠一个句柄办不成,走 center 直接执行的
1399
+ * 接口,本字段对它们恒不出现。
1400
+ * - 代开失败(打开失败/复制失败/平台不支持)时键不出现,**不改变
1401
+ * action**——请求方按「无代开」走自己的原路径,失败不升级为拒绝。
1402
+ * - 句柄所有权移交请求方,由其负责关闭;center 不保留副本。
1403
+ * - **打开语义由 openIntent 表达,不由 op 推导**。access 仍按 op 取
1404
+ * (read→只读,write→读写),但「创建/截断/独占」三项必须由请求方
1405
+ * 明说,否则 center 按最保守的一档(打开已存在、不创建不截断)开。
1406
+ * 这是刻意的:让 fopen("w") 这类要求截断的调用方**必须**表态,而不是
1407
+ * 由 center 猜——猜错就是静默的数据损坏(详见 FileOpenIntent)。
1408
+ * - **CREATE_ONLY 由 center 在这次打开上强制兑现**:本次 modifier 含
1409
+ * CREATE_ONLY 时,center 覆盖 openIntent 为「独占创建」
1410
+ * (createIfMissing + failIfExists,清掉 truncate),即 POSIX
1411
+ * O_CREAT|O_EXCL / Windows FILE_CREATE。请求方声明的 truncate 一律
1412
+ * 不生效。**为什么必须由 center 做**:CREATE_ONLY 是本次判定的产物,
1413
+ * 请求方在发问时还不知道,其 openIntent 只能反映自己的原始意图;
1414
+ * 若照原样开,一个 FILE_OVERWRITE_IF 的请求就会在「判定说只许新建」
1415
+ * 的同时把已存在的文件截断掉。
1416
+ * 这也是**唯一**能免疫 TOCTOU 的做法:CREATE_ONLY 的判据
1417
+ * (targetExists)是请求方在 hook 时点探测的,探测与打开之间目标随时
1418
+ * 可能被创建;把独占约束下沉到 center 真正那一次打开,由内核原子裁决,
1419
+ * 探测不准最多让判定偏保守,破坏不了数据。
1420
+ * 冲突(目标已存在)不是错误而是**调用方操作的正常结果**:以
1421
+ * fileTokenError=ALREADY_EXISTS 如实回报,请求方据此还原平台原生的
1422
+ * 冲突码(Windows STATUS_OBJECT_NAME_COLLISION / POSIX EEXIST)。
1423
+ * 请求方的 openIntent 本身不含 createIfMissing 时不代开(该请求不可能
1424
+ * 是真新建,与 CREATE_ONLY 语义相斥),同样以 ALREADY_EXISTS 回报。
1425
+ * createIfMissing 会真的在磁盘上创建文件,是可观测副作用:一次询问
1426
+ * 即便调用方随后没写入,也会留下空文件。
1427
+ * 仍**不复刻**发起方完整的 NtCreateFile 语义(共享模式、SUPERSEDE 的
1428
+ * 删除重建语义、备用数据流),有此要求的调用方不应走代开。此处**不含**
1429
+ * 目录与 delete-on-close:那两项由 openIntent 承载,理由见 FileOpenIntent。
1430
+ * - 实际处置由 fileTokenOutcome 回报(新建/打开既有/截断),调用方
1431
+ * 据此还原平台原生的处置结果码;自己从 openIntent 是推不出来的。
1432
+ * - **modifier 义务不因代开而豁免**:响应可能同时带 BACKUP 位与
1433
+ * fileToken,调用方拿句柄直接写**不得**跳过写前备份(tsbx hook 层
1434
+ * 在需要备份时主动调 center 代做)。现阶段依赖调用方诚实遵循,
1435
+ * center 不强制——安全边界问题挂账,另线处置。
1436
+ * 平台支持度。分歧的根子是「发起询问的」与「需要句柄的」是不是同一个
1437
+ * 进程:
1438
+ * - Windows 已实现。两者同一:沙盒进程经 tsbx hook 自己发问、自己要
1439
+ * 句柄;DuplicateHandle 又只要求 PROCESS_DUP_HANDLE,任何进程都能
1440
+ * 持有,故 center 一步投递到位。
1441
+ * - Linux 暂未实现,但路线明确。两者不同一:沙盒进程发的是裸 openat,
1442
+ * 被内核挂起,代它发问的是 sandbox-cli 进程内持有 notify fd 的
1443
+ * seccomp supervisor 线程(注意是 cli 内的线程,不是独立进程,更不是
1444
+ * center)。往被挂起进程塞 fd 只有 SECCOMP_IOCTL_NOTIF_ADDFD 一条
1445
+ * 路,而该 ioctl 打在 notify fd 上——那个 fd 就是能力本身,只有
1446
+ * supervisor 持有,center 拿不到也不该拿(传过去等于交出监管权)。
1447
+ * 故形状必然两段:center 开 → fd 经 SCM_RIGHTS 随应答交给 supervisor
1448
+ * → supervisor 用 ADDFD 注入被管进程。判据与本字段语义都不变,分歧
1449
+ * 只在最后一跳。另注:Linux 放行走 USER_NOTIF CONTINUE,内核在原
1450
+ * 进程上下文继续执行 openat,进程以自己的身份开——故代开只在「规则
1451
+ * 判 allow 但路径没挂进 mount namespace」时才需要(典型是运行期动态
1452
+ * 授权),不像 Windows 受限令牌那样恒需要。
1453
+ * - macOS 不涉及,且不同于「暂未实现」:静态 SBPL 在 spawn 前一次性
1454
+ * 生成,运行期根本不发 decide_file,没有决策点可挂。要代开得先有一层
1455
+ * 运行期拦截机制(NetworkExtension/FileProvider 已退役),是另一个
1456
+ * 工程,不是补个实现。
1457
+ * 待定(不阻塞本期):代开/代做究竟该由 center 还是 cli 承担。Linux 上
1458
+ * 句柄无论如何要经 cli 的 supervisor 转一手,那么「center 开完传给 cli 再
1459
+ * 进沙盒」与「cli 直接开」孰优?Windows 同理(cli 也有条件直接开)。当前
1460
+ * 选 center,因为规则权威在 center、不愿把判定与执行拆到两个进程;但若
1461
+ * 将来 cli 侧承担更多执行职责,此处需重新权衡。
1462
+ * **已知缺口:句柄孤儿窗口**。代开是「响应前先投递、名义值随响应回」,
1463
+ * 故响应若超时/断连丢失,句柄已在接收进程句柄表里、但无人知其值,直到
1464
+ * 该进程退出才随之释放。三端并不同构:
1465
+ * - Windows(DuplicateHandle):真有此窗口——push 进目标进程后内核不
1466
+ * 做任何回收,是三者中唯一需要自己兜底的。
1467
+ * - Linux(SCM_RIGHTS / seccomp ADDFD):内核侧自带兜底——SCM_RIGHTS
1468
+ * 的 fd 若接收方始终不收,随 socket 缓冲丢弃由内核关闭;ADDFD 配
1469
+ * SECCOMP_ADDFD_FLAG_SEND 时 fd 直接作为被拦截系统调用的返回值,
1470
+ * 投递与应答原子完成,不存在中间态。
1471
+ * - macOS:不涉及(不发 decide_file)。
1472
+ * 同类项目的做法:Windows 沙箱(如 Chromium 的 broker)同样是 broker 侧
1473
+ * DuplicateHandle 进目标再回值,对该窗口的处置是**接受泄漏、以进程生命
1474
+ * 周期为界**,并把复制放在应答前的最后一步把窗口压到最小——沙盒进程本
1475
+ * 就短命且被 Job 兜底回收,为此加一轮 ack/账本不划算。本实现取同一口径。
1476
+ * 若将来要收紧,方向是 center 侧维护待确认句柄账本 + 请求方回执,超时
1477
+ * 未回执则由 center 用 DUPLICATE_CLOSE_SOURCE 反向关闭;代价是每次代开
1478
+ * 多一轮往返,需权衡。
1266
1479
  * 历史字段留档:read/write/delete_action(字段号 1~3)与 extra_info
1267
1480
  * (字段号 5)已移除(单 action 化 + 审计素材结构化收编进 decisionRecord),
1268
1481
  * 字段号空缺不复用。
@@ -1271,7 +1484,151 @@ export interface DecideFileResponse {
1271
1484
  action: RuleAction;
1272
1485
  modifier: number;
1273
1486
  decisionRecord: DecisionRecord;
1274
- fileHandle?: string;
1487
+ fileToken?: string;
1488
+ fileTokenOutcome?: FileOpenOutcome;
1489
+ fileTokenError?: FileTokenError;
1490
+ }
1491
+ /**
1492
+ * IssueFileToken 请求 data — 请 center 代开一个文件并签发访问凭据。
1493
+ * 与 DecideFile 的内联代开(needFileToken)**语义完全一致**,差别只在
1494
+ * 入口:本命令是通用入口,内联那条是「本来就要判定」时省一次往返的优化。
1495
+ * 存在两个入口是因为判定与代开本是两件事——本地快照命中、决策缓存命中
1496
+ * 这些路径已经有结论了,只是打不开,不该为了拿凭据再走一遍完整判定。
1497
+ * Linux 将来的两段式代开(center 开 → cli supervisor 经 ADDFD 注入)也
1498
+ * 落在本命令上,那条路径上根本没有「顺便判定」这回事。
1499
+ * **仍然要判定**:本命令不是绕过规则的后门。center 照常按会话规则裁定
1500
+ * path+op(走与 decide_file 逐字相同的判定路径,含敏感检测),非 allow
1501
+ * 一律不开(响应回 action,调用方据此走拒绝路径)。
1502
+ * 由此也说明本命令**并不比内联那条省服务端开销**——省的是调用方的一次
1503
+ * 往返与请求拼装,不是 center 的判定工作。因此:正在做判定的路径请用
1504
+ * 内联(needFileToken),本命令留给「判定已在别处发生」的路径。
1505
+ * op 只接受 read/write:delete/rename 属代做,见 DecideFileRequest。
1506
+ * **域归属留档**:本命令与 DelegateFileOperation 都放在 rules 域,理由是
1507
+ * 二者**自身零状态**,唯一依赖的状态是 RulesState,跟着它走就不引入新的
1508
+ * 锁序(center 的域是状态所有权 + 锁序单位,不是功能分类;轻重分流另由
1509
+ * is_light_command 白名单决定,与域正交,新命令默认归重走 worker)。
1510
+ * 但本命令与代做有个本质区别:代做一次性做完就结束,代开会在 guest 进程里
1511
+ * 留下一个**跨请求存活的内核对象**。将来若要管这个对象(句柄孤儿账本、
1512
+ * 会话结束回收),就会产生生命周期绑 session 而非绑规则的 per-session 状态,
1513
+ * 塞进 RulesState 即语义污染——**补记账之日即重评域归属之时**。
1514
+ */
1515
+ export interface IssueFileTokenRequest {
1516
+ path: string;
1517
+ op: FileOp;
1518
+ fileTokenRecipientPid: number;
1519
+ openIntent?: FileOpenIntent;
1520
+ }
1521
+ /**
1522
+ * IssueFileToken 响应 data — 代开结果。
1523
+ * action 为本次规则裁决,**恒有值**:调用方据此区分「规则不许」与「规则
1524
+ * 许了但开不成」。fileToken 缺省即代开未发生,两种成因都不改变 action:
1525
+ * 规则非 allow(不该开),或打开/复制失败(该开但没开成)。
1526
+ * modifier 必带:本命令**照常重判**,重判可能得出调用方手上那份结论没有
1527
+ * 的副作用义务(典型是 BACKUP——期间 enable_modify_backup 被打开)。丢掉
1528
+ * 它等于让调用方凭一份过期结论跳过写前备份。
1529
+ * 契约的其余部分(凭据的不透明边界与三端实体差异、所有权移交、一次性
1530
+ * 资源、modifier 义务不豁免、孤儿窗口、平台支持度)与
1531
+ * DecideFileResponse.file_token 逐条相同,不重复。
1532
+ * 不带 decisionRecord:审计记录已在重判时按 decide_file 的口径落过一次,
1533
+ * 本响应再带一份只会让宿主重复计账。
1534
+ */
1535
+ export interface IssueFileTokenResponse {
1536
+ action: RuleAction;
1537
+ modifier: number;
1538
+ fileToken?: string;
1539
+ fileTokenOutcome?: FileOpenOutcome;
1540
+ fileTokenError?: FileTokenError;
1541
+ }
1542
+ /**
1543
+ * DelegateFileOperation 请求 data — 请 center **代替**沙盒进程执行整个文件操作。
1544
+ * 这是与「代开」并列的另一条补救路子,分界见 DecideFileRequest:代开
1545
+ * 签发凭据让沙盒自己做,代做则 center 从头做到尾、不返回凭据。
1546
+ * **溯源**:对应 guest-ipc 统一设计稿 §4.1 的 HostFileOperation
1547
+ * (该稿把代做定为 Win/Mac 共用的一等能力)。
1548
+ * 本命令与之有两处有意偏离:
1549
+ * - **操作集**只取 delete/rename,未收该稿的 mkdir/copy/chmod/link/touch。
1550
+ * 那套是 shell 命令粒度(源自 macOS toybox 代办 rm/cp/mv/chmod),而
1551
+ * 本协议的 FileOp 是判定维度粒度——决策 #23 定了「协议不再感知平台 op
1552
+ * 细节」,copy 由各平台高层拆成 write+delete,不设独立态。现阶段
1553
+ * delete/rename 在判定枚举里本就是独立值,复用 FileOp 既够用又一致。
1554
+ * **但要覆盖 mkdir/copy/chmod/touch 时必须另立执行操作枚举**:它们在
1555
+ * 判定层全被归并成 write,归并后的 write 不足以告诉 center 该做什么。
1556
+ * - **删除模式不由调用方指定**。该稿的 deleteMode(trash|unlink) 是调用方
1557
+ * 参数,而调用方在 guest 侧属不可信:报 unlink 而规则要 trash,就绕过了
1558
+ * 可恢复性这条策略。本命令改由 center 按判定所得的 RECYCLEBIN 位分流
1559
+ * (详见下方 modifier 一节),也避免了与既有 FileModifier 形成第二真相源。
1560
+ * 命名未沿用 HostFileOperation:master 全仓不使用 Guest/Host 术语,且五域
1561
+ * 53 条命令的动作段是动词开头(唯一名词例外是 approval)。
1562
+ * 适用于靠一个句柄办不成的复合操作:
1563
+ * - **删除进回收站**:要 shell 语义(Windows 的 SHFileOperation /
1564
+ * macOS 的 trashItemAtURL / Linux 的 XDG trash 规范),不是「打开后
1565
+ * 删掉」能等价的;
1566
+ * - **rename/移动**:要目标目录的写权限与原子性,源句柄给了也没用。
1567
+ * **本命令不做写前备份**,这不是遗漏。BACKUP 与 RECYCLEBIN 虽同为
1568
+ * modifier,性质却不同:
1569
+ * - **RECYCLEBIN 是执行方式**——同一个 delete,进回收站还是永久删除。
1570
+ * 它必须由执行者消费,故 center 按自己判定所得的位分流。请求里因此
1571
+ * **不带**「要不要进回收站」这类参数:那是判定的产物,不是调用方的
1572
+ * 选择,调用方谎报也无从获益。
1573
+ * - **BACKUP 是前置义务**——「改之前先留一份」。调用方走 backup 域的
1574
+ * modify_backup 履行,而那条路**在隔离下本来就通**:它只是一次 IPC,
1575
+ * 复制全在 center 内完成,调用方不需要任何写权限。既然没坏,就不该
1576
+ * 挪进本命令——那只会和调用方已做的备份重复一次。
1577
+ * 故 response.modifier 是**回报**而非要求:调用方据此对账审计,不必再做。
1578
+ * **仍然要判定**:本命令不是绕过规则的后门。走与 decide_file 逐字相同的
1579
+ * 判定路径,非 allow 一律不执行。
1580
+ * op 只接受 delete/rename:read/write 属代开,见 DecideFileRequest。
1581
+ * path 形态与 decide_file 一致(Windows 为 NT 设备路径),**不同于**
1582
+ * backup 域的 modify_backup(那里历史上用 Win32)——判定需要 NT,执行时
1583
+ * 由 center 自己转 Win32,调用方不必关心两种形态。
1584
+ * **删除语义两位(ignore_readonly / posix_semantics)与「谁来裁决」**:
1585
+ * 规则许了删除,不等于这次删除原生就办得成——只读位、目录非空、被别的
1586
+ * 句柄按不可删共享打开着,原生都会失败。这一关必须保住:center 的权限比
1587
+ * 沙盒大,不问就等于拿 center 的权限把沙盒原生办不成的删除办成了
1588
+ * (BUG #111555 就是这么来的)。
1589
+ * 裁决**由 center 做**,理由是它才是执行者:隔离态下沙盒进程的令牌被
1590
+ * 刻意剥了权,拿它去问「原生删除会不会成」问的不是同一件事——实测
1591
+ * 受限令牌在代开凭据上试设删除标记恒得 ACCESS_DENIED,与对象本身能不能
1592
+ * 删无关。而 center 裁决所需的那次 open **正是它执行所需的那次**,一次
1593
+ * 打开先试设删除标记拿裁决、再用同一句柄提交,不多开任何句柄,且裁决与
1594
+ * 执行之间没有跨进程窗口。
1595
+ * 本组两位是为了让 center 复现的那次调用与调用方**同构**:调用方带
1596
+ * IGNORE_READONLY 删只读文件时原生是成功的,不带这一位去问就会误判成
1597
+ * 「只读不让删」。缺省全 false = 最保守的一档(等价旧式 disposition)。
1598
+ * 仅 op=delete 有意义,op=rename 忽略。
1599
+ */
1600
+ export interface DelegateFileOperationRequest {
1601
+ path: string;
1602
+ op: FileOp;
1603
+ dstPath?: string;
1604
+ replaceIfExists?: boolean;
1605
+ ignoreReadonly?: boolean;
1606
+ posixSemantics?: boolean;
1607
+ }
1608
+ /**
1609
+ * DelegateFileOperation 响应 data — 代做结果。
1610
+ * action 恒有值:调用方据此区分「规则不许」与「规则许了但没做成」。
1611
+ * outcome 有值即**已执行**——调用方必须短路,绝不能再调一次原生 API。
1612
+ * modifier 是判定所得的**回报**,供调用方对账审计。其中 RECYCLEBIN 已由
1613
+ * center 在执行时消费(决定进回收站还是永久删除),BACKUP 则仍由调用方
1614
+ * 经 modify_backup 自行履行,本命令不代劳(理由见请求侧注释)。
1615
+ * error 仅在 action=allow 但 outcome 缺省时有值,说明为何没做成。
1616
+ * **native_status:原生本来就会失败**。它与 error 的区别不是详略,而是
1617
+ * 调用方要做的事完全不同:error 是「代做这条路自己没走通」,调用方按
1618
+ * 失败处理;native_status 是「这次操作原生也办不成」,调用方必须把这个
1619
+ * 状态**原样**回传给它的调用方,行为才与无沙盒一致——一次删不动的删除
1620
+ * 要如实报「删不动」,而且要报对原因(目录非空 / 只读不让删 / 被占用
1621
+ * 是三种不同的错,调用方的上层据此分流)。故本字段刻意不折成语义枚举:
1622
+ * 折一次就要在 center 侧枚举理由,而理由该由内核给(同 tsbx 侧
1623
+ * file_recycle.cpp 的论证)。对协议不透明,Windows 为 NTSTATUS。
1624
+ * 与 outcome 互斥:原生办不成就不会去执行,故 outcome 必缺省。
1625
+ */
1626
+ export interface DelegateFileOperationResponse {
1627
+ action: RuleAction;
1628
+ modifier: number;
1629
+ outcome?: FileOpOutcome;
1630
+ error?: string;
1631
+ nativeStatus?: number;
1275
1632
  }
1276
1633
  /**
1277
1634
  * DecideNetwork 请求 data — 网络访问决策(对齐 decision_ipc.cpp:237)。
@@ -1390,7 +1747,7 @@ export interface FetchProfileResponse {
1390
1747
  execParams: ProfileExecParams;
1391
1748
  }
1392
1749
  /**
1393
- * SetRulesConfig 请求 data — 运行时写入 modify_backup/auto_grant/network_strict 开关。
1750
+ * SetRulesConfig 请求 data — 运行时写入 modify_backup/auto_grant/network_strict/advanced_interception 开关。
1394
1751
  * 消息名带 Rules 前缀:proto 拆分合并后与 cipher 域的 SetConfigRequest 同
1395
1752
  * crate 共存会重名(cipher 是检测开关,本处是规则域开关,语义不同);消息名
1396
1753
  * 不进 wire(JSON 只认字段名),改名零运行时影响。
@@ -1404,11 +1761,21 @@ export interface FetchProfileResponse {
1404
1761
  * 已运行进程保持原策略(SBPL profile 在 spawn 时固化)。宿主 UI 须在开关处
1405
1762
  * 提示「跨会话立即生效」,勿让用户以为是当前会话私有设置。
1406
1763
  * 对照:网络**规则**下发带 sessionId、落 per-session 桶,是隔离的。
1764
+ * advanced_interception = 高级拦截(genie/genie#116558,Windows 原生隔离
1765
+ * 闩):host 设置页持有(settings.sandbox.advancedInterceptionEnabled),
1766
+ * **不进 GetRules 回显、不持久化**——center 重启回 false,host 每轮
1767
+ * turn-start 重新下发。置位后 fetch_profile 的 Windows 壳 JSON 携带
1768
+ * windows_isolation.restricted_token,tsbx_sdk 对**新建**沙箱进程走
1769
+ * 受限令牌臂(WRITE_RESTRICTED 主令牌 + kill-on-close 隔离 Job + 早期
1770
+ * 介入三段式);已运行进程的 rules 基线已固化,不受影响。仅 Windows 有
1771
+ * 执行面,非 win 平台 host 下发侧直接跳过(不进 IPC)。与 network_strict
1772
+ * 同为进程级全局开关,值真变才 touch revision。
1407
1773
  */
1408
1774
  export interface SetRulesConfigRequest {
1409
1775
  modifyBackupEnabled?: boolean;
1410
1776
  autoGrantEnabled?: boolean;
1411
1777
  networkStrictMode?: boolean;
1778
+ advancedInterception?: boolean;
1412
1779
  }
1413
1780
  /**
1414
1781
  * SetSessionWorkspace 请求 data — 注入该 session 的 {SESSION_WORKSPACE}
@@ -1434,7 +1801,6 @@ export interface EnableModifyBackupRequest {
1434
1801
  enabled: boolean;
1435
1802
  fileBackupMaxSizeMB?: number;
1436
1803
  modifyBackupThresholdMB?: number;
1437
- sessionRoots?: string[];
1438
1804
  excludedBackupRoots?: string[];
1439
1805
  }
1440
1806
  /** EnableModifyBackup 响应 data — 开关切换结果。 */
@@ -1,7 +1,7 @@
1
1
  import { type FileRuleActions } from './file-rule-action.js';
2
2
  import type { SecurityCenterFileRule, SecurityCenterOrderedRuleSet } from './rule-config.js';
3
3
  export { getLegacyFilePreset } from './legacy-file-preset.js';
4
- export declare const FILE_POLICY_PRESET_VERSION = 3;
4
+ export declare const FILE_POLICY_PRESET_VERSION = 4;
5
5
  export declare function getDefaultFileRuleSet(platform: NodeJS.Platform): SecurityCenterOrderedRuleSet<SecurityCenterFileRule>;
6
6
  /** Flags alone cannot prove a preset untouched: compare the entire known rule sequence. */
7
7
  export declare function isUnmodifiedLegacyFilePreset(value: SecurityCenterOrderedRuleSet<SecurityCenterFileRule>, platform: NodeJS.Platform): boolean;