lh-ops 0.1.0

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 (49) hide show
  1. package/README.md +93 -0
  2. package/bin/lh-ops +2 -0
  3. package/dist/commands/audit.js +66 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/cache-coverage.js +54 -0
  6. package/dist/commands/cache-coverage.js.map +1 -0
  7. package/dist/commands/export.js +138 -0
  8. package/dist/commands/export.js.map +1 -0
  9. package/dist/commands/login.js +50 -0
  10. package/dist/commands/login.js.map +1 -0
  11. package/dist/commands/member.js +25 -0
  12. package/dist/commands/member.js.map +1 -0
  13. package/dist/commands/models.js +23 -0
  14. package/dist/commands/models.js.map +1 -0
  15. package/dist/commands/org-list.js +45 -0
  16. package/dist/commands/org-list.js.map +1 -0
  17. package/dist/commands/org-usage.js +77 -0
  18. package/dist/commands/org-usage.js.map +1 -0
  19. package/dist/commands/org.js +72 -0
  20. package/dist/commands/org.js.map +1 -0
  21. package/dist/commands/phase2-status.js +41 -0
  22. package/dist/commands/phase2-status.js.map +1 -0
  23. package/dist/commands/plan.js +70 -0
  24. package/dist/commands/plan.js.map +1 -0
  25. package/dist/commands/pricebook.js +39 -0
  26. package/dist/commands/pricebook.js.map +1 -0
  27. package/dist/commands/scanners.js +33 -0
  28. package/dist/commands/scanners.js.map +1 -0
  29. package/dist/commands/statement.js +101 -0
  30. package/dist/commands/statement.js.map +1 -0
  31. package/dist/commands/subscription.js +32 -0
  32. package/dist/commands/subscription.js.map +1 -0
  33. package/dist/commands/token.js +61 -0
  34. package/dist/commands/token.js.map +1 -0
  35. package/dist/commands/topup.js +34 -0
  36. package/dist/commands/topup.js.map +1 -0
  37. package/dist/index.js +795 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/lib/client.js +11 -0
  40. package/dist/lib/client.js.map +1 -0
  41. package/dist/lib/credentials.js +68 -0
  42. package/dist/lib/credentials.js.map +1 -0
  43. package/dist/lib/errors.js +45 -0
  44. package/dist/lib/errors.js.map +1 -0
  45. package/dist/lib/output.js +41 -0
  46. package/dist/lib/output.js.map +1 -0
  47. package/dist/lib/resolve-client.js +42 -0
  48. package/dist/lib/resolve-client.js.map +1 -0
  49. package/package.json +35 -0
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renameOrg = renameOrg;
4
+ exports.createOrg = createOrg;
5
+ exports.showOrg = showOrg;
6
+ exports.suspendOrg = suspendOrg;
7
+ exports.activateOrg = activateOrg;
8
+ exports.listOrgTokens = listOrgTokens;
9
+ exports.renderOrgTokens = renderOrgTokens;
10
+ const lh_api_client_1 = require("lh-api-client");
11
+ const resolve_client_1 = require("../lib/resolve-client");
12
+ /** Rename a customer org (intent 1). */
13
+ async function renameOrg(input) {
14
+ const client = await (0, resolve_client_1.resolveClient)(input);
15
+ return (0, lh_api_client_1.renameOrg)(client, input.orgId, input.name);
16
+ }
17
+ async function createOrg(input) {
18
+ const client = await (0, resolve_client_1.resolveClient)(input);
19
+ const body = {
20
+ orgName: input.orgName,
21
+ adminEmail: input.adminEmail,
22
+ adminName: input.adminName,
23
+ };
24
+ if (input.planId)
25
+ body.planId = input.planId;
26
+ return client.request('/platform/orgs', {
27
+ method: 'POST',
28
+ body,
29
+ });
30
+ }
31
+ async function showOrg(input) {
32
+ const client = await (0, resolve_client_1.resolveClient)(input);
33
+ return client.request(`/platform/orgs/${encodeURIComponent(input.orgId)}`);
34
+ }
35
+ async function patchOrgStatus(input, status) {
36
+ const client = await (0, resolve_client_1.resolveClient)(input);
37
+ const body = { status };
38
+ if (input.reason)
39
+ body.reason = input.reason;
40
+ return client.request(`/platform/orgs/${encodeURIComponent(input.orgId)}/status`, { method: 'PATCH', body });
41
+ }
42
+ /** Suspend an org (#27). Existing api-keys are rejected at relay preCheck. */
43
+ function suspendOrg(input) {
44
+ return patchOrgStatus(input, 'SUSPENDED');
45
+ }
46
+ /** Reactivate a suspended org (#27). */
47
+ function activateOrg(input) {
48
+ return patchOrgStatus(input, 'ACTIVE');
49
+ }
50
+ async function listOrgTokens(input) {
51
+ const client = await (0, resolve_client_1.resolveClient)(input);
52
+ return (0, lh_api_client_1.getOrgTokens)(client, input.orgId);
53
+ }
54
+ /**
55
+ * One line per token. `remain=unlimited` renders new-api's -1 (UnlimitedQuota,
56
+ * V2). The masked key is what new-api returns — never the full secret.
57
+ */
58
+ function renderOrgTokens(rows, opts) {
59
+ if (opts.json)
60
+ return JSON.stringify(rows);
61
+ if (rows.length === 0) {
62
+ return '(no new-api tokens for this org)\n';
63
+ }
64
+ return (rows
65
+ .map((t) => {
66
+ const remain = t.remainQuota === -1 ? 'unlimited' : String(t.remainQuota);
67
+ const expired = t.isExpired ? ' EXPIRED' : '';
68
+ return `${t.tokenId} ${t.statusText}${expired} key=${t.maskedKey} remain=${remain} used=${t.usedQuota}`;
69
+ })
70
+ .join('\n') + '\n');
71
+ }
72
+ //# sourceMappingURL=org.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org.js","sourceRoot":"","sources":["../../src/commands/org.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ // T9 of v0.1.7 #279 / #284. CLI wrapper around lh-api-client's phase2
3
+ // pure logic + state-file IO. Only the CLI-specific renderer lives here
4
+ // — the rest is the shared SDK (#303 / #305 dedup).
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PHASE2_BANNER = exports.DEFAULT_STATE_PATH = exports.savePhase2State = exports.loadPhase2State = exports.savePhase2Flags = exports.loadPhase2Flags = exports.evaluatePhase2State = void 0;
7
+ exports.renderPhase2Status = renderPhase2Status;
8
+ const lh_api_client_1 = require("lh-api-client");
9
+ var lh_api_client_2 = require("lh-api-client");
10
+ Object.defineProperty(exports, "evaluatePhase2State", { enumerable: true, get: function () { return lh_api_client_2.evaluatePhase2State; } });
11
+ Object.defineProperty(exports, "loadPhase2Flags", { enumerable: true, get: function () { return lh_api_client_2.loadPhase2Flags; } });
12
+ Object.defineProperty(exports, "savePhase2Flags", { enumerable: true, get: function () { return lh_api_client_2.savePhase2Flags; } });
13
+ // Backward-compat aliases (original lh-ops used State suffix, SDK uses Flags).
14
+ // Keep one release to avoid mass-renaming tests, remove next cycle.
15
+ Object.defineProperty(exports, "loadPhase2State", { enumerable: true, get: function () { return lh_api_client_2.loadPhase2Flags; } });
16
+ Object.defineProperty(exports, "savePhase2State", { enumerable: true, get: function () { return lh_api_client_2.savePhase2Flags; } });
17
+ Object.defineProperty(exports, "DEFAULT_STATE_PATH", { enumerable: true, get: function () { return lh_api_client_2.DEFAULT_STATE_PATH; } });
18
+ Object.defineProperty(exports, "PHASE2_BANNER", { enumerable: true, get: function () { return lh_api_client_2.PHASE2_BANNER; } });
19
+ /**
20
+ * CLI renderer — text checklist by default; `--json` passes through the
21
+ * evaluated state as a structured blob for release-pack automation.
22
+ * Banner appears when ≥2/3 triggers are met.
23
+ */
24
+ function renderPhase2Status(state, opts) {
25
+ if (opts.json) {
26
+ return JSON.stringify(state);
27
+ }
28
+ const lines = [];
29
+ lines.push(`Phase 2 SPA trigger state: ${state.satisfied}/3 satisfied`);
30
+ for (const t of state.triggers) {
31
+ const mark = t.satisfied ? 'x' : ' ';
32
+ lines.push(` [${mark}] (${t.id}) ${t.name}`);
33
+ lines.push(` ${t.detail}`);
34
+ }
35
+ if (state.satisfied >= 2) {
36
+ lines.push('');
37
+ lines.push(lh_api_client_1.PHASE2_BANNER);
38
+ }
39
+ return lines.join('\n') + '\n';
40
+ }
41
+ //# sourceMappingURL=phase2-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase2-status.js","sourceRoot":"","sources":["../../src/commands/phase2-status.ts"],"names":[],"mappings":";AAAA,sEAAsE;AACtE,wEAAwE;AACxE,oDAAoD;;;AA6BpD,gDAmBC;AA7CD,iDAA8C;AAE9C,+CAUuB;AATrB,oHAAA,mBAAmB,OAAA;AACnB,gHAAA,eAAe,OAAA;AACf,gHAAA,eAAe,OAAA;AACf,+EAA+E;AAC/E,oEAAoE;AACpE,gHAAA,eAAe,OAAmB;AAClC,gHAAA,eAAe,OAAmB;AAClC,mHAAA,kBAAkB,OAAA;AAClB,8GAAA,aAAa,OAAA;AAUf;;;;GAIG;AACH,SAAgB,kBAAkB,CAChC,KAAkB,EAClB,IAAuB;IAEvB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,8BAA8B,KAAK,CAAC,SAAS,cAAc,CAAC,CAAC;IACxE,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,6BAAa,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publishPlan = publishPlan;
4
+ exports.listPlans = listPlans;
5
+ exports.showPlan = showPlan;
6
+ exports.updatePlan = updatePlan;
7
+ exports.archivePlan = archivePlan;
8
+ exports.formatPlanLine = formatPlanLine;
9
+ exports.renderPlanList = renderPlanList;
10
+ exports.renderPlan = renderPlan;
11
+ const lh_api_client_1 = require("lh-api-client");
12
+ const resolve_client_1 = require("../lib/resolve-client");
13
+ const login_1 = require("./login");
14
+ async function publishPlan(input) {
15
+ const client = await (0, resolve_client_1.resolveClient)(input);
16
+ const dto = await (0, login_1.readJsonFile)(input.filePath);
17
+ return client.request('/platform/plans', { method: 'POST', body: dto });
18
+ }
19
+ async function listPlans(input) {
20
+ const client = await (0, resolve_client_1.resolveClient)(input);
21
+ return (0, lh_api_client_1.listPlans)(client, input);
22
+ }
23
+ async function showPlan(input) {
24
+ const client = await (0, resolve_client_1.resolveClient)(input);
25
+ return (0, lh_api_client_1.getPlan)(client, input.planId);
26
+ }
27
+ async function updatePlan(input) {
28
+ const client = await (0, resolve_client_1.resolveClient)(input);
29
+ const dto = (await (0, login_1.readJsonFile)(input.filePath));
30
+ return (0, lh_api_client_1.updatePlan)(client, input.planId, dto, input.ifMatch);
31
+ }
32
+ async function archivePlan(input) {
33
+ const client = await (0, resolve_client_1.resolveClient)(input);
34
+ return (0, lh_api_client_1.archivePlan)(client, input.planId, input.ifMatch);
35
+ }
36
+ // ===== Renderers. --json bypasses formatting so operators can pipe to jq. =====
37
+ /**
38
+ * One line per plan. `updated=<updatedAt>` is shown deliberately — it is the
39
+ * optimistic-lock token the operator copies into `--if-match` for update/archive.
40
+ */
41
+ function formatPlanLine(p) {
42
+ const idShort = p.id.slice(0, 8);
43
+ const base = p.isBaseTier ? ' base' : '';
44
+ return `${idShort} ${p.family}/${p.tier} ${p.status}${base} "${p.displayName}" updated=${p.updatedAt}`;
45
+ }
46
+ function renderPlanList(plans, opts) {
47
+ if (opts.json)
48
+ return JSON.stringify(plans);
49
+ if (plans.length === 0)
50
+ return '(no plans match)\n';
51
+ return plans.map(formatPlanLine).join('\n') + '\n';
52
+ }
53
+ function renderPlan(plan, opts) {
54
+ if (opts.json)
55
+ return JSON.stringify(plan);
56
+ const quotas = plan.quotas
57
+ .map((q) => ` - ${q.dimension}: ${q.limit} / ${q.window}`)
58
+ .join('\n');
59
+ return [
60
+ `id: ${plan.id}`,
61
+ `family/tier: ${plan.family}/${plan.tier}`,
62
+ `displayName: ${plan.displayName}`,
63
+ `status: ${plan.status}${plan.isBaseTier ? ' (base tier)' : ''}`,
64
+ `updatedAt: ${plan.updatedAt} <- use as --if-match for update/archive`,
65
+ `quotas:`,
66
+ quotas || ' (none)',
67
+ '',
68
+ ].join('\n');
69
+ }
70
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publishPriceBook = publishPriceBook;
4
+ exports.activatePriceBook = activatePriceBook;
5
+ exports.listPriceBooks = listPriceBooks;
6
+ exports.renderPriceBookList = renderPriceBookList;
7
+ const lh_api_client_1 = require("lh-api-client");
8
+ const resolve_client_1 = require("../lib/resolve-client");
9
+ const login_1 = require("./login");
10
+ async function publishPriceBook(input) {
11
+ const client = await (0, resolve_client_1.resolveClient)(input);
12
+ const dto = await (0, login_1.readJsonFile)(input.filePath);
13
+ return client.request('/platform/pricebook', { method: 'POST', body: dto });
14
+ }
15
+ async function activatePriceBook(input) {
16
+ const client = await (0, resolve_client_1.resolveClient)(input);
17
+ return client.request(`/platform/pricebook/${encodeURIComponent(input.version)}/activate`, {
18
+ method: 'POST',
19
+ query: input.allowRemovals ? { allowRemovals: 'true' } : undefined,
20
+ });
21
+ }
22
+ // ===== US-2 list (#434) — thin wrapper over lh-api-client. =====
23
+ async function listPriceBooks(input) {
24
+ const client = await (0, resolve_client_1.resolveClient)(input);
25
+ return (0, lh_api_client_1.listPriceBooks)(client);
26
+ }
27
+ function renderPriceBookList(rows, opts) {
28
+ if (opts.json)
29
+ return JSON.stringify(rows);
30
+ if (rows.length === 0)
31
+ return '(no price books)\n';
32
+ return (rows
33
+ .map((r) => {
34
+ const active = r.isActive ? 'ACTIVE ' : ' ';
35
+ return `${active} ${r.version} effectiveFrom=${r.effectiveFrom}`;
36
+ })
37
+ .join('\n') + '\n');
38
+ }
39
+ //# sourceMappingURL=pricebook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricebook.js","sourceRoot":"","sources":["../../src/commands/pricebook.ts"],"names":[],"mappings":";;AAaA,4CAMC;AAOD,8CAWC;AAID,wCAKC;AAED,kDAcC;AA9DD,iDAGuB;AACvB,0DAAmE;AACnE,mCAAuC;AAQhC,KAAK,UAAU,gBAAgB,CACpC,KAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,IAAA,oBAAY,EAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;AAC9E,CAAC;AAOM,KAAK,UAAU,iBAAiB,CACrC,KAA6B;IAE7B,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,OAAO,CACnB,uBAAuB,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EACnE;QACE,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;KACnE,CACF,CAAC;AACJ,CAAC;AAED,kEAAkE;AAE3D,KAAK,UAAU,cAAc,CAClC,KAAkB;IAElB,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAA,8BAAiB,EAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,SAAgB,mBAAmB,CACjC,IAAwB,EACxB,IAAuB;IAEvB,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,oBAAoB,CAAC;IACnD,OAAO,CACL,IAAI;SACD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAClD,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,aAAa,EAAE,CAAC;IACnE,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getScannersStatus = getScannersStatus;
4
+ exports.renderScannersStatus = renderScannersStatus;
5
+ const resolve_client_1 = require("../lib/resolve-client");
6
+ /**
7
+ * US-OP-11 (T4 of v0.1.7 #279 / #282). Background-job liveness for the
8
+ * platform operator. Output answers "are workers still ticking after my
9
+ * deploy?" — one line per scanner with last/next tick + counters.
10
+ */
11
+ async function getScannersStatus(opts) {
12
+ const client = await (0, resolve_client_1.resolveClient)(opts);
13
+ const body = await client.request('/platform/scanners/status', { method: 'GET' });
14
+ return body.scanners;
15
+ }
16
+ function renderScannersStatus(rows, opts) {
17
+ if (opts.json) {
18
+ return JSON.stringify(rows);
19
+ }
20
+ if (rows.length === 0) {
21
+ return '(no scanner data yet; wait one cadence cycle)\n';
22
+ }
23
+ return (rows
24
+ .map((r) => {
25
+ const countersStr = Object.entries(r.counters)
26
+ .map(([k, v]) => `${k}=${String(v)}`)
27
+ .join(' ');
28
+ const nextTick = r.nextTickAt ?? 'n/a';
29
+ return `${r.name} ${r.status} last=${r.lastTickAt} next=${nextTick} ${countersStr}`;
30
+ })
31
+ .join('\n') + '\n');
32
+ }
33
+ //# sourceMappingURL=scanners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanners.js","sourceRoot":"","sources":["../../src/commands/scanners.ts"],"names":[],"mappings":";;AAkBA,8CASC;AAED,oDAqBC;AAlDD,0DAAmE;AAanE;;;;GAIG;AACI,KAAK,UAAU,iBAAiB,CACrC,IAAiB;IAEjB,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,IAAI,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAC/B,2BAA2B,EAC3B,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;IACF,OAAO,IAAI,CAAC,QAAQ,CAAC;AACvB,CAAC;AAED,SAAgB,oBAAoB,CAClC,IAAkB,EAClB,IAAuB;IAEvB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,iDAAiD,CAAC;IAC3D,CAAC;IACD,OAAO,CACL,IAAI;SACD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;aAC3C,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;aACpC,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,MAAM,QAAQ,GAAG,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC;QACvC,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU,SAAS,QAAQ,IAAI,WAAW,EAAE,CAAC;IACtF,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getStatement = getStatement;
4
+ exports.renderStatement = renderStatement;
5
+ const lh_api_client_1 = require("lh-api-client");
6
+ const resolve_client_1 = require("../lib/resolve-client");
7
+ /**
8
+ * US-OP-10 (T3 of v0.1.7 #279 / #281). Monthly checkpoint statement.
9
+ * CLI-side wrapper around lh-api-client's `getStatement`. Server stays
10
+ * JSON-only; presentation (md / csv) is dispatched client-side in
11
+ * `renderStatement` below.
12
+ */
13
+ async function getStatement(input) {
14
+ const client = await (0, resolve_client_1.resolveClient)(input);
15
+ return (0, lh_api_client_1.getStatement)(client, { orgId: input.orgId, month: input.month });
16
+ }
17
+ /**
18
+ * Format dispatch.
19
+ * - json: canonical pretty-printed JSON for programmatic consumption
20
+ * - md: sectioned Markdown with consumption table + balance/keys + hash
21
+ * footer; human-readable for sales reconciliation
22
+ * - csv: flat row-per-section format for one-sheet spreadsheet import
23
+ *
24
+ * Both md and csv are derived from the same payload — server stays
25
+ * JSON-only; presentation is operator-side.
26
+ */
27
+ function renderStatement(stmt, opts) {
28
+ if (opts.format === 'json')
29
+ return JSON.stringify(stmt, null, 2);
30
+ if (opts.format === 'md')
31
+ return renderStatementMd(stmt);
32
+ return renderStatementCsv(stmt);
33
+ }
34
+ function renderStatementMd(stmt) {
35
+ const lines = [];
36
+ lines.push(`# Statement — ${stmt.orgId} — ${stmt.month}`);
37
+ lines.push('');
38
+ lines.push(`Period: ${stmt.periodStart} → ${stmt.periodEnd}`);
39
+ lines.push('');
40
+ // Consumption section
41
+ lines.push('## Consumption');
42
+ lines.push('');
43
+ if (stmt.consumption.length === 0) {
44
+ lines.push('(no usage this period)');
45
+ }
46
+ else {
47
+ lines.push('| Subscription | Model | Requests | Prompt tokens | Completion tokens | Cost |');
48
+ lines.push('|---|---|---|---|---|---|');
49
+ for (const c of stmt.consumption) {
50
+ lines.push(`| ${c.subscriptionId} | ${c.model} | ${c.requestCount} | ${c.promptTokens} | ${c.completionTokens} | ${c.cost} |`);
51
+ }
52
+ }
53
+ lines.push('');
54
+ // Balance section
55
+ lines.push('## Balance');
56
+ lines.push('');
57
+ lines.push(`- Starting: ${stmt.balance.starting}`);
58
+ lines.push(`- Topups: ${stmt.balance.topups}`);
59
+ lines.push(`- Charges: ${stmt.balance.charges}`);
60
+ lines.push(`- Ending: ${stmt.balance.ending}`);
61
+ lines.push('');
62
+ // Keys section
63
+ lines.push('## API Keys');
64
+ lines.push('');
65
+ lines.push(`- Active at start: ${stmt.keys.activeStart}`);
66
+ lines.push(`- Active at end: ${stmt.keys.activeEnd}`);
67
+ lines.push(`- New: ${stmt.keys.newInPeriod}`);
68
+ lines.push(`- Revoked: ${stmt.keys.revokedInPeriod}`);
69
+ lines.push(`- Auto-inactivated: ${stmt.keys.dormancyInPeriod}`);
70
+ lines.push('');
71
+ // Chain of custody footer
72
+ lines.push('---');
73
+ lines.push(`chain-of-custody-sha256: ${stmt.reconciliationHash}`);
74
+ return lines.join('\n') + '\n';
75
+ }
76
+ // CSV: 8-column flat format. Column 1 = section name, column 2 = key,
77
+ // remaining columns hold values whose meaning depends on the section:
78
+ // consumption: subscriptionId, model, requestCount, promptTokens,
79
+ // completionTokens, cost
80
+ // balance: starting/topups/charges/ending → just one value in col 8
81
+ // keys: same shape as balance for symmetry
82
+ // This shape lets sales pivot in spreadsheet by filtering column 1.
83
+ const CSV_HEADER = 'section,key,subscriptionId,model,requestCount,promptTokens,completionTokens,cost';
84
+ function renderStatementCsv(stmt) {
85
+ const lines = [CSV_HEADER];
86
+ for (const c of stmt.consumption) {
87
+ lines.push(`consumption,,${c.subscriptionId},${c.model},${c.requestCount},${c.promptTokens},${c.completionTokens},${c.cost}`);
88
+ }
89
+ lines.push(`balance,starting,,,,,,${stmt.balance.starting}`);
90
+ lines.push(`balance,topups,,,,,,${stmt.balance.topups}`);
91
+ lines.push(`balance,charges,,,,,,${stmt.balance.charges}`);
92
+ lines.push(`balance,ending,,,,,,${stmt.balance.ending}`);
93
+ lines.push(`keys,activeStart,,,,,,${stmt.keys.activeStart}`);
94
+ lines.push(`keys,activeEnd,,,,,,${stmt.keys.activeEnd}`);
95
+ lines.push(`keys,newInPeriod,,,,,,${stmt.keys.newInPeriod}`);
96
+ lines.push(`keys,revokedInPeriod,,,,,,${stmt.keys.revokedInPeriod}`);
97
+ lines.push(`keys,dormancyInPeriod,,,,,,${stmt.keys.dormancyInPeriod}`);
98
+ lines.push(`# chain-of-custody-sha256: ${stmt.reconciliationHash}`);
99
+ return lines.join('\n') + '\n';
100
+ }
101
+ //# sourceMappingURL=statement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statement.js","sourceRoot":"","sources":["../../src/commands/statement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addSubscription = addSubscription;
4
+ exports.extendContract = extendContract;
5
+ const lh_api_client_1 = require("lh-api-client");
6
+ const resolve_client_1 = require("../lib/resolve-client");
7
+ /**
8
+ * Operator-only path (issue #83): add an additional subscription to an
9
+ * already-existing org. Maps directly to
10
+ * `POST /platform/orgs/:orgId/subscriptions` on the LH backend.
11
+ */
12
+ async function addSubscription(input) {
13
+ const client = await (0, resolve_client_1.resolveClient)(input);
14
+ const body = {
15
+ planId: input.planId,
16
+ maxKeys: input.maxKeys,
17
+ contractStart: input.contractStart,
18
+ commitmentEnd: input.commitmentEnd,
19
+ };
20
+ if (input.priceBookVersion) {
21
+ body.priceBookVersion = input.priceBookVersion;
22
+ }
23
+ return client.request(`/platform/orgs/${encodeURIComponent(input.orgId)}/subscriptions`, { method: 'POST', body });
24
+ }
25
+ async function extendContract(input) {
26
+ const client = await (0, resolve_client_1.resolveClient)(input);
27
+ return (0, lh_api_client_1.extendContract)(client, input.orgId, input.subId, {
28
+ commitmentEnd: input.commitmentEnd,
29
+ memo: input.memo,
30
+ });
31
+ }
32
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/commands/subscription.ts"],"names":[],"mappings":";;AA+BA,0CAkBC;AAaD,wCAQC;AAtED,iDAGuB;AACvB,0DAAmE;AAsBnE;;;;GAIG;AACI,KAAK,UAAU,eAAe,CACnC,KAA2B;IAE3B,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAoC;QAC5C,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC;IACF,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC3B,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;IACjD,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CACnB,kBAAkB,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,EACjE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CACzB,CAAC;AACJ,CAAC;AAaM,KAAK,UAAU,cAAc,CAClC,KAA0B;IAE1B,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAA,8BAAiB,EAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;QACzD,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.issueToken = issueToken;
4
+ exports.listTokens = listTokens;
5
+ exports.revokeToken = revokeToken;
6
+ exports.renderIssuedToken = renderIssuedToken;
7
+ exports.formatTokenLine = formatTokenLine;
8
+ exports.renderTokenList = renderTokenList;
9
+ const lh_api_client_1 = require("lh-api-client");
10
+ const resolve_client_1 = require("../lib/resolve-client");
11
+ async function issueToken(input) {
12
+ const client = await (0, resolve_client_1.resolveClient)(input);
13
+ return (0, lh_api_client_1.issuePlatformToken)(client, {
14
+ scopes: input.scopes,
15
+ label: input.label,
16
+ expiresInDays: input.expiresInDays,
17
+ });
18
+ }
19
+ async function listTokens(input) {
20
+ const client = await (0, resolve_client_1.resolveClient)(input);
21
+ return (0, lh_api_client_1.listPlatformTokens)(client);
22
+ }
23
+ async function revokeToken(input) {
24
+ const client = await (0, resolve_client_1.resolveClient)(input);
25
+ return (0, lh_api_client_1.revokePlatformToken)(client, input.tokenId);
26
+ }
27
+ // ===== Renderers =====
28
+ /**
29
+ * Issue output. The plaintext `token` is shown ONCE — make it unmissable and
30
+ * separate from the metadata so an operator copies the right value.
31
+ */
32
+ function renderIssuedToken(t, opts) {
33
+ if (opts.json)
34
+ return JSON.stringify(t);
35
+ const expires = t.expiresAt ? t.expiresAt.slice(0, 10) : 'never';
36
+ return [
37
+ `id: ${t.id}`,
38
+ `scopes: ${t.scopes.join(', ')}`,
39
+ `label: ${t.label ?? '(none)'}`,
40
+ `expires: ${expires}`,
41
+ '',
42
+ ' ⚠ Copy this token now — it is shown ONCE and cannot be retrieved again:',
43
+ '',
44
+ ` ${t.token}`,
45
+ '',
46
+ ].join('\n');
47
+ }
48
+ function formatTokenLine(t) {
49
+ const idShort = t.id.slice(0, 8);
50
+ const expires = t.expiresAt ? t.expiresAt.slice(0, 10) : 'never';
51
+ const used = t.lastUsedAt ? t.lastUsedAt.slice(0, 10) : 'never';
52
+ return `${idShort} ${t.tokenPrefix}… ${t.status} [${t.scopes.join(',')}] "${t.label ?? ''}" expires=${expires} used=${used}`;
53
+ }
54
+ function renderTokenList(tokens, opts) {
55
+ if (opts.json)
56
+ return JSON.stringify(tokens);
57
+ if (tokens.length === 0)
58
+ return '(no service-account tokens)\n';
59
+ return tokens.map(formatTokenLine).join('\n') + '\n';
60
+ }
61
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":";;AAmBA,gCAOC;AAED,gCAGC;AAMD,kCAKC;AAQD,8CAiBC;AAED,0CAKC;AAED,0CAOC;AAnFD,iDAMuB;AACvB,0DAAmE;AAY5D,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAA,kCAAkB,EAAC,MAAM,EAAE;QAChC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,UAAU,CAAC,KAAkB;IACjD,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAA,kCAAkB,EAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAMM,KAAK,UAAU,WAAW,CAC/B,KAAuB;IAEvB,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,IAAA,mCAAmB,EAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AACpD,CAAC;AAED,wBAAwB;AAExB;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,CAAc,EACd,IAAuB;IAEvB,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,OAAO;QACL,aAAa,CAAC,CAAC,EAAE,EAAE;QACnB,aAAa,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClC,aAAa,CAAC,CAAC,KAAK,IAAI,QAAQ,EAAE;QAClC,aAAa,OAAO,EAAE;QACtB,EAAE;QACF,4EAA4E;QAC5E,EAAE;QACF,OAAO,CAAC,CAAC,KAAK,EAAE;QAChB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAgB,eAAe,CAAC,CAAe;IAC7C,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChE,OAAO,GAAG,OAAO,IAAI,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,aAAa,OAAO,SAAS,IAAI,EAAE,CAAC;AAC/H,CAAC;AAED,SAAgB,eAAe,CAC7B,MAAsB,EACtB,IAAuB;IAEvB,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,+BAA+B,CAAC;IAChE,OAAO,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACvD,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeTopup = executeTopup;
4
+ exports.listTopups = listTopups;
5
+ const resolve_client_1 = require("../lib/resolve-client");
6
+ async function executeTopup(input) {
7
+ const client = await (0, resolve_client_1.resolveClient)(input);
8
+ const body = {
9
+ orgId: input.orgId,
10
+ amountUsd: input.amountUsd,
11
+ };
12
+ if (input.memo)
13
+ body.memo = input.memo;
14
+ return client.request('/platform/topups/execute', {
15
+ method: 'POST',
16
+ body,
17
+ });
18
+ }
19
+ async function listTopups(input) {
20
+ const client = await (0, resolve_client_1.resolveClient)(input);
21
+ const query = {
22
+ orgId: input.orgId,
23
+ from: input.from,
24
+ to: input.to,
25
+ actor: input.actor,
26
+ limit: input.limit,
27
+ offset: input.offset,
28
+ };
29
+ return client.request('/platform/topups', {
30
+ method: 'GET',
31
+ query,
32
+ });
33
+ }
34
+ //# sourceMappingURL=topup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topup.js","sourceRoot":"","sources":["../../src/commands/topup.ts"],"names":[],"mappings":";;AAQA,oCAcC;AA4BD,gCAiBC;AAnED,0DAAmE;AAQ5D,KAAK,UAAU,YAAY,CAChC,KAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAoC;QAC5C,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC;IACF,IAAI,KAAK,CAAC,IAAI;QAAE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IAEvC,OAAO,MAAM,CAAC,OAAO,CAAC,0BAA0B,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AA4BM,KAAK,UAAU,UAAU,CAC9B,KAAsB;IAEtB,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAa,EAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAgD;QACzD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;IAEF,OAAO,MAAM,CAAC,OAAO,CAAkB,kBAAkB,EAAE;QACzD,MAAM,EAAE,KAAK;QACb,KAAK;KACN,CAAC,CAAC;AACL,CAAC"}