@jungjaehoon/mama-os 0.32.0 → 0.32.1

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 (173) hide show
  1. package/dist/agent/agent-loop.d.ts +5 -1
  2. package/dist/agent/agent-loop.d.ts.map +1 -1
  3. package/dist/agent/agent-loop.js +62 -49
  4. package/dist/agent/agent-loop.js.map +1 -1
  5. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  6. package/dist/agent/code-act/host-bridge.js +35 -74
  7. package/dist/agent/code-act/host-bridge.js.map +1 -1
  8. package/dist/agent/gateway-tool-catalog.d.ts +14 -0
  9. package/dist/agent/gateway-tool-catalog.d.ts.map +1 -0
  10. package/dist/agent/gateway-tool-catalog.js +41 -0
  11. package/dist/agent/gateway-tool-catalog.js.map +1 -0
  12. package/dist/agent/gateway-tool-executor.d.ts +12 -1
  13. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  14. package/dist/agent/gateway-tool-executor.js +149 -15
  15. package/dist/agent/gateway-tool-executor.js.map +1 -1
  16. package/dist/agent/gateway-tools.md +5 -7
  17. package/dist/agent/tool-registry.d.ts +6 -4
  18. package/dist/agent/tool-registry.d.ts.map +1 -1
  19. package/dist/agent/tool-registry.js +62 -30
  20. package/dist/agent/tool-registry.js.map +1 -1
  21. package/dist/agent/types.d.ts +18 -2
  22. package/dist/agent/types.d.ts.map +1 -1
  23. package/dist/agent/types.js.map +1 -1
  24. package/dist/api/index.d.ts +10 -0
  25. package/dist/api/index.d.ts.map +1 -1
  26. package/dist/api/index.js +7 -16
  27. package/dist/api/index.js.map +1 -1
  28. package/dist/cli/commands/connector.d.ts +6 -1
  29. package/dist/cli/commands/connector.d.ts.map +1 -1
  30. package/dist/cli/commands/connector.js +61 -45
  31. package/dist/cli/commands/connector.js.map +1 -1
  32. package/dist/cli/commands/start.d.ts +11 -8
  33. package/dist/cli/commands/start.d.ts.map +1 -1
  34. package/dist/cli/commands/start.js +155 -88
  35. package/dist/cli/commands/start.js.map +1 -1
  36. package/dist/cli/config/types.d.ts.map +1 -1
  37. package/dist/cli/config/types.js +0 -4
  38. package/dist/cli/config/types.js.map +1 -1
  39. package/dist/cli/runtime/api-routes-init.d.ts +38 -1
  40. package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
  41. package/dist/cli/runtime/api-routes-init.js +150 -30
  42. package/dist/cli/runtime/api-routes-init.js.map +1 -1
  43. package/dist/cli/runtime/api-server-init.d.ts +4 -0
  44. package/dist/cli/runtime/api-server-init.d.ts.map +1 -1
  45. package/dist/cli/runtime/api-server-init.js +3 -1
  46. package/dist/cli/runtime/api-server-init.js.map +1 -1
  47. package/dist/cli/runtime/connector-bootstrap.d.ts +8 -0
  48. package/dist/cli/runtime/connector-bootstrap.d.ts.map +1 -0
  49. package/dist/cli/runtime/connector-bootstrap.js +14 -0
  50. package/dist/cli/runtime/connector-bootstrap.js.map +1 -0
  51. package/dist/cli/runtime/connector-init.d.ts +4 -1
  52. package/dist/cli/runtime/connector-init.d.ts.map +1 -1
  53. package/dist/cli/runtime/connector-init.js +2 -8
  54. package/dist/cli/runtime/connector-init.js.map +1 -1
  55. package/dist/cli/runtime/envelope-bootstrap.d.ts +2 -1
  56. package/dist/cli/runtime/envelope-bootstrap.d.ts.map +1 -1
  57. package/dist/cli/runtime/envelope-bootstrap.js +7 -15
  58. package/dist/cli/runtime/envelope-bootstrap.js.map +1 -1
  59. package/dist/connectors/index.d.ts +4 -1
  60. package/dist/connectors/index.d.ts.map +1 -1
  61. package/dist/connectors/index.js +3 -2
  62. package/dist/connectors/index.js.map +1 -1
  63. package/dist/connectors/private-connector-policy.d.ts +150 -0
  64. package/dist/connectors/private-connector-policy.d.ts.map +1 -0
  65. package/dist/connectors/private-connector-policy.js +289 -0
  66. package/dist/connectors/private-connector-policy.js.map +1 -0
  67. package/dist/connectors/private-prompt-overlay.d.ts +17 -0
  68. package/dist/connectors/private-prompt-overlay.d.ts.map +1 -0
  69. package/dist/connectors/private-prompt-overlay.js +156 -0
  70. package/dist/connectors/private-prompt-overlay.js.map +1 -0
  71. package/dist/db/migrations/operator-task-external-lifecycle.d.ts +8 -0
  72. package/dist/db/migrations/operator-task-external-lifecycle.d.ts.map +1 -0
  73. package/dist/db/migrations/operator-task-external-lifecycle.js +169 -0
  74. package/dist/db/migrations/operator-task-external-lifecycle.js.map +1 -0
  75. package/dist/envelope/enforcer.js +8 -7
  76. package/dist/envelope/enforcer.js.map +1 -1
  77. package/dist/envelope/reactive-config.d.ts.map +1 -1
  78. package/dist/envelope/reactive-config.js +2 -1
  79. package/dist/envelope/reactive-config.js.map +1 -1
  80. package/dist/envelope/tool-connector-scope.d.ts.map +1 -1
  81. package/dist/envelope/tool-connector-scope.js +4 -0
  82. package/dist/envelope/tool-connector-scope.js.map +1 -1
  83. package/dist/gateways/message-router.d.ts +11 -1
  84. package/dist/gateways/message-router.d.ts.map +1 -1
  85. package/dist/gateways/message-router.js +121 -41
  86. package/dist/gateways/message-router.js.map +1 -1
  87. package/dist/gateways/telegram-message-ledger.d.ts +8 -1
  88. package/dist/gateways/telegram-message-ledger.d.ts.map +1 -1
  89. package/dist/gateways/telegram-message-ledger.js +141 -24
  90. package/dist/gateways/telegram-message-ledger.js.map +1 -1
  91. package/dist/gateways/telegram.d.ts +2 -0
  92. package/dist/gateways/telegram.d.ts.map +1 -1
  93. package/dist/gateways/telegram.js +19 -12
  94. package/dist/gateways/telegram.js.map +1 -1
  95. package/dist/multi-agent/agent-process-manager.d.ts +9 -1
  96. package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
  97. package/dist/multi-agent/agent-process-manager.js +48 -20
  98. package/dist/multi-agent/agent-process-manager.js.map +1 -1
  99. package/dist/multi-agent/dashboard-agent-persona.d.ts +3 -3
  100. package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
  101. package/dist/multi-agent/dashboard-agent-persona.js +10 -13
  102. package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
  103. package/dist/multi-agent/memory-agent-persona.d.ts +1 -1
  104. package/dist/multi-agent/memory-agent-persona.d.ts.map +1 -1
  105. package/dist/multi-agent/memory-agent-persona.js +1 -1
  106. package/dist/multi-agent/wiki-agent-persona.d.ts +2 -2
  107. package/dist/multi-agent/wiki-agent-persona.js +2 -2
  108. package/dist/operator/board-slot-instructions.d.ts +1 -1
  109. package/dist/operator/board-slot-instructions.js +2 -2
  110. package/dist/operator/board-slot-instructions.js.map +1 -1
  111. package/dist/operator/briefs.d.ts +3 -0
  112. package/dist/operator/briefs.d.ts.map +1 -1
  113. package/dist/operator/briefs.js +64 -3
  114. package/dist/operator/briefs.js.map +1 -1
  115. package/dist/operator/console-brief.d.ts +6 -3
  116. package/dist/operator/console-brief.d.ts.map +1 -1
  117. package/dist/operator/console-brief.js +39 -9
  118. package/dist/operator/console-brief.js.map +1 -1
  119. package/dist/operator/external-lifecycle-candidates.d.ts +56 -0
  120. package/dist/operator/external-lifecycle-candidates.d.ts.map +1 -0
  121. package/dist/operator/external-lifecycle-candidates.js +415 -0
  122. package/dist/operator/external-lifecycle-candidates.js.map +1 -0
  123. package/dist/operator/external-lifecycle.d.ts +82 -0
  124. package/dist/operator/external-lifecycle.d.ts.map +1 -0
  125. package/dist/operator/external-lifecycle.js +27 -0
  126. package/dist/operator/external-lifecycle.js.map +1 -0
  127. package/dist/operator/file-coordination.d.ts +7 -0
  128. package/dist/operator/file-coordination.d.ts.map +1 -0
  129. package/dist/operator/file-coordination.js +84 -0
  130. package/dist/operator/file-coordination.js.map +1 -0
  131. package/dist/operator/operator-trigger-loop.d.ts +19 -4
  132. package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
  133. package/dist/operator/operator-trigger-loop.js +151 -23
  134. package/dist/operator/operator-trigger-loop.js.map +1 -1
  135. package/dist/operator/pending-report-store.d.ts +62 -3
  136. package/dist/operator/pending-report-store.d.ts.map +1 -1
  137. package/dist/operator/pending-report-store.js +297 -40
  138. package/dist/operator/pending-report-store.js.map +1 -1
  139. package/dist/operator/report-carry-delivery.d.ts +35 -0
  140. package/dist/operator/report-carry-delivery.d.ts.map +1 -0
  141. package/dist/operator/report-carry-delivery.js +55 -0
  142. package/dist/operator/report-carry-delivery.js.map +1 -0
  143. package/dist/operator/report-carry.d.ts +50 -30
  144. package/dist/operator/report-carry.d.ts.map +1 -1
  145. package/dist/operator/report-carry.js +323 -71
  146. package/dist/operator/report-carry.js.map +1 -1
  147. package/dist/operator/situation-report.d.ts +30 -11
  148. package/dist/operator/situation-report.d.ts.map +1 -1
  149. package/dist/operator/situation-report.js +42 -13
  150. package/dist/operator/situation-report.js.map +1 -1
  151. package/dist/operator/task-ledger.d.ts +101 -0
  152. package/dist/operator/task-ledger.d.ts.map +1 -1
  153. package/dist/operator/task-ledger.js +599 -124
  154. package/dist/operator/task-ledger.js.map +1 -1
  155. package/dist/operator/temporal-worker.js +1 -1
  156. package/dist/operator/worker-run.d.ts +1 -1
  157. package/dist/operator/worker-run.d.ts.map +1 -1
  158. package/dist/operator/worker-run.js +17 -5
  159. package/dist/operator/worker-run.js.map +1 -1
  160. package/dist/operator/workorder-consumer.d.ts +12 -1
  161. package/dist/operator/workorder-consumer.d.ts.map +1 -1
  162. package/dist/operator/workorder-consumer.js +125 -6
  163. package/dist/operator/workorder-consumer.js.map +1 -1
  164. package/dist/operator/workorder-hooks.d.ts +7 -2
  165. package/dist/operator/workorder-hooks.d.ts.map +1 -1
  166. package/dist/operator/workorder-hooks.js +22 -0
  167. package/dist/operator/workorder-hooks.js.map +1 -1
  168. package/dist/operator/workorder-publishers.d.ts +9 -2
  169. package/dist/operator/workorder-publishers.d.ts.map +1 -1
  170. package/dist/operator/workorder-publishers.js +167 -5
  171. package/dist/operator/workorder-publishers.js.map +1 -1
  172. package/package.json +2 -2
  173. package/scripts/generate-gateway-tools.ts +13 -3
@@ -68,6 +68,7 @@ const image_translation_tools_js_1 = require("./image-translation-tools.js");
68
68
  const attachment_text_extractor_js_1 = require("./attachment-text-extractor.js");
69
69
  const untrusted_content_js_1 = require("../utils/untrusted-content.js");
70
70
  const types_js_1 = require("./types.js");
71
+ const external_lifecycle_candidates_js_1 = require("../operator/external-lifecycle-candidates.js");
71
72
  const sqlite_js_1 = __importDefault(require("../sqlite.js"));
72
73
  const mama_tool_handlers_js_1 = require("./mama-tool-handlers.js");
73
74
  const role_manager_js_1 = require("./role-manager.js");
@@ -77,6 +78,12 @@ const index_js_1 = require("../envelope/index.js");
77
78
  const wiki_publish_adapter_js_1 = require("../wiki-artifacts/wiki-publish-adapter.js");
78
79
  const changes_projection_js_1 = require("../operator/changes-projection.js");
79
80
  const read_js_1 = require("../evidence/read.js");
81
+ const private_connector_policy_js_1 = require("../connectors/private-connector-policy.js");
82
+ const DEFAULT_PRIVATE_CONNECTOR_POLICY = (0, private_connector_policy_js_1.resolvePrivateConnectorPolicy)({
83
+ ok: true,
84
+ config: {},
85
+ enabledNames: [],
86
+ });
80
87
  function serializeTaskToolRecord(task) {
81
88
  return {
82
89
  ...task,
@@ -360,6 +367,7 @@ class GatewayToolExecutor {
360
367
  slackGateway = null;
361
368
  telegramGateway = null;
362
369
  roleManager;
370
+ privateConnectorPolicy;
363
371
  executionContextStorage = new async_hooks_1.AsyncLocalStorage();
364
372
  envelopeEnforcer = new index_js_1.EnvelopeEnforcer();
365
373
  channelGrantProvider;
@@ -592,6 +600,8 @@ class GatewayToolExecutor {
592
600
  this.wikiPublishAdapter = options.wikiPublishAdapter ?? null;
593
601
  // Pass rolesConfig from config.yaml to RoleManager
594
602
  this.roleManager = (0, role_manager_js_1.getRoleManager)(options.rolesConfig ? { rolesConfig: options.rolesConfig } : undefined);
603
+ this.privateConnectorPolicy =
604
+ options.privateConnectorPolicy ?? DEFAULT_PRIVATE_CONNECTOR_POLICY;
595
605
  if (options.mamaApi) {
596
606
  this.mamaApi = options.mamaApi;
597
607
  }
@@ -721,26 +731,34 @@ class GatewayToolExecutor {
721
731
  * @returns Object with allowed status and optional error message
722
732
  */
723
733
  checkToolPermission(toolName) {
724
- // If no context set, allow all tools (backward compatibility)
725
734
  const context = this.getActiveContext();
726
- if (!context) {
727
- if (toolName === 'code_act') {
728
- return {
729
- allowed: false,
730
- error: 'Permission denied: code_act requires an active agent role',
731
- };
732
- }
733
- return { allowed: true };
735
+ if (!context && toolName === 'code_act') {
736
+ return {
737
+ allowed: false,
738
+ error: 'Permission denied: code_act requires an active agent role',
739
+ };
734
740
  }
735
- const role = context.role;
741
+ const role = context
742
+ ? this.projectPrivateAgentContext(context).role
743
+ : this.privateConnectorPolicy.projectRole('legacy-unbound', { allowedTools: ['*'] });
736
744
  if (!this.roleManager.isToolAllowed(role, toolName)) {
737
745
  return {
738
746
  allowed: false,
739
- error: `Permission denied: ${toolName} is not allowed for role "${context.roleName}"`,
747
+ error: `Permission denied: ${toolName} is not allowed for role "${context?.roleName ?? 'legacy-unbound'}"`,
740
748
  };
741
749
  }
742
750
  return { allowed: true };
743
751
  }
752
+ projectPrivateAgentContext(context) {
753
+ const surface = (0, private_connector_policy_js_1.resolvePrivatePrincipalSurface)({ agentContext: context });
754
+ const role = this.privateConnectorPolicy.projectRole(surface, context.role);
755
+ return {
756
+ ...context,
757
+ role,
758
+ capabilities: this.roleManager.getCapabilities(role),
759
+ limitations: this.roleManager.getLimitations(role),
760
+ };
761
+ }
744
762
  /**
745
763
  * Check if a path is allowed for the current context
746
764
  * @param path - File path to check
@@ -1004,6 +1022,35 @@ class GatewayToolExecutor {
1004
1022
  }
1005
1023
  return result;
1006
1024
  }
1025
+ /**
1026
+ * External lifecycle decisions are only valid while the host-created model run that owns the
1027
+ * claimed board attempt is still running. Tool input cannot name either authority.
1028
+ */
1029
+ async requireExternalLifecycleModelRun(attemptId) {
1030
+ const modelRunId = this.getExecutionState().modelRunId;
1031
+ if (typeof modelRunId !== 'string' ||
1032
+ modelRunId.trim().length === 0 ||
1033
+ modelRunId.trim() !== modelRunId) {
1034
+ throw new types_js_1.AgentError('External lifecycle authority requires a current host-issued model run', 'WORKORDER_SUPERSEDED', undefined, false);
1035
+ }
1036
+ const api = await this.initializeMAMAApi();
1037
+ if (!api.getModelRun) {
1038
+ throw new types_js_1.AgentError('External lifecycle model-run authority is unavailable', 'WORKORDER_SUPERSEDED', undefined, false);
1039
+ }
1040
+ let modelRun;
1041
+ try {
1042
+ modelRun = await api.getModelRun(modelRunId);
1043
+ }
1044
+ catch (error) {
1045
+ throw new types_js_1.AgentError('External lifecycle model-run authority could not be verified', 'WORKORDER_SUPERSEDED', error instanceof Error ? error : undefined, false);
1046
+ }
1047
+ if (!modelRun ||
1048
+ modelRun.status !== 'running' ||
1049
+ modelRun.input_refs?.workorderAttemptId !== attemptId) {
1050
+ throw new types_js_1.AgentError('External lifecycle authority is no longer current for this claimed attempt', 'WORKORDER_SUPERSEDED', undefined, false);
1051
+ }
1052
+ return modelRunId;
1053
+ }
1007
1054
  async beginTraceIfNeeded(ctx, gatewayCallId) {
1008
1055
  if (ctx.modelRunId) {
1009
1056
  const api = await this.initializeMAMAApi();
@@ -1445,7 +1492,7 @@ class GatewayToolExecutor {
1445
1492
  async executeWithEnvelopeAndPermissions(toolName, input, gatewayCallId) {
1446
1493
  this.getExecutionState().signal?.throwIfAborted();
1447
1494
  if (!VALID_TOOLS.includes(toolName)) {
1448
- throw new types_js_1.AgentError(`Unknown tool: ${toolName}. Valid tools: ${VALID_TOOLS.join(', ')}`, 'UNKNOWN_TOOL', undefined, false);
1495
+ throw new types_js_1.AgentError(`Unknown tool: ${toolName}`, 'UNKNOWN_TOOL', undefined, false);
1449
1496
  }
1450
1497
  if (toolName.startsWith('drive_') &&
1451
1498
  this.getExecutionState().agentContext?.roleName !== 'owner_console') {
@@ -2063,6 +2110,84 @@ class GatewayToolExecutor {
2063
2110
  };
2064
2111
  }
2065
2112
  }
2113
+ case 'task_external_bind': {
2114
+ if (!this.taskLedger) {
2115
+ return { success: false, error: 'Task ledger not configured' };
2116
+ }
2117
+ const state = this.getExecutionState();
2118
+ const attemptId = state.workorderAttemptId;
2119
+ if (attemptId === undefined || !Number.isSafeInteger(attemptId) || attemptId <= 0) {
2120
+ throw new types_js_1.AgentError('task_external_bind requires a trusted claimed board attempt', 'WORKORDER_SUPERSEDED', undefined, false);
2121
+ }
2122
+ try {
2123
+ (0, external_lifecycle_candidates_js_1.validateExternalLifecycleDecision)('binding', input);
2124
+ }
2125
+ catch (error) {
2126
+ throw new types_js_1.AgentError(error instanceof Error ? error.message : 'task_external_bind input is invalid', 'TOOL_ERROR', error instanceof Error ? error : undefined, false);
2127
+ }
2128
+ const modelRunId = await this.requireExternalLifecycleModelRun(attemptId);
2129
+ let candidate;
2130
+ try {
2131
+ candidate = this.taskLedger.loadBoardCandidate(attemptId, input.candidate_id, 'binding');
2132
+ }
2133
+ catch (error) {
2134
+ throw new types_js_1.AgentError(error instanceof Error
2135
+ ? error.message
2136
+ : 'task_external_bind candidate is unavailable', 'WORKORDER_SUPERSEDED', error instanceof Error ? error : undefined, false);
2137
+ }
2138
+ const receipt = this.taskLedger.applyExternalBindingDecision(attemptId, input, {
2139
+ runId: modelRunId,
2140
+ workOrderAttemptId: attemptId,
2141
+ causeEventIds: [candidate.eventId],
2142
+ });
2143
+ return {
2144
+ success: true,
2145
+ receipt: {
2146
+ taskId: receipt.taskId,
2147
+ workorderAttemptId: receipt.workOrderAttemptId,
2148
+ outcome: receipt.outcome,
2149
+ },
2150
+ };
2151
+ }
2152
+ case 'task_lifecycle_reconcile': {
2153
+ if (!this.taskLedger) {
2154
+ return { success: false, error: 'Task ledger not configured' };
2155
+ }
2156
+ const state = this.getExecutionState();
2157
+ const attemptId = state.workorderAttemptId;
2158
+ if (attemptId === undefined || !Number.isSafeInteger(attemptId) || attemptId <= 0) {
2159
+ throw new types_js_1.AgentError('task_lifecycle_reconcile requires a trusted claimed board attempt', 'WORKORDER_SUPERSEDED', undefined, false);
2160
+ }
2161
+ try {
2162
+ (0, external_lifecycle_candidates_js_1.validateExternalLifecycleDecision)('lifecycle', input);
2163
+ }
2164
+ catch (error) {
2165
+ throw new types_js_1.AgentError(error instanceof Error ? error.message : 'task_lifecycle_reconcile input is invalid', 'TOOL_ERROR', error instanceof Error ? error : undefined, false);
2166
+ }
2167
+ const modelRunId = await this.requireExternalLifecycleModelRun(attemptId);
2168
+ let candidate;
2169
+ try {
2170
+ candidate = this.taskLedger.loadBoardCandidate(attemptId, input.candidate_id, 'lifecycle');
2171
+ }
2172
+ catch (error) {
2173
+ throw new types_js_1.AgentError(error instanceof Error
2174
+ ? error.message
2175
+ : 'task_lifecycle_reconcile candidate is unavailable', 'WORKORDER_SUPERSEDED', error instanceof Error ? error : undefined, false);
2176
+ }
2177
+ const receipt = this.taskLedger.applyExternalLifecycleDecision(attemptId, input, {
2178
+ runId: modelRunId,
2179
+ workOrderAttemptId: attemptId,
2180
+ causeEventIds: [candidate.eventId],
2181
+ });
2182
+ return {
2183
+ success: true,
2184
+ receipt: {
2185
+ taskId: receipt.taskId,
2186
+ workorderAttemptId: receipt.workOrderAttemptId,
2187
+ outcome: receipt.outcome,
2188
+ },
2189
+ };
2190
+ }
2066
2191
  case 'task_create': {
2067
2192
  if (!this.taskLedger) {
2068
2193
  return { success: false, error: 'Task ledger not configured' };
@@ -2075,6 +2200,7 @@ class GatewayToolExecutor {
2075
2200
  // else's work with it.
2076
2201
  this.taskLedger.create(input, {
2077
2202
  runId: this.getExecutionState().modelRunId ?? null,
2203
+ workOrderAttemptId: this.getExecutionState().workorderAttemptId,
2078
2204
  causeEventIds: this.getExecutionState().causeEventIds,
2079
2205
  causeKind: this.getExecutionState().source === 'operator' ? 'clock' : 'owner_message',
2080
2206
  })),
@@ -2092,6 +2218,7 @@ class GatewayToolExecutor {
2092
2218
  }
2093
2219
  const updated = this.taskLedger.update(id, patch, {
2094
2220
  runId: this.getExecutionState().modelRunId ?? null,
2221
+ workOrderAttemptId: this.getExecutionState().workorderAttemptId,
2095
2222
  // The batch this run was handed. A bounded run's changes rest on the delta it
2096
2223
  // was given, and the system knew that before the run began - so there is
2097
2224
  // nothing to ask the agent for.
@@ -2847,14 +2974,17 @@ class GatewayToolExecutor {
2847
2974
  const { CodeActSandbox, CodeActToolPolicyValidationError, CODE_ACT_MUTATION_COMMITTED_AFTER_ABORT, CODE_ACT_MUTATION_OUTCOME_UNKNOWN, HostBridge, projectCodeActToolPolicy, } = await import('./code-act/index.js');
2848
2975
  const sandbox = new CodeActSandbox();
2849
2976
  const state = this.getExecutionState();
2850
- const contextTier = state.agentContext?.tier;
2977
+ const projectedAgentContext = state.agentContext
2978
+ ? this.projectPrivateAgentContext(state.agentContext)
2979
+ : undefined;
2980
+ const contextTier = projectedAgentContext?.tier;
2851
2981
  const tier = contextTier === undefined ? 1 : contextTier;
2852
2982
  let policy;
2853
2983
  try {
2854
2984
  policy = projectCodeActToolPolicy({
2855
2985
  tier,
2856
- roleName: state.agentContext?.roleName,
2857
- role: state.agentContext?.role,
2986
+ roleName: projectedAgentContext?.roleName,
2987
+ role: projectedAgentContext?.role,
2858
2988
  disallowedTools: state.disallowedGatewayTools,
2859
2989
  requestedAllowedTools: input.allowedTools,
2860
2990
  requestedBlockedTools: input.blockedTools,
@@ -2878,6 +3008,10 @@ class GatewayToolExecutor {
2878
3008
  }
2879
3009
  const nestedExecutionContext = {
2880
3010
  ...state,
3011
+ // Preserve the registry-supplied principal object as provenance. The
3012
+ // policy above and every nested final authorization re-project it from
3013
+ // the immutable boot snapshot; replacing the object would blur which
3014
+ // trusted context the keyed call actually carried.
2881
3015
  agentContext: state.agentContext ?? undefined,
2882
3016
  executionSurface: 'code_act',
2883
3017
  parentToolName: 'code_act',