@skrr-ai/cli 0.1.60 → 0.1.62
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/base-command.js +16 -0
- package/dist/commands/agents/create.d.ts +1 -0
- package/dist/commands/agents/create.js +8 -1
- package/dist/commands/agents/delete.d.ts +14 -0
- package/dist/commands/agents/delete.js +52 -4
- package/dist/commands/agents/eval/index.d.ts +38 -0
- package/dist/commands/agents/eval/index.js +157 -0
- package/dist/commands/agents/eval/list.d.ts +13 -0
- package/dist/commands/agents/eval/list.js +53 -0
- package/dist/commands/agents/eval/show.d.ts +13 -0
- package/dist/commands/agents/eval/show.js +36 -0
- package/dist/commands/agents/import.d.ts +37 -0
- package/dist/commands/agents/import.js +233 -0
- package/dist/commands/agents/pull.d.ts +27 -0
- package/dist/commands/agents/pull.js +82 -0
- package/dist/commands/agents/push.d.ts +28 -0
- package/dist/commands/agents/push.js +112 -0
- package/dist/commands/agents/releases/ci-publish.d.ts +32 -0
- package/dist/commands/agents/releases/ci-publish.js +99 -0
- package/dist/commands/agents/releases/create.d.ts +3 -0
- package/dist/commands/agents/releases/create.js +27 -6
- package/dist/commands/agents/releases/known-issues/add.d.ts +19 -0
- package/dist/commands/agents/releases/known-issues/add.js +43 -0
- package/dist/commands/agents/releases/known-issues/list.d.ts +17 -0
- package/dist/commands/agents/releases/known-issues/list.js +55 -0
- package/dist/commands/agents/releases/known-issues/update.d.ts +18 -0
- package/dist/commands/agents/releases/known-issues/update.js +47 -0
- package/dist/commands/agents/releases/list.js +25 -3
- package/dist/commands/agents/releases/rollback.js +12 -4
- package/dist/commands/agents/releases/test-install.d.ts +22 -0
- package/dist/commands/agents/releases/test-install.js +70 -0
- package/dist/commands/agents/releases/trusted-publishers/list.d.ts +17 -0
- package/dist/commands/agents/releases/trusted-publishers/list.js +55 -0
- package/dist/commands/agents/releases/trusted-publishers/remove.d.ts +17 -0
- package/dist/commands/agents/releases/trusted-publishers/remove.js +45 -0
- package/dist/commands/agents/releases/trusted-publishers/set.d.ts +27 -0
- package/dist/commands/agents/releases/trusted-publishers/set.js +82 -0
- package/dist/commands/agents/update.d.ts +1 -0
- package/dist/commands/agents/update.js +8 -1
- package/dist/commands/agents/usage-cap.d.ts +20 -0
- package/dist/commands/agents/usage-cap.js +76 -0
- package/dist/commands/agents/validate.d.ts +22 -0
- package/dist/commands/agents/validate.js +66 -0
- package/dist/commands/agents/visibility.d.ts +13 -0
- package/dist/commands/agents/visibility.js +84 -2
- package/dist/commands/commerce/fees/show.d.ts +19 -0
- package/dist/commands/commerce/fees/show.js +75 -0
- package/dist/commands/earnings/index.d.ts +15 -0
- package/dist/commands/earnings/index.js +46 -0
- package/dist/commands/earnings/payouts.d.ts +12 -0
- package/dist/commands/earnings/payouts.js +39 -0
- package/dist/commands/earnings/statements.d.ts +19 -0
- package/dist/commands/earnings/statements.js +70 -0
- package/dist/commands/goals/key-results/create.d.ts +1 -1
- package/dist/commands/goals/key-results/create.js +5 -1
- package/dist/commands/harnesses/show.js +11 -1
- package/dist/commands/logout.js +31 -0
- package/dist/commands/machines/show.js +10 -1
- package/dist/commands/managed-execution/show.d.ts +10 -0
- package/dist/commands/managed-execution/show.js +60 -0
- package/dist/commands/spaces/show.js +35 -1
- package/dist/commands/step-up.d.ts +23 -0
- package/dist/commands/step-up.js +96 -0
- package/dist/commands/store/acquisitions/approve.d.ts +30 -0
- package/dist/commands/store/acquisitions/approve.js +100 -0
- package/dist/commands/store/acquisitions/decline.d.ts +17 -0
- package/dist/commands/store/acquisitions/decline.js +47 -0
- package/dist/commands/store/acquisitions/show.d.ts +16 -0
- package/dist/commands/store/acquisitions/show.js +49 -0
- package/dist/commands/store/admissions/approve.d.ts +19 -0
- package/dist/commands/store/admissions/approve.js +50 -0
- package/dist/commands/store/admissions/list.d.ts +15 -0
- package/dist/commands/store/admissions/list.js +60 -0
- package/dist/commands/store/admissions/refuse.d.ts +18 -0
- package/dist/commands/store/admissions/refuse.js +49 -0
- package/dist/commands/store/advisories/artifact.d.ts +15 -0
- package/dist/commands/store/advisories/artifact.js +25 -0
- package/dist/commands/store/advisories/cancel.d.ts +13 -0
- package/dist/commands/store/advisories/cancel.js +34 -0
- package/dist/commands/store/advisories/close.d.ts +18 -0
- package/dist/commands/store/advisories/close.js +51 -0
- package/dist/commands/store/advisories/confirm.d.ts +17 -0
- package/dist/commands/store/advisories/confirm.js +40 -0
- package/dist/commands/store/advisories/issue.d.ts +20 -0
- package/dist/commands/store/advisories/issue.js +59 -0
- package/dist/commands/store/advisories/list.d.ts +15 -0
- package/dist/commands/store/advisories/list.js +49 -0
- package/dist/commands/store/advisories/show.d.ts +13 -0
- package/dist/commands/store/advisories/show.js +34 -0
- package/dist/commands/store/artifacts/release.d.ts +16 -0
- package/dist/commands/store/artifacts/release.js +31 -0
- package/dist/commands/store/artifacts/used-by.d.ts +12 -0
- package/dist/commands/store/artifacts/used-by.js +20 -0
- package/dist/commands/store/browse.d.ts +5 -0
- package/dist/commands/store/browse.js +28 -1
- package/dist/commands/store/channel.d.ts +21 -0
- package/dist/commands/store/channel.js +62 -0
- package/dist/commands/store/follow.d.ts +14 -0
- package/dist/commands/store/follow.js +45 -0
- package/dist/commands/store/governance/policy.d.ts +18 -5
- package/dist/commands/store/governance/policy.js +80 -12
- package/dist/commands/store/governance/requests.d.ts +28 -0
- package/dist/commands/store/governance/requests.js +116 -0
- package/dist/commands/store/install.d.ts +3 -0
- package/dist/commands/store/install.js +101 -2
- package/dist/commands/store/issues.d.ts +26 -0
- package/dist/commands/store/issues.js +118 -0
- package/dist/commands/store/maintainers/add.d.ts +13 -0
- package/dist/commands/store/maintainers/add.js +23 -0
- package/dist/commands/store/maintainers/remove.d.ts +13 -0
- package/dist/commands/store/maintainers/remove.js +22 -0
- package/dist/commands/store/publishers/approve.d.ts +11 -0
- package/dist/commands/store/publishers/approve.js +25 -0
- package/dist/commands/store/publishers/claim.d.ts +12 -0
- package/dist/commands/store/publishers/claim.js +20 -0
- package/dist/commands/store/publishers/confirm.d.ts +11 -0
- package/dist/commands/store/publishers/confirm.js +17 -0
- package/dist/commands/store/publishers/domains/begin.d.ts +12 -0
- package/dist/commands/store/publishers/domains/begin.js +20 -0
- package/dist/commands/store/publishers/domains/list.d.ts +9 -0
- package/dist/commands/store/publishers/domains/list.js +19 -0
- package/dist/commands/store/publishers/domains/verify.d.ts +12 -0
- package/dist/commands/store/publishers/domains/verify.js +20 -0
- package/dist/commands/store/publishers/namespaces.d.ts +8 -0
- package/dist/commands/store/publishers/namespaces.js +16 -0
- package/dist/commands/store/publishers/verified.d.ts +11 -0
- package/dist/commands/store/publishers/verified.js +34 -0
- package/dist/commands/store/refund.d.ts +22 -0
- package/dist/commands/store/refund.js +80 -0
- package/dist/commands/store/report.d.ts +20 -0
- package/dist/commands/store/report.js +59 -0
- package/dist/commands/store/reports.d.ts +11 -0
- package/dist/commands/store/reports.js +52 -0
- package/dist/commands/store/signals.d.ts +18 -0
- package/dist/commands/store/signals.js +43 -0
- package/dist/commands/store/star.d.ts +17 -0
- package/dist/commands/store/star.js +41 -0
- package/dist/commands/store/stars.d.ts +10 -0
- package/dist/commands/store/stars.js +33 -0
- package/dist/commands/store/trial.d.ts +11 -0
- package/dist/commands/store/trial.js +17 -0
- package/dist/commands/store/uninstall.d.ts +19 -0
- package/dist/commands/store/uninstall.js +118 -0
- package/dist/commands/store/update.d.ts +2 -0
- package/dist/commands/store/update.js +60 -2
- package/dist/commands/store/updates.d.ts +10 -4
- package/dist/commands/store/updates.js +60 -39
- package/dist/commands/store/watch.d.ts +18 -0
- package/dist/commands/store/watch.js +44 -0
- package/dist/commands/subscriptions/health.d.ts +12 -0
- package/dist/commands/subscriptions/health.js +39 -0
- package/dist/commands/subscriptions/list.js +3 -2
- package/dist/commands/subscriptions/status.js +7 -1
- package/dist/commands/subscriptions/subscribe.d.ts +9 -2
- package/dist/commands/subscriptions/subscribe.js +141 -12
- package/dist/commands/tasks/comments/list.js +9 -1
- package/dist/commands/tasks/labels/attach.js +15 -2
- package/dist/commands/tasks/show.js +17 -3
- package/dist/commands/tasks/update.js +15 -4
- package/dist/commands/tasks/updates/add.js +5 -1
- package/dist/lib/agent-config.js +1 -0
- package/dist/lib/agent-evals.d.ts +71 -0
- package/dist/lib/agent-evals.js +359 -0
- package/dist/lib/agent-spec.d.ts +28 -0
- package/dist/lib/agent-spec.js +58 -0
- package/dist/lib/auth-storage.d.ts +12 -0
- package/dist/lib/auth-storage.js +0 -33
- package/dist/lib/commerce.d.ts +8 -0
- package/dist/lib/commerce.js +10 -0
- package/dist/lib/earnings.d.ts +36 -0
- package/dist/lib/earnings.js +164 -0
- package/dist/lib/github-oidc.d.ts +13 -0
- package/dist/lib/github-oidc.js +41 -0
- package/dist/lib/governed-store.d.ts +43 -2
- package/dist/lib/governed-store.js +25 -1
- package/dist/lib/label-ref.js +16 -0
- package/dist/lib/managed-execution.d.ts +10 -0
- package/dist/lib/managed-execution.js +43 -0
- package/dist/lib/principal-display.d.ts +20 -0
- package/dist/lib/principal-display.js +64 -0
- package/dist/lib/space-template-source.d.ts +14 -0
- package/dist/lib/space-template-source.js +41 -0
- package/dist/lib/step-up.d.ts +21 -0
- package/dist/lib/step-up.js +44 -0
- package/dist/lib/store-acquisition.d.ts +11 -0
- package/dist/lib/store-acquisition.js +40 -0
- package/dist/lib/store-advisories.d.ts +50 -0
- package/dist/lib/store-advisories.js +62 -0
- package/dist/lib/task-closure.js +1 -1
- package/dist/lib/web-url.d.ts +11 -0
- package/dist/lib/web-url.js +14 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +25471 -24177
- package/oclif.manifest.json +38931 -34119
- package/package.json +21 -3
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PERIOD_PATTERN = exports.readPayouts = exports.readStatement = exports.readStatements = exports.readAutoPayout = exports.readEarnings = void 0;
|
|
4
|
+
exports.renderEarningsSummary = renderEarningsSummary;
|
|
5
|
+
exports.renderStatementList = renderStatementList;
|
|
6
|
+
exports.renderStatement = renderStatement;
|
|
7
|
+
exports.renderPayoutHistory = renderPayoutHistory;
|
|
8
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
9
|
+
const format_1 = require("./format");
|
|
10
|
+
/**
|
|
11
|
+
* earnings.ts — the read-only publisher payout surface (OSK-12272).
|
|
12
|
+
*
|
|
13
|
+
* `skrr earnings` reads a publisher's balance, automatic-payout state, monthly
|
|
14
|
+
* statements and payout history from `/api/connect/*`. It is read-only on
|
|
15
|
+
* purpose: requesting a payout and switching automatic payouts on move money,
|
|
16
|
+
* and those routes refuse a daemon credential (`refuseDaemonScope`), so they
|
|
17
|
+
* stay in the web Earnings page where a signed-in person does them.
|
|
18
|
+
*
|
|
19
|
+
* Every read goes through `dataService`, so the path a command reaches is the
|
|
20
|
+
* same one the web page reads, and copy for server vocabularies comes from
|
|
21
|
+
* `@skrr-ai/data-provider` (`connectPayouts.ts`), shared with that page.
|
|
22
|
+
*/
|
|
23
|
+
const readEarnings = () => data_provider_1.dataService.getConnectEarnings();
|
|
24
|
+
exports.readEarnings = readEarnings;
|
|
25
|
+
const readAutoPayout = () => data_provider_1.dataService.getConnectAutoPayout();
|
|
26
|
+
exports.readAutoPayout = readAutoPayout;
|
|
27
|
+
const readStatements = (params) => data_provider_1.dataService.getConnectStatements(params);
|
|
28
|
+
exports.readStatements = readStatements;
|
|
29
|
+
const readStatement = (period) => data_provider_1.dataService.getConnectStatement(period);
|
|
30
|
+
exports.readStatement = readStatement;
|
|
31
|
+
const readPayouts = (params) => data_provider_1.dataService.getConnectPayoutHistory(params);
|
|
32
|
+
exports.readPayouts = readPayouts;
|
|
33
|
+
exports.PERIOD_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
|
|
34
|
+
function dollars(usd) {
|
|
35
|
+
if (usd == null || usd === '')
|
|
36
|
+
return '-';
|
|
37
|
+
const trimmed = String(usd).replace(/^\$/, '');
|
|
38
|
+
return trimmed.startsWith('-') ? `-$${trimmed.slice(1)}` : `$${trimmed}`;
|
|
39
|
+
}
|
|
40
|
+
function day(value) {
|
|
41
|
+
if (!value)
|
|
42
|
+
return '-';
|
|
43
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
44
|
+
return Number.isNaN(date.getTime()) ? '-' : date.toISOString().slice(0, 10);
|
|
45
|
+
}
|
|
46
|
+
/** `skrr earnings`: the balance, then how and when it is paid out. */
|
|
47
|
+
function renderEarningsSummary(earnings, autoPayout, log) {
|
|
48
|
+
log('Publisher earnings');
|
|
49
|
+
log(` Available: ${dollars(earnings.usd.available)}`);
|
|
50
|
+
log(` Pending: ${dollars(earnings.usd.pending)} (on hold until the refund window ends)`);
|
|
51
|
+
log(` Lifetime: ${dollars(earnings.usd.lifetimeEarnings)}`);
|
|
52
|
+
log('');
|
|
53
|
+
if (!earnings.connectOnboarded) {
|
|
54
|
+
log('Payouts: not set up — set up payouts on the Earnings page to be paid.');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
log(`Payouts: minimum ${dollars(earnings.minPayoutUsd)}, at most one per payout window`);
|
|
58
|
+
if (!autoPayout) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
log(` Window: every ${autoPayout.cadenceDays} days`);
|
|
62
|
+
// The same state the web page reads: a date only while it is still ahead,
|
|
63
|
+
// and an open window says what it is waiting for when the balance is short.
|
|
64
|
+
const windowState = (0, data_provider_1.connectAutoPayoutWindowState)(autoPayout);
|
|
65
|
+
if (windowState === 'opens_later') {
|
|
66
|
+
log(` Next opens: ${day(autoPayout.windowOpensAt)}`);
|
|
67
|
+
}
|
|
68
|
+
else if (windowState === 'open') {
|
|
69
|
+
log(' Next opens: open now');
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
log(` Next opens: open now — waiting for the available balance to reach ${dollars(autoPayout.minimumUsd)} (it is ${dollars(autoPayout.availableUsd)})`);
|
|
73
|
+
}
|
|
74
|
+
log(` Automatic: ${autoPayout.enabled
|
|
75
|
+
? 'on — paid out within the hour the window opens, when the available balance meets the minimum'
|
|
76
|
+
: 'off — turn it on from the Earnings page'}`);
|
|
77
|
+
const last = (0, data_provider_1.describeConnectAutoPayoutAttempt)(autoPayout.lastAutoPayout);
|
|
78
|
+
if (last && autoPayout.lastAutoPayout) {
|
|
79
|
+
log(` Last automatic payout (${day(autoPayout.lastAutoPayout.at)}): ${last}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** `skrr earnings statements`: one row per month, newest first. */
|
|
83
|
+
function renderStatementList(result, log) {
|
|
84
|
+
if (result.statements.length === 0) {
|
|
85
|
+
log('No statements yet. A statement is issued on the 1st for the month that just ended.');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
(0, format_1.renderTable)(result.statements.map((statement) => ({
|
|
89
|
+
period: statement.period,
|
|
90
|
+
opening: dollars(statement.openingBalance.totalUsd),
|
|
91
|
+
net: dollars(statement.netChangeUsd),
|
|
92
|
+
closing: dollars(statement.closingBalance.totalUsd),
|
|
93
|
+
available: dollars(statement.closingBalance.availableUsd),
|
|
94
|
+
reconciles: statement.unreconciled ? `off by ${dollars(statement.unreconciledUsd)}` : 'yes',
|
|
95
|
+
})), [
|
|
96
|
+
{ key: 'period', header: 'MONTH' },
|
|
97
|
+
{ key: 'opening', header: 'OPENING' },
|
|
98
|
+
{ key: 'net', header: 'NET CHANGE' },
|
|
99
|
+
{ key: 'closing', header: 'CLOSING' },
|
|
100
|
+
{ key: 'available', header: 'OF WHICH AVAILABLE' },
|
|
101
|
+
{ key: 'reconciles', header: 'RECONCILES' },
|
|
102
|
+
], log);
|
|
103
|
+
if (result.hasNextPage && result.nextCursor) {
|
|
104
|
+
log('');
|
|
105
|
+
log(`More: skrr earnings statements --cursor ${result.nextCursor}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function balanceLine(label, balance) {
|
|
109
|
+
return `${label}${dollars(balance.totalUsd)} (available ${dollars(balance.availableUsd)}, pending ${dollars(balance.pendingUsd)})`;
|
|
110
|
+
}
|
|
111
|
+
/** `skrr earnings statements <YYYY-MM>`: the whole statement, opening to closing. */
|
|
112
|
+
function renderStatement(statement, log) {
|
|
113
|
+
log(`Statement for ${statement.period} (UTC)`);
|
|
114
|
+
log(balanceLine(' Opening balance ', statement.openingBalance));
|
|
115
|
+
log(` ${(0, data_provider_1.describeConnectStatementOpening)(statement.openingBasis)}`);
|
|
116
|
+
log('');
|
|
117
|
+
(0, format_1.renderTable)(data_provider_1.CONNECT_STATEMENT_LINES.map((line) => {
|
|
118
|
+
const entry = statement.activity[line.key];
|
|
119
|
+
const signed = line.sign === 0
|
|
120
|
+
? dollars(entry.amountUsd)
|
|
121
|
+
: `${line.sign < 0 ? '-' : '+'}${dollars(entry.amountUsd)}`;
|
|
122
|
+
return {
|
|
123
|
+
line: line.label,
|
|
124
|
+
count: String(entry.count),
|
|
125
|
+
amount: line.sign === 0 ? `${signed} (moved, not added)` : signed,
|
|
126
|
+
};
|
|
127
|
+
}), [
|
|
128
|
+
{ key: 'line', header: 'ACTIVITY' },
|
|
129
|
+
{ key: 'count', header: 'COUNT' },
|
|
130
|
+
{ key: 'amount', header: 'AMOUNT' },
|
|
131
|
+
], log);
|
|
132
|
+
log('');
|
|
133
|
+
log(` Net change ${dollars(statement.netChangeUsd)}`);
|
|
134
|
+
log(balanceLine(' Closing balance ', statement.closingBalance));
|
|
135
|
+
const unreconciled = (0, data_provider_1.describeConnectStatementUnreconciled)(statement);
|
|
136
|
+
if (unreconciled) {
|
|
137
|
+
log('');
|
|
138
|
+
log(` ${unreconciled}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** `skrr earnings payouts`: the payout ledger, newest first. */
|
|
142
|
+
function renderPayoutHistory(result, log) {
|
|
143
|
+
if (result.payouts.length === 0) {
|
|
144
|
+
log('No payouts yet.');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
(0, format_1.renderTable)(result.payouts.map((payout) => ({
|
|
148
|
+
requested: day(payout.requestedAt),
|
|
149
|
+
amount: dollars(payout.amountUsd),
|
|
150
|
+
status: payout.status,
|
|
151
|
+
settled: day(payout.platformSettledAt ?? payout.completedAt),
|
|
152
|
+
id: payout.id,
|
|
153
|
+
})), [
|
|
154
|
+
{ key: 'requested', header: 'REQUESTED' },
|
|
155
|
+
{ key: 'amount', header: 'AMOUNT' },
|
|
156
|
+
{ key: 'status', header: 'STATUS' },
|
|
157
|
+
{ key: 'settled', header: 'SETTLED' },
|
|
158
|
+
{ key: 'id', header: 'ID', verbatim: true },
|
|
159
|
+
], log);
|
|
160
|
+
if (result.hasNextPage && result.nextCursor) {
|
|
161
|
+
log('');
|
|
162
|
+
log(`More: skrr earnings payouts --cursor ${result.nextCursor}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Actions OIDC token acquisition for trusted publishing (OSK-12311).
|
|
3
|
+
*
|
|
4
|
+
* A workflow opts in with `permissions: id-token: write`; GitHub then exposes
|
|
5
|
+
* `ACTIONS_ID_TOKEN_REQUEST_URL` / `ACTIONS_ID_TOKEN_REQUEST_TOKEN` to the
|
|
6
|
+
* job, and this job-level URL is the only place a token can be requested —
|
|
7
|
+
* the response is what `POST /api/agents/:id/ci-releases` verifies.
|
|
8
|
+
*
|
|
9
|
+
* `audience` is what the token asserts it is FOR: the API checks it against
|
|
10
|
+
* `GITHUB_ACTIONS_OIDC_AUDIENCE` (else `DOMAIN_SERVER`, else `skrr`). Leave it
|
|
11
|
+
* unset to take the job's default, or pass the deployment's canonical origin.
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchGitHubActionsOidcToken(audience?: string): Promise<string>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchGitHubActionsOidcToken = fetchGitHubActionsOidcToken;
|
|
4
|
+
/**
|
|
5
|
+
* GitHub Actions OIDC token acquisition for trusted publishing (OSK-12311).
|
|
6
|
+
*
|
|
7
|
+
* A workflow opts in with `permissions: id-token: write`; GitHub then exposes
|
|
8
|
+
* `ACTIONS_ID_TOKEN_REQUEST_URL` / `ACTIONS_ID_TOKEN_REQUEST_TOKEN` to the
|
|
9
|
+
* job, and this job-level URL is the only place a token can be requested —
|
|
10
|
+
* the response is what `POST /api/agents/:id/ci-releases` verifies.
|
|
11
|
+
*
|
|
12
|
+
* `audience` is what the token asserts it is FOR: the API checks it against
|
|
13
|
+
* `GITHUB_ACTIONS_OIDC_AUDIENCE` (else `DOMAIN_SERVER`, else `skrr`). Leave it
|
|
14
|
+
* unset to take the job's default, or pass the deployment's canonical origin.
|
|
15
|
+
*/
|
|
16
|
+
async function fetchGitHubActionsOidcToken(audience) {
|
|
17
|
+
const requestUrl = process.env.ACTIONS_ID_TOKEN_REQUEST_URL;
|
|
18
|
+
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
|
|
19
|
+
if (!requestUrl || !requestToken) {
|
|
20
|
+
throw new Error('No GitHub OIDC request context: run inside GitHub Actions with ' +
|
|
21
|
+
'`permissions: id-token: write`, or pass --oidc-token explicitly');
|
|
22
|
+
}
|
|
23
|
+
const url = new URL(requestUrl);
|
|
24
|
+
if (audience) {
|
|
25
|
+
url.searchParams.set('audience', audience);
|
|
26
|
+
}
|
|
27
|
+
const res = await fetch(url, {
|
|
28
|
+
headers: {
|
|
29
|
+
authorization: `bearer ${requestToken}`,
|
|
30
|
+
accept: 'application/json',
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
if (!res.ok) {
|
|
34
|
+
throw new Error(`GitHub OIDC token request failed (${res.status})`);
|
|
35
|
+
}
|
|
36
|
+
const body = (await res.json());
|
|
37
|
+
if (typeof body?.value !== 'string' || body.value.length === 0) {
|
|
38
|
+
throw new Error('GitHub OIDC token request returned no token');
|
|
39
|
+
}
|
|
40
|
+
return body.value;
|
|
41
|
+
}
|
|
@@ -90,15 +90,56 @@ export declare function updateOwnLicensePolicy(licenseId: string, body: BundleLi
|
|
|
90
90
|
export declare function updateWorkspaceLicensePolicy(workspaceId: string, licenseId: string, body: BundleLicensePolicyInput): Promise<{
|
|
91
91
|
license: unknown;
|
|
92
92
|
}>;
|
|
93
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* The modes the server's workspace Store policy evaluator honours
|
|
95
|
+
* (`api/server/services/commerce/WorkspaceStorePolicy.js`). `open` is also
|
|
96
|
+
* what a workspace with no policy means.
|
|
97
|
+
*/
|
|
98
|
+
export type WorkspaceStorePolicyMode = 'open' | 'deny_all' | 'allowlist';
|
|
99
|
+
/**
|
|
100
|
+
* The levels a workspace caps a release at (OSK-12262); each name is a mode
|
|
101
|
+
* the release's own capability manifest reports.
|
|
102
|
+
*/
|
|
103
|
+
export interface StoreCapabilityCeiling {
|
|
104
|
+
builtinTools?: 'none' | 'allowlist' | 'platform_default';
|
|
105
|
+
platformCapabilities?: 'not_loaded' | 'listed' | 'unrestricted';
|
|
106
|
+
delegation?: 'none' | 'specific' | 'all';
|
|
107
|
+
proactive?: boolean;
|
|
108
|
+
firstContact?: boolean;
|
|
109
|
+
sharedData?: 'none' | 'bootstrap' | 'memory' | 'full';
|
|
110
|
+
/** Allowed `tool:|connector:|data:|network:|secret:` keys; `*` allows all. */
|
|
111
|
+
permissions?: string[];
|
|
112
|
+
}
|
|
113
|
+
/** `GET /workspaces/:workspaceId/policy` — members read the policy that governs them. */
|
|
114
|
+
export declare function getWorkspaceStorePolicy(workspaceId: string): Promise<{
|
|
115
|
+
policy: unknown;
|
|
116
|
+
}>;
|
|
117
|
+
/** `PUT /workspaces/:workspaceId/policy` — which releases a workspace may install and run. */
|
|
94
118
|
export declare function setWorkspaceStorePolicy(workspaceId: string, body: {
|
|
95
|
-
mode:
|
|
119
|
+
mode: WorkspaceStorePolicyMode;
|
|
96
120
|
allowedReleaseIds: string[];
|
|
121
|
+
capabilityCeiling?: StoreCapabilityCeiling | null;
|
|
97
122
|
policyId?: string;
|
|
98
123
|
expectedRevision?: number;
|
|
99
124
|
}): Promise<{
|
|
100
125
|
policy: unknown;
|
|
101
126
|
}>;
|
|
127
|
+
/** `POST /workspaces/:workspaceId/store-requests` — a member asks for a refused release. */
|
|
128
|
+
export declare function submitStoreInstallRequest(workspaceId: string, body: {
|
|
129
|
+
releaseId: string;
|
|
130
|
+
note?: string;
|
|
131
|
+
requestId?: string;
|
|
132
|
+
}): Promise<{
|
|
133
|
+
request: unknown;
|
|
134
|
+
}>;
|
|
135
|
+
/** `GET /workspaces/:workspaceId/store-requests` — the queue (owner) or your own asks (member). */
|
|
136
|
+
export declare function listStoreInstallRequests(workspaceId: string, status?: string): Promise<{
|
|
137
|
+
requests: unknown[];
|
|
138
|
+
}>;
|
|
139
|
+
/** `POST …/store-requests/:requestId/approve|decline` — the owner's answer. */
|
|
140
|
+
export declare function decideStoreInstallRequest(workspaceId: string, requestId: string, decision: 'approve' | 'decline'): Promise<{
|
|
141
|
+
request: unknown;
|
|
142
|
+
}>;
|
|
102
143
|
/** `POST /workspaces/:workspaceId/assignments` — give a seat to a member or Space. */
|
|
103
144
|
export declare function assignWorkspaceStoreLicense(workspaceId: string, body: {
|
|
104
145
|
licenseId: string;
|
|
@@ -6,7 +6,11 @@ exports.publishGovernedStoreRelease = publishGovernedStoreRelease;
|
|
|
6
6
|
exports.createGovernedStoreLicense = createGovernedStoreLicense;
|
|
7
7
|
exports.updateOwnLicensePolicy = updateOwnLicensePolicy;
|
|
8
8
|
exports.updateWorkspaceLicensePolicy = updateWorkspaceLicensePolicy;
|
|
9
|
+
exports.getWorkspaceStorePolicy = getWorkspaceStorePolicy;
|
|
9
10
|
exports.setWorkspaceStorePolicy = setWorkspaceStorePolicy;
|
|
11
|
+
exports.submitStoreInstallRequest = submitStoreInstallRequest;
|
|
12
|
+
exports.listStoreInstallRequests = listStoreInstallRequests;
|
|
13
|
+
exports.decideStoreInstallRequest = decideStoreInstallRequest;
|
|
10
14
|
exports.assignWorkspaceStoreLicense = assignWorkspaceStoreLicense;
|
|
11
15
|
const api_fetch_1 = require("./api-fetch");
|
|
12
16
|
const triggers_1 = require("./triggers");
|
|
@@ -69,10 +73,30 @@ async function updateOwnLicensePolicy(licenseId, body) {
|
|
|
69
73
|
async function updateWorkspaceLicensePolicy(workspaceId, licenseId, body) {
|
|
70
74
|
return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/licenses/${encodeURIComponent(licenseId)}/update-policy`, { method: 'PATCH', body });
|
|
71
75
|
}
|
|
72
|
-
/** `
|
|
76
|
+
/** `GET /workspaces/:workspaceId/policy` — members read the policy that governs them. */
|
|
77
|
+
async function getWorkspaceStorePolicy(workspaceId) {
|
|
78
|
+
return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/policy`, { method: 'GET' });
|
|
79
|
+
}
|
|
80
|
+
/** `PUT /workspaces/:workspaceId/policy` — which releases a workspace may install and run. */
|
|
73
81
|
async function setWorkspaceStorePolicy(workspaceId, body) {
|
|
74
82
|
return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/policy`, { method: 'PUT', body });
|
|
75
83
|
}
|
|
84
|
+
/** `POST /workspaces/:workspaceId/store-requests` — a member asks for a refused release. */
|
|
85
|
+
async function submitStoreInstallRequest(workspaceId, body) {
|
|
86
|
+
return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests`, { method: 'POST', body });
|
|
87
|
+
}
|
|
88
|
+
/** `GET /workspaces/:workspaceId/store-requests` — the queue (owner) or your own asks (member). */
|
|
89
|
+
async function listStoreInstallRequests(workspaceId, status) {
|
|
90
|
+
return (0, api_fetch_1.apiFetch)((0, triggers_1.withQuery)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests`, status ? { status } : {}), { method: 'GET' });
|
|
91
|
+
}
|
|
92
|
+
/** `POST …/store-requests/:requestId/approve|decline` — the owner's answer. */
|
|
93
|
+
async function decideStoreInstallRequest(workspaceId, requestId, decision) {
|
|
94
|
+
// Two literal paths — the parity checker reads route coverage from literals.
|
|
95
|
+
const path = decision === 'approve'
|
|
96
|
+
? `/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests/${encodeURIComponent(requestId)}/approve`
|
|
97
|
+
: `/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests/${encodeURIComponent(requestId)}/decline`;
|
|
98
|
+
return (0, api_fetch_1.apiFetch)(path, { method: 'POST', body: {} });
|
|
99
|
+
}
|
|
76
100
|
/** `POST /workspaces/:workspaceId/assignments` — give a seat to a member or Space. */
|
|
77
101
|
async function assignWorkspaceStoreLicense(workspaceId, body) {
|
|
78
102
|
return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/assignments`, { method: 'POST', body });
|
package/dist/lib/label-ref.js
CHANGED
|
@@ -48,6 +48,17 @@ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
|
|
|
48
48
|
function looksLikeLabelId(ref) {
|
|
49
49
|
return UUID_RE.test(ref.trim());
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* A label id that lost characters in a copy — hex and dashes, but not the
|
|
53
|
+
* uuid shape. It can NEVER be a label name (names are human words), so it must
|
|
54
|
+
* not fall into the name path, where the refusal would tell the caller to
|
|
55
|
+
* create a label literally named `ed3f89d3-875b-…`. The honest message is
|
|
56
|
+
* "this looks like a truncated id".
|
|
57
|
+
*/
|
|
58
|
+
const ID_SHAPED_RE = /^[0-9a-f-]{20,}$/i;
|
|
59
|
+
function looksLikeTruncatedLabelId(ref) {
|
|
60
|
+
return !looksLikeLabelId(ref) && ref.includes('-') && ID_SHAPED_RE.test(ref.trim());
|
|
61
|
+
}
|
|
51
62
|
/** Levenshtein, iterative, two rows. Only ever runs on a refusal path. */
|
|
52
63
|
function distance(a, b) {
|
|
53
64
|
if (a === b)
|
|
@@ -148,6 +159,11 @@ async function resolveLabelRefs(refs, context) {
|
|
|
148
159
|
resolved.push(ref);
|
|
149
160
|
continue;
|
|
150
161
|
}
|
|
162
|
+
if (looksLikeTruncatedLabelId(ref)) {
|
|
163
|
+
throw new LabelRefError(`"${ref}" looks like a label id but is not a complete one — ` +
|
|
164
|
+
`an id was probably truncated when copied. ` +
|
|
165
|
+
`Get the full id with \`labels list --json\`.`);
|
|
166
|
+
}
|
|
151
167
|
const needle = ref.toLowerCase();
|
|
152
168
|
const matches = vocabulary.filter((row) => (row.name ?? '').toLowerCase() === needle);
|
|
153
169
|
if (matches.length === 1) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ManagedExecutionAgent {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
position: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Agent Worker has no Machine row. The durable, user-visible relationship is
|
|
8
|
+
* an Agent's ordered execution policy, which this projection exposes.
|
|
9
|
+
*/
|
|
10
|
+
export declare function managedExecutionAgents(response: unknown): ManagedExecutionAgent[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.managedExecutionAgents = managedExecutionAgents;
|
|
4
|
+
function agentWorkerPosition(agent) {
|
|
5
|
+
const policy = agent.executionPolicy;
|
|
6
|
+
if (Array.isArray(policy?.targets)) {
|
|
7
|
+
const index = policy.targets.findIndex((target) => Boolean(target) &&
|
|
8
|
+
typeof target === 'object' &&
|
|
9
|
+
target.kind === 'agent-worker' &&
|
|
10
|
+
target.enabled !== false);
|
|
11
|
+
return index >= 0 ? index + 1 : null;
|
|
12
|
+
}
|
|
13
|
+
const executionOrder = agent.executionOrder;
|
|
14
|
+
if (!Array.isArray(executionOrder))
|
|
15
|
+
return null;
|
|
16
|
+
const index = executionOrder.findIndex((target) => Boolean(target) &&
|
|
17
|
+
typeof target === 'object' &&
|
|
18
|
+
target.kind === 'agent-worker');
|
|
19
|
+
return index >= 0 ? index + 1 : null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Agent Worker has no Machine row. The durable, user-visible relationship is
|
|
23
|
+
* an Agent's ordered execution policy, which this projection exposes.
|
|
24
|
+
*/
|
|
25
|
+
function managedExecutionAgents(response) {
|
|
26
|
+
const envelope = response;
|
|
27
|
+
const agents = Array.isArray(response)
|
|
28
|
+
? response
|
|
29
|
+
: Array.isArray(envelope?.data)
|
|
30
|
+
? envelope.data
|
|
31
|
+
: Array.isArray(envelope?.agents)
|
|
32
|
+
? envelope.agents
|
|
33
|
+
: [];
|
|
34
|
+
return agents
|
|
35
|
+
.filter((agent) => Boolean(agent) && typeof agent === 'object')
|
|
36
|
+
.map((agent) => ({ agent, position: agentWorkerPosition(agent) }))
|
|
37
|
+
.filter((entry) => entry.position !== null)
|
|
38
|
+
.map(({ agent, position }) => {
|
|
39
|
+
const id = String(agent.id ?? agent._id ?? '');
|
|
40
|
+
return { id, name: String(agent.name ?? (id || 'Unnamed agent')), position };
|
|
41
|
+
})
|
|
42
|
+
.sort((a, b) => a.position - b.position || a.name.localeCompare(b.name));
|
|
43
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* principal-display.ts — render a principal as a name a person recognises.
|
|
3
|
+
*
|
|
4
|
+
* WHY
|
|
5
|
+
* ---
|
|
6
|
+
* `tasks show`, `comments list` and friends print author/assignee ids verbatim
|
|
7
|
+
* (`Author: 68ed5a0482dd30a0a610a916`). An id is correct on the wire and
|
|
8
|
+
* useless at a keyboard — the one thing the column is for is "who is this".
|
|
9
|
+
*
|
|
10
|
+
* Resolution is best-effort and bounded to two cheap sources: the caller's own
|
|
11
|
+
* record (`/api/user`) and the Space member roster (`GET
|
|
12
|
+
* /api/spaces/:id/members`) when the task has a Space. An unresolvable id
|
|
13
|
+
* prints unchanged — a roster read failure must never fail the command, so
|
|
14
|
+
* every fetch is caught.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolvePrincipalNames(ids: ReadonlyArray<unknown>, options?: {
|
|
17
|
+
spaceId?: string | null;
|
|
18
|
+
}): Promise<Map<string, string>>;
|
|
19
|
+
/** The name when known, else the id unchanged — never blank. */
|
|
20
|
+
export declare function displayPrincipal(id: unknown, names: Map<string, string> | undefined): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* principal-display.ts — render a principal as a name a person recognises.
|
|
4
|
+
*
|
|
5
|
+
* WHY
|
|
6
|
+
* ---
|
|
7
|
+
* `tasks show`, `comments list` and friends print author/assignee ids verbatim
|
|
8
|
+
* (`Author: 68ed5a0482dd30a0a610a916`). An id is correct on the wire and
|
|
9
|
+
* useless at a keyboard — the one thing the column is for is "who is this".
|
|
10
|
+
*
|
|
11
|
+
* Resolution is best-effort and bounded to two cheap sources: the caller's own
|
|
12
|
+
* record (`/api/user`) and the Space member roster (`GET
|
|
13
|
+
* /api/spaces/:id/members`) when the task has a Space. An unresolvable id
|
|
14
|
+
* prints unchanged — a roster read failure must never fail the command, so
|
|
15
|
+
* every fetch is caught.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.resolvePrincipalNames = resolvePrincipalNames;
|
|
19
|
+
exports.displayPrincipal = displayPrincipal;
|
|
20
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
21
|
+
async function resolvePrincipalNames(ids, options = {}) {
|
|
22
|
+
const wanted = new Set(ids.filter((id) => typeof id === 'string' && id.length > 0));
|
|
23
|
+
const names = new Map();
|
|
24
|
+
if (wanted.size === 0)
|
|
25
|
+
return names;
|
|
26
|
+
const add = (id, display) => {
|
|
27
|
+
const key = typeof id === 'string' ? id : id != null ? String(id) : undefined;
|
|
28
|
+
const name = typeof display === 'string' && display.trim() ? display.trim() : undefined;
|
|
29
|
+
if (key && name && wanted.has(key) && !names.has(key))
|
|
30
|
+
names.set(key, name);
|
|
31
|
+
};
|
|
32
|
+
const reads = [
|
|
33
|
+
data_provider_1.dataService
|
|
34
|
+
.getUser()
|
|
35
|
+
.then((me) => {
|
|
36
|
+
const display = me?.name || me?.username || me?.email;
|
|
37
|
+
add(me?.id ?? me?._id, display);
|
|
38
|
+
})
|
|
39
|
+
.catch(() => undefined),
|
|
40
|
+
];
|
|
41
|
+
if (options.spaceId) {
|
|
42
|
+
reads.push(data_provider_1.dataService
|
|
43
|
+
.getSpaceMembers(options.spaceId)
|
|
44
|
+
.then((members) => {
|
|
45
|
+
for (const member of members?.users ?? []) {
|
|
46
|
+
const display = member.user?.name || member.user?.username || member.user?.email;
|
|
47
|
+
add(member.userId, display);
|
|
48
|
+
add(member.user?._id, display);
|
|
49
|
+
}
|
|
50
|
+
for (const agent of members?.agents ?? []) {
|
|
51
|
+
add(agent.id, agent.name);
|
|
52
|
+
add(agent._id, agent.name);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.catch(() => undefined));
|
|
56
|
+
}
|
|
57
|
+
await Promise.all(reads);
|
|
58
|
+
return names;
|
|
59
|
+
}
|
|
60
|
+
/** The name when known, else the id unchanged — never blank. */
|
|
61
|
+
function displayPrincipal(id, names) {
|
|
62
|
+
const key = id == null ? '-' : String(id);
|
|
63
|
+
return names?.get(key) ?? key;
|
|
64
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SpaceTemplateSource, SpaceTemplateSourceResponse } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* The `Template:` / `Update:` lines `skrr spaces show` prints for a Space a
|
|
4
|
+
* template install created. The same states the web notice draws, and for the
|
|
5
|
+
* same reason each is spelled out: "up to date" is printed only when the check
|
|
6
|
+
* answered `current`, and a failed check says it failed rather than printing
|
|
7
|
+
* nothing — silence would read as "no update".
|
|
8
|
+
*/
|
|
9
|
+
export declare function templateSourceLines({ source, check, checkError, baseURL, }: {
|
|
10
|
+
source: SpaceTemplateSource;
|
|
11
|
+
check?: SpaceTemplateSourceResponse | null;
|
|
12
|
+
checkError?: string;
|
|
13
|
+
baseURL: string;
|
|
14
|
+
}): string[];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.templateSourceLines = templateSourceLines;
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const web_url_1 = require("./web-url");
|
|
6
|
+
/**
|
|
7
|
+
* The `Template:` / `Update:` lines `skrr spaces show` prints for a Space a
|
|
8
|
+
* template install created. The same states the web notice draws, and for the
|
|
9
|
+
* same reason each is spelled out: "up to date" is printed only when the check
|
|
10
|
+
* answered `current`, and a failed check says it failed rather than printing
|
|
11
|
+
* nothing — silence would read as "no update".
|
|
12
|
+
*/
|
|
13
|
+
function templateSourceLines({ source, check, checkError, baseURL, }) {
|
|
14
|
+
const title = source.templateTitle?.trim() || source.templateId;
|
|
15
|
+
const installed = (0, data_provider_1.spaceTemplateVersionLabel)(source);
|
|
16
|
+
const installedOn = typeof source.installedAt === 'string' ? source.installedAt.slice(0, 10) : undefined;
|
|
17
|
+
const lines = [
|
|
18
|
+
`Template: ${title}${installed ? ` · ${installed}` : ''}${installedOn ? ` (installed ${installedOn})` : ''}`,
|
|
19
|
+
];
|
|
20
|
+
if (checkError) {
|
|
21
|
+
lines.push(`Update: check failed (${checkError})`);
|
|
22
|
+
return lines;
|
|
23
|
+
}
|
|
24
|
+
const link = (0, web_url_1.webUrl)(baseURL, { kind: 'spaceTemplate', templateId: source.templateId });
|
|
25
|
+
switch (check?.status) {
|
|
26
|
+
case 'update_available': {
|
|
27
|
+
const latest = (0, data_provider_1.spaceTemplateVersionLabel)(check.latest);
|
|
28
|
+
lines.push(`Update: ${latest ? `${latest} available` : 'the template changed since install'}${link ? ` — ${link}` : ''}`);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case 'current':
|
|
32
|
+
lines.push('Update: up to date');
|
|
33
|
+
break;
|
|
34
|
+
case 'unavailable':
|
|
35
|
+
lines.push('Update: template no longer available');
|
|
36
|
+
break;
|
|
37
|
+
default:
|
|
38
|
+
lines.push('Update: not checked');
|
|
39
|
+
}
|
|
40
|
+
return lines;
|
|
41
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the CLI says about step-up authentication before Store publishing
|
|
3
|
+
* (OSK-12275).
|
|
4
|
+
*
|
|
5
|
+
* A public release reaches everyone who installs it, so the server refuses to
|
|
6
|
+
* publish one, or to move the release buyers are served, on the strength of a
|
|
7
|
+
* CLI token alone: it answers `STEP_UP_REQUIRED` until this same login has
|
|
8
|
+
* proved a second factor through `skrr step-up`. The vocabulary (the code, the
|
|
9
|
+
* reasons, the window) is `@skrr-ai/data-provider`'s; only the sentences live
|
|
10
|
+
* here, because each reason has a different next step and a refusal that says
|
|
11
|
+
* "forbidden" would leave a publisher guessing which one applies.
|
|
12
|
+
*/
|
|
13
|
+
import type { TStepUpChallenge } from '@skrr-ai/data-provider';
|
|
14
|
+
/**
|
|
15
|
+
* The explanation printed when a command is refused with `STEP_UP_REQUIRED`.
|
|
16
|
+
* `challenge` may be `null` for a body this CLI could not read, which still
|
|
17
|
+
* gets the ordinary remedy rather than a bare status line.
|
|
18
|
+
*/
|
|
19
|
+
export declare function describeStepUpRequired(challenge: TStepUpChallenge | null, bin: string): string;
|
|
20
|
+
/** The clock time a verification lasts until, in the reader's local time. */
|
|
21
|
+
export declare function formatStepUpExpiry(expiresAt: string | undefined): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeStepUpRequired = describeStepUpRequired;
|
|
4
|
+
exports.formatStepUpExpiry = formatStepUpExpiry;
|
|
5
|
+
const NOTHING_CHANGED = 'Nothing was published or changed.';
|
|
6
|
+
function windowPhrase(windowSeconds) {
|
|
7
|
+
const minutes = Math.max(1, Math.round((windowSeconds ?? 600) / 60));
|
|
8
|
+
return `${minutes} minute${minutes === 1 ? '' : 's'}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The explanation printed when a command is refused with `STEP_UP_REQUIRED`.
|
|
12
|
+
* `challenge` may be `null` for a body this CLI could not read, which still
|
|
13
|
+
* gets the ordinary remedy rather than a bare status line.
|
|
14
|
+
*/
|
|
15
|
+
function describeStepUpRequired(challenge, bin) {
|
|
16
|
+
const window = windowPhrase(challenge?.windowSeconds);
|
|
17
|
+
switch (challenge?.reason) {
|
|
18
|
+
case 'two_factor_not_enabled':
|
|
19
|
+
return [
|
|
20
|
+
`Publishing to the Store needs two-factor authentication, and this account has none. ${NOTHING_CHANGED}`,
|
|
21
|
+
'Turn it on in the web app (Settings → Account → Two-factor authentication),',
|
|
22
|
+
`then run \`${bin} step-up\` and run this command again within ${window}.`,
|
|
23
|
+
].join('\n');
|
|
24
|
+
case 'credential_not_session_bound':
|
|
25
|
+
return [
|
|
26
|
+
`This credential is not tied to a sign-in session, so it cannot be verified for publishing. ${NOTHING_CHANGED}`,
|
|
27
|
+
`Run \`${bin} login\`, then \`${bin} step-up\`, and run this command again within ${window}.`,
|
|
28
|
+
].join('\n');
|
|
29
|
+
default:
|
|
30
|
+
return [
|
|
31
|
+
`Publishing needs a fresh identity check: a public release reaches everyone who installs it, so this login alone is not enough. ${NOTHING_CHANGED}`,
|
|
32
|
+
`Run \`${bin} step-up\` and enter the code from your authenticator app, then run this command again within ${window}.`,
|
|
33
|
+
].join('\n');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** The clock time a verification lasts until, in the reader's local time. */
|
|
37
|
+
function formatStepUpExpiry(expiresAt) {
|
|
38
|
+
if (!expiresAt)
|
|
39
|
+
return 'the end of the verification window';
|
|
40
|
+
const date = new Date(expiresAt);
|
|
41
|
+
if (Number.isNaN(date.getTime()))
|
|
42
|
+
return 'the end of the verification window';
|
|
43
|
+
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
44
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { StoreAcquisitionRequest } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* A purchase an agent asked to make, as the lines a terminal shows (OSK-12240).
|
|
4
|
+
*
|
|
5
|
+
* The same server copy the web approval card renders: every field comes from
|
|
6
|
+
* `GET /api/store/acquisition-requests/:id`, which the fulfillment path built
|
|
7
|
+
* from the listing it resolved. Nothing the requesting agent wrote reaches
|
|
8
|
+
* these lines. The words themselves come from `@skrr-ai/data-provider`, so the
|
|
9
|
+
* terminal and the card cannot describe one request two ways.
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeAcquisitionRequestLines(request: StoreAcquisitionRequest): string[];
|