evolcore 0.0.25 → 0.0.27

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 (304) hide show
  1. package/CHANGELOG.md +632 -565
  2. package/LICENSE +21 -21
  3. package/README.md +455 -455
  4. package/bin/codex-managed-acl.ps1 +203 -160
  5. package/bin/codex-managed-hook.mjs +208 -208
  6. package/bin/ec-safe-output.js +327 -327
  7. package/bin/ec.js +40 -29
  8. package/bin/install-codex-managed-hooks.mjs +582 -555
  9. package/dist/agents/baseagent-availability.js +68 -0
  10. package/dist/agents/baseagent.js +96 -46
  11. package/dist/agents/claude-runner.js +172 -33
  12. package/dist/agents/codex/app-server-client.js +76 -31
  13. package/dist/agents/codex/catalog.js +1 -1
  14. package/dist/agents/codex/diagnostics.js +34 -1
  15. package/dist/agents/codex-runner.js +434 -446
  16. package/dist/agents/ecagent-runner.js +174 -34
  17. package/dist/agents/gemini-runner.js +8 -7
  18. package/dist/agents/runner-types.js +75 -19
  19. package/dist/aun/aid/agentmd.js +151 -36
  20. package/dist/aun/aid/client.js +1 -1
  21. package/dist/aun/aid/control-aid.js +180 -1
  22. package/dist/aun/aid/identity.js +4 -4
  23. package/dist/aun/aid/index.js +1 -1
  24. package/dist/aun/aid/store.js +17 -13
  25. package/dist/aun/group/history.js +303 -0
  26. package/dist/aun/group/identity.js +43 -0
  27. package/dist/aun/group/index.js +5 -0
  28. package/dist/aun/{msg/group.js → group/operations.js} +162 -39
  29. package/dist/aun/{menu-client.js → menu/client.js} +85 -6
  30. package/dist/aun/menu/index.js +2 -0
  31. package/dist/aun/menu/transport.js +49 -0
  32. package/dist/aun/msg/index.js +2 -1
  33. package/dist/aun/msg/managed-operation.js +85 -19
  34. package/dist/aun/msg/mention-schema.js +51 -0
  35. package/dist/aun/msg/p2p.js +19 -9
  36. package/dist/aun/msg/upload.js +43 -80
  37. package/dist/aun/outbox.js +29 -7
  38. package/dist/aun/rpc/client.js +1 -0
  39. package/dist/aun/storage/client.js +39 -50
  40. package/dist/channels/aun.js +842 -318
  41. package/dist/channels/daemon.js +10 -6
  42. package/dist/cli/agent-command.js +212 -89
  43. package/dist/cli/agent-create.js +626 -11
  44. package/dist/cli/agent.js +125 -13
  45. package/dist/cli/aun-commands.js +487 -337
  46. package/dist/cli/bench.js +20 -20
  47. package/dist/cli/config.js +55 -33
  48. package/dist/cli/contact.js +72 -15
  49. package/dist/cli/ctl-command.js +24 -24
  50. package/dist/cli/daemon-commands.js +140 -63
  51. package/dist/cli/diag.js +31 -0
  52. package/dist/cli/fs-command.js +70 -70
  53. package/dist/cli/handoff-command.js +46 -14
  54. package/dist/cli/index.js +91 -79
  55. package/dist/cli/init.js +34 -1
  56. package/dist/cli/link-rules.js +21 -21
  57. package/dist/cli/managed-command-guard.js +5 -1
  58. package/dist/cli/menu-client.js +51 -32
  59. package/dist/cli/model.js +3 -3
  60. package/dist/cli/net-check.js +22 -22
  61. package/dist/cli/queue-command.js +31 -31
  62. package/dist/cli/response.js +32 -32
  63. package/dist/cli/restart-monitor.js +103 -42
  64. package/dist/cli/stats.js +51 -51
  65. package/dist/cli/task-command.js +59 -0
  66. package/dist/cli/task-context.js +97 -49
  67. package/dist/cli/trigger-command.js +74 -64
  68. package/dist/config/builtin-roles.js +11 -0
  69. package/dist/config/config-field-policy.js +11 -0
  70. package/dist/config/config-manager.js +32 -4
  71. package/dist/config/config-operation-service.js +160 -0
  72. package/dist/config/contact-book-store.js +1 -1
  73. package/dist/config/contact-book.js +1 -1
  74. package/dist/config/contact-operation-service.js +97 -8
  75. package/dist/config/peer-role-resolver.js +1 -1
  76. package/dist/config/resolved-config-op.js +30 -7
  77. package/dist/config-store.js +1 -1
  78. package/dist/core/agent-application-service.js +7 -1
  79. package/dist/core/audit/event-key.js +17 -2
  80. package/dist/core/audit/log-integrity.js +34 -8
  81. package/dist/core/auth/agent-delegation.js +48 -14
  82. package/dist/core/auth/auth-gateway.js +2 -0
  83. package/dist/core/auth/authorization-audit.js +53 -49
  84. package/dist/core/auth/operation-authorizer.js +90 -7
  85. package/dist/core/auth/operation-catalog.js +145 -4
  86. package/dist/core/auth/remote-access-store.js +155 -10
  87. package/dist/core/bootstrap-messages.js +66 -7
  88. package/dist/core/bootstrap-service.js +111 -20
  89. package/dist/core/command/agent-control.js +88 -7
  90. package/dist/core/command/agent-storage-menu.js +443 -0
  91. package/dist/core/command/cli-intent-parser.js +19 -0
  92. package/dist/core/command/command-handler.js +159 -65
  93. package/dist/core/command/data-root-resolver.js +273 -0
  94. package/dist/core/command/diag-service.js +118 -0
  95. package/dist/core/command/group-menu.js +7 -2
  96. package/dist/core/command/menu-catalog.js +46 -7
  97. package/dist/core/command/menu-handler.js +392 -100
  98. package/dist/core/command/menu-protocol.js +45 -6
  99. package/dist/core/command/menu-token-store.js +41 -8
  100. package/dist/core/command/role-menu.js +2 -2
  101. package/dist/core/command/slash-gate.js +34 -4
  102. package/dist/core/command/slash-handler.js +123 -43
  103. package/dist/core/event-catalog.js +4 -0
  104. package/dist/core/evolagent-registry.js +28 -2
  105. package/dist/core/group/invite-service.js +924 -0
  106. package/dist/core/handoff/runtime.js +205 -27
  107. package/dist/core/handoff/store.js +193 -4
  108. package/dist/core/interaction-router.js +22 -8
  109. package/dist/core/message/im-renderer.js +146 -34
  110. package/dist/core/message/message-bridge.js +163 -20
  111. package/dist/core/message/message-log.js +5 -3
  112. package/dist/core/message/message-queue.js +99 -41
  113. package/dist/core/message/message-utils.js +1 -0
  114. package/dist/core/message/response-engine.js +755 -144
  115. package/dist/core/model/catalog-service.js +79 -49
  116. package/dist/core/model/context-window-suffix.js +33 -0
  117. package/dist/core/model/model-catalog.js +1 -1
  118. package/dist/core/model/model-permission.js +12 -3
  119. package/dist/core/permission/approval-gateway.js +36 -3
  120. package/dist/core/permission/ec-command-parser.js +112 -41
  121. package/dist/core/permission/protected-paths.js +134 -16
  122. package/dist/core/permission/sandbox-runtime.js +108 -17
  123. package/dist/core/permission/tool-error-code.js +15 -0
  124. package/dist/core/permission/tool-policy.js +9 -8
  125. package/dist/core/relation/peer-identity.js +57 -6
  126. package/dist/core/relation/shared-data.js +106 -0
  127. package/dist/core/role/runtime-policy.js +64 -0
  128. package/dist/core/runtime-lock.js +10 -26
  129. package/dist/core/session/runner-task-history.js +170 -0
  130. package/dist/core/session/session-manager.js +34 -6
  131. package/dist/core/session/session-mapper.js +41 -0
  132. package/dist/core/session/session-turn-coordinator.js +37 -7
  133. package/dist/core/session/session-turns.js +48 -7
  134. package/dist/core/task/task-recovery-service.js +176 -0
  135. package/dist/core/task/task-resume-operation.js +32 -0
  136. package/dist/eck/group-rules-sync.js +5 -3
  137. package/dist/eck/kit-renderer.js +1 -0
  138. package/dist/index.js +588 -217
  139. package/dist/ipc.js +193 -15
  140. package/dist/paths.js +17 -4
  141. package/dist/product.js +2 -0
  142. package/dist/response-system/engines/v1/proactive-flow.js +59 -2
  143. package/dist/stats/billing.js +41 -15
  144. package/dist/stats/db.js +159 -159
  145. package/dist/stats/eck-vars.js +9 -9
  146. package/dist/stats/price-resolver.js +28 -10
  147. package/dist/stats/query.js +139 -139
  148. package/dist/stats/role-budget.js +6 -6
  149. package/dist/stats/writer.js +51 -51
  150. package/dist/trigger/event-source.js +19 -0
  151. package/dist/trigger/feedback.js +233 -40
  152. package/dist/trigger/parser.js +55 -5
  153. package/dist/trigger/patch.js +9 -0
  154. package/dist/trigger/scheduler.js +30 -4
  155. package/dist/trigger/validation.js +20 -3
  156. package/dist/utils/cross-platform.js +30 -1
  157. package/dist/utils/ecweb-utils.js +1 -0
  158. package/dist/utils/error-dict.json +160 -160
  159. package/dist/utils/error-utils.js +61 -2
  160. package/dist/utils/evolcore-version.js +129 -0
  161. package/dist/utils/logger.js +26 -14
  162. package/dist/utils/macos-autostart.js +22 -22
  163. package/dist/utils/model-prices.jsonl +23 -23
  164. package/dist/utils/npm-ops.js +176 -35
  165. package/dist/utils/tool-summary.js +59 -3
  166. package/dist/utils/welcome.js +196 -23
  167. package/ecagent/LICENSE +21 -21
  168. package/ecagent/NOTICE +11 -11
  169. package/ecagent/README.md +61 -61
  170. package/ecagent/dist/harness/agent-harness.js +3 -0
  171. package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
  172. package/ecagent/dist/harness/compaction/compaction.js +83 -83
  173. package/ecagent/dist/harness/messages.js +7 -7
  174. package/ecagent/dist/harness/session/jsonl-storage.js +21 -2
  175. package/kits/docs/GUIDE.md +20 -20
  176. package/kits/docs/INDEX.md +60 -66
  177. package/kits/docs/aun/CHEATSHEET.md +19 -19
  178. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
  179. package/kits/docs/channels/aun.md +69 -56
  180. package/kits/docs/channels/feishu.md +56 -56
  181. package/kits/docs/context-assembly.md +379 -367
  182. package/kits/docs/eck_templates/GUIDE.template.md +22 -22
  183. package/kits/docs/eck_templates/INDEX.template.md +28 -28
  184. package/kits/docs/eck_templates/path-registry.template.md +33 -33
  185. package/kits/docs/eck_templates/runtime.template.md +19 -19
  186. package/kits/docs/evolcore/INDEX.md +76 -71
  187. package/kits/docs/evolcore/agent-create.md +202 -165
  188. package/kits/docs/evolcore/agent.md +99 -67
  189. package/kits/docs/evolcore/aid.md +68 -60
  190. package/kits/docs/evolcore/codex-windows-sandbox.md +146 -146
  191. package/kits/docs/evolcore/config.md +241 -195
  192. package/kits/docs/evolcore/contact.md +75 -68
  193. package/kits/docs/evolcore/ctl.md +46 -46
  194. package/kits/docs/evolcore/event.md +216 -216
  195. package/kits/docs/evolcore/fs-architecture.md +1215 -1215
  196. package/kits/docs/evolcore/fs.md +110 -110
  197. package/kits/docs/evolcore/group-collaboration.md +244 -244
  198. package/kits/docs/evolcore/group-fs.md +17 -17
  199. package/kits/docs/evolcore/group-rules.md +251 -251
  200. package/kits/docs/evolcore/group.md +267 -152
  201. package/kits/docs/evolcore/menu-client.md +58 -34
  202. package/kits/docs/evolcore/model.md +50 -50
  203. package/kits/docs/evolcore/msg.md +169 -165
  204. package/kits/docs/evolcore/response.md +75 -75
  205. package/kits/docs/evolcore/rpc.md +37 -37
  206. package/kits/docs/evolcore/self-summary.md +29 -29
  207. package/kits/docs/evolcore/stats.md +83 -83
  208. package/kits/docs/evolcore/storage.md +53 -50
  209. package/kits/docs/evolcore/task.md +14 -0
  210. package/kits/docs/evolcore/trigger.md +623 -575
  211. package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
  212. package/kits/docs/identity/PATH_OPS.md +16 -16
  213. package/kits/docs/identity/ROLE_DETAIL.md +25 -25
  214. package/kits/docs/identity/identity-tools.md +26 -26
  215. package/kits/docs/path-registry.md +62 -62
  216. package/kits/docs/prompt-loading-architecture.md +269 -269
  217. package/kits/docs/venues/aun-group.md +45 -45
  218. package/kits/docs/venues/aun-private.md +10 -10
  219. package/kits/docs/venues/client-desktop.md +10 -10
  220. package/kits/docs/venues/client-mobile.md +10 -10
  221. package/kits/docs/venues/feishu-group.md +13 -13
  222. package/kits/docs/venues/feishu-private.md +9 -9
  223. package/kits/docs/venues/group.md +42 -25
  224. package/kits/docs/venues/private.md +10 -10
  225. package/kits/eck_manifest.auxiliary.json +43 -43
  226. package/kits/eck_manifest.json +217 -190
  227. package/kits/eck_message_manifest.json +74 -74
  228. package/kits/migrations/README-role-config-v4.md +32 -32
  229. package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
  230. package/kits/migrations/migrate-role-config-v4.mjs +614 -614
  231. package/kits/migrations/migrate-role-config-v5.mjs +365 -365
  232. package/kits/migrations/rename-config-file.mjs +99 -99
  233. package/kits/rules/01-overview.md +166 -162
  234. package/kits/rules/02-navigation.md +96 -96
  235. package/kits/rules/03-identity.md +36 -36
  236. package/kits/rules/04-relation.md +76 -75
  237. package/kits/rules/05-venue.md +60 -60
  238. package/kits/rules/06-channel.md +65 -63
  239. package/kits/schemas/_meta.json +53 -53
  240. package/kits/schemas/agent-config.schema.1.json +177 -177
  241. package/kits/schemas/agent-config.schema.10.json +395 -395
  242. package/kits/schemas/agent-config.schema.11.json +421 -421
  243. package/kits/schemas/agent-config.schema.12.json +451 -427
  244. package/kits/schemas/agent-config.schema.2.json +239 -239
  245. package/kits/schemas/agent-config.schema.3.json +119 -119
  246. package/kits/schemas/agent-config.schema.4.json +208 -208
  247. package/kits/schemas/agent-config.schema.5.json +326 -326
  248. package/kits/schemas/agent-config.schema.6.json +322 -322
  249. package/kits/schemas/agent-config.schema.7.json +303 -303
  250. package/kits/schemas/agent-config.schema.8.json +304 -304
  251. package/kits/schemas/agent-config.schema.9.json +364 -364
  252. package/kits/schemas/contact-book.schema.1.json +36 -36
  253. package/kits/schemas/contact-book.schema.2.json +43 -43
  254. package/kits/schemas/contact-book.schema.3.json +67 -67
  255. package/kits/schemas/daemon.schema.1.json +91 -91
  256. package/kits/schemas/daemon.schema.2.json +101 -101
  257. package/kits/schemas/daemon.schema.3.json +123 -123
  258. package/kits/schemas/daemon.schema.4.json +136 -136
  259. package/kits/schemas/daemon.schema.5.json +135 -135
  260. package/kits/schemas/daemon.schema.6.json +131 -131
  261. package/kits/schemas/defaults.schema.1.json +81 -81
  262. package/kits/schemas/defaults.schema.2.json +85 -85
  263. package/kits/schemas/defaults.schema.3.json +73 -73
  264. package/kits/schemas/defaults.schema.4.json +107 -107
  265. package/kits/schemas/defaults.schema.5.json +119 -119
  266. package/kits/schemas/menu-exec-schema-commands.md +208 -208
  267. package/kits/schemas/migrations/README.md +30 -30
  268. package/kits/schemas/relation-config.schema.1.json +158 -158
  269. package/kits/schemas/relation-config.schema.2.json +73 -73
  270. package/kits/schemas/relation-config.schema.3.json +50 -50
  271. package/kits/schemas/relation-config.schema.4.json +47 -47
  272. package/kits/schemas/relation-config.schema.5.json +47 -47
  273. package/kits/schemas/relation-config.schema.6.json +46 -46
  274. package/kits/schemas/relation-config.schema.7.json +59 -59
  275. package/kits/schemas/relation-config.schema.8.json +103 -103
  276. package/kits/schemas/role-config.schema.1.json +215 -201
  277. package/kits/schemas/role-registry.schema.1.json +35 -35
  278. package/kits/schemas/single-session.schema.1.json +31 -31
  279. package/kits/schemas/single-session.schema.2.json +57 -57
  280. package/kits/schemas/single-session.schema.3.json +32 -32
  281. package/kits/templates/bootstrap-welcome.md +17 -17
  282. package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
  283. package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
  284. package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
  285. package/kits/templates/message-fragments/inject-default.md +2 -2
  286. package/kits/templates/message-fragments/item.md +2 -2
  287. package/kits/templates/roles/admin.json +92 -92
  288. package/kits/templates/roles/member.json +101 -96
  289. package/kits/templates/roles/owner.json +9 -9
  290. package/kits/templates/roles/visitor.json +90 -85
  291. package/kits/templates/system-fragments/baseagent.md +14 -14
  292. package/kits/templates/system-fragments/bootstrap.md +53 -34
  293. package/kits/templates/system-fragments/channel.md +28 -64
  294. package/kits/templates/system-fragments/commands.md +36 -28
  295. package/kits/templates/system-fragments/group-unread-history.md +7 -0
  296. package/kits/templates/system-fragments/identity.md +13 -13
  297. package/kits/templates/system-fragments/relation.md +19 -19
  298. package/kits/templates/system-fragments/reply.md +56 -0
  299. package/kits/templates/system-fragments/session.md +59 -59
  300. package/kits/templates/system-fragments/venue.md +31 -31
  301. package/package.json +104 -98
  302. package/dist/aun/group-identity.js +0 -9
  303. /package/dist/aun/{group-fs-download.js → group/fs-download.js} +0 -0
  304. /package/dist/aun/{msg/group-index.js → group/index-rpc.js} +0 -0
@@ -1,160 +1,203 @@
1
- param([Parameter(Mandatory = $true)][string]$Request)
2
-
3
- # Called by the Node installer. Paths and security descriptors are data, never
4
- # interpolated into PowerShell source. Use Windows PowerShell's built-in .NET ACL API.
5
- $ErrorActionPreference = 'Stop'
6
- $ProgressPreference = 'SilentlyContinue'
7
- # A parent pwsh session can export its incompatible PowerShell 7 modules.
8
- # This helper always runs in Windows PowerShell 5.1.
9
- $env:PSModulePath = Join-Path $PSHOME 'Modules'
10
- [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
11
-
12
- function Get-Descriptor([string]$Target) {
13
- return (Get-Acl -LiteralPath $Target).GetSecurityDescriptorSddlForm(
14
- [Security.AccessControl.AccessControlSections]'Access,Owner,Group')
15
- }
16
-
17
- function Set-Descriptor([string]$Target, [string]$Sddl) {
18
- $acl = Get-Acl -LiteralPath $Target
19
- $acl.SetSecurityDescriptorSddlForm($Sddl, [Security.AccessControl.AccessControlSections]'Access,Owner,Group')
20
- Set-Acl -LiteralPath $Target -AclObject $acl
21
- }
22
-
23
- function Add-Grant($Acl, [string]$Sid, [Security.AccessControl.FileSystemRights]$Rights, [bool]$Directory) {
24
- $inheritance = if ($Directory) { [Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit' } else { [Security.AccessControl.InheritanceFlags]::None }
25
- $rule = New-Object Security.AccessControl.FileSystemAccessRule(
26
- (New-Object Security.Principal.SecurityIdentifier($Sid)), $Rights, $inheritance,
27
- [Security.AccessControl.PropagationFlags]::None, [Security.AccessControl.AccessControlType]::Allow)
28
- $Acl.AddAccessRule($rule)
29
- }
30
-
31
- function Initialize-AccessProbe {
32
- # An elevated process reading the file is not evidence that a normal process
33
- # can read it. Evaluate the DACL with its UAC linked token when available.
34
- Add-Type -TypeDefinition @'
35
- using System;
36
- using System.Runtime.InteropServices;
37
- using System.Security.Principal;
38
- public static class EvolCoreAclProbe {
39
- [StructLayout(LayoutKind.Sequential)]
40
- struct Mapping { public uint Read, Write, Execute, All; }
41
- [DllImport("advapi32.dll", SetLastError=true)]
42
- static extern bool GetTokenInformation(IntPtr token, int type, out IntPtr linked, int size, out int returned);
43
- [DllImport("advapi32.dll", SetLastError=true)]
44
- static extern bool DuplicateTokenEx(IntPtr token, uint desiredAccess, IntPtr tokenAttributes,
45
- int impersonationLevel, int tokenType, out IntPtr duplicate);
46
- [DllImport("advapi32.dll", SetLastError=true)]
47
- static extern bool AccessCheck(byte[] descriptor, IntPtr token, uint desired,
48
- ref Mapping mapping, byte[] privileges, ref uint length, out uint granted, out bool allowed);
49
- [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr handle);
50
- public static string TokenKind;
51
- public static long Granted(byte[] descriptor) {
52
- using (var identity = WindowsIdentity.GetCurrent()) {
53
- var principal = new WindowsPrincipal(identity);
54
- IntPtr token = identity.Token, linked = IntPtr.Zero, duplicate = IntPtr.Zero;
55
- try {
56
- if (identity.IsSystem || principal.IsInRole(WindowsBuiltInRole.Administrator)) {
57
- int size;
58
- if (!GetTokenInformation(token, 19, out linked, IntPtr.Size, out size)) {
59
- TokenKind = "unavailable";
60
- return -1;
61
- }
62
- token = linked;
63
- TokenKind = "linked-token";
64
- } else { TokenKind = "current-token"; }
65
- // AccessCheck only needs SecurityIdentification (1). A UAC linked
66
- // token can be limited to that level, so requesting the higher
67
- // SecurityImpersonation level fails with ERROR_BAD_IMPERSONATION_LEVEL.
68
- if (!DuplicateTokenEx(token, 0x0000000A, IntPtr.Zero, 1, 2, out duplicate))
69
- throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
70
- var mapping = new Mapping { Read=0x120089, Write=0x120116, Execute=0x1200a0, All=0x1f01ff };
71
- uint length=1024, granted;
72
- bool allowed;
73
- if (!AccessCheck(descriptor, duplicate, 0x02000000, ref mapping,
74
- new byte[length], ref length, out granted, out allowed))
75
- throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
76
- return allowed ? granted : 0;
77
- } finally {
78
- if (duplicate != IntPtr.Zero) CloseHandle(duplicate);
79
- if (linked != IntPtr.Zero) CloseHandle(linked);
80
- }
81
- }
82
- }
83
- }
84
- '@
85
- }
86
-
87
- function Verify-Access($Entry) {
88
- $target = [string]$Entry.path
89
- $acl = Get-Acl -LiteralPath $target
90
- $read = [long][Security.AccessControl.FileSystemRights]::ReadAndExecute
91
- $write = [long][Security.AccessControl.FileSystemRights]'Write,Delete,DeleteSubdirectoriesAndFiles,ChangePermissions,TakeOwnership'
92
- if ($Entry.protected) {
93
- $grants = @{}
94
- foreach ($rule in $acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])) {
95
- if (($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -ne 0) { continue }
96
- $sid = $rule.IdentityReference.Value
97
- $rights = [long]$rule.FileSystemRights
98
- if ($sid -in @('S-1-1-0','S-1-5-11','S-1-5-32-545')) {
99
- if ($rule.AccessControlType -eq 'Allow' -and ($rights -band $write) -ne 0) {
100
- throw "Unsafe write permission on ${target}: $sid has $($rule.FileSystemRights). Existing policy was not removed."
101
- }
102
- if ($rule.AccessControlType -eq 'Deny' -and ($rights -band $read) -ne 0) {
103
- throw "Read permission denied on ${target}: $sid. Existing policy was not removed."
104
- }
105
- }
106
- if ($rule.AccessControlType -eq 'Allow') { $grants[$sid] = ([long]$grants[$sid]) -bor $rights }
107
- }
108
- foreach ($sid in @('S-1-5-18','S-1-5-32-544','S-1-5-32-545')) {
109
- $required = if ($sid -eq 'S-1-5-32-545') { $read } else { [long][Security.AccessControl.FileSystemRights]::FullControl }
110
- if ((([long]$grants[$sid]) -band $required) -ne $required) { throw "Missing required access on ${target}: $sid" }
111
- }
112
- }
113
- $granted = [EvolCoreAclProbe]::Granted($acl.GetSecurityDescriptorBinaryForm())
114
- if ($granted -ge 0) {
115
- $required = if ($Entry.execute) { $read } else { [long][Security.AccessControl.FileSystemRights]::Read }
116
- if (($granted -band $required) -ne $required) { throw "Normal-token read/execute access denied: $target" }
117
- if ($Entry.protected -and ($granted -band $write) -ne 0) { throw "Normal token can modify the protected file or its ACL: $target" }
118
- }
119
- return @{ path = $target; userProbe = [EvolCoreAclProbe]::TokenKind }
120
- }
121
-
122
- try {
123
- $payload = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Request)) | ConvertFrom-Json
124
- $result = switch ($payload.action) {
125
- 'preflight' {
126
- $principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
127
- if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
128
- throw 'Machine-wide Codex hook provisioning requires an elevated Windows installer. npm installation does not require this step.'
129
- }
130
- @{ elevated = $true }
131
- }
132
- 'snapshot' { @{ sddl = (Get-Descriptor $payload.path) } }
133
- 'prepare' {
134
- $target = [string]$payload.path
135
- if ($payload.reference) {
136
- # Same-directory staging preserves the shared configuration's owner,
137
- # inherited policy and custom administrator ACEs. Never reset its ACL.
138
- Set-Descriptor $target (Get-Descriptor $payload.reference)
139
- } else {
140
- $flags = if ($payload.directory) { 'OICI' } else { '' }
141
- Set-Descriptor $target "O:BAG:BAD:P(A;${flags};FA;;;SY)(A;${flags};FA;;;BA)(A;${flags};FRFX;;;BU)"
142
- }
143
- $acl = Get-Acl -LiteralPath $target
144
- Add-Grant $acl 'S-1-5-18' 'FullControl' ([bool]$payload.directory)
145
- Add-Grant $acl 'S-1-5-32-544' 'FullControl' ([bool]$payload.directory)
146
- Add-Grant $acl 'S-1-5-32-545' 'ReadAndExecute' ([bool]$payload.directory)
147
- Set-Acl -LiteralPath $target -AclObject $acl
148
- @{ prepared = $true }
149
- }
150
- 'verify' {
151
- Initialize-AccessProbe
152
- @($payload.entries | ForEach-Object { Verify-Access $_ })
153
- }
154
- default { throw "Unknown ACL operation: $($payload.action)" }
155
- }
156
- ConvertTo-Json -InputObject $result -Depth 8 -Compress
157
- } catch {
158
- [Console]::Error.WriteLine("[evolcore] ACL $($payload.action) failed for $($payload.path): $($_.Exception.Message)")
159
- exit 1
160
- }
1
+ param([Parameter(Mandatory = $true)][string]$Request)
2
+
3
+ # Called by the Node installer. Paths and security descriptors are data, never
4
+ # interpolated into PowerShell source. Use Windows PowerShell's built-in .NET ACL API.
5
+ $ErrorActionPreference = 'Stop'
6
+ $ProgressPreference = 'SilentlyContinue'
7
+ # A parent pwsh session can export its incompatible PowerShell 7 modules.
8
+ # This helper always runs in Windows PowerShell 5.1.
9
+ $env:PSModulePath = Join-Path $PSHOME 'Modules'
10
+ [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
11
+
12
+ function Get-Descriptor([string]$Target) {
13
+ return (Get-Acl -LiteralPath $Target).GetSecurityDescriptorSddlForm(
14
+ [Security.AccessControl.AccessControlSections]'Access,Owner,Group')
15
+ }
16
+
17
+ function Set-Descriptor([string]$Target, [string]$Sddl) {
18
+ $acl = Get-Acl -LiteralPath $Target
19
+ $acl.SetSecurityDescriptorSddlForm($Sddl, [Security.AccessControl.AccessControlSections]'Access,Owner,Group')
20
+ Set-Acl -LiteralPath $Target -AclObject $acl
21
+ }
22
+
23
+ function Add-Grant($Acl, [string]$Sid, [Security.AccessControl.FileSystemRights]$Rights, [bool]$Directory) {
24
+ $inheritance = if ($Directory) { [Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit' } else { [Security.AccessControl.InheritanceFlags]::None }
25
+ $rule = New-Object Security.AccessControl.FileSystemAccessRule(
26
+ (New-Object Security.Principal.SecurityIdentifier($Sid)), $Rights, $inheritance,
27
+ [Security.AccessControl.PropagationFlags]::None, [Security.AccessControl.AccessControlType]::Allow)
28
+ $Acl.AddAccessRule($rule)
29
+ }
30
+
31
+ function Grant-PipeAccess([string]$Target) {
32
+ $prefix = '\\.\pipe\'
33
+ if (-not $Target.StartsWith($prefix, [StringComparison]::OrdinalIgnoreCase)) {
34
+ throw 'Only a local named pipe can receive Codex sandbox access.'
35
+ }
36
+ $pipeName = $Target.Substring($prefix.Length)
37
+ if (-not $pipeName -or $pipeName.Contains('\') -or $pipeName.Contains('/')) {
38
+ throw 'Invalid local named pipe name.'
39
+ }
40
+ $accounts = @()
41
+ foreach ($name in @('CodexSandboxOffline', 'CodexSandboxOnline')) {
42
+ try {
43
+ $account = New-Object Security.Principal.NTAccount([Environment]::MachineName, $name)
44
+ $sid = $account.Translate([Security.Principal.SecurityIdentifier])
45
+ $accounts += @{ name = $name; sid = $sid }
46
+ } catch [Security.Principal.IdentityNotMappedException] {
47
+ # Codex creates these local users during sandbox provisioning. Do not
48
+ # replace a missing user with Everyone, Authenticated Users, or a group.
49
+ }
50
+ }
51
+ if ($accounts.Count -eq 0) { return @{ granted = @() } }
52
+ $pipe = New-Object System.IO.Pipes.NamedPipeClientStream('.', $pipeName,
53
+ [System.IO.Pipes.PipeAccessRights]'ReadWrite,ReadPermissions,ChangePermissions',
54
+ [System.IO.Pipes.PipeOptions]::Asynchronous,
55
+ [Security.Principal.TokenImpersonationLevel]::Identification,
56
+ [System.IO.HandleInheritability]::None)
57
+ try {
58
+ $pipe.Connect(5000)
59
+ $acl = $pipe.GetAccessControl()
60
+ $rights = [System.IO.Pipes.PipeAccessRights]'ReadWrite,Synchronize'
61
+ foreach ($account in $accounts) {
62
+ # GenericWrite/FullControl also grant CreateNewInstance on named pipes.
63
+ # Grant only data I/O to the actual restricted user; the sandbox group
64
+ # alone does not satisfy Windows restricted-token access checks.
65
+ $acl.AddAccessRule((New-Object System.IO.Pipes.PipeAccessRule(
66
+ $account.sid, $rights, [Security.AccessControl.AccessControlType]::Allow)))
67
+ }
68
+ $pipe.SetAccessControl($acl)
69
+ return @{ granted = @($accounts | ForEach-Object { $_.name }) }
70
+ } finally { $pipe.Dispose() }
71
+ }
72
+
73
+ function Initialize-AccessProbe {
74
+ # An elevated process reading the file is not evidence that a normal process
75
+ # can read it. Evaluate the DACL with its UAC linked token when available.
76
+ Add-Type -TypeDefinition @'
77
+ using System;
78
+ using System.Runtime.InteropServices;
79
+ using System.Security.Principal;
80
+ public static class EvolCoreAclProbe {
81
+ [StructLayout(LayoutKind.Sequential)]
82
+ struct Mapping { public uint Read, Write, Execute, All; }
83
+ [DllImport("advapi32.dll", SetLastError=true)]
84
+ static extern bool GetTokenInformation(IntPtr token, int type, out IntPtr linked, int size, out int returned);
85
+ [DllImport("advapi32.dll", SetLastError=true)]
86
+ static extern bool DuplicateTokenEx(IntPtr token, uint desiredAccess, IntPtr tokenAttributes,
87
+ int impersonationLevel, int tokenType, out IntPtr duplicate);
88
+ [DllImport("advapi32.dll", SetLastError=true)]
89
+ static extern bool AccessCheck(byte[] descriptor, IntPtr token, uint desired,
90
+ ref Mapping mapping, byte[] privileges, ref uint length, out uint granted, out bool allowed);
91
+ [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr handle);
92
+ public static string TokenKind;
93
+ public static long Granted(byte[] descriptor) {
94
+ using (var identity = WindowsIdentity.GetCurrent()) {
95
+ var principal = new WindowsPrincipal(identity);
96
+ IntPtr token = identity.Token, linked = IntPtr.Zero, duplicate = IntPtr.Zero;
97
+ try {
98
+ if (identity.IsSystem || principal.IsInRole(WindowsBuiltInRole.Administrator)) {
99
+ int size;
100
+ if (!GetTokenInformation(token, 19, out linked, IntPtr.Size, out size)) {
101
+ TokenKind = "unavailable";
102
+ return -1;
103
+ }
104
+ token = linked;
105
+ TokenKind = "linked-token";
106
+ } else { TokenKind = "current-token"; }
107
+ // AccessCheck only needs SecurityIdentification (1). A UAC linked
108
+ // token can be limited to that level, so requesting the higher
109
+ // SecurityImpersonation level fails with ERROR_BAD_IMPERSONATION_LEVEL.
110
+ if (!DuplicateTokenEx(token, 0x0000000A, IntPtr.Zero, 1, 2, out duplicate))
111
+ throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
112
+ var mapping = new Mapping { Read=0x120089, Write=0x120116, Execute=0x1200a0, All=0x1f01ff };
113
+ uint length=1024, granted;
114
+ bool allowed;
115
+ if (!AccessCheck(descriptor, duplicate, 0x02000000, ref mapping,
116
+ new byte[length], ref length, out granted, out allowed))
117
+ throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
118
+ return allowed ? granted : 0;
119
+ } finally {
120
+ if (duplicate != IntPtr.Zero) CloseHandle(duplicate);
121
+ if (linked != IntPtr.Zero) CloseHandle(linked);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ '@
127
+ }
128
+
129
+ function Verify-Access($Entry) {
130
+ $target = [string]$Entry.path
131
+ $acl = Get-Acl -LiteralPath $target
132
+ $read = [long][Security.AccessControl.FileSystemRights]::ReadAndExecute
133
+ $write = [long][Security.AccessControl.FileSystemRights]'Write,Delete,DeleteSubdirectoriesAndFiles,ChangePermissions,TakeOwnership'
134
+ if ($Entry.protected) {
135
+ $grants = @{}
136
+ foreach ($rule in $acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])) {
137
+ if (($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -ne 0) { continue }
138
+ $sid = $rule.IdentityReference.Value
139
+ $rights = [long]$rule.FileSystemRights
140
+ if ($sid -in @('S-1-1-0','S-1-5-11','S-1-5-32-545')) {
141
+ if ($rule.AccessControlType -eq 'Allow' -and ($rights -band $write) -ne 0) {
142
+ throw "Unsafe write permission on ${target}: $sid has $($rule.FileSystemRights). Existing policy was not removed."
143
+ }
144
+ if ($rule.AccessControlType -eq 'Deny' -and ($rights -band $read) -ne 0) {
145
+ throw "Read permission denied on ${target}: $sid. Existing policy was not removed."
146
+ }
147
+ }
148
+ if ($rule.AccessControlType -eq 'Allow') { $grants[$sid] = ([long]$grants[$sid]) -bor $rights }
149
+ }
150
+ foreach ($sid in @('S-1-5-18','S-1-5-32-544','S-1-5-32-545')) {
151
+ $required = if ($sid -eq 'S-1-5-32-545') { $read } else { [long][Security.AccessControl.FileSystemRights]::FullControl }
152
+ if ((([long]$grants[$sid]) -band $required) -ne $required) { throw "Missing required access on ${target}: $sid" }
153
+ }
154
+ }
155
+ $granted = [EvolCoreAclProbe]::Granted($acl.GetSecurityDescriptorBinaryForm())
156
+ if ($granted -ge 0) {
157
+ $required = if ($Entry.execute) { $read } else { [long][Security.AccessControl.FileSystemRights]::Read }
158
+ if (($granted -band $required) -ne $required) { throw "Normal-token read/execute access denied: $target" }
159
+ if ($Entry.protected -and ($granted -band $write) -ne 0) { throw "Normal token can modify the protected file or its ACL: $target" }
160
+ }
161
+ return @{ path = $target; userProbe = [EvolCoreAclProbe]::TokenKind }
162
+ }
163
+
164
+ try {
165
+ $payload = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Request)) | ConvertFrom-Json
166
+ $result = switch ($payload.action) {
167
+ 'pipe' { Grant-PipeAccess ([string]$payload.path) }
168
+ 'preflight' {
169
+ $principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
170
+ if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
171
+ throw 'Machine-wide Codex hook provisioning requires an elevated Windows installer. npm installation does not require this step.'
172
+ }
173
+ @{ elevated = $true }
174
+ }
175
+ 'snapshot' { @{ sddl = (Get-Descriptor $payload.path) } }
176
+ 'prepare' {
177
+ $target = [string]$payload.path
178
+ if ($payload.reference) {
179
+ # Same-directory staging preserves the shared configuration's owner,
180
+ # inherited policy and custom administrator ACEs. Never reset its ACL.
181
+ Set-Descriptor $target (Get-Descriptor $payload.reference)
182
+ } else {
183
+ $flags = if ($payload.directory) { 'OICI' } else { '' }
184
+ Set-Descriptor $target "O:BAG:BAD:P(A;${flags};FA;;;SY)(A;${flags};FA;;;BA)(A;${flags};FRFX;;;BU)"
185
+ }
186
+ $acl = Get-Acl -LiteralPath $target
187
+ Add-Grant $acl 'S-1-5-18' 'FullControl' ([bool]$payload.directory)
188
+ Add-Grant $acl 'S-1-5-32-544' 'FullControl' ([bool]$payload.directory)
189
+ Add-Grant $acl 'S-1-5-32-545' 'ReadAndExecute' ([bool]$payload.directory)
190
+ Set-Acl -LiteralPath $target -AclObject $acl
191
+ @{ prepared = $true }
192
+ }
193
+ 'verify' {
194
+ Initialize-AccessProbe
195
+ @($payload.entries | ForEach-Object { Verify-Access $_ })
196
+ }
197
+ default { throw "Unknown ACL operation: $($payload.action)" }
198
+ }
199
+ ConvertTo-Json -InputObject $result -Depth 8 -Compress
200
+ } catch {
201
+ [Console]::Error.WriteLine("[evolcore] ACL $($payload.action) failed for $($payload.path): $($_.Exception.Message)")
202
+ exit 1
203
+ }