@vellumai/credential-executor 0.10.7 → 0.10.8-dev.202607102228.5945895

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 (65) hide show
  1. package/Dockerfile +1 -1
  2. package/node_modules/@vellumai/service-contracts/package.json +1 -2
  3. package/node_modules/@vellumai/service-contracts/src/__tests__/attachment-naming.test.ts +104 -0
  4. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +0 -2
  5. package/node_modules/@vellumai/service-contracts/src/attachment-naming.ts +118 -0
  6. package/node_modules/@vellumai/service-contracts/src/credential-rpc.ts +3 -5
  7. package/node_modules/@vellumai/service-contracts/src/index.ts +2 -4
  8. package/node_modules/@vellumai/service-contracts/src/rpc.ts +4 -447
  9. package/package.json +2 -3
  10. package/src/__tests__/bulk-set-credentials.test.ts +1 -1
  11. package/src/__tests__/local-standalone.test.ts +5 -36
  12. package/src/__tests__/managed-integration.test.ts +112 -91
  13. package/src/__tests__/managed-reconnect.test.ts +2 -2
  14. package/src/__tests__/transport.test.ts +23 -27
  15. package/src/cli.ts +1 -1
  16. package/src/index.ts +8 -88
  17. package/src/main.ts +228 -340
  18. package/src/paths.ts +4 -20
  19. package/src/server.ts +52 -469
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/grants.test.ts +0 -686
  21. package/node_modules/@vellumai/service-contracts/src/grants.ts +0 -184
  22. package/node_modules/@vellumai/service-contracts/src/rendering.ts +0 -135
  23. package/src/__tests__/command-executor.test.ts +0 -1879
  24. package/src/__tests__/command-validator.test.ts +0 -1405
  25. package/src/__tests__/command-workspace.test.ts +0 -1050
  26. package/src/__tests__/grant-store.test.ts +0 -689
  27. package/src/__tests__/http-executor.test.ts +0 -1336
  28. package/src/__tests__/http-policy.test.ts +0 -1069
  29. package/src/__tests__/local-materializers.test.ts +0 -860
  30. package/src/__tests__/local-token-refresh.test.ts +0 -361
  31. package/src/__tests__/manage-secure-command-tool.test.ts +0 -134
  32. package/src/__tests__/managed-lazy-getters.test.ts +0 -359
  33. package/src/__tests__/managed-materializers.test.ts +0 -1028
  34. package/src/__tests__/managed-rejection.test.ts +0 -43
  35. package/src/__tests__/toolstore.test.ts +0 -773
  36. package/src/audit/store.ts +0 -188
  37. package/src/commands/auth-adapters.ts +0 -169
  38. package/src/commands/egress-hooks.ts +0 -203
  39. package/src/commands/executor.ts +0 -1155
  40. package/src/commands/output-scan.ts +0 -157
  41. package/src/commands/profiles.ts +0 -286
  42. package/src/commands/validator.ts +0 -702
  43. package/src/commands/workspace.ts +0 -550
  44. package/src/grants/index.ts +0 -17
  45. package/src/grants/persistent-store.ts +0 -309
  46. package/src/grants/rpc-handlers.ts +0 -293
  47. package/src/grants/temporary-store.ts +0 -289
  48. package/src/http/audit.ts +0 -84
  49. package/src/http/executor.ts +0 -684
  50. package/src/http/path-template.ts +0 -245
  51. package/src/http/policy.ts +0 -238
  52. package/src/http/response-filter.ts +0 -233
  53. package/src/managed-errors.ts +0 -9
  54. package/src/managed-lazy-getters.ts +0 -106
  55. package/src/managed-main.ts +0 -822
  56. package/src/materializers/local-oauth-lookup.ts +0 -98
  57. package/src/materializers/local-token-refresh.ts +0 -287
  58. package/src/materializers/local.ts +0 -316
  59. package/src/materializers/managed-platform.ts +0 -295
  60. package/src/subjects/local.ts +0 -177
  61. package/src/subjects/managed.ts +0 -311
  62. package/src/subjects/policy.ts +0 -79
  63. package/src/toolstore/integrity.ts +0 -94
  64. package/src/toolstore/manifest.ts +0 -154
  65. package/src/toolstore/publish.ts +0 -571
@@ -1,184 +0,0 @@
1
- /**
2
- * CES grant proposal, grant record, and audit record schemas.
3
- *
4
- * These schemas define the wire format for:
5
- * - HTTP grant proposals (requesting permission to make an authenticated HTTP call)
6
- * - Command grant proposals (requesting permission to run an authenticated command)
7
- * - Temporary grant decisions (approval/denial from a guardian)
8
- * - Persistent grant records (stored by CES after approval)
9
- * - Audit record summaries (materialization events)
10
- */
11
-
12
- import { z } from "zod";
13
-
14
- // ---------------------------------------------------------------------------
15
- // Grant proposal types
16
- // ---------------------------------------------------------------------------
17
-
18
- /**
19
- * Proposal to make an authenticated HTTP request using a credential.
20
- */
21
- export const HttpGrantProposalSchema = z.object({
22
- type: z.literal("http"),
23
- /** CES credential handle identifying which credential to use. */
24
- credentialHandle: z.string(),
25
- /** HTTP method (e.g. "GET", "POST"). */
26
- method: z.string(),
27
- /** Target URL. */
28
- url: z.string(),
29
- /** Human-readable description of why this request is needed. */
30
- purpose: z.string(),
31
- /** Optional constrained set of URL patterns this grant covers. */
32
- allowedUrlPatterns: z.array(z.string()).optional(),
33
- });
34
- export type HttpGrantProposal = z.infer<typeof HttpGrantProposalSchema>;
35
-
36
- /**
37
- * Proposal to run an authenticated command using credential environment variables.
38
- */
39
- export const CommandGrantProposalSchema = z.object({
40
- type: z.literal("command"),
41
- /** CES credential handle identifying which credential to use. */
42
- credentialHandle: z.string(),
43
- /** The command to execute (without credential values — CES injects those). */
44
- command: z.string(),
45
- /** Human-readable description of why this command is needed. */
46
- purpose: z.string(),
47
- /** Optional constrained set of command patterns this grant covers. */
48
- allowedCommandPatterns: z.array(z.string()).optional(),
49
- });
50
- export type CommandGrantProposal = z.infer<typeof CommandGrantProposalSchema>;
51
-
52
- /**
53
- * Union of all grant proposal types.
54
- */
55
- export const GrantProposalSchema = z.discriminatedUnion("type", [
56
- HttpGrantProposalSchema,
57
- CommandGrantProposalSchema,
58
- ]);
59
- export type GrantProposal = z.infer<typeof GrantProposalSchema>;
60
-
61
- // ---------------------------------------------------------------------------
62
- // Grant decisions (temporary — before persistence)
63
- // ---------------------------------------------------------------------------
64
-
65
- export const GrantDecision = {
66
- Approved: "approved",
67
- Denied: "denied",
68
- } as const;
69
-
70
- export type GrantDecision = (typeof GrantDecision)[keyof typeof GrantDecision];
71
-
72
- /**
73
- * A temporary grant decision from a guardian, before CES persists it.
74
- */
75
- export const TemporaryGrantDecisionSchema = z.object({
76
- /** The proposal this decision applies to. */
77
- proposal: GrantProposalSchema,
78
- /** Deterministic hash of the proposal (see rendering.ts). */
79
- proposalHash: z.string(),
80
- /** The guardian's decision. */
81
- decision: z.enum(["approved", "denied"]),
82
- /** Who made the decision (guardian identifier). */
83
- decidedBy: z.string(),
84
- /** ISO-8601 timestamp of the decision. */
85
- decidedAt: z.string(),
86
- /** Optional human-readable reason for the decision. */
87
- reason: z.string().optional(),
88
- /** How long the grant should remain valid (ISO-8601 duration, e.g. "PT1H"). */
89
- ttl: z.string().optional(),
90
- /**
91
- * The type of grant to create. Determines persistence behaviour:
92
- * - `allow_once`: Temporary single-use grant (consumed after one use)
93
- * - `allow_10m`: Temporary timed grant (10-minute TTL)
94
- * - `allow_conversation`: Temporary conversation-scoped grant (lives for conversation)
95
- * - `always_allow`: Persistent grant (survives restart)
96
- *
97
- * When omitted, defaults to `always_allow` for backwards compatibility.
98
- */
99
- grantType: z.enum(["allow_once", "allow_10m", "allow_conversation", "always_allow"]).optional(),
100
- });
101
- export type TemporaryGrantDecision = z.infer<
102
- typeof TemporaryGrantDecisionSchema
103
- >;
104
-
105
- // ---------------------------------------------------------------------------
106
- // Persistent grant records (CES-owned)
107
- // ---------------------------------------------------------------------------
108
-
109
- export const GrantStatus = {
110
- Active: "active",
111
- Expired: "expired",
112
- Revoked: "revoked",
113
- Consumed: "consumed",
114
- } as const;
115
-
116
- export type GrantStatus = (typeof GrantStatus)[keyof typeof GrantStatus];
117
-
118
- /**
119
- * A persistent grant record stored by CES.
120
- *
121
- * Grants authorize a specific agent connection to use a credential for a
122
- * constrained purpose. They are never sent to the assistant with secret
123
- * values — only metadata.
124
- */
125
- export const PersistentGrantRecordSchema = z.object({
126
- /** Unique grant identifier. */
127
- grantId: z.string(),
128
- /** The CES connection that created this grant. */
129
- sessionId: z.string(),
130
- /** The credential handle this grant authorizes. */
131
- credentialHandle: z.string(),
132
- /** The proposal type (http or command). */
133
- proposalType: z.enum(["http", "command"]),
134
- /** Deterministic hash of the original proposal. */
135
- proposalHash: z.string(),
136
- /** Constrained purposes — URL patterns for HTTP, command patterns for commands. */
137
- allowedPurposes: z.array(z.string()),
138
- /** Current grant status. */
139
- status: z.enum(["active", "expired", "revoked", "consumed"]),
140
- /** Who approved the grant. */
141
- grantedBy: z.string(),
142
- /** ISO-8601 timestamp when the grant was created. */
143
- createdAt: z.string(),
144
- /** ISO-8601 timestamp when the grant expires (null if no expiry). */
145
- expiresAt: z.string().nullable(),
146
- /** ISO-8601 timestamp when the grant was consumed (null if unconsumed). */
147
- consumedAt: z.string().nullable(),
148
- /** ISO-8601 timestamp when the grant was revoked (null if active). */
149
- revokedAt: z.string().nullable(),
150
- });
151
- export type PersistentGrantRecord = z.infer<typeof PersistentGrantRecordSchema>;
152
-
153
- // ---------------------------------------------------------------------------
154
- // Audit record summaries
155
- // ---------------------------------------------------------------------------
156
-
157
- /**
158
- * Summary of a credential materialization event, as exposed by CES
159
- * for audit inspection.
160
- *
161
- * Audit records never contain secret values — only metadata about what
162
- * was accessed, when, by whom, and whether it succeeded.
163
- */
164
- export const AuditRecordSummarySchema = z.object({
165
- /** Unique audit record identifier. */
166
- auditId: z.string(),
167
- /** The grant that authorized this materialization. */
168
- grantId: z.string(),
169
- /** The credential handle that was materialized. */
170
- credentialHandle: z.string(),
171
- /** The tool that triggered materialization. */
172
- toolName: z.string(),
173
- /** Target of the operation (URL for HTTP, command summary for commands). */
174
- target: z.string(),
175
- /** The CES connection that triggered materialization. */
176
- sessionId: z.string(),
177
- /** Whether the execution succeeded. */
178
- success: z.boolean(),
179
- /** Error message if execution failed (no secrets). */
180
- errorMessage: z.string().optional(),
181
- /** ISO-8601 timestamp of the materialization event. */
182
- timestamp: z.string(),
183
- });
184
- export type AuditRecordSummary = z.infer<typeof AuditRecordSummarySchema>;
@@ -1,135 +0,0 @@
1
- /**
2
- * Canonical proposal rendering and deterministic hashing.
3
- *
4
- * Both the assistant and CES must produce identical human-readable text and
5
- * proposal hashes for the same proposal object. This module provides the
6
- * shared implementations so neither side has to duplicate the logic.
7
- *
8
- * Hashing algorithm:
9
- * 1. Recursively sort object keys (depth-first).
10
- * 2. Serialize to a canonical JSON string with no whitespace.
11
- * 3. SHA-256 hash the UTF-8 bytes and return a lowercase hex digest.
12
- *
13
- * This matches the algorithm used by `tool-approval-digest.ts` in the
14
- * assistant, ensuring consistency across the approval pipeline.
15
- */
16
-
17
- import { createHash } from "node:crypto";
18
- import type { GrantProposal } from "./grants.js";
19
-
20
- // ---------------------------------------------------------------------------
21
- // Canonical JSON serialization
22
- // ---------------------------------------------------------------------------
23
-
24
- /**
25
- * Recursively sort all object keys and return a deterministic JSON string.
26
- *
27
- * Handles nested objects, arrays (element order preserved), and primitive
28
- * values. `undefined` values inside objects are omitted (matching
29
- * JSON.stringify semantics). `null` is preserved.
30
- */
31
- export function canonicalJsonSerialize(value: unknown): string {
32
- return JSON.stringify(sortKeysDeep(value));
33
- }
34
-
35
- function sortKeysDeep(value: unknown): unknown {
36
- if (value == null) return value;
37
-
38
- if (Array.isArray(value)) {
39
- return value.map(sortKeysDeep);
40
- }
41
-
42
- if (typeof value === "object") {
43
- const sorted: Record<string, unknown> = {};
44
- const keys = Object.keys(value as Record<string, unknown>).sort();
45
- for (const key of keys) {
46
- sorted[key] = sortKeysDeep((value as Record<string, unknown>)[key]);
47
- }
48
- return sorted;
49
- }
50
-
51
- // Primitive — number, string, boolean
52
- return value;
53
- }
54
-
55
- // ---------------------------------------------------------------------------
56
- // Proposal hashing
57
- // ---------------------------------------------------------------------------
58
-
59
- /**
60
- * Compute a deterministic SHA-256 hex digest for a grant proposal.
61
- *
62
- * Two proposals with the same canonical content (regardless of key ordering)
63
- * will always produce the same hash. This hash is used to match grant
64
- * decisions to proposals in the approval pipeline.
65
- */
66
- export function hashProposal(proposal: GrantProposal): string {
67
- const canonical = canonicalJsonSerialize(proposal);
68
- return createHash("sha256").update(canonical, "utf8").digest("hex");
69
- }
70
-
71
- // ---------------------------------------------------------------------------
72
- // Human-readable proposal rendering
73
- // ---------------------------------------------------------------------------
74
-
75
- /**
76
- * Render a grant proposal as a human-readable text block suitable for
77
- * display in approval UIs and guardian notifications.
78
- *
79
- * The rendering is deterministic for the same proposal, so both assistant
80
- * and CES produce identical text.
81
- */
82
- export function renderProposal(proposal: GrantProposal): string {
83
- switch (proposal.type) {
84
- case "http":
85
- return renderHttpProposal(proposal);
86
- case "command":
87
- return renderCommandProposal(proposal);
88
- default: {
89
- const _exhaustive: never = proposal;
90
- throw new Error(`Unknown proposal type: ${(_exhaustive as GrantProposal).type}`);
91
- }
92
- }
93
- }
94
-
95
- function renderHttpProposal(proposal: GrantProposal & { type: "http" }): string {
96
- const lines: string[] = [
97
- `Authenticated HTTP Request`,
98
- ` Method: ${proposal.method}`,
99
- ` URL: ${proposal.url}`,
100
- ` Credential: ${proposal.credentialHandle}`,
101
- ` Purpose: ${proposal.purpose}`,
102
- ];
103
-
104
- if (proposal.allowedUrlPatterns && proposal.allowedUrlPatterns.length > 0) {
105
- lines.push(` Allowed URL patterns:`);
106
- for (const pattern of proposal.allowedUrlPatterns) {
107
- lines.push(` - ${pattern}`);
108
- }
109
- }
110
-
111
- return lines.join("\n");
112
- }
113
-
114
- function renderCommandProposal(
115
- proposal: GrantProposal & { type: "command" },
116
- ): string {
117
- const lines: string[] = [
118
- `Authenticated Command Execution`,
119
- ` Command: ${proposal.command}`,
120
- ` Credential: ${proposal.credentialHandle}`,
121
- ` Purpose: ${proposal.purpose}`,
122
- ];
123
-
124
- if (
125
- proposal.allowedCommandPatterns &&
126
- proposal.allowedCommandPatterns.length > 0
127
- ) {
128
- lines.push(` Allowed command patterns:`);
129
- for (const pattern of proposal.allowedCommandPatterns) {
130
- lines.push(` - ${pattern}`);
131
- }
132
- }
133
-
134
- return lines.join("\n");
135
- }