@tenderprompt/cli 0.1.19 → 0.1.20
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/index.js +391 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110,6 +110,10 @@ Commands:
|
|
|
110
110
|
Show publish job status by job id
|
|
111
111
|
tender app publish watch <app-id>
|
|
112
112
|
Stream or print lifecycle events for a publish job
|
|
113
|
+
tender app outbound-auth list <app-id>
|
|
114
|
+
List pending and approved outbound auth grants
|
|
115
|
+
tender app outbound-auth approve <app-id>
|
|
116
|
+
Approve manifest-declared outbound auth grants
|
|
113
117
|
tender app analytics summary <app-id>
|
|
114
118
|
Read artifact analytics totals and trend points
|
|
115
119
|
tender app analytics query <app-id> --spec <file|->
|
|
@@ -155,6 +159,8 @@ Examples:
|
|
|
155
159
|
tender app preview status artifact_123 --commit $(git rev-parse HEAD) --json
|
|
156
160
|
tender app preview watch artifact_123 --job job_123 --stream --json
|
|
157
161
|
tender app publish artifact_123 --commit $(git rev-parse HEAD) --confirm publish --stream --json
|
|
162
|
+
tender app outbound-auth list artifact_123 --json
|
|
163
|
+
tender app outbound-auth approve artifact_123 --all --confirm approve --json
|
|
158
164
|
tender app analytics summary artifact_123 --range 30d --json
|
|
159
165
|
tender app analytics query artifact_123 --spec chart.json --json
|
|
160
166
|
tender app analytics suggestions artifact_123 --range 30d --json
|
|
@@ -293,6 +299,10 @@ Commands:
|
|
|
293
299
|
Show publish job status by job id
|
|
294
300
|
tender app publish watch <app-id>
|
|
295
301
|
Replay lifecycle events for a publish job id
|
|
302
|
+
tender app outbound-auth list <app-id>
|
|
303
|
+
List pending and approved outbound auth grants
|
|
304
|
+
tender app outbound-auth approve <app-id>
|
|
305
|
+
Approve manifest-declared outbound auth grants
|
|
296
306
|
tender app analytics summary <app-id>
|
|
297
307
|
Read artifact analytics totals and trend points
|
|
298
308
|
tender app analytics query <app-id> --spec <file|->
|
|
@@ -355,6 +365,8 @@ Examples:
|
|
|
355
365
|
tender app publish artifact_123 --dry-run --json
|
|
356
366
|
tender app publish status artifact_123 --job job_123 --json
|
|
357
367
|
tender app publish watch artifact_123 --job job_123 --stream --json
|
|
368
|
+
tender app outbound-auth list artifact_123 --json
|
|
369
|
+
tender app outbound-auth approve artifact_123 --all --confirm approve --json
|
|
358
370
|
tender app analytics summary artifact_123 --range 30d --json
|
|
359
371
|
tender app analytics query artifact_123 --spec chart.json --json
|
|
360
372
|
tender app analytics suggestions artifact_123 --range 30d --json
|
|
@@ -1024,6 +1036,32 @@ Options:
|
|
|
1024
1036
|
Examples:
|
|
1025
1037
|
tender app publish watch artifact_123 --job job_123 --stream --json`;
|
|
1026
1038
|
}
|
|
1039
|
+
function outboundAuthHelp() {
|
|
1040
|
+
return `Usage:
|
|
1041
|
+
tender app outbound-auth list <app-id> [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
1042
|
+
tender app outbound-auth approve <app-id> (--all | --binding <id> --secret <key> --host <host> --location <header|query> --name <name>) --confirm approve [--path-prefix <path>] [--scheme <scheme>] [--base-url <url>] [--token <token>] [--profile <name>] [--json]
|
|
1043
|
+
|
|
1044
|
+
Commands:
|
|
1045
|
+
list List manifest-declared outbound auth grants and approval status.
|
|
1046
|
+
approve Approve one grant, or all currently pending grants with --all.
|
|
1047
|
+
|
|
1048
|
+
Options:
|
|
1049
|
+
--all Approve every pending outbound auth grant declared by the current manifest.
|
|
1050
|
+
--binding <id> Binding id from bindings/<id>/binding.json.
|
|
1051
|
+
--secret <key> Secret key backing the injected credential.
|
|
1052
|
+
--host <host> Exact outbound host.
|
|
1053
|
+
--location <value> header or query.
|
|
1054
|
+
--name <name> Header name or query parameter name.
|
|
1055
|
+
--path-prefix <path> Optional path prefix from outboundAuth.
|
|
1056
|
+
--scheme <scheme> Optional header auth scheme from outboundAuth.
|
|
1057
|
+
--confirm approve Required for approval.
|
|
1058
|
+
--json Emit stable JSON for coding agents.
|
|
1059
|
+
|
|
1060
|
+
Examples:
|
|
1061
|
+
tender app outbound-auth list artifact_123 --json
|
|
1062
|
+
tender app outbound-auth approve artifact_123 --all --confirm approve --json
|
|
1063
|
+
tender app outbound-auth approve artifact_123 --binding google-chat --secret GOOGLE_CHAT_KEY --host chat.googleapis.com --location query --name key --path-prefix /v1/spaces/ --confirm approve --json`;
|
|
1064
|
+
}
|
|
1027
1065
|
function tenderCliCapabilities() {
|
|
1028
1066
|
return {
|
|
1029
1067
|
ok: true,
|
|
@@ -1057,6 +1095,7 @@ function tenderCliCapabilities() {
|
|
|
1057
1095
|
'tender app analytics --help',
|
|
1058
1096
|
'tender app db --help',
|
|
1059
1097
|
'tender app bindings outbound --help',
|
|
1098
|
+
'tender app outbound-auth --help',
|
|
1060
1099
|
],
|
|
1061
1100
|
},
|
|
1062
1101
|
workflows: [
|
|
@@ -1130,11 +1169,13 @@ function tenderCliCapabilities() {
|
|
|
1130
1169
|
'git push tender main',
|
|
1131
1170
|
'tender app agent heartbeat <artifact-id> --source codex --status working --phase building_preview --summary "Waiting for preview build" --commit $(git rev-parse HEAD) --json',
|
|
1132
1171
|
'tender app preview <artifact-id> --commit $(git rev-parse HEAD) --stream --json',
|
|
1172
|
+
'tender app outbound-auth list <artifact-id> --json',
|
|
1133
1173
|
'tender app publish <artifact-id> --dry-run --json',
|
|
1134
1174
|
'tender app publish <artifact-id> --commit $(git rev-parse HEAD) --confirm publish --stream --json',
|
|
1135
1175
|
],
|
|
1136
1176
|
notes: [
|
|
1137
1177
|
'Send heartbeat updates only at meaningful milestones or when waiting for user input; do not send rapid polling updates.',
|
|
1178
|
+
'If preview or publish reports outbound auth grant approval required, run tender app outbound-auth approve <artifact-id> --all --confirm approve --json, then retry.',
|
|
1138
1179
|
'Publishing is production-facing and requires explicit user intent.',
|
|
1139
1180
|
],
|
|
1140
1181
|
},
|
|
@@ -2260,6 +2301,201 @@ function parsePublishWatchArgs(args) {
|
|
|
2260
2301
|
json: options.json,
|
|
2261
2302
|
};
|
|
2262
2303
|
}
|
|
2304
|
+
function parseOutboundAuthLocation(value) {
|
|
2305
|
+
if (value !== 'header' && value !== 'query') {
|
|
2306
|
+
throw new TenderCliUsageError('--location must be one of header or query.');
|
|
2307
|
+
}
|
|
2308
|
+
return value;
|
|
2309
|
+
}
|
|
2310
|
+
function parseOutboundAuthListArgs(args) {
|
|
2311
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
2312
|
+
return { command: 'help', topic: 'app outbound-auth' };
|
|
2313
|
+
}
|
|
2314
|
+
const artifactId = args[0];
|
|
2315
|
+
if (!artifactId || artifactId.startsWith('-')) {
|
|
2316
|
+
throw new TenderCliUsageError('app id is required. Example: tender app outbound-auth list <app-id> --json');
|
|
2317
|
+
}
|
|
2318
|
+
let baseUrl = null;
|
|
2319
|
+
let flagToken = null;
|
|
2320
|
+
let profileName = null;
|
|
2321
|
+
let json = false;
|
|
2322
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
2323
|
+
const arg = args[index];
|
|
2324
|
+
if (arg === '--json') {
|
|
2325
|
+
json = true;
|
|
2326
|
+
continue;
|
|
2327
|
+
}
|
|
2328
|
+
if (arg === '--base-url') {
|
|
2329
|
+
baseUrl = parseBaseUrlFlag(args, index);
|
|
2330
|
+
index += 1;
|
|
2331
|
+
continue;
|
|
2332
|
+
}
|
|
2333
|
+
if (arg === '--token') {
|
|
2334
|
+
flagToken = parseTokenFlag(args, index);
|
|
2335
|
+
index += 1;
|
|
2336
|
+
continue;
|
|
2337
|
+
}
|
|
2338
|
+
if (arg === '--profile') {
|
|
2339
|
+
profileName = parseProfileName(args[index + 1], '--profile');
|
|
2340
|
+
index += 1;
|
|
2341
|
+
continue;
|
|
2342
|
+
}
|
|
2343
|
+
throw new TenderCliUsageError(`Unknown outbound-auth list option: ${arg}`);
|
|
2344
|
+
}
|
|
2345
|
+
return {
|
|
2346
|
+
command: 'app outbound-auth list',
|
|
2347
|
+
artifactId,
|
|
2348
|
+
baseUrl,
|
|
2349
|
+
flagToken,
|
|
2350
|
+
profileName,
|
|
2351
|
+
json,
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
function parseOutboundAuthApproveArgs(args) {
|
|
2355
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
2356
|
+
return { command: 'help', topic: 'app outbound-auth' };
|
|
2357
|
+
}
|
|
2358
|
+
const artifactId = args[0];
|
|
2359
|
+
if (!artifactId || artifactId.startsWith('-')) {
|
|
2360
|
+
throw new TenderCliUsageError('app id is required. Example: tender app outbound-auth approve <app-id> --all --confirm approve --json');
|
|
2361
|
+
}
|
|
2362
|
+
let baseUrl = null;
|
|
2363
|
+
let flagToken = null;
|
|
2364
|
+
let profileName = null;
|
|
2365
|
+
let confirm = null;
|
|
2366
|
+
let approveAll = false;
|
|
2367
|
+
let bindingId = null;
|
|
2368
|
+
let secret = null;
|
|
2369
|
+
let host = null;
|
|
2370
|
+
let location = null;
|
|
2371
|
+
let name = null;
|
|
2372
|
+
let scheme = null;
|
|
2373
|
+
let pathPrefix = null;
|
|
2374
|
+
let json = false;
|
|
2375
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
2376
|
+
const arg = args[index];
|
|
2377
|
+
if (arg === '--json') {
|
|
2378
|
+
json = true;
|
|
2379
|
+
continue;
|
|
2380
|
+
}
|
|
2381
|
+
if (arg === '--all') {
|
|
2382
|
+
approveAll = true;
|
|
2383
|
+
continue;
|
|
2384
|
+
}
|
|
2385
|
+
if (arg === '--confirm') {
|
|
2386
|
+
const value = args[index + 1];
|
|
2387
|
+
if (!value || value.startsWith('-')) {
|
|
2388
|
+
throw new TenderCliUsageError('--confirm requires the value approve.');
|
|
2389
|
+
}
|
|
2390
|
+
confirm = value;
|
|
2391
|
+
index += 1;
|
|
2392
|
+
continue;
|
|
2393
|
+
}
|
|
2394
|
+
if (arg === '--binding') {
|
|
2395
|
+
const value = args[index + 1];
|
|
2396
|
+
if (!value || value.startsWith('-')) {
|
|
2397
|
+
throw new TenderCliUsageError('--binding requires a binding id.');
|
|
2398
|
+
}
|
|
2399
|
+
bindingId = value;
|
|
2400
|
+
index += 1;
|
|
2401
|
+
continue;
|
|
2402
|
+
}
|
|
2403
|
+
if (arg === '--secret') {
|
|
2404
|
+
const value = args[index + 1];
|
|
2405
|
+
if (!value || value.startsWith('-')) {
|
|
2406
|
+
throw new TenderCliUsageError('--secret requires a secret key.');
|
|
2407
|
+
}
|
|
2408
|
+
secret = value;
|
|
2409
|
+
index += 1;
|
|
2410
|
+
continue;
|
|
2411
|
+
}
|
|
2412
|
+
if (arg === '--host') {
|
|
2413
|
+
const value = args[index + 1];
|
|
2414
|
+
if (!value || value.startsWith('-')) {
|
|
2415
|
+
throw new TenderCliUsageError('--host requires a host.');
|
|
2416
|
+
}
|
|
2417
|
+
host = value;
|
|
2418
|
+
index += 1;
|
|
2419
|
+
continue;
|
|
2420
|
+
}
|
|
2421
|
+
if (arg === '--location') {
|
|
2422
|
+
location = parseOutboundAuthLocation(args[index + 1]);
|
|
2423
|
+
index += 1;
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
if (arg === '--name') {
|
|
2427
|
+
const value = args[index + 1];
|
|
2428
|
+
if (!value || value.startsWith('-')) {
|
|
2429
|
+
throw new TenderCliUsageError('--name requires a header or query parameter name.');
|
|
2430
|
+
}
|
|
2431
|
+
name = value;
|
|
2432
|
+
index += 1;
|
|
2433
|
+
continue;
|
|
2434
|
+
}
|
|
2435
|
+
if (arg === '--scheme') {
|
|
2436
|
+
const value = args[index + 1];
|
|
2437
|
+
if (!value || value.startsWith('-')) {
|
|
2438
|
+
throw new TenderCliUsageError('--scheme requires an auth scheme.');
|
|
2439
|
+
}
|
|
2440
|
+
scheme = value;
|
|
2441
|
+
index += 1;
|
|
2442
|
+
continue;
|
|
2443
|
+
}
|
|
2444
|
+
if (arg === '--path-prefix') {
|
|
2445
|
+
const value = args[index + 1];
|
|
2446
|
+
if (!value || value.startsWith('-')) {
|
|
2447
|
+
throw new TenderCliUsageError('--path-prefix requires a path prefix.');
|
|
2448
|
+
}
|
|
2449
|
+
pathPrefix = value;
|
|
2450
|
+
index += 1;
|
|
2451
|
+
continue;
|
|
2452
|
+
}
|
|
2453
|
+
if (arg === '--base-url') {
|
|
2454
|
+
baseUrl = parseBaseUrlFlag(args, index);
|
|
2455
|
+
index += 1;
|
|
2456
|
+
continue;
|
|
2457
|
+
}
|
|
2458
|
+
if (arg === '--token') {
|
|
2459
|
+
flagToken = parseTokenFlag(args, index);
|
|
2460
|
+
index += 1;
|
|
2461
|
+
continue;
|
|
2462
|
+
}
|
|
2463
|
+
if (arg === '--profile') {
|
|
2464
|
+
profileName = parseProfileName(args[index + 1], '--profile');
|
|
2465
|
+
index += 1;
|
|
2466
|
+
continue;
|
|
2467
|
+
}
|
|
2468
|
+
throw new TenderCliUsageError(`Unknown outbound-auth approve option: ${arg}`);
|
|
2469
|
+
}
|
|
2470
|
+
if (confirm !== 'approve') {
|
|
2471
|
+
throw new TenderCliUsageError('outbound-auth approve requires --confirm approve.');
|
|
2472
|
+
}
|
|
2473
|
+
if (approveAll && (bindingId || secret || host || location || name || scheme || pathPrefix)) {
|
|
2474
|
+
throw new TenderCliUsageError('Use either --all or one explicit grant, not both.');
|
|
2475
|
+
}
|
|
2476
|
+
if (!approveAll && (!bindingId || !secret || !host || !location || !name)) {
|
|
2477
|
+
throw new TenderCliUsageError('Explicit approval requires --binding, --secret, --host, --location, and --name. Example: tender app outbound-auth approve <app-id> --binding google-chat --secret GOOGLE_CHAT_KEY --host chat.googleapis.com --location query --name key --confirm approve --json');
|
|
2478
|
+
}
|
|
2479
|
+
return {
|
|
2480
|
+
command: 'app outbound-auth approve',
|
|
2481
|
+
artifactId,
|
|
2482
|
+
approveAll,
|
|
2483
|
+
confirm,
|
|
2484
|
+
grant: {
|
|
2485
|
+
bindingId,
|
|
2486
|
+
secret,
|
|
2487
|
+
host,
|
|
2488
|
+
location,
|
|
2489
|
+
name,
|
|
2490
|
+
scheme,
|
|
2491
|
+
pathPrefix,
|
|
2492
|
+
},
|
|
2493
|
+
baseUrl,
|
|
2494
|
+
flagToken,
|
|
2495
|
+
profileName,
|
|
2496
|
+
json,
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2263
2499
|
function parseArtifactsListArgs(args) {
|
|
2264
2500
|
if (args.includes('--help') || args.includes('-h')) {
|
|
2265
2501
|
return { command: 'help', topic: 'app list' };
|
|
@@ -4692,6 +4928,18 @@ function parseTenderArgs(args) {
|
|
|
4692
4928
|
if (resourceArgs[1] === 'bindings' && (resourceArgs[2] === undefined || resourceArgs[2] === '--help' || resourceArgs[2] === '-h')) {
|
|
4693
4929
|
return { command: 'help', topic: 'app bindings outbound' };
|
|
4694
4930
|
}
|
|
4931
|
+
if (resourceArgs[1] === 'outbound-auth' && (resourceArgs[2] === undefined || resourceArgs[2] === '--help' || resourceArgs[2] === '-h')) {
|
|
4932
|
+
return { command: 'help', topic: 'app outbound-auth' };
|
|
4933
|
+
}
|
|
4934
|
+
if (resourceArgs[1] === 'outbound-auth' && resourceArgs[2] === 'list') {
|
|
4935
|
+
return parseOutboundAuthListArgs(resourceArgs.slice(3));
|
|
4936
|
+
}
|
|
4937
|
+
if (resourceArgs[1] === 'outbound-auth' && resourceArgs[2] === 'approve') {
|
|
4938
|
+
return parseOutboundAuthApproveArgs(resourceArgs.slice(3));
|
|
4939
|
+
}
|
|
4940
|
+
if (resourceArgs[1] === 'outbound-auth') {
|
|
4941
|
+
throw new TenderCliUsageError(`Unknown app outbound-auth command: ${resourceArgs[2]}`);
|
|
4942
|
+
}
|
|
4695
4943
|
if (resourceArgs[1] === 'analytics' && (resourceArgs[2] === undefined || resourceArgs[2] === '--help' || resourceArgs[2] === '-h')) {
|
|
4696
4944
|
return { command: 'help', topic: 'app analytics' };
|
|
4697
4945
|
}
|
|
@@ -7451,7 +7699,7 @@ async function postLifecycle(input) {
|
|
|
7451
7699
|
}
|
|
7452
7700
|
const payload = await parseJsonResponse(response);
|
|
7453
7701
|
if (!response.ok || !payload?.ok) {
|
|
7454
|
-
throw new Error(payload
|
|
7702
|
+
throw new Error(formatApiFailureMessage(payload, `Artifact ${input.operation} request failed with HTTP ${response.status}.`));
|
|
7455
7703
|
}
|
|
7456
7704
|
const result = {
|
|
7457
7705
|
ok: true,
|
|
@@ -7473,6 +7721,18 @@ async function postLifecycle(input) {
|
|
|
7473
7721
|
}
|
|
7474
7722
|
return 0;
|
|
7475
7723
|
}
|
|
7724
|
+
function readNextCommand(next) {
|
|
7725
|
+
if (!next || typeof next !== 'object' || Array.isArray(next)) {
|
|
7726
|
+
return null;
|
|
7727
|
+
}
|
|
7728
|
+
const command = next.command;
|
|
7729
|
+
return typeof command === 'string' && command.trim() ? command.trim() : null;
|
|
7730
|
+
}
|
|
7731
|
+
function formatApiFailureMessage(payload, fallback) {
|
|
7732
|
+
const message = payload?.message ?? payload?.reasonCode ?? fallback;
|
|
7733
|
+
const command = readNextCommand(payload?.next);
|
|
7734
|
+
return command ? `${message}\nNext: ${command}` : message;
|
|
7735
|
+
}
|
|
7476
7736
|
async function runValidate(command, io, runtime) {
|
|
7477
7737
|
return await postLifecycle({
|
|
7478
7738
|
command,
|
|
@@ -7671,6 +7931,127 @@ async function runPublish(command, io, runtime) {
|
|
|
7671
7931
|
runtime,
|
|
7672
7932
|
});
|
|
7673
7933
|
}
|
|
7934
|
+
async function requestOutboundAuthList(input) {
|
|
7935
|
+
const response = await input.fetcher(`${input.credentials.baseUrl}/api/v1/artifacts/${encodeURIComponent(input.command.artifactId)}/outbound-auth/grants`, {
|
|
7936
|
+
headers: {
|
|
7937
|
+
authorization: `Bearer ${input.credentials.token}`,
|
|
7938
|
+
},
|
|
7939
|
+
});
|
|
7940
|
+
const payload = await parseJsonResponse(response);
|
|
7941
|
+
if (!response.ok || !payload?.ok) {
|
|
7942
|
+
throw new Error(formatApiFailureMessage(payload, `Outbound auth grant lookup failed with HTTP ${response.status}.`));
|
|
7943
|
+
}
|
|
7944
|
+
return payload;
|
|
7945
|
+
}
|
|
7946
|
+
function formatOutboundAuthGrant(grant) {
|
|
7947
|
+
return `${grant.bindingId} -> ${grant.secret} -> ${grant.host} -> ${grant.location}:${grant.name}${grant.pathPrefix ? ` -> ${grant.pathPrefix}` : ''}${grant.scheme ? ` -> ${grant.scheme}` : ''}`;
|
|
7948
|
+
}
|
|
7949
|
+
function readExplicitOutboundAuthGrant(command) {
|
|
7950
|
+
const { bindingId, secret, host, location, name, scheme, pathPrefix } = command.grant;
|
|
7951
|
+
if (!bindingId || !secret || !host || !location || !name) {
|
|
7952
|
+
throw new TenderCliUsageError('Explicit approval requires --binding, --secret, --host, --location, and --name.');
|
|
7953
|
+
}
|
|
7954
|
+
return {
|
|
7955
|
+
bindingId,
|
|
7956
|
+
secret,
|
|
7957
|
+
host,
|
|
7958
|
+
location,
|
|
7959
|
+
name,
|
|
7960
|
+
...(scheme ? { scheme } : {}),
|
|
7961
|
+
...(pathPrefix ? { pathPrefix } : {}),
|
|
7962
|
+
};
|
|
7963
|
+
}
|
|
7964
|
+
async function approveOutboundAuthGrant(input) {
|
|
7965
|
+
const response = await input.fetcher(`${input.credentials.baseUrl}/api/v1/artifacts/${encodeURIComponent(input.command.artifactId)}/outbound-auth/grants/approve`, {
|
|
7966
|
+
method: 'POST',
|
|
7967
|
+
headers: {
|
|
7968
|
+
authorization: `Bearer ${input.credentials.token}`,
|
|
7969
|
+
'content-type': 'application/json',
|
|
7970
|
+
},
|
|
7971
|
+
body: JSON.stringify(input.grant),
|
|
7972
|
+
});
|
|
7973
|
+
const payload = await parseJsonResponse(response);
|
|
7974
|
+
if (!response.ok || !payload?.ok || !payload.approved) {
|
|
7975
|
+
throw new Error(formatApiFailureMessage(payload, `Outbound auth grant approval failed with HTTP ${response.status}.`));
|
|
7976
|
+
}
|
|
7977
|
+
return payload.approved;
|
|
7978
|
+
}
|
|
7979
|
+
async function runOutboundAuthList(command, io, runtime) {
|
|
7980
|
+
const credentials = await resolveApiCredentials({
|
|
7981
|
+
baseUrl: command.baseUrl,
|
|
7982
|
+
flagToken: command.flagToken,
|
|
7983
|
+
profileName: command.profileName,
|
|
7984
|
+
env: runtime.env ?? process.env,
|
|
7985
|
+
});
|
|
7986
|
+
const payload = await requestOutboundAuthList({
|
|
7987
|
+
command,
|
|
7988
|
+
credentials,
|
|
7989
|
+
fetcher: runtime.fetcher ?? fetch,
|
|
7990
|
+
});
|
|
7991
|
+
const result = {
|
|
7992
|
+
ok: true,
|
|
7993
|
+
command: command.command,
|
|
7994
|
+
baseUrl: credentials.baseUrl,
|
|
7995
|
+
authSource: credentials.source,
|
|
7996
|
+
profile: credentials.profileName,
|
|
7997
|
+
artifactId: command.artifactId,
|
|
7998
|
+
grants: payload.grants ?? [],
|
|
7999
|
+
pendingCount: payload.pendingCount ?? 0,
|
|
8000
|
+
approvedCount: payload.approvedCount ?? 0,
|
|
8001
|
+
next: payload.next ?? null,
|
|
8002
|
+
};
|
|
8003
|
+
if (command.json) {
|
|
8004
|
+
io.stdout(JSON.stringify(result, null, 2));
|
|
8005
|
+
}
|
|
8006
|
+
else {
|
|
8007
|
+
const grants = result.grants.map((grant) => `${grant.approved ? 'approved' : 'pending'}: ${formatOutboundAuthGrant(grant)}`);
|
|
8008
|
+
io.stdout([
|
|
8009
|
+
`app_id: ${command.artifactId}`,
|
|
8010
|
+
`pending: ${result.pendingCount}`,
|
|
8011
|
+
`approved: ${result.approvedCount}`,
|
|
8012
|
+
...grants,
|
|
8013
|
+
...(readNextCommand(result.next) ? [`next: ${readNextCommand(result.next)}`] : []),
|
|
8014
|
+
].join('\n'));
|
|
8015
|
+
}
|
|
8016
|
+
return 0;
|
|
8017
|
+
}
|
|
8018
|
+
async function runOutboundAuthApprove(command, io, runtime) {
|
|
8019
|
+
const credentials = await resolveApiCredentials({
|
|
8020
|
+
baseUrl: command.baseUrl,
|
|
8021
|
+
flagToken: command.flagToken,
|
|
8022
|
+
profileName: command.profileName,
|
|
8023
|
+
env: runtime.env ?? process.env,
|
|
8024
|
+
});
|
|
8025
|
+
const fetcher = runtime.fetcher ?? fetch;
|
|
8026
|
+
const grants = command.approveAll
|
|
8027
|
+
? (await requestOutboundAuthList({ command, credentials, fetcher })).grants?.filter((grant) => !grant.approved) ?? []
|
|
8028
|
+
: [readExplicitOutboundAuthGrant(command)];
|
|
8029
|
+
const approved = [];
|
|
8030
|
+
for (const grant of grants) {
|
|
8031
|
+
approved.push(await approveOutboundAuthGrant({ command, credentials, fetcher, grant }));
|
|
8032
|
+
}
|
|
8033
|
+
const result = {
|
|
8034
|
+
ok: true,
|
|
8035
|
+
command: command.command,
|
|
8036
|
+
baseUrl: credentials.baseUrl,
|
|
8037
|
+
authSource: credentials.source,
|
|
8038
|
+
profile: credentials.profileName,
|
|
8039
|
+
artifactId: command.artifactId,
|
|
8040
|
+
approvedCount: approved.length,
|
|
8041
|
+
approved,
|
|
8042
|
+
};
|
|
8043
|
+
if (command.json) {
|
|
8044
|
+
io.stdout(JSON.stringify(result, null, 2));
|
|
8045
|
+
}
|
|
8046
|
+
else {
|
|
8047
|
+
io.stdout([
|
|
8048
|
+
`app_id: ${command.artifactId}`,
|
|
8049
|
+
`approved: ${approved.length}`,
|
|
8050
|
+
...approved.map((grant) => formatOutboundAuthGrant(grant)),
|
|
8051
|
+
].join('\n'));
|
|
8052
|
+
}
|
|
8053
|
+
return 0;
|
|
8054
|
+
}
|
|
7674
8055
|
async function requestPublishJob(input) {
|
|
7675
8056
|
const response = await input.fetcher(`${input.credentials.baseUrl}/api/v1/artifacts/${encodeURIComponent(input.command.artifactId)}/jobs/${encodeURIComponent(input.command.jobId)}`, {
|
|
7676
8057
|
headers: {
|
|
@@ -8702,6 +9083,9 @@ export async function runTenderCli(args, io = {
|
|
|
8702
9083
|
else if (command.topic === 'app publish watch') {
|
|
8703
9084
|
io.stdout(publishWatchHelp());
|
|
8704
9085
|
}
|
|
9086
|
+
else if (command.topic === 'app outbound-auth') {
|
|
9087
|
+
io.stdout(outboundAuthHelp());
|
|
9088
|
+
}
|
|
8705
9089
|
else if (command.topic === 'app analytics') {
|
|
8706
9090
|
io.stdout(analyticsHelp());
|
|
8707
9091
|
}
|
|
@@ -8854,6 +9238,12 @@ export async function runTenderCli(args, io = {
|
|
|
8854
9238
|
if (command.command === 'app publish watch') {
|
|
8855
9239
|
return await runPublishWatch(command, io, runtime);
|
|
8856
9240
|
}
|
|
9241
|
+
if (command.command === 'app outbound-auth list') {
|
|
9242
|
+
return await runOutboundAuthList(command, io, runtime);
|
|
9243
|
+
}
|
|
9244
|
+
if (command.command === 'app outbound-auth approve') {
|
|
9245
|
+
return await runOutboundAuthApprove(command, io, runtime);
|
|
9246
|
+
}
|
|
8857
9247
|
if (command.command === 'app analytics summary') {
|
|
8858
9248
|
return await runAnalyticsSummary(command, io, runtime);
|
|
8859
9249
|
}
|