@autohq/cli 0.1.364 → 0.1.366
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/dist/agent-bridge.js +55 -4
- package/dist/index.js +211 -11
- package/package.json +1 -1
package/dist/agent-bridge.js
CHANGED
|
@@ -23492,7 +23492,7 @@ Object.assign(lookup, {
|
|
|
23492
23492
|
// package.json
|
|
23493
23493
|
var package_default = {
|
|
23494
23494
|
name: "@autohq/cli",
|
|
23495
|
-
version: "0.1.
|
|
23495
|
+
version: "0.1.366",
|
|
23496
23496
|
license: "SEE LICENSE IN README.md",
|
|
23497
23497
|
publishConfig: {
|
|
23498
23498
|
access: "public"
|
|
@@ -26200,11 +26200,48 @@ var EncryptedSecretValueSchema = external_exports.object({
|
|
|
26200
26200
|
dekAuthTag: SecretAesGcmAuthTagSchema
|
|
26201
26201
|
});
|
|
26202
26202
|
var SecretDescriptionSchema = external_exports.string().trim().max(1024);
|
|
26203
|
+
var SECRET_IDLE_EXPIRY_MAX_SECONDS = 10 * 365 * 24 * 60 * 60;
|
|
26204
|
+
var SecretExpiresAtSchema = external_exports.string().datetime({ offset: true });
|
|
26205
|
+
var SecretIdleExpirySecondsSchema = external_exports.number().int().min(1).max(SECRET_IDLE_EXPIRY_MAX_SECONDS);
|
|
26206
|
+
var SECRET_BINDING_HOST_PATTERN = /^(?=.{1,253}$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
26207
|
+
var SECRET_BINDING_HEADER_PATTERN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
26208
|
+
var SECRET_BINDING_FORBIDDEN_HEADERS = /* @__PURE__ */ new Set([
|
|
26209
|
+
"connection",
|
|
26210
|
+
"content-length",
|
|
26211
|
+
"host",
|
|
26212
|
+
"transfer-encoding"
|
|
26213
|
+
]);
|
|
26214
|
+
var SecretBindingHostSchema = external_exports.string().trim().toLowerCase().regex(
|
|
26215
|
+
SECRET_BINDING_HOST_PATTERN,
|
|
26216
|
+
"Binding hosts must be exact lowercase hostnames (no wildcards, schemes, ports, or paths)"
|
|
26217
|
+
);
|
|
26218
|
+
var SecretBindingHeaderSchema = external_exports.string().trim().min(1).max(128).regex(SECRET_BINDING_HEADER_PATTERN, "Invalid HTTP header name").refine(
|
|
26219
|
+
(header) => !SECRET_BINDING_FORBIDDEN_HEADERS.has(header.toLowerCase()),
|
|
26220
|
+
"This header cannot carry a secret binding"
|
|
26221
|
+
);
|
|
26222
|
+
var SecretBindingSchema = external_exports.object({
|
|
26223
|
+
hosts: external_exports.array(SecretBindingHostSchema).min(1).max(16),
|
|
26224
|
+
header: SecretBindingHeaderSchema,
|
|
26225
|
+
format: external_exports.string().min(1).max(256).refine(
|
|
26226
|
+
(format) => format.includes("{value}"),
|
|
26227
|
+
"Binding format must contain the {value} placeholder"
|
|
26228
|
+
).optional()
|
|
26229
|
+
});
|
|
26203
26230
|
var SecretSetRequestSchema = external_exports.object({
|
|
26204
26231
|
value: external_exports.string(),
|
|
26205
26232
|
description: SecretDescriptionSchema.nullable().optional(),
|
|
26206
|
-
protected: external_exports.boolean().optional()
|
|
26207
|
-
|
|
26233
|
+
protected: external_exports.boolean().optional(),
|
|
26234
|
+
binding: SecretBindingSchema.nullable().optional(),
|
|
26235
|
+
expiresAt: SecretExpiresAtSchema.nullable().optional(),
|
|
26236
|
+
idleExpirySeconds: SecretIdleExpirySecondsSchema.nullable().optional()
|
|
26237
|
+
});
|
|
26238
|
+
var SecretExpiryUpdateRequestSchema = external_exports.object({
|
|
26239
|
+
expiresAt: SecretExpiresAtSchema.nullable().optional(),
|
|
26240
|
+
idleExpirySeconds: SecretIdleExpirySecondsSchema.nullable().optional()
|
|
26241
|
+
}).refine(
|
|
26242
|
+
(input) => input.expiresAt !== void 0 || input.idleExpirySeconds !== void 0,
|
|
26243
|
+
{ message: "Provide expiresAt and/or idleExpirySeconds" }
|
|
26244
|
+
);
|
|
26208
26245
|
var SecretRotateRequestSchema = external_exports.object({
|
|
26209
26246
|
value: external_exports.string()
|
|
26210
26247
|
});
|
|
@@ -26215,10 +26252,21 @@ var SecretMetadataSchema = external_exports.object({
|
|
|
26215
26252
|
name: ResourceNameSchema,
|
|
26216
26253
|
description: external_exports.string().nullable(),
|
|
26217
26254
|
protected: external_exports.boolean(),
|
|
26255
|
+
// Defaulted rather than required so a newer client parsing an older
|
|
26256
|
+
// server's metadata (deploy skew) treats an absent binding as unbound.
|
|
26257
|
+
binding: SecretBindingSchema.nullable().default(null),
|
|
26218
26258
|
createdAt: external_exports.string().datetime(),
|
|
26219
26259
|
updatedAt: external_exports.string().datetime(),
|
|
26220
26260
|
lastRotatedAt: external_exports.string().datetime().nullable(),
|
|
26221
|
-
lastAccessedAt: external_exports.string().datetime().nullable()
|
|
26261
|
+
lastAccessedAt: external_exports.string().datetime().nullable(),
|
|
26262
|
+
// Like binding, defaulted for deploy skew: an older server that never sends
|
|
26263
|
+
// expiry fields parses as a secret that never expires.
|
|
26264
|
+
expiresAt: external_exports.string().datetime().nullable().default(null),
|
|
26265
|
+
idleExpirySeconds: external_exports.number().int().nullable().default(null),
|
|
26266
|
+
// Computed server-side: true when expiresAt has passed or the secret has
|
|
26267
|
+
// been unused past idleExpirySeconds. Expired secrets resolve as absent
|
|
26268
|
+
// everywhere but stay listed so operators can see and delete them.
|
|
26269
|
+
expired: external_exports.boolean().default(false)
|
|
26222
26270
|
});
|
|
26223
26271
|
var SecretSetResponseSchema = external_exports.object({
|
|
26224
26272
|
secret: SecretMetadataSchema
|
|
@@ -26229,6 +26277,9 @@ var SecretListResponseSchema = external_exports.object({
|
|
|
26229
26277
|
var SecretDeleteResponseSchema = external_exports.object({
|
|
26230
26278
|
secret: SecretMetadataSchema
|
|
26231
26279
|
});
|
|
26280
|
+
var SecretExpiryUpdateResponseSchema = external_exports.object({
|
|
26281
|
+
secret: SecretMetadataSchema
|
|
26282
|
+
});
|
|
26232
26283
|
var SecretRevealResponseSchema = external_exports.object({
|
|
26233
26284
|
secret: SecretMetadataSchema,
|
|
26234
26285
|
value: external_exports.string()
|
package/dist/index.js
CHANGED
|
@@ -17599,7 +17599,7 @@ var init_mounts = __esm({
|
|
|
17599
17599
|
});
|
|
17600
17600
|
|
|
17601
17601
|
// ../../packages/schemas/src/secrets.ts
|
|
17602
|
-
var SECRET_ENCRYPTION_ALGORITHM, SecretEnvNameSchema, SecretCiphertextFieldSchema, SecretAesGcmIvSchema, SecretAesGcmAuthTagSchema, SecretEnvValueSchema, SecretEnvSchema, EncryptedSecretValueSchema, SecretDescriptionSchema, SecretSetRequestSchema, SecretRotateRequestSchema, SecretMetadataSchema, SecretSetResponseSchema, SecretListResponseSchema, SecretDeleteResponseSchema, SecretRevealResponseSchema;
|
|
17602
|
+
var SECRET_ENCRYPTION_ALGORITHM, SecretEnvNameSchema, SecretCiphertextFieldSchema, SecretAesGcmIvSchema, SecretAesGcmAuthTagSchema, SecretEnvValueSchema, SecretEnvSchema, EncryptedSecretValueSchema, SecretDescriptionSchema, SECRET_IDLE_EXPIRY_MAX_SECONDS, SecretExpiresAtSchema, SecretIdleExpirySecondsSchema, SECRET_BINDING_HOST_PATTERN, SECRET_BINDING_HEADER_PATTERN, SECRET_BINDING_FORBIDDEN_HEADERS, SecretBindingHostSchema, SecretBindingHeaderSchema, SecretBindingSchema, SecretSetRequestSchema, SecretExpiryUpdateRequestSchema, SecretRotateRequestSchema, SecretMetadataSchema, SecretSetResponseSchema, SecretListResponseSchema, SecretDeleteResponseSchema, SecretExpiryUpdateResponseSchema, SecretRevealResponseSchema;
|
|
17603
17603
|
var init_secrets = __esm({
|
|
17604
17604
|
"../../packages/schemas/src/secrets.ts"() {
|
|
17605
17605
|
"use strict";
|
|
@@ -17632,11 +17632,48 @@ var init_secrets = __esm({
|
|
|
17632
17632
|
dekAuthTag: SecretAesGcmAuthTagSchema
|
|
17633
17633
|
});
|
|
17634
17634
|
SecretDescriptionSchema = external_exports.string().trim().max(1024);
|
|
17635
|
+
SECRET_IDLE_EXPIRY_MAX_SECONDS = 10 * 365 * 24 * 60 * 60;
|
|
17636
|
+
SecretExpiresAtSchema = external_exports.string().datetime({ offset: true });
|
|
17637
|
+
SecretIdleExpirySecondsSchema = external_exports.number().int().min(1).max(SECRET_IDLE_EXPIRY_MAX_SECONDS);
|
|
17638
|
+
SECRET_BINDING_HOST_PATTERN = /^(?=.{1,253}$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
17639
|
+
SECRET_BINDING_HEADER_PATTERN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
17640
|
+
SECRET_BINDING_FORBIDDEN_HEADERS = /* @__PURE__ */ new Set([
|
|
17641
|
+
"connection",
|
|
17642
|
+
"content-length",
|
|
17643
|
+
"host",
|
|
17644
|
+
"transfer-encoding"
|
|
17645
|
+
]);
|
|
17646
|
+
SecretBindingHostSchema = external_exports.string().trim().toLowerCase().regex(
|
|
17647
|
+
SECRET_BINDING_HOST_PATTERN,
|
|
17648
|
+
"Binding hosts must be exact lowercase hostnames (no wildcards, schemes, ports, or paths)"
|
|
17649
|
+
);
|
|
17650
|
+
SecretBindingHeaderSchema = external_exports.string().trim().min(1).max(128).regex(SECRET_BINDING_HEADER_PATTERN, "Invalid HTTP header name").refine(
|
|
17651
|
+
(header) => !SECRET_BINDING_FORBIDDEN_HEADERS.has(header.toLowerCase()),
|
|
17652
|
+
"This header cannot carry a secret binding"
|
|
17653
|
+
);
|
|
17654
|
+
SecretBindingSchema = external_exports.object({
|
|
17655
|
+
hosts: external_exports.array(SecretBindingHostSchema).min(1).max(16),
|
|
17656
|
+
header: SecretBindingHeaderSchema,
|
|
17657
|
+
format: external_exports.string().min(1).max(256).refine(
|
|
17658
|
+
(format) => format.includes("{value}"),
|
|
17659
|
+
"Binding format must contain the {value} placeholder"
|
|
17660
|
+
).optional()
|
|
17661
|
+
});
|
|
17635
17662
|
SecretSetRequestSchema = external_exports.object({
|
|
17636
17663
|
value: external_exports.string(),
|
|
17637
17664
|
description: SecretDescriptionSchema.nullable().optional(),
|
|
17638
|
-
protected: external_exports.boolean().optional()
|
|
17639
|
-
|
|
17665
|
+
protected: external_exports.boolean().optional(),
|
|
17666
|
+
binding: SecretBindingSchema.nullable().optional(),
|
|
17667
|
+
expiresAt: SecretExpiresAtSchema.nullable().optional(),
|
|
17668
|
+
idleExpirySeconds: SecretIdleExpirySecondsSchema.nullable().optional()
|
|
17669
|
+
});
|
|
17670
|
+
SecretExpiryUpdateRequestSchema = external_exports.object({
|
|
17671
|
+
expiresAt: SecretExpiresAtSchema.nullable().optional(),
|
|
17672
|
+
idleExpirySeconds: SecretIdleExpirySecondsSchema.nullable().optional()
|
|
17673
|
+
}).refine(
|
|
17674
|
+
(input) => input.expiresAt !== void 0 || input.idleExpirySeconds !== void 0,
|
|
17675
|
+
{ message: "Provide expiresAt and/or idleExpirySeconds" }
|
|
17676
|
+
);
|
|
17640
17677
|
SecretRotateRequestSchema = external_exports.object({
|
|
17641
17678
|
value: external_exports.string()
|
|
17642
17679
|
});
|
|
@@ -17647,10 +17684,21 @@ var init_secrets = __esm({
|
|
|
17647
17684
|
name: ResourceNameSchema,
|
|
17648
17685
|
description: external_exports.string().nullable(),
|
|
17649
17686
|
protected: external_exports.boolean(),
|
|
17687
|
+
// Defaulted rather than required so a newer client parsing an older
|
|
17688
|
+
// server's metadata (deploy skew) treats an absent binding as unbound.
|
|
17689
|
+
binding: SecretBindingSchema.nullable().default(null),
|
|
17650
17690
|
createdAt: external_exports.string().datetime(),
|
|
17651
17691
|
updatedAt: external_exports.string().datetime(),
|
|
17652
17692
|
lastRotatedAt: external_exports.string().datetime().nullable(),
|
|
17653
|
-
lastAccessedAt: external_exports.string().datetime().nullable()
|
|
17693
|
+
lastAccessedAt: external_exports.string().datetime().nullable(),
|
|
17694
|
+
// Like binding, defaulted for deploy skew: an older server that never sends
|
|
17695
|
+
// expiry fields parses as a secret that never expires.
|
|
17696
|
+
expiresAt: external_exports.string().datetime().nullable().default(null),
|
|
17697
|
+
idleExpirySeconds: external_exports.number().int().nullable().default(null),
|
|
17698
|
+
// Computed server-side: true when expiresAt has passed or the secret has
|
|
17699
|
+
// been unused past idleExpirySeconds. Expired secrets resolve as absent
|
|
17700
|
+
// everywhere but stay listed so operators can see and delete them.
|
|
17701
|
+
expired: external_exports.boolean().default(false)
|
|
17654
17702
|
});
|
|
17655
17703
|
SecretSetResponseSchema = external_exports.object({
|
|
17656
17704
|
secret: SecretMetadataSchema
|
|
@@ -17661,6 +17709,9 @@ var init_secrets = __esm({
|
|
|
17661
17709
|
SecretDeleteResponseSchema = external_exports.object({
|
|
17662
17710
|
secret: SecretMetadataSchema
|
|
17663
17711
|
});
|
|
17712
|
+
SecretExpiryUpdateResponseSchema = external_exports.object({
|
|
17713
|
+
secret: SecretMetadataSchema
|
|
17714
|
+
});
|
|
17664
17715
|
SecretRevealResponseSchema = external_exports.object({
|
|
17665
17716
|
secret: SecretMetadataSchema,
|
|
17666
17717
|
value: external_exports.string()
|
|
@@ -30511,6 +30562,25 @@ function createApiClient(input) {
|
|
|
30511
30562
|
}
|
|
30512
30563
|
return SecretSetResponseSchema.parse(await response.json());
|
|
30513
30564
|
},
|
|
30565
|
+
async updateSecretExpiry(name, request, options = {}) {
|
|
30566
|
+
const organization = await activeOrganization();
|
|
30567
|
+
const path2 = `${secretPath(organization.organizationId, options.projectId, name)}/expiry`;
|
|
30568
|
+
const response = await authenticatedFetch(
|
|
30569
|
+
apiUrl(path2, options.apiBaseUrl),
|
|
30570
|
+
{
|
|
30571
|
+
method: "PATCH",
|
|
30572
|
+
headers: {
|
|
30573
|
+
"content-type": "application/json"
|
|
30574
|
+
},
|
|
30575
|
+
body: JSON.stringify(request)
|
|
30576
|
+
},
|
|
30577
|
+
options.apiBaseUrl
|
|
30578
|
+
);
|
|
30579
|
+
if (!response.ok) {
|
|
30580
|
+
throw new Error(await responseErrorMessage(response));
|
|
30581
|
+
}
|
|
30582
|
+
return SecretExpiryUpdateResponseSchema.parse(await response.json());
|
|
30583
|
+
},
|
|
30514
30584
|
async revealSecret(name, options = {}) {
|
|
30515
30585
|
const organization = await activeOrganization();
|
|
30516
30586
|
const path2 = `${secretPath(organization.organizationId, options.projectId, name)}/value`;
|
|
@@ -31577,7 +31647,7 @@ var init_package = __esm({
|
|
|
31577
31647
|
"package.json"() {
|
|
31578
31648
|
package_default = {
|
|
31579
31649
|
name: "@autohq/cli",
|
|
31580
|
-
version: "0.1.
|
|
31650
|
+
version: "0.1.366",
|
|
31581
31651
|
license: "SEE LICENSE IN README.md",
|
|
31582
31652
|
publishConfig: {
|
|
31583
31653
|
access: "public"
|
|
@@ -50019,6 +50089,7 @@ function memberLine2(member, style) {
|
|
|
50019
50089
|
}
|
|
50020
50090
|
|
|
50021
50091
|
// src/commands/secrets/actions.ts
|
|
50092
|
+
init_src();
|
|
50022
50093
|
async function setSecret(input) {
|
|
50023
50094
|
const value = await secretValue({
|
|
50024
50095
|
options: input.commandOptions,
|
|
@@ -50030,7 +50101,9 @@ async function setSecret(input) {
|
|
|
50030
50101
|
{
|
|
50031
50102
|
value,
|
|
50032
50103
|
...input.commandOptions.description === void 0 ? {} : { description: input.commandOptions.description },
|
|
50033
|
-
...resolveProtectedFlag(input.commandOptions)
|
|
50104
|
+
...resolveProtectedFlag(input.commandOptions),
|
|
50105
|
+
...resolveExpiryFields(input.commandOptions),
|
|
50106
|
+
...resolveBindingFlags(input.commandOptions)
|
|
50034
50107
|
},
|
|
50035
50108
|
{
|
|
50036
50109
|
projectId: await secretProjectId(input),
|
|
@@ -50055,6 +50128,17 @@ async function rotateSecret(input) {
|
|
|
50055
50128
|
);
|
|
50056
50129
|
writeRotateResponse(response, input);
|
|
50057
50130
|
}
|
|
50131
|
+
async function updateSecretExpiry(input) {
|
|
50132
|
+
const fields = resolveExpiryFields(input.commandOptions);
|
|
50133
|
+
if (fields.expiresAt === void 0 && fields.idleExpirySeconds === void 0) {
|
|
50134
|
+
throw new Error("Provide --expires-at and/or --idle-expiry.");
|
|
50135
|
+
}
|
|
50136
|
+
const response = await input.client.updateSecretExpiry(input.name, fields, {
|
|
50137
|
+
projectId: await secretProjectId(input),
|
|
50138
|
+
apiBaseUrl: input.commandOptions.apiBaseUrl
|
|
50139
|
+
});
|
|
50140
|
+
writeExpiryResponse(response, input);
|
|
50141
|
+
}
|
|
50058
50142
|
async function revealSecret(input) {
|
|
50059
50143
|
const response = await input.client.revealSecret(input.name, {
|
|
50060
50144
|
projectId: await secretProjectId(input),
|
|
@@ -50077,9 +50161,23 @@ async function listSecrets(input) {
|
|
|
50077
50161
|
}
|
|
50078
50162
|
for (const secret of response.secrets) {
|
|
50079
50163
|
const flags = secret.protected ? "protected" : "revealable";
|
|
50080
|
-
|
|
50081
|
-
|
|
50082
|
-
|
|
50164
|
+
const parts = [
|
|
50165
|
+
secret.name,
|
|
50166
|
+
scopeLabel(secret.projectId),
|
|
50167
|
+
flags,
|
|
50168
|
+
`updated ${secret.updatedAt}`
|
|
50169
|
+
];
|
|
50170
|
+
if (secret.expired) {
|
|
50171
|
+
parts.push("expired");
|
|
50172
|
+
} else {
|
|
50173
|
+
if (secret.expiresAt !== null) {
|
|
50174
|
+
parts.push(`expires ${secret.expiresAt}`);
|
|
50175
|
+
}
|
|
50176
|
+
if (secret.idleExpirySeconds !== null) {
|
|
50177
|
+
parts.push(`idle-expiry ${secret.idleExpirySeconds}s`);
|
|
50178
|
+
}
|
|
50179
|
+
}
|
|
50180
|
+
input.context.writeOutput(parts.join(" "));
|
|
50083
50181
|
}
|
|
50084
50182
|
}
|
|
50085
50183
|
function resolveProtectedFlag(options) {
|
|
@@ -50094,6 +50192,67 @@ function resolveProtectedFlag(options) {
|
|
|
50094
50192
|
}
|
|
50095
50193
|
return {};
|
|
50096
50194
|
}
|
|
50195
|
+
function parseExpiresAt(input) {
|
|
50196
|
+
if (input === "never") {
|
|
50197
|
+
return null;
|
|
50198
|
+
}
|
|
50199
|
+
const parsed = new Date(input);
|
|
50200
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
50201
|
+
throw new Error(
|
|
50202
|
+
`Invalid --expires-at value "${input}". Use an ISO 8601 timestamp or "never".`
|
|
50203
|
+
);
|
|
50204
|
+
}
|
|
50205
|
+
return parsed.toISOString();
|
|
50206
|
+
}
|
|
50207
|
+
function parseIdleExpiry(input) {
|
|
50208
|
+
if (input === "never") {
|
|
50209
|
+
return null;
|
|
50210
|
+
}
|
|
50211
|
+
const match = /^(\d+)(s|m|h|d)?$/.exec(input);
|
|
50212
|
+
if (!match) {
|
|
50213
|
+
throw new Error(
|
|
50214
|
+
`Invalid --idle-expiry value "${input}". Use seconds or a duration like 30d, 12h, 90m, 3600s, or "never".`
|
|
50215
|
+
);
|
|
50216
|
+
}
|
|
50217
|
+
const unitSeconds = { s: 1, m: 60, h: 3600, d: 86400 }[match[2] ?? "s"] ?? 1;
|
|
50218
|
+
const seconds = Number(match[1]) * unitSeconds;
|
|
50219
|
+
if (seconds < 1 || seconds > SECRET_IDLE_EXPIRY_MAX_SECONDS) {
|
|
50220
|
+
throw new Error(
|
|
50221
|
+
`--idle-expiry must be between 1 second and ${SECRET_IDLE_EXPIRY_MAX_SECONDS} seconds (10 years).`
|
|
50222
|
+
);
|
|
50223
|
+
}
|
|
50224
|
+
return seconds;
|
|
50225
|
+
}
|
|
50226
|
+
function resolveExpiryFields(options) {
|
|
50227
|
+
return {
|
|
50228
|
+
...options.expiresAt === void 0 ? {} : { expiresAt: parseExpiresAt(options.expiresAt) },
|
|
50229
|
+
...options.idleExpiry === void 0 ? {} : { idleExpirySeconds: parseIdleExpiry(options.idleExpiry) }
|
|
50230
|
+
};
|
|
50231
|
+
}
|
|
50232
|
+
function resolveBindingFlags(options) {
|
|
50233
|
+
const hasBindingFlags = (options.bindHost?.length ?? 0) > 0 || options.bindHeader !== void 0 || options.bindFormat !== void 0;
|
|
50234
|
+
if (options.unbind) {
|
|
50235
|
+
if (hasBindingFlags) {
|
|
50236
|
+
throw new Error("Use either --unbind or the --bind-* flags, not both.");
|
|
50237
|
+
}
|
|
50238
|
+
return { binding: null };
|
|
50239
|
+
}
|
|
50240
|
+
if (!hasBindingFlags) {
|
|
50241
|
+
return {};
|
|
50242
|
+
}
|
|
50243
|
+
if (!options.bindHost?.length || options.bindHeader === void 0) {
|
|
50244
|
+
throw new Error(
|
|
50245
|
+
"Binding a secret requires at least one --bind-host and a --bind-header."
|
|
50246
|
+
);
|
|
50247
|
+
}
|
|
50248
|
+
return {
|
|
50249
|
+
binding: {
|
|
50250
|
+
hosts: options.bindHost,
|
|
50251
|
+
header: options.bindHeader,
|
|
50252
|
+
...options.bindFormat === void 0 ? {} : { format: options.bindFormat }
|
|
50253
|
+
}
|
|
50254
|
+
};
|
|
50255
|
+
}
|
|
50097
50256
|
async function removeSecret(input) {
|
|
50098
50257
|
await confirmDestructiveAction(input.context, {
|
|
50099
50258
|
message: `This will remove secret "${input.name}".`,
|
|
@@ -50175,6 +50334,16 @@ function writeRotateResponse(response, input) {
|
|
|
50175
50334
|
`secret ${response.secret.name} rotated scope=${scopeLabel(response.secret.projectId)}`
|
|
50176
50335
|
);
|
|
50177
50336
|
}
|
|
50337
|
+
function writeExpiryResponse(response, input) {
|
|
50338
|
+
if (input.commandOptions.json) {
|
|
50339
|
+
input.context.writeOutput(JSON.stringify(response));
|
|
50340
|
+
return;
|
|
50341
|
+
}
|
|
50342
|
+
const idle = response.secret.idleExpirySeconds === null ? "never" : `${response.secret.idleExpirySeconds}s`;
|
|
50343
|
+
input.context.writeOutput(
|
|
50344
|
+
`secret ${response.secret.name} expiry updated scope=${scopeLabel(response.secret.projectId)} expires=${response.secret.expiresAt ?? "never"} idle=${idle}`
|
|
50345
|
+
);
|
|
50346
|
+
}
|
|
50178
50347
|
function writeRevealResponse(response, input) {
|
|
50179
50348
|
if (input.commandOptions.json) {
|
|
50180
50349
|
input.context.writeOutput(JSON.stringify(response));
|
|
@@ -50248,10 +50417,27 @@ function registerSecretCommands(program, context) {
|
|
|
50248
50417
|
secrets.command("set").description("Create or update a secret without printing its value.").argument("<name>", "secret name").option("--project <project>", "project id; defaults to organization scope").option("--stdin", "read the secret value from stdin").option("--value <value>", "secret value").option(
|
|
50249
50418
|
"--from-env <name>",
|
|
50250
50419
|
"read the secret value from an environment variable"
|
|
50251
|
-
).option("--description <text>", "human-readable description for the secret").option(
|
|
50420
|
+
).option("--description <text>", "human-readable description for the secret").option(
|
|
50421
|
+
"--bind-host <host>",
|
|
50422
|
+
"bind the secret to an exact destination host (repeatable); bound secrets are injected at the sandbox edge instead of entering the sandbox",
|
|
50423
|
+
(host, hosts) => [...hosts, host],
|
|
50424
|
+
[]
|
|
50425
|
+
).option(
|
|
50426
|
+
"--bind-header <header>",
|
|
50427
|
+
"HTTP header the bound secret is injected into (e.g. Authorization)"
|
|
50428
|
+
).option(
|
|
50429
|
+
"--bind-format <format>",
|
|
50430
|
+
'header value template around the secret, e.g. "Bearer {value}"'
|
|
50431
|
+
).option("--unbind", "clear an existing destination binding").option("--protected", "mark write-only: refuse plaintext reveal (default)").option(
|
|
50252
50432
|
"--unprotected",
|
|
50253
50433
|
"allow scope-gated plaintext reveal of this secret"
|
|
50254
|
-
).option("--raw", "allow empty values and preserve stdin exactly").option(
|
|
50434
|
+
).option("--raw", "allow empty values and preserve stdin exactly").option(
|
|
50435
|
+
"--expires-at <timestamp>",
|
|
50436
|
+
'absolute expiry as an ISO 8601 timestamp, or "never" to clear'
|
|
50437
|
+
).option(
|
|
50438
|
+
"--idle-expiry <duration>",
|
|
50439
|
+
'expire after this long unused (seconds or 30d/12h/90m/3600s), or "never" to clear'
|
|
50440
|
+
).option("--json", "print the updated secret metadata as JSON").option("--api-url <url>", "Auto API base URL").option("--api-base-url <url>", "Auto API base URL").action(async (name, commandOptions) => {
|
|
50255
50441
|
await setSecret({
|
|
50256
50442
|
client: createContextApiClient(context),
|
|
50257
50443
|
commandOptions: withApiBaseUrl(context, commandOptions),
|
|
@@ -50270,6 +50456,20 @@ function registerSecretCommands(program, context) {
|
|
|
50270
50456
|
name
|
|
50271
50457
|
});
|
|
50272
50458
|
});
|
|
50459
|
+
secrets.command("expiry").description("Update a secret's expiry without changing its value.").argument("<name>", "secret name").option("--project <project>", "project id; defaults to organization scope").option(
|
|
50460
|
+
"--expires-at <timestamp>",
|
|
50461
|
+
'absolute expiry as an ISO 8601 timestamp, or "never" to clear'
|
|
50462
|
+
).option(
|
|
50463
|
+
"--idle-expiry <duration>",
|
|
50464
|
+
'expire after this long unused (seconds or 30d/12h/90m/3600s), or "never" to clear'
|
|
50465
|
+
).option("--json", "print the updated secret metadata as JSON").option("--api-url <url>", "Auto API base URL").option("--api-base-url <url>", "Auto API base URL").action(async (name, commandOptions) => {
|
|
50466
|
+
await updateSecretExpiry({
|
|
50467
|
+
client: createContextApiClient(context),
|
|
50468
|
+
commandOptions: withApiBaseUrl(context, commandOptions),
|
|
50469
|
+
context,
|
|
50470
|
+
name
|
|
50471
|
+
});
|
|
50472
|
+
});
|
|
50273
50473
|
secrets.command("reveal").description(
|
|
50274
50474
|
"Print the decrypted value of a non-protected secret (audited)."
|
|
50275
50475
|
).argument("<name>", "secret name").option("--project <project>", "project id; defaults to organization scope").option("--json", "print the secret value and metadata as JSON").option("--api-url <url>", "Auto API base URL").option("--api-base-url <url>", "Auto API base URL").action(async (name, commandOptions) => {
|