@declaw/sdk 1.1.13 → 1.2.0
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.
- package/CHANGELOG.md +21 -0
- package/LICENSE +1 -1
- package/dist/index.cjs +565 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +327 -12
- package/dist/index.d.ts +327 -12
- package/dist/index.js +553 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
CommandExitError: () => CommandExitError,
|
|
38
38
|
CommandHandle: () => CommandHandle,
|
|
39
39
|
Commands: () => Commands,
|
|
40
|
+
ConflictError: () => ConflictError,
|
|
40
41
|
ConnectionConfig: () => ConnectionConfig,
|
|
41
42
|
DEFAULT_MASK_PATTERNS: () => DEFAULT_MASK_PATTERNS,
|
|
42
43
|
FileType: () => FileType,
|
|
@@ -45,6 +46,7 @@ __export(index_exports, {
|
|
|
45
46
|
FilesystemEventType: () => FilesystemEventType,
|
|
46
47
|
GitAuthError: () => GitAuthError,
|
|
47
48
|
GitUpstreamError: () => GitUpstreamError,
|
|
49
|
+
Governance: () => Governance,
|
|
48
50
|
InjectionAction: () => InjectionAction,
|
|
49
51
|
InjectionSensitivity: () => InjectionSensitivity,
|
|
50
52
|
InvalidArgumentError: () => InvalidArgumentError,
|
|
@@ -66,12 +68,16 @@ __export(index_exports, {
|
|
|
66
68
|
TemplateError: () => TemplateError,
|
|
67
69
|
TimeoutError: () => TimeoutError,
|
|
68
70
|
TransformDirection: () => TransformDirection,
|
|
71
|
+
VolumeFiles: () => VolumeFiles,
|
|
72
|
+
VolumeLocks: () => VolumeLocks,
|
|
69
73
|
Volumes: () => Volumes,
|
|
70
74
|
WatchHandle: () => WatchHandle,
|
|
71
75
|
applyTransformation: () => applyTransformation,
|
|
72
76
|
codeSecurityConfigToJSON: () => codeSecurityConfigToJSON,
|
|
77
|
+
contentGateConfigToJSON: () => contentGateConfigToJSON,
|
|
73
78
|
createAuditConfig: () => createAuditConfig,
|
|
74
79
|
createCodeSecurityConfig: () => createCodeSecurityConfig,
|
|
80
|
+
createContentGateConfig: () => createContentGateConfig,
|
|
75
81
|
createEnvSecurityConfig: () => createEnvSecurityConfig,
|
|
76
82
|
createInjectionDefenseConfig: () => createInjectionDefenseConfig,
|
|
77
83
|
createInvisibleTextConfig: () => createInvisibleTextConfig,
|
|
@@ -90,11 +96,17 @@ __export(index_exports, {
|
|
|
90
96
|
parseBuildInfo: () => parseBuildInfo,
|
|
91
97
|
parseCodeSecurityConfig: () => parseCodeSecurityConfig,
|
|
92
98
|
parseCommandResult: () => parseCommandResult,
|
|
99
|
+
parseContentGateConfig: () => parseContentGateConfig,
|
|
93
100
|
parseEntryInfo: () => parseEntryInfo,
|
|
94
101
|
parseEnvSecurityConfig: () => parseEnvSecurityConfig,
|
|
102
|
+
parseFileEntry: () => parseFileEntry,
|
|
103
|
+
parseFileInfo: () => parseFileInfo,
|
|
95
104
|
parseFilesystemEvent: () => parseFilesystemEvent,
|
|
105
|
+
parseGovernancePack: () => parseGovernancePack,
|
|
96
106
|
parseInjectionDefenseConfig: () => parseInjectionDefenseConfig,
|
|
97
107
|
parseInvisibleTextConfig: () => parseInvisibleTextConfig,
|
|
108
|
+
parseLockLease: () => parseLockLease,
|
|
109
|
+
parseLockStatus: () => parseLockStatus,
|
|
98
110
|
parseNetworkPolicy: () => parseNetworkPolicy,
|
|
99
111
|
parsePIIConfig: () => parsePIIConfig,
|
|
100
112
|
parseProcessInfo: () => parseProcessInfo,
|
|
@@ -191,6 +203,12 @@ var NotEnoughSpaceError = class extends SandboxError {
|
|
|
191
203
|
this.name = "NotEnoughSpaceError";
|
|
192
204
|
}
|
|
193
205
|
};
|
|
206
|
+
var ConflictError = class extends SandboxError {
|
|
207
|
+
constructor(message, opts) {
|
|
208
|
+
super(message, opts);
|
|
209
|
+
this.name = "ConflictError";
|
|
210
|
+
}
|
|
211
|
+
};
|
|
194
212
|
var TemplateError = class extends SandboxError {
|
|
195
213
|
constructor(message, opts) {
|
|
196
214
|
super(message, opts);
|
|
@@ -271,10 +289,13 @@ function getDispatcher() {
|
|
|
271
289
|
return _dispatcherPromise;
|
|
272
290
|
}
|
|
273
291
|
var STATUS_ERROR_MAP = {
|
|
292
|
+
400: InvalidArgumentError,
|
|
274
293
|
401: AuthenticationError,
|
|
275
294
|
403: AuthenticationError,
|
|
276
295
|
404: NotFoundError,
|
|
277
296
|
408: TimeoutError,
|
|
297
|
+
409: ConflictError,
|
|
298
|
+
413: NotEnoughSpaceError,
|
|
278
299
|
422: InvalidArgumentError,
|
|
279
300
|
507: NotEnoughSpaceError
|
|
280
301
|
};
|
|
@@ -933,6 +954,49 @@ function invisibleTextConfigToJSON(config) {
|
|
|
933
954
|
return result;
|
|
934
955
|
}
|
|
935
956
|
|
|
957
|
+
// src/security/customPolicy.ts
|
|
958
|
+
function parseCustomPolicyConfig(data) {
|
|
959
|
+
return {
|
|
960
|
+
enabled: data.enabled ?? false,
|
|
961
|
+
inlineRego: data.inline_rego ?? data.inlineRego,
|
|
962
|
+
inlineModules: data.inline_modules ?? data.inlineModules,
|
|
963
|
+
policyRef: data.policy_ref ?? data.policyRef,
|
|
964
|
+
defaultDeny: data.default_deny ?? data.defaultDeny ?? false
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
function customPolicyConfigToJSON(config) {
|
|
968
|
+
return {
|
|
969
|
+
enabled: config.enabled,
|
|
970
|
+
inline_rego: config.inlineRego,
|
|
971
|
+
inline_modules: config.inlineModules,
|
|
972
|
+
policy_ref: config.policyRef,
|
|
973
|
+
default_deny: config.defaultDeny
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/security/contentGate.ts
|
|
978
|
+
function createContentGateConfig(opts) {
|
|
979
|
+
return {
|
|
980
|
+
enabled: opts?.enabled ?? false,
|
|
981
|
+
domains: opts?.domains
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
function parseContentGateConfig(data) {
|
|
985
|
+
return {
|
|
986
|
+
enabled: data.enabled ?? false,
|
|
987
|
+
domains: data.domains
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
function contentGateConfigToJSON(config) {
|
|
991
|
+
const result = {
|
|
992
|
+
enabled: config.enabled
|
|
993
|
+
};
|
|
994
|
+
if (config.domains !== void 0) {
|
|
995
|
+
result.domains = config.domains;
|
|
996
|
+
}
|
|
997
|
+
return result;
|
|
998
|
+
}
|
|
999
|
+
|
|
936
1000
|
// src/security/policy.ts
|
|
937
1001
|
function createSecurityPolicy(opts) {
|
|
938
1002
|
return {
|
|
@@ -944,12 +1008,16 @@ function createSecurityPolicy(opts) {
|
|
|
944
1008
|
envSecurity: opts?.envSecurity ?? createEnvSecurityConfig(),
|
|
945
1009
|
toxicity: opts?.toxicity,
|
|
946
1010
|
codeSecurity: opts?.codeSecurity,
|
|
947
|
-
invisibleText: opts?.invisibleText
|
|
1011
|
+
invisibleText: opts?.invisibleText,
|
|
1012
|
+
contentGate: opts?.contentGate,
|
|
1013
|
+
customPolicy: opts?.customPolicy
|
|
948
1014
|
};
|
|
949
1015
|
}
|
|
950
1016
|
function parseSecurityPolicy(data) {
|
|
951
1017
|
const injDef = data.injection_defense ?? data.injectionDefense;
|
|
952
1018
|
const auditData = data.audit;
|
|
1019
|
+
const customPolicyData = data.custom_policy ?? data.customPolicy;
|
|
1020
|
+
const contentGateData = data.content_gate ?? data.contentGate;
|
|
953
1021
|
return {
|
|
954
1022
|
pii: data.pii ? parsePIIConfig(data.pii) : createPIIConfig(),
|
|
955
1023
|
injectionDefense: typeof injDef === "boolean" ? injDef : injDef ? parseInjectionDefenseConfig(injDef) : false,
|
|
@@ -959,7 +1027,9 @@ function parseSecurityPolicy(data) {
|
|
|
959
1027
|
envSecurity: data.env_security ?? data.envSecurity ? parseEnvSecurityConfig(data.env_security ?? data.envSecurity) : createEnvSecurityConfig(),
|
|
960
1028
|
toxicity: data.toxicity ? parseToxicityConfig(data.toxicity) : void 0,
|
|
961
1029
|
codeSecurity: data.code_security ?? data.codeSecurity ? parseCodeSecurityConfig(data.code_security ?? data.codeSecurity) : void 0,
|
|
962
|
-
invisibleText: data.invisible_text ?? data.invisibleText ? parseInvisibleTextConfig(data.invisible_text ?? data.invisibleText) : void 0
|
|
1030
|
+
invisibleText: data.invisible_text ?? data.invisibleText ? parseInvisibleTextConfig(data.invisible_text ?? data.invisibleText) : void 0,
|
|
1031
|
+
contentGate: contentGateData ? parseContentGateConfig(contentGateData) : void 0,
|
|
1032
|
+
customPolicy: customPolicyData ? parseCustomPolicyConfig(customPolicyData) : void 0
|
|
963
1033
|
};
|
|
964
1034
|
}
|
|
965
1035
|
function securityPolicyToJSON(policy) {
|
|
@@ -1009,6 +1079,12 @@ function securityPolicyToJSON(policy) {
|
|
|
1009
1079
|
if (policy.invisibleText) {
|
|
1010
1080
|
result.invisible_text = invisibleTextConfigToJSON(policy.invisibleText);
|
|
1011
1081
|
}
|
|
1082
|
+
if (policy.contentGate) {
|
|
1083
|
+
result.content_gate = contentGateConfigToJSON(policy.contentGate);
|
|
1084
|
+
}
|
|
1085
|
+
if (policy.customPolicy) {
|
|
1086
|
+
result.custom_policy = customPolicyConfigToJSON(policy.customPolicy);
|
|
1087
|
+
}
|
|
1012
1088
|
return result;
|
|
1013
1089
|
}
|
|
1014
1090
|
function requiresTlsInterception(policy) {
|
|
@@ -2027,11 +2103,53 @@ function parseVolumeInfo(data) {
|
|
|
2027
2103
|
sizeBytes: Number(data.size_bytes ?? 0),
|
|
2028
2104
|
contentType: String(data.content_type ?? ""),
|
|
2029
2105
|
metadata: data.metadata ?? {},
|
|
2030
|
-
createdAt: String(data.created_at ?? "")
|
|
2106
|
+
createdAt: String(data.created_at ?? ""),
|
|
2107
|
+
backend: String(data.backend ?? ""),
|
|
2108
|
+
quotaBytes: Number(data.quota_bytes ?? 0),
|
|
2109
|
+
updatedAt: String(data.updated_at ?? "")
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
function parseFileEntry(data) {
|
|
2113
|
+
return {
|
|
2114
|
+
name: String(data.name ?? ""),
|
|
2115
|
+
path: String(data.path ?? ""),
|
|
2116
|
+
isDir: Boolean(data.is_dir ?? false),
|
|
2117
|
+
size: Number(data.size ?? 0),
|
|
2118
|
+
modTime: String(data.mod_time ?? ""),
|
|
2119
|
+
mode: Number(data.mode ?? 0)
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
function parseFileInfo(data) {
|
|
2123
|
+
return {
|
|
2124
|
+
...parseFileEntry(data),
|
|
2125
|
+
version: String(data.version ?? "")
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
function parseLockLease(data) {
|
|
2129
|
+
return {
|
|
2130
|
+
token: String(data.token ?? ""),
|
|
2131
|
+
ttlSeconds: Number(data.ttl_seconds ?? 0),
|
|
2132
|
+
expiresAt: String(data.expires_at ?? "")
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
function parseLockStatus(data) {
|
|
2136
|
+
return {
|
|
2137
|
+
held: Boolean(data.held ?? false),
|
|
2138
|
+
expiresInMs: Number(data.expires_in_ms ?? 0)
|
|
2031
2139
|
};
|
|
2032
2140
|
}
|
|
2033
2141
|
function volumeAttachmentToJSON(att) {
|
|
2034
|
-
|
|
2142
|
+
const out = {
|
|
2143
|
+
volume_id: att.volumeId,
|
|
2144
|
+
mount_path: att.mountPath
|
|
2145
|
+
};
|
|
2146
|
+
if (att.mode) {
|
|
2147
|
+
out.mode = att.mode;
|
|
2148
|
+
}
|
|
2149
|
+
if (att.subpath) {
|
|
2150
|
+
out.subpath = att.subpath;
|
|
2151
|
+
}
|
|
2152
|
+
return out;
|
|
2035
2153
|
}
|
|
2036
2154
|
|
|
2037
2155
|
// src/sandbox/sandbox.ts
|
|
@@ -2857,7 +2975,7 @@ var Template = class {
|
|
|
2857
2975
|
}
|
|
2858
2976
|
};
|
|
2859
2977
|
|
|
2860
|
-
// src/volumes/
|
|
2978
|
+
// src/volumes/files.ts
|
|
2861
2979
|
var VALID_VOLUME_ID_RE = /^[a-zA-Z0-9_-]+$/;
|
|
2862
2980
|
function assertValidVolumeId(id) {
|
|
2863
2981
|
if (!id || !VALID_VOLUME_ID_RE.test(id)) {
|
|
@@ -2866,8 +2984,223 @@ function assertValidVolumeId(id) {
|
|
|
2866
2984
|
);
|
|
2867
2985
|
}
|
|
2868
2986
|
}
|
|
2987
|
+
var VolumeFiles = class {
|
|
2988
|
+
volumeId;
|
|
2989
|
+
opts;
|
|
2990
|
+
constructor(volumeId, opts) {
|
|
2991
|
+
assertValidVolumeId(volumeId);
|
|
2992
|
+
this.volumeId = volumeId;
|
|
2993
|
+
this.opts = opts;
|
|
2994
|
+
}
|
|
2995
|
+
client() {
|
|
2996
|
+
const config = new ConnectionConfig({
|
|
2997
|
+
apiKey: this.opts?.apiKey,
|
|
2998
|
+
domain: this.opts?.domain,
|
|
2999
|
+
apiUrl: this.opts?.apiUrl,
|
|
3000
|
+
requestTimeout: this.opts?.requestTimeout
|
|
3001
|
+
});
|
|
3002
|
+
return getSharedClient(config);
|
|
3003
|
+
}
|
|
3004
|
+
timeout() {
|
|
3005
|
+
return this.opts?.requestTimeout;
|
|
3006
|
+
}
|
|
3007
|
+
/** Write raw bytes to `path`. Optionally conditional on `ifVersion` (CAS). */
|
|
3008
|
+
async write(path, data, opts) {
|
|
3009
|
+
if (!path) {
|
|
3010
|
+
throw new InvalidArgumentError("path is required");
|
|
3011
|
+
}
|
|
3012
|
+
const params = { path };
|
|
3013
|
+
if (opts?.ifVersion) {
|
|
3014
|
+
params.if_version = opts.ifVersion;
|
|
3015
|
+
}
|
|
3016
|
+
const body = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
3017
|
+
const resp = await this.client().put(`/volumes/${this.volumeId}/files/raw`, {
|
|
3018
|
+
params,
|
|
3019
|
+
body,
|
|
3020
|
+
headers: { "Content-Type": "application/octet-stream" },
|
|
3021
|
+
timeout: opts?.requestTimeout ?? this.timeout()
|
|
3022
|
+
});
|
|
3023
|
+
return String(resp.path ?? path);
|
|
3024
|
+
}
|
|
3025
|
+
/** Read raw bytes from `path`. */
|
|
3026
|
+
async read(path) {
|
|
3027
|
+
if (!path) {
|
|
3028
|
+
throw new InvalidArgumentError("path is required");
|
|
3029
|
+
}
|
|
3030
|
+
return this.client().getBytes(`/volumes/${this.volumeId}/files/raw`, {
|
|
3031
|
+
params: { path },
|
|
3032
|
+
timeout: this.timeout()
|
|
3033
|
+
});
|
|
3034
|
+
}
|
|
3035
|
+
/** List directory entries under `path`. */
|
|
3036
|
+
async list(path) {
|
|
3037
|
+
if (!path) {
|
|
3038
|
+
throw new InvalidArgumentError("path is required");
|
|
3039
|
+
}
|
|
3040
|
+
const resp = await this.client().get(`/volumes/${this.volumeId}/files/list`, {
|
|
3041
|
+
params: { path },
|
|
3042
|
+
timeout: this.timeout()
|
|
3043
|
+
});
|
|
3044
|
+
const rows = resp.entries ?? [];
|
|
3045
|
+
return rows.map(parseFileEntry);
|
|
3046
|
+
}
|
|
3047
|
+
/** Stat `path`, returning the entry plus the CAS `version` token. */
|
|
3048
|
+
async info(path) {
|
|
3049
|
+
if (!path) {
|
|
3050
|
+
throw new InvalidArgumentError("path is required");
|
|
3051
|
+
}
|
|
3052
|
+
const resp = await this.client().get(`/volumes/${this.volumeId}/files/info`, {
|
|
3053
|
+
params: { path },
|
|
3054
|
+
timeout: this.timeout()
|
|
3055
|
+
});
|
|
3056
|
+
return parseFileInfo(resp);
|
|
3057
|
+
}
|
|
3058
|
+
/** Return whether `path` exists. */
|
|
3059
|
+
async exists(path) {
|
|
3060
|
+
if (!path) {
|
|
3061
|
+
throw new InvalidArgumentError("path is required");
|
|
3062
|
+
}
|
|
3063
|
+
const resp = await this.client().get(`/volumes/${this.volumeId}/files/exists`, {
|
|
3064
|
+
params: { path },
|
|
3065
|
+
timeout: this.timeout()
|
|
3066
|
+
});
|
|
3067
|
+
return Boolean(resp.exists ?? false);
|
|
3068
|
+
}
|
|
3069
|
+
/** Remove `path`. Pass `{ recursive: true }` to remove a directory tree. */
|
|
3070
|
+
async remove(path, opts) {
|
|
3071
|
+
if (!path) {
|
|
3072
|
+
throw new InvalidArgumentError("path is required");
|
|
3073
|
+
}
|
|
3074
|
+
const params = {
|
|
3075
|
+
path,
|
|
3076
|
+
recursive: opts?.recursive ? "true" : "false"
|
|
3077
|
+
};
|
|
3078
|
+
await this.client().delete(`/volumes/${this.volumeId}/files`, {
|
|
3079
|
+
params,
|
|
3080
|
+
timeout: opts?.requestTimeout ?? this.timeout()
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
/** Rename `oldPath` to `newPath`. */
|
|
3084
|
+
async rename(oldPath, newPath) {
|
|
3085
|
+
if (!oldPath || !newPath) {
|
|
3086
|
+
throw new InvalidArgumentError("oldPath and newPath are required");
|
|
3087
|
+
}
|
|
3088
|
+
const resp = await this.client().patch(`/volumes/${this.volumeId}/files`, {
|
|
3089
|
+
json: { old_path: oldPath, new_path: newPath },
|
|
3090
|
+
timeout: this.timeout()
|
|
3091
|
+
});
|
|
3092
|
+
return {
|
|
3093
|
+
oldPath: String(resp.old_path ?? oldPath),
|
|
3094
|
+
newPath: String(resp.new_path ?? newPath)
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
/** Create a directory at `path`. */
|
|
3098
|
+
async mkdir(path) {
|
|
3099
|
+
if (!path) {
|
|
3100
|
+
throw new InvalidArgumentError("path is required");
|
|
3101
|
+
}
|
|
3102
|
+
const resp = await this.client().post(`/volumes/${this.volumeId}/files/mkdir`, {
|
|
3103
|
+
json: { path },
|
|
3104
|
+
timeout: this.timeout()
|
|
3105
|
+
});
|
|
3106
|
+
return String(resp.path ?? path);
|
|
3107
|
+
}
|
|
3108
|
+
};
|
|
3109
|
+
|
|
3110
|
+
// src/volumes/locks.ts
|
|
3111
|
+
var VALID_VOLUME_ID_RE2 = /^[a-zA-Z0-9_-]+$/;
|
|
3112
|
+
function assertValidVolumeId2(id) {
|
|
3113
|
+
if (!id || !VALID_VOLUME_ID_RE2.test(id)) {
|
|
3114
|
+
throw new InvalidArgumentError(
|
|
3115
|
+
`Invalid volume ID: "${id}". Must be alphanumeric with hyphens/underscores only.`
|
|
3116
|
+
);
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
var VolumeLocks = class {
|
|
3120
|
+
volumeId;
|
|
3121
|
+
opts;
|
|
3122
|
+
constructor(volumeId, opts) {
|
|
3123
|
+
assertValidVolumeId2(volumeId);
|
|
3124
|
+
this.volumeId = volumeId;
|
|
3125
|
+
this.opts = opts;
|
|
3126
|
+
}
|
|
3127
|
+
client() {
|
|
3128
|
+
const config = new ConnectionConfig({
|
|
3129
|
+
apiKey: this.opts?.apiKey,
|
|
3130
|
+
domain: this.opts?.domain,
|
|
3131
|
+
apiUrl: this.opts?.apiUrl,
|
|
3132
|
+
requestTimeout: this.opts?.requestTimeout
|
|
3133
|
+
});
|
|
3134
|
+
return getSharedClient(config);
|
|
3135
|
+
}
|
|
3136
|
+
timeout() {
|
|
3137
|
+
return this.opts?.requestTimeout;
|
|
3138
|
+
}
|
|
3139
|
+
/** Acquire a lock on `path`. Throws ConflictError (409) if already held. */
|
|
3140
|
+
async acquire(path, ttlSeconds) {
|
|
3141
|
+
if (!path) {
|
|
3142
|
+
throw new InvalidArgumentError("path is required");
|
|
3143
|
+
}
|
|
3144
|
+
const json = { path };
|
|
3145
|
+
if (ttlSeconds !== void 0) {
|
|
3146
|
+
json.ttl_seconds = ttlSeconds;
|
|
3147
|
+
}
|
|
3148
|
+
const resp = await this.client().post(`/volumes/${this.volumeId}/locks`, {
|
|
3149
|
+
json,
|
|
3150
|
+
timeout: this.timeout()
|
|
3151
|
+
});
|
|
3152
|
+
return parseLockLease(resp);
|
|
3153
|
+
}
|
|
3154
|
+
/** Release a lock on `path` held under `token`. Throws ConflictError (409) if not the holder. */
|
|
3155
|
+
async release(path, token) {
|
|
3156
|
+
if (!path || !token) {
|
|
3157
|
+
throw new InvalidArgumentError("path and token are required");
|
|
3158
|
+
}
|
|
3159
|
+
const resp = await this.client().delete(`/volumes/${this.volumeId}/locks`, {
|
|
3160
|
+
json: { path, token },
|
|
3161
|
+
timeout: this.timeout()
|
|
3162
|
+
});
|
|
3163
|
+
return Boolean(resp.released ?? false);
|
|
3164
|
+
}
|
|
3165
|
+
/** Renew a lock on `path` held under `token`. Throws ConflictError (409) if not the holder. */
|
|
3166
|
+
async renew(path, token, ttlSeconds) {
|
|
3167
|
+
if (!path || !token) {
|
|
3168
|
+
throw new InvalidArgumentError("path and token are required");
|
|
3169
|
+
}
|
|
3170
|
+
const json = { path, token };
|
|
3171
|
+
if (ttlSeconds !== void 0) {
|
|
3172
|
+
json.ttl_seconds = ttlSeconds;
|
|
3173
|
+
}
|
|
3174
|
+
const resp = await this.client().post(`/volumes/${this.volumeId}/locks/renew`, {
|
|
3175
|
+
json,
|
|
3176
|
+
timeout: this.timeout()
|
|
3177
|
+
});
|
|
3178
|
+
return { ...parseLockLease(resp), token };
|
|
3179
|
+
}
|
|
3180
|
+
/** Query whether `path` is currently locked. */
|
|
3181
|
+
async status(path) {
|
|
3182
|
+
if (!path) {
|
|
3183
|
+
throw new InvalidArgumentError("path is required");
|
|
3184
|
+
}
|
|
3185
|
+
const resp = await this.client().get(`/volumes/${this.volumeId}/locks`, {
|
|
3186
|
+
params: { path },
|
|
3187
|
+
timeout: this.timeout()
|
|
3188
|
+
});
|
|
3189
|
+
return parseLockStatus(resp);
|
|
3190
|
+
}
|
|
3191
|
+
};
|
|
3192
|
+
|
|
3193
|
+
// src/volumes/volumes.ts
|
|
3194
|
+
var VALID_VOLUME_ID_RE3 = /^[a-zA-Z0-9_-]+$/;
|
|
3195
|
+
function assertValidVolumeId3(id) {
|
|
3196
|
+
if (!id || !VALID_VOLUME_ID_RE3.test(id)) {
|
|
3197
|
+
throw new InvalidArgumentError(
|
|
3198
|
+
`Invalid volume ID: "${id}". Must be alphanumeric with hyphens/underscores only.`
|
|
3199
|
+
);
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
2869
3202
|
var Volumes = class {
|
|
2870
|
-
/** Create a volume by streaming a tarball to the server. */
|
|
3203
|
+
/** Create a volume by streaming a tarball (gzip tar.gz) to the server. */
|
|
2871
3204
|
static async create(name, data, opts) {
|
|
2872
3205
|
if (!name) {
|
|
2873
3206
|
throw new InvalidArgumentError("volume name is required");
|
|
@@ -2888,9 +3221,113 @@ var Volumes = class {
|
|
|
2888
3221
|
});
|
|
2889
3222
|
return parseVolumeInfo(resp);
|
|
2890
3223
|
}
|
|
3224
|
+
/**
|
|
3225
|
+
* Capture the attached volume's mount path in `sandboxId` into a NEW volume.
|
|
3226
|
+
*
|
|
3227
|
+
* The source volume is left unchanged. If `name` is omitted the server names
|
|
3228
|
+
* the new volume "<source-name>-commit". Returns the new VolumeInfo.
|
|
3229
|
+
*/
|
|
3230
|
+
static async commit(sandboxId, volumeId, name, opts) {
|
|
3231
|
+
if (!sandboxId || !VALID_VOLUME_ID_RE3.test(sandboxId)) {
|
|
3232
|
+
throw new InvalidArgumentError(
|
|
3233
|
+
`Invalid sandbox ID: "${sandboxId}". Must be alphanumeric with hyphens/underscores only.`
|
|
3234
|
+
);
|
|
3235
|
+
}
|
|
3236
|
+
assertValidVolumeId3(volumeId);
|
|
3237
|
+
const config = new ConnectionConfig({
|
|
3238
|
+
apiKey: opts?.apiKey,
|
|
3239
|
+
domain: opts?.domain,
|
|
3240
|
+
apiUrl: opts?.apiUrl,
|
|
3241
|
+
requestTimeout: opts?.requestTimeout
|
|
3242
|
+
});
|
|
3243
|
+
const client = getSharedClient(config);
|
|
3244
|
+
const resp = await client.post(`/sandboxes/${sandboxId}/volumes/${volumeId}/commit`, {
|
|
3245
|
+
params: name ? { name } : void 0,
|
|
3246
|
+
timeout: opts?.requestTimeout
|
|
3247
|
+
});
|
|
3248
|
+
return parseVolumeInfo(resp);
|
|
3249
|
+
}
|
|
3250
|
+
/**
|
|
3251
|
+
* Snapshot an arbitrary absolute in-sandbox `path` into a NEW volume.
|
|
3252
|
+
*
|
|
3253
|
+
* Unlike `commit` (which captures an already-attached volume's mount path),
|
|
3254
|
+
* `snapshot` captures any path in the running sandbox. `name` defaults to
|
|
3255
|
+
* "snapshot" on the server. Synthetic paths (/proc, /sys, /dev) are rejected.
|
|
3256
|
+
*/
|
|
3257
|
+
static async snapshot(sandboxId, path, name, opts) {
|
|
3258
|
+
if (!sandboxId || !VALID_VOLUME_ID_RE3.test(sandboxId)) {
|
|
3259
|
+
throw new InvalidArgumentError(
|
|
3260
|
+
`Invalid sandbox ID: "${sandboxId}". Must be alphanumeric with hyphens/underscores only.`
|
|
3261
|
+
);
|
|
3262
|
+
}
|
|
3263
|
+
if (!path) {
|
|
3264
|
+
throw new InvalidArgumentError("path is required");
|
|
3265
|
+
}
|
|
3266
|
+
const config = new ConnectionConfig({
|
|
3267
|
+
apiKey: opts?.apiKey,
|
|
3268
|
+
domain: opts?.domain,
|
|
3269
|
+
apiUrl: opts?.apiUrl,
|
|
3270
|
+
requestTimeout: opts?.requestTimeout
|
|
3271
|
+
});
|
|
3272
|
+
const client = getSharedClient(config);
|
|
3273
|
+
const params = { path };
|
|
3274
|
+
if (name) {
|
|
3275
|
+
params.name = name;
|
|
3276
|
+
}
|
|
3277
|
+
const resp = await client.post(`/sandboxes/${sandboxId}/volumes/snapshot`, {
|
|
3278
|
+
params,
|
|
3279
|
+
timeout: opts?.requestTimeout
|
|
3280
|
+
});
|
|
3281
|
+
return parseVolumeInfo(resp);
|
|
3282
|
+
}
|
|
3283
|
+
/**
|
|
3284
|
+
* Create an empty file-granular volume. Requires a file-granular backend
|
|
3285
|
+
* (503 if not configured). Returns the new VolumeInfo.
|
|
3286
|
+
*/
|
|
3287
|
+
static async empty(name, opts) {
|
|
3288
|
+
if (!name) {
|
|
3289
|
+
throw new InvalidArgumentError("volume name is required");
|
|
3290
|
+
}
|
|
3291
|
+
const config = new ConnectionConfig({
|
|
3292
|
+
apiKey: opts?.apiKey,
|
|
3293
|
+
domain: opts?.domain,
|
|
3294
|
+
apiUrl: opts?.apiUrl,
|
|
3295
|
+
requestTimeout: opts?.requestTimeout
|
|
3296
|
+
});
|
|
3297
|
+
const client = getSharedClient(config);
|
|
3298
|
+
const resp = await client.post("/volumes/empty", {
|
|
3299
|
+
params: { name },
|
|
3300
|
+
timeout: opts?.requestTimeout
|
|
3301
|
+
});
|
|
3302
|
+
return parseVolumeInfo(resp);
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* Ingest a gzip tar.gz archive into a NEW file-granular volume. Requires a
|
|
3306
|
+
* file-granular backend (503 if not configured). 413 on quota exceeded.
|
|
3307
|
+
*/
|
|
3308
|
+
static async ingest(name, data, opts) {
|
|
3309
|
+
if (!name) {
|
|
3310
|
+
throw new InvalidArgumentError("volume name is required");
|
|
3311
|
+
}
|
|
3312
|
+
const config = new ConnectionConfig({
|
|
3313
|
+
apiKey: opts?.apiKey,
|
|
3314
|
+
domain: opts?.domain,
|
|
3315
|
+
apiUrl: opts?.apiUrl,
|
|
3316
|
+
requestTimeout: opts?.requestTimeout
|
|
3317
|
+
});
|
|
3318
|
+
const client = getSharedClient(config);
|
|
3319
|
+
const body = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
3320
|
+
const resp = await client.post("/volumes/ingest", {
|
|
3321
|
+
params: { name },
|
|
3322
|
+
body,
|
|
3323
|
+
headers: { "Content-Type": opts?.contentType ?? "application/gzip" },
|
|
3324
|
+
timeout: opts?.requestTimeout
|
|
3325
|
+
});
|
|
3326
|
+
return parseVolumeInfo(resp);
|
|
3327
|
+
}
|
|
2891
3328
|
/** Fetch metadata for a single volume. */
|
|
2892
3329
|
static async get(volumeId, opts) {
|
|
2893
|
-
|
|
3330
|
+
assertValidVolumeId3(volumeId);
|
|
2894
3331
|
const config = new ConnectionConfig({
|
|
2895
3332
|
apiKey: opts?.apiKey,
|
|
2896
3333
|
domain: opts?.domain,
|
|
@@ -2918,9 +3355,23 @@ var Volumes = class {
|
|
|
2918
3355
|
const rows = resp.volumes ?? [];
|
|
2919
3356
|
return rows.map(parseVolumeInfo);
|
|
2920
3357
|
}
|
|
3358
|
+
/** Download the volume's contents as raw bytes (the stored archive/blob). */
|
|
3359
|
+
static async download(volumeId, opts) {
|
|
3360
|
+
assertValidVolumeId3(volumeId);
|
|
3361
|
+
const config = new ConnectionConfig({
|
|
3362
|
+
apiKey: opts?.apiKey,
|
|
3363
|
+
domain: opts?.domain,
|
|
3364
|
+
apiUrl: opts?.apiUrl,
|
|
3365
|
+
requestTimeout: opts?.requestTimeout
|
|
3366
|
+
});
|
|
3367
|
+
const client = getSharedClient(config);
|
|
3368
|
+
return client.getBytes(`/volumes/${volumeId}/download`, {
|
|
3369
|
+
timeout: opts?.requestTimeout
|
|
3370
|
+
});
|
|
3371
|
+
}
|
|
2921
3372
|
/** Delete a volume and its blob. Idempotent on the wire. */
|
|
2922
3373
|
static async delete(volumeId, opts) {
|
|
2923
|
-
|
|
3374
|
+
assertValidVolumeId3(volumeId);
|
|
2924
3375
|
const config = new ConnectionConfig({
|
|
2925
3376
|
apiKey: opts?.apiKey,
|
|
2926
3377
|
domain: opts?.domain,
|
|
@@ -2930,6 +3381,100 @@ var Volumes = class {
|
|
|
2930
3381
|
const client = getSharedClient(config);
|
|
2931
3382
|
await client.delete(`/volumes/${volumeId}`, { timeout: opts?.requestTimeout });
|
|
2932
3383
|
}
|
|
3384
|
+
/**
|
|
3385
|
+
* File-granular operations (read/write/list/info/exists/remove/rename/mkdir,
|
|
3386
|
+
* plus CAS via `write(..., { ifVersion })`) on `volumeId`. File-granular
|
|
3387
|
+
* volumes only.
|
|
3388
|
+
*/
|
|
3389
|
+
static files(volumeId, opts) {
|
|
3390
|
+
return new VolumeFiles(volumeId, opts);
|
|
3391
|
+
}
|
|
3392
|
+
/** Advisory locks (acquire/release/renew/status) over a (volume, path). */
|
|
3393
|
+
static locks(volumeId, opts) {
|
|
3394
|
+
return new VolumeLocks(volumeId, opts);
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
|
|
3398
|
+
// src/governance/models.ts
|
|
3399
|
+
function parseGovernanceControl(data) {
|
|
3400
|
+
return {
|
|
3401
|
+
control: String(data.control ?? ""),
|
|
3402
|
+
gate: String(data.gate ?? ""),
|
|
3403
|
+
rule: String(data.rule ?? ""),
|
|
3404
|
+
playbook: String(data.playbook ?? "")
|
|
3405
|
+
};
|
|
3406
|
+
}
|
|
3407
|
+
function parseGovernanceAdvisory(data) {
|
|
3408
|
+
return {
|
|
3409
|
+
control: String(data.control ?? ""),
|
|
3410
|
+
reason: String(data.reason ?? "")
|
|
3411
|
+
};
|
|
3412
|
+
}
|
|
3413
|
+
function parseGovernancePack(data) {
|
|
3414
|
+
const rawEnforces = data.enforces ?? [];
|
|
3415
|
+
const rawAdvisory = data.advisory ?? [];
|
|
3416
|
+
return {
|
|
3417
|
+
name: String(data.name ?? ""),
|
|
3418
|
+
version: String(data.version ?? ""),
|
|
3419
|
+
framework: String(data.framework ?? ""),
|
|
3420
|
+
description: String(data.description ?? ""),
|
|
3421
|
+
gates: data.gates ?? [],
|
|
3422
|
+
enforces: rawEnforces.map(parseGovernanceControl),
|
|
3423
|
+
advisory: rawAdvisory.map(parseGovernanceAdvisory),
|
|
3424
|
+
policyRef: String(data.policy_ref ?? data.policyRef ?? ""),
|
|
3425
|
+
seeded: Boolean(data.seeded ?? false)
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
// src/governance/governance.ts
|
|
3430
|
+
var VALID_PACK_NAME_RE = /^[a-zA-Z0-9_-]+$/;
|
|
3431
|
+
function assertValidPackName(name) {
|
|
3432
|
+
if (!name || !VALID_PACK_NAME_RE.test(name)) {
|
|
3433
|
+
throw new InvalidArgumentError(
|
|
3434
|
+
`Invalid pack name: "${name}". Must be alphanumeric with hyphens/underscores only.`
|
|
3435
|
+
);
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
var Governance = class {
|
|
3439
|
+
/**
|
|
3440
|
+
* List all available governance packs.
|
|
3441
|
+
*
|
|
3442
|
+
* Sends GET /governance/packs and returns the `packs` array.
|
|
3443
|
+
*/
|
|
3444
|
+
static async listPacks(opts) {
|
|
3445
|
+
const config = new ConnectionConfig({
|
|
3446
|
+
apiKey: opts?.apiKey,
|
|
3447
|
+
domain: opts?.domain,
|
|
3448
|
+
apiUrl: opts?.apiUrl,
|
|
3449
|
+
requestTimeout: opts?.requestTimeout
|
|
3450
|
+
});
|
|
3451
|
+
const client = getSharedClient(config);
|
|
3452
|
+
const resp = await client.get("/governance/packs", {
|
|
3453
|
+
timeout: opts?.requestTimeout
|
|
3454
|
+
});
|
|
3455
|
+
const rows = resp.packs ?? [];
|
|
3456
|
+
return rows.map(parseGovernancePack);
|
|
3457
|
+
}
|
|
3458
|
+
/**
|
|
3459
|
+
* Fetch a single governance pack by name.
|
|
3460
|
+
*
|
|
3461
|
+
* Sends GET /governance/packs/:name and returns the pack object.
|
|
3462
|
+
* Throws InvalidArgumentError if the name contains unsafe characters.
|
|
3463
|
+
*/
|
|
3464
|
+
static async getPack(name, opts) {
|
|
3465
|
+
assertValidPackName(name);
|
|
3466
|
+
const config = new ConnectionConfig({
|
|
3467
|
+
apiKey: opts?.apiKey,
|
|
3468
|
+
domain: opts?.domain,
|
|
3469
|
+
apiUrl: opts?.apiUrl,
|
|
3470
|
+
requestTimeout: opts?.requestTimeout
|
|
3471
|
+
});
|
|
3472
|
+
const client = getSharedClient(config);
|
|
3473
|
+
const resp = await client.get(`/governance/packs/${name}`, {
|
|
3474
|
+
timeout: opts?.requestTimeout
|
|
3475
|
+
});
|
|
3476
|
+
return parseGovernancePack(resp);
|
|
3477
|
+
}
|
|
2933
3478
|
};
|
|
2934
3479
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2935
3480
|
0 && (module.exports = {
|
|
@@ -2940,6 +3485,7 @@ var Volumes = class {
|
|
|
2940
3485
|
CommandExitError,
|
|
2941
3486
|
CommandHandle,
|
|
2942
3487
|
Commands,
|
|
3488
|
+
ConflictError,
|
|
2943
3489
|
ConnectionConfig,
|
|
2944
3490
|
DEFAULT_MASK_PATTERNS,
|
|
2945
3491
|
FileType,
|
|
@@ -2948,6 +3494,7 @@ var Volumes = class {
|
|
|
2948
3494
|
FilesystemEventType,
|
|
2949
3495
|
GitAuthError,
|
|
2950
3496
|
GitUpstreamError,
|
|
3497
|
+
Governance,
|
|
2951
3498
|
InjectionAction,
|
|
2952
3499
|
InjectionSensitivity,
|
|
2953
3500
|
InvalidArgumentError,
|
|
@@ -2969,12 +3516,16 @@ var Volumes = class {
|
|
|
2969
3516
|
TemplateError,
|
|
2970
3517
|
TimeoutError,
|
|
2971
3518
|
TransformDirection,
|
|
3519
|
+
VolumeFiles,
|
|
3520
|
+
VolumeLocks,
|
|
2972
3521
|
Volumes,
|
|
2973
3522
|
WatchHandle,
|
|
2974
3523
|
applyTransformation,
|
|
2975
3524
|
codeSecurityConfigToJSON,
|
|
3525
|
+
contentGateConfigToJSON,
|
|
2976
3526
|
createAuditConfig,
|
|
2977
3527
|
createCodeSecurityConfig,
|
|
3528
|
+
createContentGateConfig,
|
|
2978
3529
|
createEnvSecurityConfig,
|
|
2979
3530
|
createInjectionDefenseConfig,
|
|
2980
3531
|
createInvisibleTextConfig,
|
|
@@ -2993,11 +3544,17 @@ var Volumes = class {
|
|
|
2993
3544
|
parseBuildInfo,
|
|
2994
3545
|
parseCodeSecurityConfig,
|
|
2995
3546
|
parseCommandResult,
|
|
3547
|
+
parseContentGateConfig,
|
|
2996
3548
|
parseEntryInfo,
|
|
2997
3549
|
parseEnvSecurityConfig,
|
|
3550
|
+
parseFileEntry,
|
|
3551
|
+
parseFileInfo,
|
|
2998
3552
|
parseFilesystemEvent,
|
|
3553
|
+
parseGovernancePack,
|
|
2999
3554
|
parseInjectionDefenseConfig,
|
|
3000
3555
|
parseInvisibleTextConfig,
|
|
3556
|
+
parseLockLease,
|
|
3557
|
+
parseLockStatus,
|
|
3001
3558
|
parseNetworkPolicy,
|
|
3002
3559
|
parsePIIConfig,
|
|
3003
3560
|
parseProcessInfo,
|