@skrr-ai/cli 0.1.47 → 0.1.48

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.
Files changed (274) hide show
  1. package/README.md +1 -1
  2. package/dist/base-command.d.ts +18 -0
  3. package/dist/base-command.js +61 -1
  4. package/dist/commands/agents/chat.d.ts +21 -0
  5. package/dist/commands/agents/chat.js +26 -9
  6. package/dist/commands/balance/usage/breakdown.d.ts +14 -0
  7. package/dist/commands/balance/usage/breakdown.js +68 -0
  8. package/dist/commands/balance/usage.js +24 -0
  9. package/dist/commands/commerce/entitlements/explain.d.ts +22 -0
  10. package/dist/commands/commerce/entitlements/explain.js +40 -0
  11. package/dist/commands/commerce/incidents/audit.d.ts +20 -0
  12. package/dist/commands/commerce/incidents/audit.js +37 -0
  13. package/dist/commands/commerce/incidents/list.d.ts +22 -0
  14. package/dist/commands/commerce/incidents/list.js +49 -0
  15. package/dist/commands/commerce/incidents/resolve.d.ts +23 -0
  16. package/dist/commands/commerce/incidents/resolve.js +45 -0
  17. package/dist/commands/commerce/incidents/retry.d.ts +22 -0
  18. package/dist/commands/commerce/incidents/retry.js +45 -0
  19. package/dist/commands/commerce/incidents/show.d.ts +13 -0
  20. package/dist/commands/commerce/incidents/show.js +30 -0
  21. package/dist/commands/commerce/offers/approve.d.ts +17 -0
  22. package/dist/commands/commerce/offers/approve.js +33 -0
  23. package/dist/commands/commerce/offers/create.d.ts +18 -0
  24. package/dist/commands/commerce/offers/create.js +34 -0
  25. package/dist/commands/commerce/offers/publish.d.ts +13 -0
  26. package/dist/commands/commerce/offers/publish.js +28 -0
  27. package/dist/commands/commerce/offers/retire.d.ts +17 -0
  28. package/dist/commands/commerce/offers/retire.js +32 -0
  29. package/dist/commands/commerce/offers/validate.d.ts +18 -0
  30. package/dist/commands/commerce/offers/validate.js +33 -0
  31. package/dist/commands/commerce/products/create.d.ts +10 -0
  32. package/dist/commands/commerce/products/create.js +25 -0
  33. package/dist/commands/commerce/promotions/redeem.d.ts +13 -0
  34. package/dist/commands/commerce/promotions/redeem.js +32 -0
  35. package/dist/commands/commerce/terms/accept.d.ts +18 -0
  36. package/dist/commands/commerce/terms/accept.js +39 -0
  37. package/dist/commands/commerce/terms/show.d.ts +10 -0
  38. package/dist/commands/commerce/terms/show.js +34 -0
  39. package/dist/commands/commerce/trials/conversion-preview.d.ts +18 -0
  40. package/dist/commands/commerce/trials/conversion-preview.js +39 -0
  41. package/dist/commands/commerce/trials/start.d.ts +23 -0
  42. package/dist/commands/commerce/trials/start.js +58 -0
  43. package/dist/commands/commitments/accounting.d.ts +39 -0
  44. package/dist/commands/commitments/accounting.js +116 -0
  45. package/dist/commands/commitments/action-history.d.ts +1 -0
  46. package/dist/commands/commitments/action-history.js +8 -1
  47. package/dist/commands/commitments/case.d.ts +1 -0
  48. package/dist/commands/commitments/case.js +19 -3
  49. package/dist/commands/commitments/cases.d.ts +1 -0
  50. package/dist/commands/commitments/cases.js +11 -1
  51. package/dist/commands/commitments/checks.d.ts +1 -0
  52. package/dist/commands/commitments/checks.js +5 -1
  53. package/dist/commands/commitments/cost.d.ts +62 -0
  54. package/dist/commands/commitments/cost.js +130 -0
  55. package/dist/commands/commitments/create.js +1 -1
  56. package/dist/commands/commitments/delete.d.ts +1 -0
  57. package/dist/commands/commitments/delete.js +56 -6
  58. package/dist/commands/commitments/feedback.js +9 -1
  59. package/dist/commands/commitments/handover.js +16 -0
  60. package/dist/commands/commitments/hypotheses.d.ts +1 -0
  61. package/dist/commands/commitments/hypotheses.js +17 -2
  62. package/dist/commands/commitments/links/list.js +4 -1
  63. package/dist/commands/commitments/liveness.d.ts +18 -0
  64. package/dist/commands/commitments/liveness.js +80 -0
  65. package/dist/commands/commitments/metrics.d.ts +1 -0
  66. package/dist/commands/commitments/metrics.js +8 -1
  67. package/dist/commands/commitments/next-tick.d.ts +39 -0
  68. package/dist/commands/commitments/next-tick.js +122 -0
  69. package/dist/commands/commitments/observations.d.ts +1 -0
  70. package/dist/commands/commitments/observations.js +19 -2
  71. package/dist/commands/commitments/pause.js +12 -0
  72. package/dist/commands/commitments/receipt.d.ts +2 -0
  73. package/dist/commands/commitments/receipt.js +16 -2
  74. package/dist/commands/commitments/remediation-proposal.js +6 -2
  75. package/dist/commands/commitments/remediation-proposals.js +5 -1
  76. package/dist/commands/commitments/restore.d.ts +25 -0
  77. package/dist/commands/commitments/restore.js +46 -0
  78. package/dist/commands/commitments/show.js +32 -0
  79. package/dist/commands/commitments/trigger-status.js +33 -0
  80. package/dist/commands/commitments/update.d.ts +1 -0
  81. package/dist/commands/commitments/update.js +31 -5
  82. package/dist/commands/commitments/wake-capabilities.d.ts +0 -1
  83. package/dist/commands/commitments/wake-capabilities.js +8 -4
  84. package/dist/commands/enterprise/budgets/create.d.ts +11 -0
  85. package/dist/commands/enterprise/budgets/create.js +27 -0
  86. package/dist/commands/enterprise/budgets/evaluate.d.ts +17 -0
  87. package/dist/commands/enterprise/budgets/evaluate.js +32 -0
  88. package/dist/commands/enterprise/budgets/publish.d.ts +14 -0
  89. package/dist/commands/enterprise/budgets/publish.js +30 -0
  90. package/dist/commands/enterprise/contracts/activate.d.ts +14 -0
  91. package/dist/commands/enterprise/contracts/activate.js +30 -0
  92. package/dist/commands/enterprise/contracts/create.d.ts +14 -0
  93. package/dist/commands/enterprise/contracts/create.js +32 -0
  94. package/dist/commands/enterprise/contracts/issue.d.ts +18 -0
  95. package/dist/commands/enterprise/contracts/issue.js +34 -0
  96. package/dist/commands/enterprise/domains/begin.d.ts +20 -0
  97. package/dist/commands/enterprise/domains/begin.js +39 -0
  98. package/dist/commands/enterprise/domains/verify.d.ts +14 -0
  99. package/dist/commands/enterprise/domains/verify.js +32 -0
  100. package/dist/commands/enterprise/external-config/activate.d.ts +22 -0
  101. package/dist/commands/enterprise/external-config/activate.js +49 -0
  102. package/dist/commands/enterprise/external-config/set.d.ts +25 -0
  103. package/dist/commands/enterprise/external-config/set.js +123 -0
  104. package/dist/commands/enterprise/external-config/show.d.ts +12 -0
  105. package/dist/commands/enterprise/external-config/show.js +39 -0
  106. package/dist/commands/enterprise/external-config/suspend.d.ts +13 -0
  107. package/dist/commands/enterprise/external-config/suspend.js +41 -0
  108. package/dist/commands/enterprise/finance/close-snapshot.d.ts +11 -0
  109. package/dist/commands/enterprise/finance/close-snapshot.js +28 -0
  110. package/dist/commands/enterprise/finance/record-document.d.ts +18 -0
  111. package/dist/commands/enterprise/finance/record-document.js +35 -0
  112. package/dist/commands/enterprise/profile.d.ts +20 -0
  113. package/dist/commands/enterprise/profile.js +38 -0
  114. package/dist/commands/login.d.ts +13 -0
  115. package/dist/commands/login.js +77 -0
  116. package/dist/commands/machines/dedicated/index.js +3 -0
  117. package/dist/commands/machines/dedicated/service/apply.d.ts +23 -0
  118. package/dist/commands/machines/dedicated/service/apply.js +99 -0
  119. package/dist/commands/machines/dedicated/service/approve.d.ts +23 -0
  120. package/dist/commands/machines/dedicated/service/approve.js +52 -0
  121. package/dist/commands/machines/dedicated/service/create.d.ts +55 -0
  122. package/dist/commands/machines/dedicated/service/create.js +222 -0
  123. package/dist/commands/machines/dedicated/service/edit.d.ts +30 -0
  124. package/dist/commands/machines/dedicated/service/edit.js +146 -0
  125. package/dist/commands/machines/dedicated/service/exec.d.ts +26 -0
  126. package/dist/commands/machines/dedicated/service/exec.js +92 -0
  127. package/dist/commands/machines/dedicated/service/export.d.ts +29 -0
  128. package/dist/commands/machines/dedicated/service/export.js +106 -0
  129. package/dist/commands/machines/dedicated/service/index.d.ts +14 -0
  130. package/dist/commands/machines/dedicated/service/index.js +49 -0
  131. package/dist/commands/machines/dedicated/service/logs.d.ts +33 -0
  132. package/dist/commands/machines/dedicated/service/logs.js +148 -0
  133. package/dist/commands/machines/dedicated/service/ls.d.ts +20 -0
  134. package/dist/commands/machines/dedicated/service/ls.js +80 -0
  135. package/dist/commands/machines/dedicated/service/restart.d.ts +14 -0
  136. package/dist/commands/machines/dedicated/service/restart.js +29 -0
  137. package/dist/commands/machines/dedicated/service/rm.d.ts +20 -0
  138. package/dist/commands/machines/dedicated/service/rm.js +33 -0
  139. package/dist/commands/machines/dedicated/service/secret/index.d.ts +14 -0
  140. package/dist/commands/machines/dedicated/service/secret/index.js +25 -0
  141. package/dist/commands/machines/dedicated/service/secret/rm.d.ts +22 -0
  142. package/dist/commands/machines/dedicated/service/secret/rm.js +54 -0
  143. package/dist/commands/machines/dedicated/service/secret/set.d.ts +22 -0
  144. package/dist/commands/machines/dedicated/service/secret/set.js +93 -0
  145. package/dist/commands/machines/dedicated/service/start.d.ts +14 -0
  146. package/dist/commands/machines/dedicated/service/start.js +29 -0
  147. package/dist/commands/machines/dedicated/service/status.d.ts +21 -0
  148. package/dist/commands/machines/dedicated/service/status.js +85 -0
  149. package/dist/commands/machines/dedicated/service/stop.d.ts +20 -0
  150. package/dist/commands/machines/dedicated/service/stop.js +35 -0
  151. package/dist/commands/machines/dedicated/service/top.d.ts +22 -0
  152. package/dist/commands/machines/dedicated/service/top.js +120 -0
  153. package/dist/commands/machines/dedicated/sign-in-status.d.ts +22 -0
  154. package/dist/commands/machines/dedicated/sign-in-status.js +79 -0
  155. package/dist/commands/machines/dedicated/ssh-config.d.ts +28 -0
  156. package/dist/commands/machines/dedicated/ssh-config.js +66 -0
  157. package/dist/commands/machines/dedicated/ssh-proxy.d.ts +22 -0
  158. package/dist/commands/machines/dedicated/ssh-proxy.js +62 -0
  159. package/dist/commands/machines/dedicated/ssh.d.ts +29 -0
  160. package/dist/commands/machines/dedicated/ssh.js +121 -0
  161. package/dist/commands/native/allow-all.d.ts +14 -0
  162. package/dist/commands/native/allow-all.js +25 -0
  163. package/dist/commands/native/allow.d.ts +24 -0
  164. package/dist/commands/native/allow.js +45 -0
  165. package/dist/commands/native/deny.d.ts +24 -0
  166. package/dist/commands/native/deny.js +43 -0
  167. package/dist/commands/native/disable.d.ts +17 -0
  168. package/dist/commands/native/disable.js +28 -0
  169. package/dist/commands/native/enable.d.ts +12 -0
  170. package/dist/commands/native/enable.js +29 -0
  171. package/dist/commands/native/list-apps.d.ts +19 -0
  172. package/dist/commands/native/list-apps.js +30 -0
  173. package/dist/commands/native/restrict-to.d.ts +22 -0
  174. package/dist/commands/native/restrict-to.js +41 -0
  175. package/dist/commands/native/status.d.ts +19 -0
  176. package/dist/commands/native/status.js +33 -0
  177. package/dist/commands/native.d.ts +39 -0
  178. package/dist/commands/native.js +76 -0
  179. package/dist/commands/service/index.d.ts +14 -0
  180. package/dist/commands/service/index.js +31 -0
  181. package/dist/commands/service/logs.d.ts +18 -0
  182. package/dist/commands/service/logs.js +53 -0
  183. package/dist/commands/service/ls.d.ts +13 -0
  184. package/dist/commands/service/ls.js +48 -0
  185. package/dist/commands/service/propose.d.ts +34 -0
  186. package/dist/commands/service/propose.js +113 -0
  187. package/dist/commands/service/status.d.ts +17 -0
  188. package/dist/commands/service/status.js +56 -0
  189. package/dist/commands/spaces/auto-executor/runs.d.ts +13 -0
  190. package/dist/commands/spaces/auto-executor/runs.js +56 -0
  191. package/dist/commands/store/governance/artifacts.d.ts +25 -0
  192. package/dist/commands/store/governance/artifacts.js +55 -0
  193. package/dist/commands/store/governance/assign.d.ts +16 -0
  194. package/dist/commands/store/governance/assign.js +54 -0
  195. package/dist/commands/store/governance/create-license.d.ts +18 -0
  196. package/dist/commands/store/governance/create-license.js +35 -0
  197. package/dist/commands/store/governance/install-plan.d.ts +25 -0
  198. package/dist/commands/store/governance/install-plan.js +56 -0
  199. package/dist/commands/store/governance/license-policy.d.ts +30 -0
  200. package/dist/commands/store/governance/license-policy.js +69 -0
  201. package/dist/commands/store/governance/policy.d.ts +25 -0
  202. package/dist/commands/store/governance/policy.js +65 -0
  203. package/dist/commands/store/governance/publish-release.d.ts +17 -0
  204. package/dist/commands/store/governance/publish-release.js +34 -0
  205. package/dist/commands/tasks/deliverable/add.d.ts +15 -0
  206. package/dist/commands/tasks/deliverable/add.js +174 -0
  207. package/dist/commands/tasks/deliverable/archive.d.ts +35 -0
  208. package/dist/commands/tasks/deliverable/archive.js +205 -0
  209. package/dist/commands/tasks/labels/detach.js +3 -0
  210. package/dist/commands/tasks/labels/suggest.d.ts +24 -0
  211. package/dist/commands/tasks/labels/suggest.js +69 -0
  212. package/dist/commands/tasks/list.d.ts +16 -2
  213. package/dist/commands/tasks/list.js +100 -24
  214. package/dist/commands/tasks/show.d.ts +23 -0
  215. package/dist/commands/tasks/show.js +51 -1
  216. package/dist/commands/wiki/rm.d.ts +22 -1
  217. package/dist/commands/wiki/rm.js +52 -3
  218. package/dist/lib/agentic-stream.js +10 -2
  219. package/dist/lib/balance.d.ts +6 -1
  220. package/dist/lib/balance.js +15 -0
  221. package/dist/lib/commerce-command.d.ts +48 -0
  222. package/dist/lib/commerce-command.js +70 -0
  223. package/dist/lib/commerce.d.ts +93 -0
  224. package/dist/lib/commerce.js +129 -0
  225. package/dist/lib/commitment-product.js +1 -1
  226. package/dist/lib/commitments.d.ts +202 -29
  227. package/dist/lib/commitments.js +300 -33
  228. package/dist/lib/dedicated-lease-command.js +10 -0
  229. package/dist/lib/dedicated-machines.d.ts +37 -0
  230. package/dist/lib/dedicated-machines.js +47 -0
  231. package/dist/lib/dedicated-service-command.d.ts +60 -0
  232. package/dist/lib/dedicated-service-command.js +182 -0
  233. package/dist/lib/dedicated-service.d.ts +342 -0
  234. package/dist/lib/dedicated-service.js +741 -0
  235. package/dist/lib/dedicated-ssh.d.ts +136 -0
  236. package/dist/lib/dedicated-ssh.js +387 -0
  237. package/dist/lib/delegated-cli.js +51 -13
  238. package/dist/lib/enterprise-commerce.d.ts +67 -0
  239. package/dist/lib/enterprise-commerce.js +112 -0
  240. package/dist/lib/enterprise-external-configuration.d.ts +60 -0
  241. package/dist/lib/enterprise-external-configuration.js +58 -0
  242. package/dist/lib/first-party-harness.js +17 -3
  243. package/dist/lib/governed-store.d.ts +110 -0
  244. package/dist/lib/governed-store.js +79 -0
  245. package/dist/lib/guest-service-command.d.ts +16 -0
  246. package/dist/lib/guest-service-command.js +32 -0
  247. package/dist/lib/guest-service.d.ts +67 -0
  248. package/dist/lib/guest-service.js +112 -0
  249. package/dist/lib/prompt.d.ts +1 -0
  250. package/dist/lib/prompt.js +1 -0
  251. package/dist/lib/task-asset-upload.d.ts +20 -0
  252. package/dist/lib/task-asset-upload.js +30 -8
  253. package/dist/lib/task-extras.d.ts +23 -0
  254. package/dist/lib/task-extras.js +6 -0
  255. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.d.ts +9 -3
  256. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.js +10 -3
  257. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  258. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +6 -5
  259. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +16 -0
  260. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +21 -4
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +1 -1
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +24 -2
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.d.ts +9 -3
  264. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.js +10 -3
  265. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  266. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  267. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +16 -0
  268. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +20 -4
  269. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +1 -1
  270. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +24 -2
  271. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  272. package/dist/node_modules/@skrr-ai/data-provider/index.js +5060 -4827
  273. package/oclif.manifest.json +37416 -31416
  274. package/package.json +43 -1
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const enterprise_commerce_1 = require("../../../lib/enterprise-commerce");
6
+ const commerce_command_1 = require("../../../lib/commerce-command");
7
+ /** Go and look for the challenge. The server checks; the caller supplies no proof. */
8
+ class EnterpriseDomainsVerify extends base_command_1.BaseCommand {
9
+ static description = 'Verify a published domain challenge for an enterprise workspace (admin). The platform goes and looks — evidence is never accepted from the caller.';
10
+ static examples = [
11
+ '<%= config.bin %> enterprise domains verify <workspace-id> --file ./domain.json',
12
+ ];
13
+ static args = {
14
+ workspace: core_1.Args.string({ description: 'Workspace id', required: true, ignoreStdin: true }),
15
+ };
16
+ static flags = { ...commerce_command_1.jsonBodyFlags };
17
+ async run() {
18
+ this.requireAuth();
19
+ const { args, flags } = await this.parse(EnterpriseDomainsVerify);
20
+ const body = await (0, commerce_command_1.jsonBodyFrom)(this, flags.file);
21
+ let result;
22
+ try {
23
+ result = await (0, enterprise_commerce_1.verifyEnterpriseDomain)(args.workspace, body);
24
+ }
25
+ catch (error) {
26
+ this.handleApiError(error);
27
+ return;
28
+ }
29
+ this.log(JSON.stringify(result, null, 2));
30
+ }
31
+ }
32
+ exports.default = EnterpriseDomainsVerify;
@@ -0,0 +1,22 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * `skrr enterprise external-config activate` — ask for the destination to be
4
+ * verified, and say plainly that asking is all this did.
5
+ *
6
+ * The route answers 202 with a verification job: the evidence that the
7
+ * destination really accepts writes is produced by the writer and verifier
8
+ * workloads, never handed in by the caller. A command that printed "activated"
9
+ * here would be reporting a request as a result — the same collapse a green
10
+ * pipeline and a deployed commit have already cost this repo three times.
11
+ */
12
+ export default class EnterpriseExternalConfigActivate extends BaseCommand {
13
+ static description: string;
14
+ static examples: string[];
15
+ static args: {
16
+ workspace: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
17
+ };
18
+ static flags: {
19
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const enterprise_external_configuration_1 = require("../../../lib/enterprise-external-configuration");
6
+ /**
7
+ * `skrr enterprise external-config activate` — ask for the destination to be
8
+ * verified, and say plainly that asking is all this did.
9
+ *
10
+ * The route answers 202 with a verification job: the evidence that the
11
+ * destination really accepts writes is produced by the writer and verifier
12
+ * workloads, never handed in by the caller. A command that printed "activated"
13
+ * here would be reporting a request as a result — the same collapse a green
14
+ * pipeline and a deployed commit have already cost this repo three times.
15
+ */
16
+ class EnterpriseExternalConfigActivate extends base_command_1.BaseCommand {
17
+ static description = "Request activation of a workspace's enterprise external configuration. This enqueues verification; the destination is not live until verification passes.";
18
+ static examples = [
19
+ '<%= config.bin %> enterprise external-config activate <workspace-id>',
20
+ '<%= config.bin %> enterprise external-config activate <workspace-id> --json',
21
+ ];
22
+ static args = {
23
+ workspace: core_1.Args.string({ description: 'Workspace id', required: true, ignoreStdin: true }),
24
+ };
25
+ static flags = {
26
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
27
+ };
28
+ async run() {
29
+ this.requireAuth();
30
+ const { args, flags } = await this.parse(EnterpriseExternalConfigActivate);
31
+ let response;
32
+ try {
33
+ response = await (0, enterprise_external_configuration_1.activateEnterpriseExternalConfiguration)(args.workspace);
34
+ }
35
+ catch (error) {
36
+ this.handleApiError(error);
37
+ return;
38
+ }
39
+ if (flags.json) {
40
+ this.log(JSON.stringify(response, null, 2));
41
+ return;
42
+ }
43
+ const job = response.verificationJob || {};
44
+ this.log(`Verification requested${job.id ? ` (job ${job.id})` : ''}${job.status ? `, ${job.status}` : ''}.`);
45
+ this.log('Not live yet: the writer and verifier workloads produce the evidence, and this command ' +
46
+ 'cannot supply it. Re-read with `enterprise external-config show`.');
47
+ }
48
+ }
49
+ exports.default = EnterpriseExternalConfigActivate;
@@ -0,0 +1,25 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * `skrr enterprise external-config set` — create or replace one exact revision.
4
+ *
5
+ * `--expect-revision` is the whole safety story and is deliberately not
6
+ * optional-by-convenience: WITH it the write is a compare-and-set against the
7
+ * revision you read, WITHOUT it the write means "there is nothing here yet".
8
+ * Those are two intents, so the command refuses to guess which one you meant
9
+ * when the answer is knowable — `show` prints the revision for exactly this.
10
+ */
11
+ export default class EnterpriseExternalConfigSet extends BaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static args: {
15
+ workspace: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
16
+ };
17
+ static flags: {
18
+ file: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ 'expect-revision': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ create: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ 'configuration-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
+ };
24
+ run(): Promise<void>;
25
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("node:fs"));
37
+ const core_1 = require("@oclif/core");
38
+ const base_command_1 = require("../../../base-command");
39
+ const enterprise_external_configuration_1 = require("../../../lib/enterprise-external-configuration");
40
+ /**
41
+ * `skrr enterprise external-config set` — create or replace one exact revision.
42
+ *
43
+ * `--expect-revision` is the whole safety story and is deliberately not
44
+ * optional-by-convenience: WITH it the write is a compare-and-set against the
45
+ * revision you read, WITHOUT it the write means "there is nothing here yet".
46
+ * Those are two intents, so the command refuses to guess which one you meant
47
+ * when the answer is knowable — `show` prints the revision for exactly this.
48
+ */
49
+ class EnterpriseExternalConfigSet extends base_command_1.BaseCommand {
50
+ static description = "Create or replace a workspace's enterprise external configuration. Replacing is fenced on the revision you read, so two operators cannot silently overwrite each other.";
51
+ static examples = [
52
+ '<%= config.bin %> enterprise external-config set <workspace-id> --file ./export.json --create',
53
+ '<%= config.bin %> enterprise external-config set <workspace-id> --file ./export.json --expect-revision 3',
54
+ ];
55
+ static args = {
56
+ workspace: core_1.Args.string({ description: 'Workspace id', required: true, ignoreStdin: true }),
57
+ };
58
+ static flags = {
59
+ file: core_1.Flags.string({
60
+ description: 'Path to the configuration JSON, or - to read stdin',
61
+ required: true,
62
+ }),
63
+ 'expect-revision': core_1.Flags.integer({
64
+ description: 'Replace exactly this revision (from `show`). Refused together with --create.',
65
+ }),
66
+ create: core_1.Flags.boolean({
67
+ description: 'This workspace has no configuration yet. Refused together with --expect-revision.',
68
+ }),
69
+ 'configuration-id': core_1.Flags.string({
70
+ description: 'Configuration id, when the service needs one',
71
+ }),
72
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
73
+ };
74
+ async run() {
75
+ this.requireAuth();
76
+ const { args, flags } = await this.parse(EnterpriseExternalConfigSet);
77
+ const expectedRevision = flags['expect-revision'];
78
+ if (flags.create && expectedRevision !== undefined) {
79
+ this.error('--create and --expect-revision are two different intents: one says nothing is there, the other says replace exactly this. Pass one.', { exit: 2 });
80
+ }
81
+ if (!flags.create && expectedRevision === undefined) {
82
+ this.error("Pass --expect-revision <n> (see `enterprise external-config show`) to replace the configuration, or --create when there is none yet. An unfenced replace can overwrite another operator's write.", { exit: 2 });
83
+ }
84
+ let raw;
85
+ try {
86
+ raw = flags.file === '-' ? fs.readFileSync(0, 'utf8') : fs.readFileSync(flags.file, 'utf8');
87
+ }
88
+ catch {
89
+ this.error(`Could not read ${flags.file === '-' ? 'stdin' : flags.file}`, { exit: 1 });
90
+ return;
91
+ }
92
+ let configuration;
93
+ try {
94
+ configuration = JSON.parse(raw);
95
+ }
96
+ catch (error) {
97
+ this.error(`${flags.file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, { exit: 1 });
98
+ return;
99
+ }
100
+ let response;
101
+ try {
102
+ response = await (0, enterprise_external_configuration_1.upsertEnterpriseExternalConfiguration)(args.workspace, {
103
+ configuration,
104
+ configurationId: flags['configuration-id'],
105
+ expectedRevision,
106
+ });
107
+ }
108
+ catch (error) {
109
+ this.handleApiError(error);
110
+ return;
111
+ }
112
+ if (flags.json) {
113
+ this.log(JSON.stringify(response, null, 2));
114
+ return;
115
+ }
116
+ for (const line of (0, enterprise_external_configuration_1.describeEnterpriseExternalConfiguration)(response.configuration)) {
117
+ this.log(line);
118
+ }
119
+ // Saying it here because the next command is the one that costs something.
120
+ this.log('\nStored. It is not exporting yet — run `enterprise external-config activate`.');
121
+ }
122
+ }
123
+ exports.default = EnterpriseExternalConfigSet;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class EnterpriseExternalConfigShow extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ workspace: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const enterprise_external_configuration_1 = require("../../../lib/enterprise-external-configuration");
6
+ class EnterpriseExternalConfigShow extends base_command_1.BaseCommand {
7
+ static description = "Show a workspace's enterprise external configuration — where its audit and log export goes, and whether that destination is live.";
8
+ static examples = [
9
+ '<%= config.bin %> enterprise external-config show <workspace-id>',
10
+ '<%= config.bin %> enterprise external-config show <workspace-id> --json',
11
+ ];
12
+ static args = {
13
+ workspace: core_1.Args.string({ description: 'Workspace id', required: true, ignoreStdin: true }),
14
+ };
15
+ static flags = {
16
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
17
+ };
18
+ async run() {
19
+ this.requireAuth();
20
+ const { args, flags } = await this.parse(EnterpriseExternalConfigShow);
21
+ let response;
22
+ try {
23
+ response = await (0, enterprise_external_configuration_1.getEnterpriseExternalConfiguration)(args.workspace);
24
+ }
25
+ catch (error) {
26
+ this.handleApiError(error);
27
+ return;
28
+ }
29
+ if (flags.json) {
30
+ this.log(JSON.stringify(response, null, 2));
31
+ return;
32
+ }
33
+ for (const line of (0, enterprise_external_configuration_1.describeEnterpriseExternalConfiguration)(response.configuration)) {
34
+ this.log(line);
35
+ }
36
+ this.log('\nUse --json for the configuration body itself.');
37
+ }
38
+ }
39
+ exports.default = EnterpriseExternalConfigShow;
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class EnterpriseExternalConfigSuspend extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ workspace: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'expect-revision': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const enterprise_external_configuration_1 = require("../../../lib/enterprise-external-configuration");
6
+ class EnterpriseExternalConfigSuspend extends base_command_1.BaseCommand {
7
+ static description = "Stop a workspace's enterprise external export. Fenced on the revision you read, so it cannot suspend a configuration somebody else has since replaced.";
8
+ static examples = [
9
+ '<%= config.bin %> enterprise external-config suspend <workspace-id> --expect-revision 4',
10
+ ];
11
+ static args = {
12
+ workspace: core_1.Args.string({ description: 'Workspace id', required: true, ignoreStdin: true }),
13
+ };
14
+ static flags = {
15
+ 'expect-revision': core_1.Flags.integer({
16
+ description: 'The revision to suspend, from `enterprise external-config show`',
17
+ required: true,
18
+ }),
19
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
20
+ };
21
+ async run() {
22
+ this.requireAuth();
23
+ const { args, flags } = await this.parse(EnterpriseExternalConfigSuspend);
24
+ let response;
25
+ try {
26
+ response = await (0, enterprise_external_configuration_1.suspendEnterpriseExternalConfiguration)(args.workspace, flags['expect-revision']);
27
+ }
28
+ catch (error) {
29
+ this.handleApiError(error);
30
+ return;
31
+ }
32
+ if (flags.json) {
33
+ this.log(JSON.stringify(response, null, 2));
34
+ return;
35
+ }
36
+ for (const line of (0, enterprise_external_configuration_1.describeEnterpriseExternalConfiguration)(response.configuration)) {
37
+ this.log(line);
38
+ }
39
+ }
40
+ }
41
+ exports.default = EnterpriseExternalConfigSuspend;
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /** Freeze a period's figures. A snapshot is a claim about a closed period. */
3
+ export default class EnterpriseFinanceCloseSnapshot extends BaseCommand {
4
+ static description: string;
5
+ static examples: string[];
6
+ static flags: {
7
+ file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const base_command_1 = require("../../../base-command");
4
+ const enterprise_commerce_1 = require("../../../lib/enterprise-commerce");
5
+ const commerce_command_1 = require("../../../lib/commerce-command");
6
+ /** Freeze a period's figures. A snapshot is a claim about a closed period. */
7
+ class EnterpriseFinanceCloseSnapshot extends base_command_1.BaseCommand {
8
+ static description = "Create a finance-close snapshot, freezing a period's figures (admin).";
9
+ static examples = [
10
+ '<%= config.bin %> enterprise finance close-snapshot --file ./period.json',
11
+ ];
12
+ static flags = { ...commerce_command_1.jsonBodyFlags };
13
+ async run() {
14
+ this.requireAuth();
15
+ const { flags } = await this.parse(EnterpriseFinanceCloseSnapshot);
16
+ const body = await (0, commerce_command_1.jsonBodyFrom)(this, flags.file);
17
+ let result;
18
+ try {
19
+ result = await (0, enterprise_commerce_1.createEnterpriseFinanceCloseSnapshot)(body);
20
+ }
21
+ catch (error) {
22
+ this.handleApiError(error);
23
+ return;
24
+ }
25
+ this.log(JSON.stringify(result, null, 2));
26
+ }
27
+ }
28
+ exports.default = EnterpriseFinanceCloseSnapshot;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Record a financial document the platform did NOT generate.
4
+ *
5
+ * The route says `manual` and the command keeps the word. A document the
6
+ * platform produced and one somebody typed in are different evidence, and a
7
+ * verb that read simply "record" would let the second be mistaken for the
8
+ * first later, when it matters.
9
+ */
10
+ export default class EnterpriseFinanceRecordDocument extends BaseCommand {
11
+ static description: string;
12
+ static examples: string[];
13
+ static flags: {
14
+ file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const base_command_1 = require("../../../base-command");
4
+ const enterprise_commerce_1 = require("../../../lib/enterprise-commerce");
5
+ const commerce_command_1 = require("../../../lib/commerce-command");
6
+ /**
7
+ * Record a financial document the platform did NOT generate.
8
+ *
9
+ * The route says `manual` and the command keeps the word. A document the
10
+ * platform produced and one somebody typed in are different evidence, and a
11
+ * verb that read simply "record" would let the second be mistaken for the
12
+ * first later, when it matters.
13
+ */
14
+ class EnterpriseFinanceRecordDocument extends base_command_1.BaseCommand {
15
+ static description = 'Record a financial document the platform did not generate (admin). Manual entry — it is evidence somebody supplied, not evidence the platform produced.';
16
+ static examples = [
17
+ '<%= config.bin %> enterprise finance record-document --file ./invoice.json',
18
+ ];
19
+ static flags = { ...commerce_command_1.jsonBodyFlags };
20
+ async run() {
21
+ this.requireAuth();
22
+ const { flags } = await this.parse(EnterpriseFinanceRecordDocument);
23
+ const body = await (0, commerce_command_1.jsonBodyFrom)(this, flags.file);
24
+ let result;
25
+ try {
26
+ result = await (0, enterprise_commerce_1.recordEnterpriseFinancialDocument)(body);
27
+ }
28
+ catch (error) {
29
+ this.handleApiError(error);
30
+ return;
31
+ }
32
+ this.log(JSON.stringify(result, null, 2));
33
+ }
34
+ }
35
+ exports.default = EnterpriseFinanceRecordDocument;
@@ -0,0 +1,20 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * `skrr enterprise profile <workspace-id>` — the workspace's enterprise profile.
4
+ *
5
+ * A PUT, so this replaces the profile rather than patching it. The command
6
+ * says so in its description instead of pretending to merge, because a
7
+ * partial body sent to a replacing endpoint silently drops whatever it omits.
8
+ */
9
+ export default class EnterpriseProfile extends BaseCommand {
10
+ static description: string;
11
+ static examples: string[];
12
+ static args: {
13
+ workspace: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
14
+ };
15
+ static flags: {
16
+ file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
18
+ };
19
+ run(): Promise<void>;
20
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const enterprise_commerce_1 = require("../../lib/enterprise-commerce");
6
+ const commerce_command_1 = require("../../lib/commerce-command");
7
+ /**
8
+ * `skrr enterprise profile <workspace-id>` — the workspace's enterprise profile.
9
+ *
10
+ * A PUT, so this replaces the profile rather than patching it. The command
11
+ * says so in its description instead of pretending to merge, because a
12
+ * partial body sent to a replacing endpoint silently drops whatever it omits.
13
+ */
14
+ class EnterpriseProfile extends base_command_1.BaseCommand {
15
+ static description = "Replace a workspace's enterprise profile (admin). This is a full replace, not a merge — anything your body omits is dropped.";
16
+ static examples = [
17
+ '<%= config.bin %> enterprise profile <workspace-id> --file ./profile.json',
18
+ ];
19
+ static args = {
20
+ workspace: core_1.Args.string({ description: 'Workspace id', required: true, ignoreStdin: true }),
21
+ };
22
+ static flags = { ...commerce_command_1.jsonBodyFlags };
23
+ async run() {
24
+ this.requireAuth();
25
+ const { args, flags } = await this.parse(EnterpriseProfile);
26
+ const body = await (0, commerce_command_1.jsonBodyFrom)(this, flags.file);
27
+ let result;
28
+ try {
29
+ result = await (0, enterprise_commerce_1.upsertEnterpriseProfile)(args.workspace, body);
30
+ }
31
+ catch (error) {
32
+ this.handleApiError(error);
33
+ return;
34
+ }
35
+ this.log(JSON.stringify(result, null, 2));
36
+ }
37
+ }
38
+ exports.default = EnterpriseProfile;
@@ -66,4 +66,17 @@ export default class Login extends BaseCommand {
66
66
  * only when the client can locally confirm the alphabet is wrong.
67
67
  */
68
68
  private runRecoveryCodeLogin;
69
+ /**
70
+ * C3 step 2 — the server accepted the recovery code and staged a
71
+ * Redis-backed OTP challenge, emailing the code to the account address.
72
+ * Prompt for it and complete the redemption; /redeem/confirm is the only
73
+ * endpoint that mints the token pair.
74
+ */
75
+ private confirmRecoveryChallenge;
76
+ /**
77
+ * A credential-minting flow may persist only a response that carries a
78
+ * credential. Asserts the token-bearing contract before writeToBackend so
79
+ * a successful-but-tokenless answer can never clobber the stored bundle.
80
+ */
81
+ private assertRedeemResult;
69
82
  }
@@ -12,6 +12,7 @@ const login_1 = require("../lib/login");
12
12
  const device_code_1 = require("../lib/device-code");
13
13
  const api_fetch_1 = require("../lib/api-fetch");
14
14
  const auth_storage_1 = require("../lib/auth-storage");
15
+ const prompt_1 = require("../lib/prompt");
15
16
  /**
16
17
  * `skrr login`
17
18
  *
@@ -337,6 +338,18 @@ class Login extends base_command_1.BaseCommand {
337
338
  }
338
339
  this.handleApiError(err);
339
340
  }
341
+ // C3 step 2 — a challenge-shaped answer means the server staged an OTP
342
+ // and emailed it to the account address; complete the redemption with
343
+ // POST /redeem/confirm, the only endpoint that mints tokens.
344
+ if (typeof result.challengeId === 'string' && result.challengeId.length > 0) {
345
+ result = await this.confirmRecoveryChallenge(result.challengeId);
346
+ }
347
+ // Persist only a response that actually carries a credential. A
348
+ // tokenless body (an unexpected shape, or a challenge we could not
349
+ // complete) must never reach writeToBackend — writing undefined token
350
+ // fields destroys the stored credential (Keychain delete-all on macOS,
351
+ // an origin-only cli-auth.json elsewhere) and redeems nothing.
352
+ this.assertRedeemResult(result);
340
353
  // Persist via the CLI's canonical token-save path (Keychain on macOS, file elsewhere).
341
354
  (0, auth_storage_1.writeToBackend)({
342
355
  token: result.token,
@@ -351,5 +364,69 @@ class Login extends base_command_1.BaseCommand {
351
364
  `${(0, config_1.describeDeployment)(this.cliConfig.baseURL)}.`);
352
365
  this.log(`Run \`${this.config.bin} whoami\` to confirm your identity.`);
353
366
  }
367
+ /**
368
+ * C3 step 2 — the server accepted the recovery code and staged a
369
+ * Redis-backed OTP challenge, emailing the code to the account address.
370
+ * Prompt for it and complete the redemption; /redeem/confirm is the only
371
+ * endpoint that mints the token pair.
372
+ */
373
+ async confirmRecoveryChallenge(challengeId) {
374
+ if (!process.stdin.isTTY) {
375
+ this.error('This server requires a confirmation code that was emailed to the account ' +
376
+ 'address, and there is no terminal to enter it. Run this command ' +
377
+ 'interactively. No credentials were changed.', { exit: 1 });
378
+ }
379
+ const otp = await (0, prompt_1.prompt)('Enter the recovery confirmation code from your email: ', {
380
+ hidden: true,
381
+ });
382
+ if (!otp) {
383
+ this.error('No confirmation code entered; recovery aborted. No credentials were changed.', {
384
+ exit: 1,
385
+ });
386
+ }
387
+ try {
388
+ return await (0, api_fetch_1.apiFetch)('/api/auth/recovery/redeem/confirm', {
389
+ method: 'POST',
390
+ // Recovery redeem is public — no credential needed.
391
+ body: { challengeId, otp },
392
+ });
393
+ }
394
+ catch (err) {
395
+ if (err instanceof api_fetch_1.ApiFetchError) {
396
+ if (err.status === 401) {
397
+ this.error('Confirmation code is incorrect. The challenge was consumed — ' +
398
+ 'run the command again with the recovery code to receive a new one.', { exit: 1 });
399
+ }
400
+ if (err.status === 410) {
401
+ this.error('Recovery challenge expired. Run the command again to restart.', { exit: 1 });
402
+ }
403
+ if (err.status === 429) {
404
+ this.error('Too many recovery attempts. Please wait 15 minutes before trying again.', {
405
+ exit: 1,
406
+ });
407
+ }
408
+ }
409
+ this.handleApiError(err);
410
+ }
411
+ }
412
+ /**
413
+ * A credential-minting flow may persist only a response that carries a
414
+ * credential. Asserts the token-bearing contract before writeToBackend so
415
+ * a successful-but-tokenless answer can never clobber the stored bundle.
416
+ */
417
+ assertRedeemResult(result) {
418
+ const candidate = result;
419
+ if (!candidate ||
420
+ typeof candidate.token !== 'string' ||
421
+ candidate.token.length === 0 ||
422
+ typeof candidate.refreshToken !== 'string' ||
423
+ candidate.refreshToken.length === 0 ||
424
+ !candidate.user ||
425
+ typeof candidate.user.email !== 'string' ||
426
+ candidate.user.email.length === 0) {
427
+ this.error('Recovery did not return a session — the server answered with an unexpected ' +
428
+ 'response shape. No credentials were changed. Update the skrr CLI if this persists.', { exit: 1 });
429
+ }
430
+ }
354
431
  }
355
432
  exports.default = Login;
@@ -28,6 +28,8 @@ class DedicatedMachines extends core_1.Command {
28
28
  '<%= config.bin %> machines dedicated spending-limit <lease-id> --cents 30000',
29
29
  '<%= config.bin %> machines dedicated health-check <lease-id>',
30
30
  '<%= config.bin %> machines dedicated incident-close <lease-id>',
31
+ '<%= config.bin %> machines dedicated service create <lease-id> --name worker -- node dist/worker.js',
32
+ '<%= config.bin %> machines dedicated service ls <lease-id>',
31
33
  '<%= config.bin %> machines dedicated destroy <lease-id>',
32
34
  ];
33
35
  async run() {
@@ -51,6 +53,7 @@ class DedicatedMachines extends core_1.Command {
51
53
  ['spending-limit', 'change the monthly spending cap'],
52
54
  ['health-check', 'probe daemon and disk liveness'],
53
55
  ['incident-close', 'close AZ-recovery evidence hold'],
56
+ ['service', 'declare workloads the machine keeps running'],
54
57
  ['destroy', 'stop compute; keep or purge the workspace disk'],
55
58
  ];
56
59
  this.log('skrr Dedicated Runtime commands:');