@pixelbyte-software/pixcode 1.42.3 → 1.42.4

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 (31) hide show
  1. package/dist/assets/{index-BnaWRV1a.js → index-cTGs3Dvx.js} +72 -72
  2. package/dist/index.html +1 -1
  3. package/dist-server/server/claude-sdk.js +23 -2
  4. package/dist-server/server/claude-sdk.js.map +1 -1
  5. package/dist-server/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.js.map +1 -1
  6. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js +2 -0
  7. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js.map +1 -1
  8. package/dist-server/server/modules/orchestration/a2a/routes.js +2 -0
  9. package/dist-server/server/modules/orchestration/a2a/routes.js.map +1 -1
  10. package/dist-server/server/modules/orchestration/index.js +1 -0
  11. package/dist-server/server/modules/orchestration/index.js.map +1 -1
  12. package/dist-server/server/modules/orchestration/security/permission-policy.js +269 -0
  13. package/dist-server/server/modules/orchestration/security/permission-policy.js.map +1 -0
  14. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +115 -1
  15. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
  16. package/dist-server/server/modules/orchestration/workflows/workflow-trace.js +32 -0
  17. package/dist-server/server/modules/orchestration/workflows/workflow-trace.js.map +1 -1
  18. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js +103 -0
  19. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js.map +1 -1
  20. package/package.json +1 -1
  21. package/scripts/smoke/permission-policy.mjs +50 -0
  22. package/server/claude-sdk.js +24 -2
  23. package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +8 -0
  24. package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +2 -0
  25. package/server/modules/orchestration/a2a/routes.ts +6 -0
  26. package/server/modules/orchestration/index.ts +18 -0
  27. package/server/modules/orchestration/security/permission-policy.ts +401 -0
  28. package/server/modules/orchestration/workflows/workflow-runner.ts +141 -1
  29. package/server/modules/orchestration/workflows/workflow-trace.ts +32 -0
  30. package/server/modules/orchestration/workflows/workflow.routes.ts +121 -0
  31. package/server/modules/orchestration/workflows/workflow.types.ts +9 -1
@@ -9,6 +9,14 @@ import {
9
9
  import { workflowStore } from '@/modules/orchestration/workflows/workflow-store.js';
10
10
  import { buildWorkflowTrace } from '@/modules/orchestration/workflows/workflow-trace.js';
11
11
  import { findPixcodeAppRoot } from '@/modules/orchestration/workflows/workspace-target.js';
12
+ import {
13
+ DEFAULT_PERMISSION_POLICY,
14
+ PERMISSION_CAPABILITIES,
15
+ PERMISSION_POLICY_MODES,
16
+ PIXCODE_PERMISSION_POLICY_PROTOCOL,
17
+ evaluatePermissionRequest,
18
+ normalizePermissionPolicy,
19
+ } from '@/modules/orchestration/security/permission-policy.js';
12
20
 
13
21
  const TERMINAL_RUN_STATES = new Set(['completed', 'failed', 'canceled']);
14
22
 
@@ -73,6 +81,36 @@ function replayOptions(req: express.Request): {
73
81
  };
74
82
  }
75
83
 
84
+ function readRunArray(run: { metadata?: Record<string, unknown> }, key: string): Array<Record<string, unknown>> {
85
+ const value = run.metadata?.[key];
86
+ return Array.isArray(value)
87
+ ? value.filter((item): item is Record<string, unknown> => Boolean(item && typeof item === 'object'))
88
+ : [];
89
+ }
90
+
91
+ function updateApproval(
92
+ run: { metadata?: Record<string, unknown> },
93
+ requestId: string,
94
+ patch: Record<string, unknown>,
95
+ ): boolean {
96
+ const approvals = readRunArray(run, 'pendingPermissionApprovals');
97
+ let changed = false;
98
+ const nextApprovals = approvals.map((approval) => {
99
+ if (approval.id !== requestId) return approval;
100
+ changed = true;
101
+ return {
102
+ ...approval,
103
+ ...patch,
104
+ };
105
+ });
106
+ if (!changed) return false;
107
+ run.metadata = {
108
+ ...run.metadata,
109
+ pendingPermissionApprovals: nextApprovals,
110
+ };
111
+ return true;
112
+ }
113
+
76
114
  function sendRunSnapshot(res: express.Response, runId: string): boolean {
77
115
  const run = workflowStore.getRun(runId);
78
116
  if (!run) {
@@ -162,6 +200,89 @@ export function createWorkflowRouter(): Router {
162
200
  });
163
201
  });
164
202
 
203
+ router.get('/workflows/permission-policy', (_req, res) => {
204
+ res.json({
205
+ protocol: PIXCODE_PERMISSION_POLICY_PROTOCOL,
206
+ capabilities: PERMISSION_CAPABILITIES,
207
+ modes: PERMISSION_POLICY_MODES,
208
+ defaultPolicy: DEFAULT_PERMISSION_POLICY,
209
+ });
210
+ });
211
+
212
+ router.post('/workflows/permission-policy/evaluate', (req, res) => {
213
+ try {
214
+ res.json({
215
+ decision: evaluatePermissionRequest({
216
+ policy: normalizePermissionPolicy(req.body?.policy),
217
+ request: req.body?.request ?? { source: 'api' },
218
+ }),
219
+ });
220
+ } catch (error) {
221
+ res.status(400).json({
222
+ error: {
223
+ code: 'PERMISSION_POLICY_INVALID',
224
+ message: error instanceof Error ? error.message : String(error),
225
+ },
226
+ });
227
+ }
228
+ });
229
+
230
+ router.get('/workflows/runs/:runId/permission-approvals', (req, res) => {
231
+ const run = workflowStore.getRun(req.params.runId);
232
+ if (!run) {
233
+ res.status(404).json({ error: { code: 'RUN_NOT_FOUND', message: req.params.runId } });
234
+ return;
235
+ }
236
+
237
+ res.json({
238
+ runId: run.id,
239
+ pendingApprovals: readRunArray(run, 'pendingPermissionApprovals')
240
+ .filter((approval) => approval.status === 'pending'),
241
+ approvalHistory: readRunArray(run, 'pendingPermissionApprovals')
242
+ .filter((approval) => approval.status !== 'pending'),
243
+ });
244
+ });
245
+
246
+ router.post('/workflows/runs/:runId/permission-approvals/:requestId', (req, res) => {
247
+ const run = workflowStore.getRun(req.params.runId);
248
+ if (!run) {
249
+ res.status(404).json({ error: { code: 'RUN_NOT_FOUND', message: req.params.runId } });
250
+ return;
251
+ }
252
+
253
+ const allow = req.body?.allow === true;
254
+ const deny = req.body?.allow === false;
255
+ if (!allow && !deny) {
256
+ res.status(400).json({
257
+ error: {
258
+ code: 'PERMISSION_DECISION_REQUIRED',
259
+ message: 'Permission approval requires allow=true or allow=false.',
260
+ },
261
+ });
262
+ return;
263
+ }
264
+
265
+ const updated = updateApproval(run, req.params.requestId, {
266
+ status: allow ? 'allowed' : 'denied',
267
+ resolvedAt: Date.now(),
268
+ resolvedBy: readRequestUserId(req),
269
+ resolutionMessage: readOptionalString(req.body?.message),
270
+ });
271
+ if (!updated) {
272
+ res.status(404).json({ error: { code: 'APPROVAL_NOT_FOUND', message: req.params.requestId } });
273
+ return;
274
+ }
275
+
276
+ workflowStore.setRun(run);
277
+ res.json({
278
+ runId: run.id,
279
+ pendingApprovals: readRunArray(run, 'pendingPermissionApprovals')
280
+ .filter((approval) => approval.status === 'pending'),
281
+ approvalHistory: readRunArray(run, 'pendingPermissionApprovals')
282
+ .filter((approval) => approval.status !== 'pending'),
283
+ });
284
+ });
285
+
165
286
  router.get('/workflows/runs/:runId/replay-plan', (req, res) => {
166
287
  const run = workflowStore.getRun(req.params.runId);
167
288
  if (!run) {
@@ -1,6 +1,10 @@
1
1
  import type { WorkflowContextPacket } from '@/modules/orchestration/workflows/context-packet.js';
2
2
  import type { WorkflowFallbackTrigger } from '@/modules/orchestration/workflows/workflow-fallback-policy.js';
3
3
  import type { WorkflowHandoffArtifact } from '@/modules/orchestration/workflows/handoff-artifact.js';
4
+ import type {
5
+ PermissionDecision,
6
+ PermissionPolicy,
7
+ } from '@/modules/orchestration/security/permission-policy.js';
4
8
 
5
9
  export type WorkflowRunStatus = 'queued' | 'running' | 'completed' | 'failed' | 'canceled';
6
10
  export type WorkflowNodeStatus = WorkflowRunStatus | 'skipped';
@@ -18,6 +22,8 @@ export interface WorkflowNode {
18
22
  assignment?: string;
19
23
  model?: string;
20
24
  permissionMode?: string;
25
+ permissionPolicy?: PermissionPolicy;
26
+ permissionDecisions?: PermissionDecision[];
21
27
  toolsSettings?: Record<string, unknown>;
22
28
  isolation?: 'host' | 'worktree' | 'docker';
23
29
  timeoutMs?: number;
@@ -44,6 +50,8 @@ export interface WorkflowNodeRun {
44
50
  promptPreview?: string;
45
51
  model?: string;
46
52
  permissionMode?: string;
53
+ permissionPolicy?: PermissionPolicy;
54
+ permissionDecisions?: PermissionDecision[];
47
55
  timeoutMs?: number;
48
56
  stage?: string;
49
57
  internal?: boolean;
@@ -84,7 +92,7 @@ export interface WorkflowRun {
84
92
 
85
93
  export interface WorkflowTraceEvent {
86
94
  id: string;
87
- type: 'run' | 'node' | 'provider' | 'message' | 'artifact' | 'file' | 'error';
95
+ type: 'run' | 'node' | 'provider' | 'message' | 'artifact' | 'file' | 'error' | 'permission_policy';
88
96
  severity: 'info' | 'warning' | 'error';
89
97
  status: WorkflowRunStatus | WorkflowNodeStatus | 'submitted';
90
98
  timestamp: number;