@hyperbrowser/sdk 1.4.1 → 1.5.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.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SecretsService = void 0;
4
+ const customer_key_1 = require("../customer-key");
4
5
  const error_1 = require("../error");
5
6
  const secret_references_1 = require("../sandbox/secret-references");
6
7
  const secret_values_1 = require("../secret-values");
@@ -12,6 +13,17 @@ const MAX_LIST_LIMIT = 100;
12
13
  /** Teams hold at most 100 secrets, so one page of search results covers every match. */
13
14
  const NAME_LOOKUP_LIMIT = MAX_LIST_LIMIT;
14
15
  const secretPath = (id) => `/secrets/${encodeURIComponent(id)}`;
16
+ const isCustomerProtected = (secret) => secret.protection === "customer";
17
+ /** Throws unless `version` is a version number, or `"latest"` where allowed. */
18
+ const assertVersion = (version, allowLatest) => {
19
+ if (allowLatest && version === "latest")
20
+ return;
21
+ if (!Number.isSafeInteger(version) ||
22
+ version < 1 ||
23
+ version > secret_references_1.MAX_SECRET_VERSION) {
24
+ throw new error_1.HyperbrowserError(`version must be an integer from 1 to ${secret_references_1.MAX_SECRET_VERSION}${allowLatest ? ' or "latest"' : ""}`);
25
+ }
26
+ };
15
27
  const rethrow = (error, message) => {
16
28
  if (error instanceof error_1.HyperbrowserError) {
17
29
  throw error;
@@ -22,6 +34,11 @@ const rethrow = (error, message) => {
22
34
  * Secrets are encrypted locally to the platform's public key; the API only
23
35
  * ever receives envelopes, and values are never returned.
24
36
  *
37
+ * A customer-protected secret's versions are also wrapped locally with your
38
+ * own key (`createCustomerKey()`, or your own `CustomerKey`), so the platform
39
+ * stores nothing it can open alone. Each use passes the reference `unwrap()`
40
+ * returns.
41
+ *
25
42
  * Methods that take `secret` accept its ID or its exact name. A UUID-shaped
26
43
  * argument is tried as an ID first and then as a name, since names may look
27
44
  * like UUIDs.
@@ -67,13 +84,26 @@ class SecretsService extends base_1.BaseService {
67
84
  * empty secret behind.
68
85
  */
69
86
  async create(params) {
70
- const { name, description, type, allowedOrigins, value } = params ?? {};
87
+ const { name, description, type, allowedOrigins, value, customerKey } = params ?? {};
71
88
  if (typeof name !== "string" || !secret_references_1.SECRET_NAME_PATTERN.test(name)) {
72
89
  throw new error_1.HyperbrowserError("Secret name must be 1-128 letters, digits, '_' or '-', starting with a letter or digit");
73
90
  }
74
91
  if (type !== undefined && (typeof type !== "string" || !type)) {
75
92
  throw (0, error_1.invalidRequest)('type must be "secret", "totp" or "op_token"');
76
93
  }
94
+ const protection = params.protection ?? (customerKey !== undefined ? "customer" : undefined);
95
+ if (protection !== undefined && protection !== "platform" && protection !== "customer") {
96
+ throw (0, error_1.invalidRequest)('protection must be "platform" or "customer"');
97
+ }
98
+ if (customerKey !== undefined) {
99
+ if (protection !== "customer") {
100
+ throw (0, error_1.invalidRequest)('customerKey is only for secrets with protection "customer"');
101
+ }
102
+ (0, customer_key_1.assertCustomerKey)(customerKey);
103
+ }
104
+ if (protection === "customer" && value !== undefined && customerKey === undefined) {
105
+ throw (0, error_1.invalidRequest)("A customer-protected secret's value is wrapped with your own key: pass customerKey");
106
+ }
77
107
  const plaintext = value === undefined ? undefined : (0, secret_values_1.secretPlaintext)(type ?? "secret", value);
78
108
  const sealer = plaintext === undefined ? undefined : secrets_envelope_1.SecretsSealer.fromPublicKey(await this.getPublicKey());
79
109
  const metadata = allowedOrigins === undefined ? undefined : { browser: { allowedOrigins } };
@@ -81,7 +111,7 @@ class SecretsService extends base_1.BaseService {
81
111
  try {
82
112
  secret = await this.request("/secrets", {
83
113
  method: "POST",
84
- body: JSON.stringify({ name, description, type, metadata }),
114
+ body: JSON.stringify({ name, description, type, metadata, protection }),
85
115
  });
86
116
  }
87
117
  catch (error) {
@@ -91,7 +121,7 @@ class SecretsService extends base_1.BaseService {
91
121
  return secret;
92
122
  }
93
123
  try {
94
- const version = await this.uploadVersion(secret, sealer, plaintext);
124
+ const version = await this.uploadVersion(secret, sealer, plaintext, customerKey);
95
125
  return { ...secret, latestVersion: version.version };
96
126
  }
97
127
  catch (error) {
@@ -143,18 +173,124 @@ class SecretsService extends base_1.BaseService {
143
173
  * value is checked against the rules of the secret's type, such as a TOTP
144
174
  * seed's format, before it is sealed.
145
175
  */
146
- async addVersion(secret, value) {
176
+ async addVersion(secret, value, options = {}) {
147
177
  (0, secrets_envelope_1.secretValueBytes)(value);
178
+ const { customerKey } = options ?? {};
179
+ if (customerKey !== undefined)
180
+ (0, customer_key_1.assertCustomerKey)(customerKey);
148
181
  const sealer = secrets_envelope_1.SecretsSealer.fromPublicKey(await this.getPublicKey());
149
182
  try {
150
183
  const resolved = await this.resolve(secret);
184
+ const customer = isCustomerProtected(resolved);
185
+ if (customer && customerKey === undefined) {
186
+ throw (0, error_1.invalidRequest)(`Secret ${resolved.name} is customer-protected: pass customerKey to wrap the value with`);
187
+ }
188
+ if (!customer && customerKey !== undefined) {
189
+ throw (0, error_1.invalidRequest)(`Secret ${resolved.name} is not customer-protected, so its versions aren't wrapped: omit customerKey`);
190
+ }
151
191
  const plaintext = (0, secret_values_1.secretPlaintext)(resolved.type ?? "secret", value);
152
- return await this.uploadVersion(resolved, sealer, plaintext);
192
+ return await this.uploadVersion(resolved, sealer, plaintext, customerKey);
153
193
  }
154
194
  catch (error) {
155
195
  return rethrow(error, `Failed to add a version to secret ${secret}`);
156
196
  }
157
197
  }
198
+ /**
199
+ * A customer-protected version's wrapped envelope, for unwrapping with
200
+ * your own key. Most callers want `unwrap()`, which also unwraps it.
201
+ */
202
+ async getWrappedVersion(secret, version = "latest") {
203
+ assertVersion(version, true);
204
+ try {
205
+ const { id } = await this.resolve(secret);
206
+ return await this.fetchWrapped(id, version);
207
+ }
208
+ catch (error) {
209
+ return rethrow(error, `Failed to get the wrapped version of secret ${secret}`);
210
+ }
211
+ }
212
+ /**
213
+ * Unwrap a customer-protected version locally with your own key, giving
214
+ * the reference each use passes: as a sandbox's or process's `secrets`
215
+ * entry, or as a 1Password `token`. It is pinned to the version unwrapped.
216
+ * The unwrapped envelope is checked against the digest stored with the
217
+ * version, and only the platform can open it.
218
+ *
219
+ * `customerKey` may be several keys, such as during a rotation; the one
220
+ * whose `kid` wrapped the version is used.
221
+ */
222
+ async unwrap(secret, customerKey, options = {}) {
223
+ const version = options?.version ?? "latest";
224
+ assertVersion(version, true);
225
+ (0, customer_key_1.assertCustomerKeys)(customerKey);
226
+ try {
227
+ const resolved = await this.resolve(secret);
228
+ const wrapped = await this.fetchWrapped(resolved.id, version);
229
+ const unwrapped = await (0, customer_key_1.unwrapVersion)(wrapped, customerKey, `Version ${wrapped.version} of secret ${resolved.name}`);
230
+ return { name: resolved.name, version: wrapped.version, unwrapped };
231
+ }
232
+ catch (error) {
233
+ return rethrow(error, `Failed to unwrap secret ${secret}`);
234
+ }
235
+ }
236
+ /**
237
+ * Rewrap a customer-protected secret's versions with a new key, for
238
+ * rotating your own key. Each version is unwrapped with `from` and wrapped
239
+ * with `to` locally; the value never changes and the platform never sees
240
+ * it. Returns the versions rewrapped.
241
+ */
242
+ async rewrap(secret, params) {
243
+ const { from, to, versions } = params ?? {};
244
+ (0, customer_key_1.assertCustomerKeys)(from, "from", { allowEmpty: true });
245
+ (0, customer_key_1.assertCustomerKey)(to, "to");
246
+ if (versions !== undefined) {
247
+ if (!Array.isArray(versions))
248
+ throw (0, error_1.invalidRequest)("versions must be an array of version numbers");
249
+ versions.forEach((version) => assertVersion(version, false));
250
+ }
251
+ try {
252
+ const detail = await this.resolveDetail(secret);
253
+ if (!isCustomerProtected(detail)) {
254
+ throw (0, error_1.invalidRequest)(`Secret ${detail.name} is not customer-protected; it has no wrapping`);
255
+ }
256
+ const wanted = versions ??
257
+ detail.versions.filter(({ outerKid }) => outerKid !== to.kid).map(({ version }) => version);
258
+ const rewrapped = [];
259
+ for (const version of wanted) {
260
+ const wrapped = await this.fetchWrapped(detail.id, version);
261
+ const label = `Version ${version} of secret ${detail.name}`;
262
+ const inner = await (0, customer_key_1.unwrapVersion)(wrapped, from, label);
263
+ const envelope = await (0, customer_key_1.wrapEnvelope)(to, inner, detail.encryptionContext);
264
+ rewrapped.push(await this.putWrapping(detail.id, version, { envelope, innerDigest: wrapped.innerDigest }));
265
+ }
266
+ return rewrapped;
267
+ }
268
+ catch (error) {
269
+ return rethrow(error, `Failed to rewrap secret ${secret}`);
270
+ }
271
+ }
272
+ /**
273
+ * Replace a customer-protected version's outer envelope with one you
274
+ * wrapped yourself. `innerDigest` must match the version's: only the
275
+ * wrapping changes, never the value. `rewrap()` does this for you.
276
+ */
277
+ async replaceVersionWrapping(secret, version, params) {
278
+ assertVersion(version, false);
279
+ const { envelope, innerDigest } = params ?? {};
280
+ if (typeof envelope !== "string" || !envelope) {
281
+ throw (0, error_1.invalidRequest)("envelope must be the wrapped envelope");
282
+ }
283
+ if (typeof innerDigest !== "string" || !innerDigest) {
284
+ throw (0, error_1.invalidRequest)("innerDigest must be the version's innerDigest");
285
+ }
286
+ try {
287
+ const { id } = await this.resolve(secret);
288
+ return await this.putWrapping(id, version, { envelope, innerDigest });
289
+ }
290
+ catch (error) {
291
+ return rethrow(error, `Failed to replace the wrapping of version ${version} of secret ${secret}`);
292
+ }
293
+ }
158
294
  /**
159
295
  * Replace the origins a secret may be filled into in browser sessions, or
160
296
  * clear them with `null` (it then can't be filled until origins are set
@@ -180,9 +316,7 @@ class SecretsService extends base_1.BaseService {
180
316
  }
181
317
  /** Delete one stored version. The latest version cannot be deleted. */
182
318
  async deleteVersion(secret, version) {
183
- if (!Number.isSafeInteger(version) || version < 1 || version > secret_references_1.MAX_SECRET_VERSION) {
184
- throw new error_1.HyperbrowserError(`version must be an integer from 1 to ${secret_references_1.MAX_SECRET_VERSION}`);
185
- }
319
+ assertVersion(version, false);
186
320
  try {
187
321
  const { id } = await this.resolve(secret);
188
322
  return await this.request(`${secretPath(id)}/versions/${version}`, {
@@ -193,11 +327,32 @@ class SecretsService extends base_1.BaseService {
193
327
  return rethrow(error, `Failed to delete version ${version} of secret ${secret}`);
194
328
  }
195
329
  }
196
- /** Sealed to the context the API returned for the secret; never one built here. */
197
- uploadVersion(secret, sealer, plaintext) {
330
+ /**
331
+ * Sealed to the context the API returned for the secret; never one built
332
+ * here. With a customer key, the sealed envelope is wrapped to the same
333
+ * context and the API keeps only the wrapped one and the inner digest.
334
+ */
335
+ async uploadVersion(secret, sealer, plaintext, customerKey) {
336
+ const inner = sealer.seal(secret.encryptionContext, plaintext);
337
+ const body = customerKey === undefined
338
+ ? { envelope: inner }
339
+ : {
340
+ envelope: await (0, customer_key_1.wrapEnvelope)(customerKey, inner, secret.encryptionContext),
341
+ innerDigest: (0, customer_key_1.secretEnvelopeDigest)(inner),
342
+ innerKid: sealer.kid,
343
+ };
198
344
  return this.request(`${secretPath(secret.id)}/versions`, {
199
345
  method: "POST",
200
- body: JSON.stringify({ envelope: sealer.seal(secret.encryptionContext, plaintext) }),
346
+ body: JSON.stringify(body),
347
+ });
348
+ }
349
+ fetchWrapped(id, version) {
350
+ return this.request(`${secretPath(id)}/versions/${version}/wrapped`);
351
+ }
352
+ putWrapping(id, version, body) {
353
+ return this.request(`${secretPath(id)}/versions/${version}/wrapping`, {
354
+ method: "PUT",
355
+ body: JSON.stringify(body),
201
356
  });
202
357
  }
203
358
  async resolve(secret) {
@@ -244,12 +244,53 @@ class SessionsService extends base_1.BaseService {
244
244
  */
245
245
  async uploadFile(id, fileOptions) {
246
246
  const { fileInput, fileName } = fileOptions;
247
+ // Our own file stream, destroyed when the upload settles. A stream the
248
+ // caller passes in stays theirs and is never destroyed here.
249
+ let ownedStream;
250
+ let sourceStream;
251
+ let streamError;
252
+ let rejectStreamError;
253
+ const streamFailure = new Promise((_, reject) => {
254
+ rejectStreamError = reject;
255
+ });
256
+ streamFailure.catch(() => { });
257
+ // Aborts the in-flight request when the body fails, so the socket is not
258
+ // held open until the request timeout.
259
+ const controller = new AbortController();
260
+ let readLabel = "";
261
+ // form-data re-emits a source stream's "error" on the FormData, and
262
+ // node-fetch pipes the body without an error listener, so an unlistened
263
+ // FormData error is thrown as an uncaught exception. Every FormData body
264
+ // therefore gets a listener, whatever the input type.
265
+ const onStreamError = (error) => {
266
+ if (!streamError) {
267
+ streamError = new client_1.HyperbrowserError(`Failed to read file ${readLabel}: ${error.message}`, undefined);
268
+ }
269
+ controller.abort();
270
+ rejectStreamError?.(streamError);
271
+ };
272
+ const buildBody = (file, filename) => {
273
+ const formData = new form_data_1.default();
274
+ formData.on("error", onStreamError);
275
+ if (!Buffer.isBuffer(file)) {
276
+ sourceStream = file;
277
+ file.on("error", onStreamError);
278
+ }
279
+ formData.append("file", file, { filename });
280
+ return {
281
+ method: "POST",
282
+ body: formData,
283
+ headers: formData.getHeaders(),
284
+ signal: controller.signal,
285
+ };
286
+ };
247
287
  try {
248
288
  let fetchOptions;
249
289
  if (typeof fileInput === "string") {
250
290
  let stats;
251
291
  try {
252
292
  stats = await fs_1.promises.stat(fileInput);
293
+ await fs_1.promises.access(fileInput, fs_1.constants.R_OK);
253
294
  }
254
295
  catch (error) {
255
296
  if (error.code === "ENOENT") {
@@ -263,61 +304,47 @@ class SessionsService extends base_1.BaseService {
263
304
  if (!stats.isFile()) {
264
305
  throw new client_1.HyperbrowserError(`Path is not a file: ${fileInput}`, undefined);
265
306
  }
266
- const formData = new form_data_1.default();
267
- const fileStream = (0, fs_1.createReadStream)(fileInput);
268
- const fileBaseName = fileName || path.basename(fileInput);
269
- fileStream.on("error", (error) => {
270
- throw new client_1.HyperbrowserError(`Failed to read file ${fileInput}: ${error.message}`, undefined);
271
- });
272
- formData.append("file", fileStream, {
273
- filename: fileBaseName,
274
- });
275
- fetchOptions = {
276
- method: "POST",
277
- body: formData,
278
- headers: formData.getHeaders(),
279
- };
307
+ readLabel = `at ${fileInput}`;
308
+ ownedStream = (0, fs_1.createReadStream)(fileInput);
309
+ fetchOptions = buildBody(ownedStream, fileName || path.basename(fileInput));
280
310
  }
281
311
  else if (this.isReadableStream(fileInput)) {
282
- const formData = new form_data_1.default();
283
312
  let tmpFileName = fileName || `file-${Date.now()}`;
284
313
  if (fileInput.path && typeof fileInput.path === "string" && !fileName) {
285
314
  tmpFileName = path.basename(fileInput.path);
286
315
  }
287
- formData.append("file", fileInput, {
288
- filename: tmpFileName,
289
- });
290
- fetchOptions = {
291
- method: "POST",
292
- body: formData,
293
- headers: formData.getHeaders(),
294
- };
316
+ readLabel = `stream ${tmpFileName}`;
317
+ fetchOptions = buildBody(fileInput, tmpFileName);
295
318
  }
296
319
  else if (Buffer.isBuffer(fileInput)) {
297
320
  if (!fileName) {
298
321
  throw new client_1.HyperbrowserError("fileName is required when uploading Buffer data", undefined);
299
322
  }
300
- const formData = new form_data_1.default();
301
- formData.append("file", fileInput, {
302
- filename: fileName,
303
- });
304
- fetchOptions = {
305
- method: "POST",
306
- body: formData,
307
- headers: formData.getHeaders(),
308
- };
323
+ readLabel = `buffer ${fileName}`;
324
+ fetchOptions = buildBody(fileInput, fileName);
309
325
  }
310
326
  else {
311
327
  throw new client_1.HyperbrowserError("Unsupported file input type. Please provide a file path string, ReadStream, or Buffer.", undefined);
312
328
  }
313
- return await this.request(`/session/${id}/uploads`, fetchOptions);
329
+ const requestPromise = this.request(`/session/${id}/uploads`, fetchOptions);
330
+ requestPromise.catch(() => { });
331
+ return await Promise.race([requestPromise, streamFailure]);
314
332
  }
315
333
  catch (error) {
334
+ if (streamError) {
335
+ throw streamError;
336
+ }
316
337
  if (error instanceof client_1.HyperbrowserError) {
317
338
  throw error;
318
339
  }
319
340
  throw new client_1.HyperbrowserError(`Failed to upload file for session ${id}: ${error}`, undefined);
320
341
  }
342
+ finally {
343
+ if (sourceStream && sourceStream !== ownedStream) {
344
+ sourceStream.removeListener("error", onStreamError);
345
+ }
346
+ ownedStream?.destroy();
347
+ }
321
348
  }
322
349
  /**
323
350
  * Helper method to check if input is a readable stream
@@ -1,10 +1,17 @@
1
- import { CreateVaultParams, UpdateVaultParams, Vault, VaultDeleteResult, VaultListParams, VaultListResponse } from "../types/vault";
1
+ import { CustomerKey } from "../customer-key";
2
+ import { CreateVaultParams, UpdateVaultParams, Vault, VaultDeleteResult, VaultListParams, VaultListResponse, VaultReference, WrappedVault } from "../types/vault";
2
3
  import { BaseService } from "./base";
3
4
  /**
4
5
  * Vaults name a set of environment variables whose values come from stored
5
6
  * secrets. Pass one as `vault` to a sandbox process
6
7
  * or sandbox create, or attach it to a browser session with
7
- * `credentials: [{ vault }]` and fill its entries by name.
8
+ * `credentials: [{ vault }]` and fill its entries by name. A session
9
+ * attaches the vault by reference, so each fill uses its entries as they are
10
+ * then.
11
+ *
12
+ * Entries may be customer-protected secrets. Each sandbox or process use then
13
+ * passes the vault as `unwrap()` returns it, with those entries' envelopes
14
+ * unwrapped with your own key.
8
15
  *
9
16
  * Methods that take `vault` accept its ID or its exact name. A UUID-shaped
10
17
  * argument is tried as an ID first and then as a name.
@@ -22,5 +29,21 @@ export declare class VaultsService extends BaseService {
22
29
  update(vault: string, params: UpdateVaultParams): Promise<Vault>;
23
30
  /** Delete a vault. The secrets its entries name are kept. */
24
31
  delete(vault: string): Promise<VaultDeleteResult>;
32
+ /**
33
+ * The wrapped envelopes of a vault's customer-protected entries, each at
34
+ * the version its entry resolves to now. Most callers want `unwrap()`.
35
+ */
36
+ getWrapped(vault: string): Promise<WrappedVault>;
37
+ /**
38
+ * Unwrap a vault's customer-protected entries locally with your own key,
39
+ * giving the reference to pass as a sandbox's or process's `vault`. Each
40
+ * envelope is checked against the digest stored with its version. A vault
41
+ * with no customer-protected entries needs none and can be passed by name.
42
+ *
43
+ * `customerKey` may be several keys; each entry uses the one whose `kid`
44
+ * wrapped it. If an entry changes after this, uses fail with
45
+ * `SECRET_VAULT_CHANGED`: unwrap the vault again.
46
+ */
47
+ unwrap(vault: string, customerKey: CustomerKey | readonly CustomerKey[]): Promise<VaultReference>;
25
48
  private resolve;
26
49
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VaultsService = void 0;
4
+ const customer_key_1 = require("../customer-key");
4
5
  const error_1 = require("../error");
5
6
  const base_1 = require("./base");
6
7
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -11,7 +12,13 @@ const vaultPath = (id) => `/vaults/${encodeURIComponent(id)}`;
11
12
  * Vaults name a set of environment variables whose values come from stored
12
13
  * secrets. Pass one as `vault` to a sandbox process
13
14
  * or sandbox create, or attach it to a browser session with
14
- * `credentials: [{ vault }]` and fill its entries by name.
15
+ * `credentials: [{ vault }]` and fill its entries by name. A session
16
+ * attaches the vault by reference, so each fill uses its entries as they are
17
+ * then.
18
+ *
19
+ * Entries may be customer-protected secrets. Each sandbox or process use then
20
+ * passes the vault as `unwrap()` returns it, with those entries' envelopes
21
+ * unwrapped with your own key.
15
22
  *
16
23
  * Methods that take `vault` accept its ID or its exact name. A UUID-shaped
17
24
  * argument is tried as an ID first and then as a name.
@@ -50,6 +57,36 @@ class VaultsService extends base_1.BaseService {
50
57
  const { id } = await this.resolve(vault);
51
58
  return await this.request(vaultPath(id), { method: "DELETE" });
52
59
  }
60
+ /**
61
+ * The wrapped envelopes of a vault's customer-protected entries, each at
62
+ * the version its entry resolves to now. Most callers want `unwrap()`.
63
+ */
64
+ async getWrapped(vault) {
65
+ const { id } = await this.resolve(vault);
66
+ return await this.request(`${vaultPath(id)}/wrapped`);
67
+ }
68
+ /**
69
+ * Unwrap a vault's customer-protected entries locally with your own key,
70
+ * giving the reference to pass as a sandbox's or process's `vault`. Each
71
+ * envelope is checked against the digest stored with its version. A vault
72
+ * with no customer-protected entries needs none and can be passed by name.
73
+ *
74
+ * `customerKey` may be several keys; each entry uses the one whose `kid`
75
+ * wrapped it. If an entry changes after this, uses fail with
76
+ * `SECRET_VAULT_CHANGED`: unwrap the vault again.
77
+ */
78
+ async unwrap(vault, customerKey) {
79
+ (0, customer_key_1.assertCustomerKeys)(customerKey, "customerKey", { allowEmpty: true });
80
+ const wrapped = await this.getWrapped(vault);
81
+ const unwrapped = {};
82
+ for (const [env, entry] of Object.entries(wrapped.entries ?? {})) {
83
+ unwrapped[env] = {
84
+ version: entry.version,
85
+ unwrapped: await (0, customer_key_1.unwrapVersion)(entry, customerKey, `Entry ${env} of vault ${wrapped.name} (version ${entry.version} of secret ${entry.name})`),
86
+ };
87
+ }
88
+ return { name: wrapped.name, unwrapped };
89
+ }
53
90
  async resolve(key) {
54
91
  if (typeof key !== "string" || !key.trim()) {
55
92
  throw (0, error_1.invalidRequest)("A vault ID or name is required");
@@ -65,10 +65,10 @@ WebsiteCrawlTool.openaiToolDefinition = openai_1.CRAWL_TOOL_OPENAI;
65
65
  WebsiteCrawlTool.anthropicToolDefinition = anthropic_1.CRAWL_TOOL_ANTHROPIC;
66
66
  class WebsiteExtractTool {
67
67
  static async runnable(hb, params) {
68
- if (params.schema && typeof params.schema === "string") {
69
- params.schema = JSON.parse(params.schema);
70
- }
71
- const resp = await hb.extract.startAndWait(params);
68
+ const requestParams = params.schema && typeof params.schema === "string"
69
+ ? { ...params, schema: JSON.parse(params.schema) }
70
+ : { ...params };
71
+ const resp = await hb.extract.startAndWait(requestParams);
72
72
  return resp.data ? JSON.stringify(resp.data) : "";
73
73
  }
74
74
  }
@@ -30,7 +30,7 @@ export type BrowserUseLlm = "gpt-4o" | "gpt-4o-mini" | "gpt-4.1" | "gpt-4.1-mini
30
30
  | "claude-3-5-sonnet-20241022"
31
31
  /** @deprecated Retired; the API maps this to "claude-sonnet-5". */
32
32
  | "claude-3-5-haiku-20241022" | "gemini-2.0-flash" | "gemini-2.5-flash" | "gemini-3.8-flash";
33
- export type ClaudeComputerUseLlm = "claude-opus-5-5" | "claude-fable-5-1" | "claude-opus-5" | "claude-opus-4-8" | "claude-opus-4-7" | "claude-opus-4-6" | "claude-opus-4-5" | "claude-sonnet-5-5" | "claude-sonnet-5" | "claude-sonnet-4-6" | "claude-haiku-5-5" | "claude-haiku-4-5-20251001"
33
+ export type ClaudeComputerUseLlm = "claude-opus-5-5" | "claude-fable-5-2" | "claude-fable-5-1" | "claude-opus-5" | "claude-opus-4-8" | "claude-opus-4-7" | "claude-opus-4-6" | "claude-opus-4-5" | "claude-sonnet-5-5" | "claude-sonnet-5" | "claude-sonnet-4-6" | "claude-haiku-5-5" | "claude-haiku-4-5-20251001"
34
34
  /** @deprecated Retires November 30, 2026; use "claude-sonnet-5-5". */
35
35
  | "claude-sonnet-4-5"
36
36
  /** @deprecated Retired; the API maps this to "claude-sonnet-4-6". */
@@ -48,7 +48,7 @@ export type HyperAgentVersion = "0.8.0" | "1.1.0";
48
48
  export type HyperAgentLlm = "gpt-6-luna" | "gpt-5.6-luna" | "gpt-5.5" | "gpt-5.2" | "gpt-5.1" | "gpt-5" | "gpt-5-mini" | "gpt-4o" | "gpt-4o-mini" | "gpt-4.1" | "gpt-4.1-mini" | "gpt-4.1-nano" | "claude-sonnet-5" | "claude-sonnet-4-6" | "claude-haiku-5-5"
49
49
  /** @deprecated Retires November 30, 2026; use "claude-sonnet-5". */
50
50
  | "claude-sonnet-4-5" | "gemini-2.5-flash" | "gemini-3.8-flash" | "gemini-3.7-flash" | "gemini-3-flash-preview";
51
- export type GeminiComputerUseLlm = "gemini-4-argon" | "gemini-3.8-flash" | "gemini-3.7-flash" | "gemini-3.6-flash" | "gemini-3.5-flash" | "gemini-3.5-flash-lite" | "gemini-3-flash-preview" | "gemini-2.5-computer-use-preview-10-2025";
51
+ export type GeminiComputerUseLlm = "gemini-4-carbon" | "gemini-4-argon" | "gemini-3.8-flash" | "gemini-3.7-flash" | "gemini-3.6-flash" | "gemini-3.5-flash" | "gemini-3.5-flash-lite" | "gemini-3-flash-preview" | "gemini-2.5-computer-use-preview-10-2025";
52
52
  export type GeminiComputerUseReasoningEffort = "minimal" | "low" | "medium" | "high";
53
53
  export type GrokComputerUseLlm = "grok-4.7" | "grok-4.6" | "grok-4.5";
54
54
  export type GrokReasoningEffort = "low" | "medium" | "high";
@@ -1,13 +1,22 @@
1
+ import type { SandboxStoredSecretReference } from "./sandbox";
1
2
  /** A secret attached to a browser session, which fill may type into its pages. */
2
3
  export interface SessionCredential {
3
4
  id: string;
4
5
  name: string;
5
6
  }
7
+ /**
8
+ * A vault attached to a browser session by reference: each fill uses its
9
+ * entries as they are at that moment.
10
+ */
11
+ export interface SessionVault {
12
+ id: string;
13
+ name: string;
14
+ }
6
15
  /**
7
16
  * What to attach to a browser session at creation: a secret by name (or
8
- * `{ secret }`), `{ vault }` for the secrets a vault's entries name, or
9
- * `{ onePassword }` for an `op_token` secret that fills may read 1Password
10
- * fields with.
17
+ * `{ secret }`), `{ vault }` for a vault by reference (each fill reads its
18
+ * entries as they are then), or `{ onePassword }` for an `op_token` secret
19
+ * that fills may read 1Password fields with.
11
20
  */
12
21
  export type SessionCredentialSource = string | {
13
22
  secret: string;
@@ -47,8 +56,8 @@ export interface CredentialFillField {
47
56
  * the request names the origins it may be typed on.
48
57
  */
49
58
  export interface CredentialFillOnePassword {
50
- /** The `op_token` secret attached to the session, by name; its latest version is used. */
51
- token: string;
59
+ /** The `op_token` secret attached to the session: its name (its latest version is used), or a reference. */
60
+ token: string | SandboxStoredSecretReference;
52
61
  /** The 1Password vault's name or ID. */
53
62
  vault: string;
54
63
  /**
@@ -1,7 +1,7 @@
1
1
  export { HyperbrowserConfig } from "./config";
2
2
  export * from "./webmcp";
3
3
  export { StartCrawlJobParams, StartCrawlJobResponse, CrawledPage, CrawlJobResponse, GetCrawlJobParams, CrawlJobStatusResponse, } from "./crawl";
4
- export { StartScrapeJobParams, StartScrapeJobResponse, ScrapeJobData, ScrapeJobResponse, ScrapeOptions, ScrapeJobStatusResponse, BatchScrapeJobStatusResponse, StorageStateOptions, } from "./scrape";
4
+ export { StartScrapeJobParams, StartScrapeJobResponse, ScrapeJobData, ScrapeJobResponse, ScrapeOptions, ScrapeJobStatusResponse, StartBatchScrapeJobParams, StartBatchScrapeJobResponse, BatchScrapeJobStatusResponse, BatchScrapeJobResponse, GetBatchScrapeJobParams, ScrapedPage, ScreenshotOptions, StorageStateOptions, } from "./scrape";
5
5
  export { StartExtractJobParams, StartExtractJobResponse, ExtractJobResponse, ExtractJobStatusResponse, ExtractJobMetadata, } from "./extract";
6
6
  export { StartBrowserUseTaskParams, StartBrowserUseTaskResponse, BrowserUseTaskStatusResponse, BrowserUseTaskResponse, BrowserUseTaskData, BrowserUseApiKeys, BrowserUseTaskMetadata, BrowserUseStep, BrowserUseAgentBrain, BrowserUseAgentOutput, BrowserUseActionResult, BrowserUseStepMetadata, BrowserUseTabInfo, BrowserUseBrowserStateHistory, BrowserUseAgentHistory, BrowserUseAgentOutputV0710, BrowserUseActionResultV0710, BrowserUseBrowserStateHistoryV0710, BrowserUseStepMetadataV0710, BrowserUseAgentHistoryV0710, BrowserUseAgentHistoryLatest, } from "./agents/browser-use";
7
7
  export { StartClaudeComputerUseTaskParams, StartClaudeComputerUseTaskResponse, ClaudeComputerUseTaskStatusResponse, ClaudeComputerUseTaskResponse, ClaudeComputerUseTaskData, ClaudeComputerUseStepResponse, ClaudeComputerUseApiKeys, ClaudeComputerUseTaskMetadata, } from "./agents/claude-computer-use";
@@ -11,12 +11,14 @@ export { StartGeminiComputerUseTaskParams, StartGeminiComputerUseTaskResponse, G
11
11
  export { StartGrokComputerUseTaskParams, StartGrokComputerUseTaskResponse, GrokComputerUseTaskStatusResponse, GrokComputerUseTaskResponse, GrokComputerUseTaskData, GrokComputerUseStepResponse, GrokComputerUseApiKeys, GrokComputerUseTaskMetadata, } from "./agents/grok-computer-use";
12
12
  export { StartMetaComputerUseTaskParams, StartMetaComputerUseTaskResponse, MetaComputerUseTaskStatusResponse, MetaComputerUseTaskResponse, MetaComputerUseTaskData, MetaComputerUseStepResponse, MetaComputerUseStepError, MetaComputerUseStepIncompleteDetails, MetaComputerUseStepReasoning, MetaComputerUseApiKeys, MetaComputerUseTaskMetadata, } from "./agents/meta-computer-use";
13
13
  export { StartJevComputerUseTaskParams, StartJevComputerUseTaskResponse, JevComputerUseTaskStatusResponse, JevComputerUseTaskResponse, JevComputerUseTaskData, JevComputerUseStepResponse, JevComputerUseApiKeys, JevComputerUseTaskMetadata, } from "./agents/jev-computer-use";
14
- export { BasicResponse, BrowserMemorySize, SessionStatus, Session, SessionDetail, SessionGetParams, SessionListParams, SessionListResponse, ScreenConfig, CaptchaEvaluationPageResult, CaptchaEvaluationParams, CaptchaEvaluationResponse, CaptchaEvaluationTarget, CaptchaEvaluationType, CaptchaSolverType, CreateSessionParams, CreateSessionSnapshotResponse, GetSessionDownloadsUrlResponse, GetSessionVideoRecordingUrlResponse, GetSessionRecordingUrlResponse, ImageCaptchaParam, UploadFileResponse, UploadFileOptions, GetActiveSessionsCountResponse, SessionEventLogListParams, SessionEventLogListResponse, SessionEventLog, SessionProfile, SessionLaunchState, SessionWebBotAuth, SessionCreditBreakdown, StartSessionFromSnapshotParams, WebBotAuthParams, ProxyRoute, UpdateSessionProfileParams, UpdateSessionProxyLocationParams, UpdateSessionProxyParams, UpdateSessionScreenParams, UpdateSessionSolveCaptchasParams, UpdateSessionSolveCaptchasResponse, } from "./session";
15
- export { SandboxStatus, SandboxRuntimeTarget, SandboxNetworkPolicy, SandboxNetworkPolicyPatch, SandboxNetworkUpdateResult, Sandbox, SandboxDetail, SandboxVolumeMountType, SandboxVolumeMount, SandboxSecretReference, SandboxSecrets, SandboxResolvedSecret, SandboxStoredSecretBinding, SandboxOnePasswordBinding, SandboxSecretSource, SandboxOnePassword, SandboxOnePasswordField, SandboxListParams, SandboxListResponse, SandboxImageSource, SandboxImageSummary, SandboxImageListParams, SandboxImageListResponse, SandboxSnapshotStatus, SandboxSnapshotSummary, SandboxSnapshotListParams, SandboxSnapshotListResponse, SandboxSnapshotDeleteResult, SandboxImageDeleteResult, SandboxImageInit, SandboxImageBuildStatus, SandboxImageBuildInputFormat, SandboxImageBuildSourcePlatform, SandboxImageBuildUpload, SandboxImageBuild, SandboxBuildContextBundle, SandboxBuildContextMode, SandboxBuildContextManifest, SandboxDockerImageConfig, SandboxDockerImageLayer, SandboxDockerImageManifest, CreateSandboxImageBuildParams, ReuseSandboxDockerImageParams, CompleteSandboxImageBuildParams, SandboxImageBuildCreateResult, SandboxDockerImageReuseResult, SandboxImageBuildResolutionOutcome, SandboxImageBuildResolution, SandboxImageBuildWaitOptions, BuildSandboxImageFromDockerImageOptions, BuildSandboxImageFromDockerfileOptions, GetOrBuildSandboxImageOptions, SandboxImageBuildListParams, SandboxImageBuildListResponse, CreateSandboxParams, SandboxMemorySnapshotParams, SandboxMemorySnapshotResult, SandboxExposeParams, SandboxExposeResult, SandboxUnexposeResult, SandboxProcessStatus, SandboxExecParams, SandboxExecOptions, SandboxProcessSummary, SandboxProcessResult, SandboxProcessListParams, SandboxProcessListResponse, SandboxProcessWaitParams, SandboxProcessSignal, SandboxProcessStdinParams, SandboxProcessOutputEvent, SandboxProcessExitEvent, SandboxProcessStreamEvent, SandboxFileType, SandboxFileInfo, SandboxFileWriteInfo, SandboxFileListOptions, SandboxFileReadFormat, SandboxFileReadOptions, SandboxFileWriteData, SandboxFileWriteEntry, SandboxFileTextWriteOptions, SandboxFileBytesWriteOptions, SandboxFileMakeDirOptions, SandboxFileCopyParams, SandboxFileChmodParams, SandboxFileChownParams, SandboxFileTransferResult, SandboxFileSystemEventType, SandboxFileSystemEvent, SandboxWatchDirOptions, SandboxPresignFileParams, SandboxPresignedUrl, SandboxTerminalCreateParams, SandboxTerminalOutputChunk, SandboxTerminalStatus, SandboxTerminalWaitParams, SandboxTerminalKillParams, SandboxTerminalEvent, } from "./sandbox";
14
+ export { BasicResponse, BrowserMemorySize, SessionStatus, Session, SessionDetail, SessionGetParams, SessionListParams, SessionListResponse, ScreenConfig, CreateSessionProfile, CaptchaEvaluationPageResult, CaptchaEvaluationParams, CaptchaEvaluationResponse, CaptchaEvaluationTarget, CaptchaEvaluationType, CaptchaSolverType, CreateSessionParams, CreateSessionSnapshotResponse, SessionRecording, GetSessionDownloadsUrlResponse, GetSessionVideoRecordingUrlResponse, GetSessionRecordingUrlResponse, ImageCaptchaParam, UploadFileResponse, UploadFileOptions, GetActiveSessionsCountResponse, SessionEventLogListParams, SessionEventLogListResponse, SessionEventLog, SessionProfile, SessionLaunchState, SessionWebBotAuth, SessionCreditBreakdown, StartSessionFromSnapshotParams, WebBotAuthParams, ProxyRoute, UpdateSessionProfileParams, UpdateSessionProxyLocationParams, UpdateSessionProxyParams, UpdateSessionScreenParams, UpdateSessionSolveCaptchasParams, UpdateSessionSolveCaptchasResponse, } from "./session";
15
+ export { SandboxStatus, SandboxRuntimeTarget, SandboxNetworkPolicy, SandboxNetworkPolicyPatch, SandboxNetworkUpdateResult, Sandbox, SandboxDetail, SandboxVolumeMountType, SandboxVolumeMount, SandboxSecretReference, SandboxStoredSecretReference, SandboxSecrets, SandboxVaultSource, SandboxResolvedSecret, SandboxStoredSecretBinding, SandboxOnePasswordBinding, SandboxSecretSource, SandboxOnePassword, SandboxOnePasswordField, SandboxListParams, SandboxListResponse, SandboxImageSource, SandboxImageSummary, SandboxImageListParams, SandboxImageListResponse, SandboxSnapshotStatus, SandboxSnapshotSummary, SandboxSnapshotListParams, SandboxSnapshotListResponse, SandboxSnapshotDeleteResult, SandboxImageDeleteResult, SandboxImageInit, SandboxImageBuildStatus, SandboxImageBuildInputFormat, SandboxImageBuildSourcePlatform, SandboxImageBuildUpload, SandboxImageBuild, SandboxBuildContextBundle, SandboxBuildContextMode, SandboxBuildContextManifest, SandboxDockerImageConfig, SandboxDockerImageLayer, SandboxDockerImageManifest, CreateSandboxImageBuildParams, ReuseSandboxDockerImageParams, CompleteSandboxImageBuildParams, SandboxImageBuildCreateResult, SandboxDockerImageReuseResult, SandboxImageBuildResolutionOutcome, SandboxImageBuildResolution, SandboxImageBuildWaitOptions, BuildSandboxImageFromDockerImageOptions, BuildSandboxImageFromDockerfileOptions, GetOrBuildSandboxImageOptions, SandboxImageBuildListParams, SandboxImageBuildListResponse, CreateSandboxParams, SandboxMemorySnapshotParams, SandboxMemorySnapshotResult, SandboxExposeParams, SandboxExposeResult, SandboxUnexposeResult, SandboxProcessStatus, SandboxExecParams, SandboxExecOptions, SandboxProcessSummary, SandboxProcessResult, SandboxProcessListParams, SandboxProcessListResponse, SandboxProcessWaitParams, SandboxProcessSignal, SandboxProcessStdinParams, SandboxProcessOutputEvent, SandboxProcessExitEvent, SandboxProcessStreamEvent, SandboxFileType, SandboxFileInfo, SandboxFileWriteInfo, SandboxFileListOptions, SandboxFileReadFormat, SandboxFileReadOptions, SandboxFileWriteData, SandboxFileWriteEntry, SandboxFileTextWriteOptions, SandboxFileBytesWriteOptions, SandboxFileMakeDirOptions, SandboxFileCopyParams, SandboxFileChmodParams, SandboxFileChownParams, SandboxFileTransferResult, SandboxFileSystemEventType, SandboxFileSystemEvent, SandboxWatchDirOptions, SandboxPresignFileParams, SandboxPresignedUrl, SandboxTerminalCreateParams, SandboxTerminalOutputChunk, SandboxTerminalStatus, SandboxTerminalWaitParams, SandboxTerminalKillParams, SandboxTerminalEvent, } from "./sandbox";
16
16
  export { CreateVolumeParams, Volume, VolumeListParams, VolumeListResponse, VolumeDeleteResult, } from "./volume";
17
- export { SecretValue, SecretType, SecretBrowserMetadata, SecretMetadata, UpdateSecretMetadata, SecretsPublicKey, SecretsPublicKeyJwk, Secret, SecretVersion, SecretDetail, CreateSecretParams, UpdateSecretParams, SecretListParams, SecretListResponse, SecretDeleteResult, SecretVersionDeleteResult, } from "./secret";
18
- export { SessionCredential, SessionCredentialSource, CredentialFillField, CredentialFillRef, CredentialFillOnePassword, FillCredentialParams, CredentialFillOutcome, CredentialFillFieldResult, CredentialFillResult, CredentialFillPage, } from "./credential";
19
- export { Vault, VaultEntry, VaultEntryParams, CreateVaultParams, UpdateVaultParams, VaultListParams, VaultListResponse, VaultDeleteResult, } from "./vault";
17
+ export { SecretValue, SecretType, SecretProtection, SecretBrowserMetadata, SecretMetadata, UpdateSecretMetadata, SecretsPublicKey, SecretsPublicKeyJwk, Secret, SecretVersion, SecretDetail, CreateSecretParams, UpdateSecretParams, SecretListParams, SecretListResponse, SecretDeleteResult, SecretVersionDeleteResult, WrappedSecretVersion, UnwrappedSecretReference, UnwrapSecretOptions, AddSecretVersionOptions, ReplaceSecretVersionWrappingParams, RewrapSecretParams, } from "./secret";
18
+ export { SessionCredential, SessionCredentialSource, SessionVault } from "./credential";
19
+ export type { CustomerKey, CustomerKeyAlgorithm, CustomerKeyInput, CustomerKeyOptions, } from "../customer-key";
20
+ export { CredentialFillField, CredentialFillRef, CredentialFillOnePassword, FillCredentialParams, CredentialFillOutcome, CredentialFillFieldResult, CredentialFillResult, CredentialFillPage, } from "./credential";
21
+ export { Vault, VaultEntry, VaultEntryParams, CreateVaultParams, UpdateVaultParams, VaultListParams, VaultListResponse, VaultDeleteResult, WrappedVault, WrappedVaultEntry, VaultUnwrappedEntry, VaultReference, } from "./vault";
20
22
  export { CreateProfileParams, ForkProfileParams, ProfileResponse, CreateProfileResponse, ProfileListParams, ProfileListResponse, } from "./profile";
21
23
  export { CreateExtensionParams, CreateExtensionResponse, ListExtensionsResponse, } from "./extension";
22
24
  export { ExtractJobStatus, BrowserUseTaskStatus, BrowserUseLlm, ClaudeComputerUseLlm, ClaudeComputerUseReasoningEffort, CuaLlm, CuaReasoningEffort, GeminiComputerUseLlm, GeminiComputerUseReasoningEffort, GrokComputerUseLlm, GrokReasoningEffort, MetaComputerUseLlm, MetaReasoningEffort, JevComputerUseLlm, JevTextLlm, ScrapeScreenshotFormat, ScrapeJobStatus, CrawlJobStatus, Country, State, ISO639_1, OperatingSystem, Platform, ScrapeFormat, ScrapeWaitUntil, ScrapePageStatus, CrawlPageStatus, RecordingStatus, DownloadsStatus, HyperAgentLlm, HyperAgentTaskStatus, ClaudeComputerUseTaskStatus, CuaTaskStatus, GeminiComputerUseTaskStatus, GrokComputerUseTaskStatus, MetaComputerUseTaskStatus, JevComputerUseTaskStatus, SessionEventLogType, SessionRegion, BrowserUseVersion, HyperAgentVersion, } from "./constants";
@@ -24,6 +26,7 @@ export { TeamCreditInfo } from "./team";
24
26
  export { ComputerAction, Coordinate, ClickActionParams, DragActionParams, PressKeysActionParams, MoveMouseActionParams, ScreenshotActionParams, CursorPositionActionParams, ScrollAtCursorActionParams, ScrollActionParams, TypeTextActionParams, ComputerActionParams, ComputerActionResponse, ComputerActionMouseButton, ComputerActionResponseData, HoldKeyActionParams, MouseDownActionParams, MouseUpActionParams, GetClipboardTextActionParams, PutSelectionTextActionParams, ComputerActionResponseDataClipboardText, ListWindowsActionParams, ComputerActionWindow, ComputerActionResponseDataListWindows, ComputerActionResponseDataCursorPosition, } from "./computer-action";
25
27
  export { FetchParams, FetchResponse, FetchResponseData, FetchStatus } from "./web/fetch";
26
28
  export { StartBatchFetchJobParams, GetBatchFetchJobParams, StartBatchFetchJobResponse, BatchFetchJobStatusResponse, BatchFetchJobResponse, BatchFetchJobStatus, } from "./web/batch-fetch";
29
+ export { WebCrawlJobStatus, WebCrawlOptions, StartWebCrawlJobParams, GetWebCrawlJobParams, StartWebCrawlJobResponse, WebCrawlJobStatusResponse, WebCrawlJobResponse, } from "./web/crawl";
27
30
  export { WebSearchParams, WebSearchResponse, WebSearchResponseData, WebSearchResultItem, WebSearchFilters, WebSearchLocation, WebSearchFiletype, WebSearchStatus, } from "./web/search";
28
31
  export { FetchStealthMode, FetchSanitizeMode, FetchWaitUntil, FetchScreenshotFormat, PageStatus, FetchOutputScreenshotOptions, FetchStorageStateOptions, FetchBrowserLocationOptions, PageData, FetchOutputMarkdown, FetchOutputHtml, FetchOutputLinks, FetchOutputScreenshot, FetchOutputJsonOptions, FetchOutputJson, FetchOutputBranding, FetchOutputFormat, FetchOutputOptions, FetchBrowserOptions, FetchNavigationOptions, FetchCacheOptions, } from "./web/common";
29
32
  export { BrandingProfile, BrandingColors, BrandingFont, BrandingFontRole, BrandingTypography, BrandingFontFamilies, BrandingFontStacks, BrandingFontSizes, BrandingSpacing, BrandingComponents, BrandingButtonStyle, BrandingInputStyle, BrandingBorderRadiusCorners, BrandingImages, BrandingPersonality, BrandingPersonalityTone, BrandingPersonalityEnergy, BrandingDesignSystem, BrandingDesignFramework, BrandingConfidence, BrandingColorScheme, } from "./web/branding";