@miosa/cli 1.1.9 → 1.1.11
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/README.md +38 -0
- package/dist/action-authority.d.ts +98 -0
- package/dist/action-authority.d.ts.map +1 -0
- package/dist/action-authority.js +108 -0
- package/dist/action-authority.js.map +1 -0
- package/dist/app-document.d.ts +23 -0
- package/dist/app-document.d.ts.map +1 -0
- package/dist/app-document.js +180 -0
- package/dist/app-document.js.map +1 -0
- package/dist/bin/miosa.js +1 -0
- package/dist/bin/miosa.js.map +1 -1
- package/dist/commands/actions.d.ts +3 -0
- package/dist/commands/actions.d.ts.map +1 -0
- package/dist/commands/actions.js +222 -0
- package/dist/commands/actions.js.map +1 -0
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +343 -1
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +48 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/generated/action-capabilities.d.ts +806 -0
- package/dist/generated/action-capabilities.d.ts.map +1 -0
- package/dist/generated/action-capabilities.js +1010 -0
- package/dist/generated/action-capabilities.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { ActionAuthorityClient } from "../action-authority.js";
|
|
3
|
+
import { MiosaClient } from "../client.js";
|
|
4
|
+
import { loadConfig } from "../config.js";
|
|
5
|
+
import { renderTable } from "../ui/table.js";
|
|
6
|
+
import { handleError, isJsonMode, printJson } from "./util.js";
|
|
7
|
+
function authority() {
|
|
8
|
+
return new ActionAuthorityClient(new MiosaClient(loadConfig()));
|
|
9
|
+
}
|
|
10
|
+
function parseJson(value) {
|
|
11
|
+
if (!value)
|
|
12
|
+
return {};
|
|
13
|
+
const parsed = JSON.parse(value);
|
|
14
|
+
if (!parsed || Array.isArray(parsed) || typeof parsed !== "object") {
|
|
15
|
+
throw new Error("--params and --constraints must be JSON objects.");
|
|
16
|
+
}
|
|
17
|
+
return parsed;
|
|
18
|
+
}
|
|
19
|
+
export function register(program) {
|
|
20
|
+
const actions = program
|
|
21
|
+
.command("actions")
|
|
22
|
+
.description("Inspect and manage unified MIOSA agent-action authority");
|
|
23
|
+
actions
|
|
24
|
+
.command("catalog")
|
|
25
|
+
.description("List server-owned, version-pinned action capabilities")
|
|
26
|
+
.option("--json", "Output JSON")
|
|
27
|
+
.action(async (opts) => {
|
|
28
|
+
try {
|
|
29
|
+
const catalog = await authority().catalog();
|
|
30
|
+
if (isJsonMode(opts))
|
|
31
|
+
return printJson({ data: catalog });
|
|
32
|
+
renderTable(catalog, [
|
|
33
|
+
{ header: "ACTION", key: "name", width: 30 },
|
|
34
|
+
{ header: "VERSION", key: "version", width: 10 },
|
|
35
|
+
{ header: "RISK", key: "risk", width: 12 },
|
|
36
|
+
{ header: "SCOPE", key: "scope", width: 12 },
|
|
37
|
+
{ header: "APPROVAL", key: "approval", width: 12 },
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
handleError(error);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
actions
|
|
45
|
+
.command("check <capability>")
|
|
46
|
+
.description("Ask the authority whether one exact invocation may run")
|
|
47
|
+
.option("--params <json>", "Exact action parameters", "{}")
|
|
48
|
+
.option("--workspace <id>", "Workspace scope")
|
|
49
|
+
.option("--invocation-id <id>", "Stable caller-provided invocation ID")
|
|
50
|
+
.option("--json", "Output JSON")
|
|
51
|
+
.action(async (capability, opts) => {
|
|
52
|
+
try {
|
|
53
|
+
const decision = await authority().authorize(capability, parseJson(opts.params), {
|
|
54
|
+
workspaceId: opts.workspace,
|
|
55
|
+
invocationId: opts.invocationId,
|
|
56
|
+
});
|
|
57
|
+
if (isJsonMode(opts))
|
|
58
|
+
return printJson(decision);
|
|
59
|
+
console.log(decision.decision === "allow"
|
|
60
|
+
? chalk.green("ALLOW")
|
|
61
|
+
: decision.decision === "pending_approval"
|
|
62
|
+
? chalk.yellow("PENDING APPROVAL")
|
|
63
|
+
: chalk.red("DENY"));
|
|
64
|
+
if (decision.approval_request_id) {
|
|
65
|
+
console.log(`Approval request: ${decision.approval_request_id}`);
|
|
66
|
+
}
|
|
67
|
+
if (decision.receipt_id)
|
|
68
|
+
console.log(`Receipt: ${decision.receipt_id}`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
handleError(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const approvals = actions
|
|
75
|
+
.command("approvals")
|
|
76
|
+
.description("Manage one-time approvals");
|
|
77
|
+
approvals
|
|
78
|
+
.command("list")
|
|
79
|
+
.option("--status <status>", "Filter by status")
|
|
80
|
+
.option("--json", "Output JSON")
|
|
81
|
+
.action(async (opts) => {
|
|
82
|
+
try {
|
|
83
|
+
const rows = await authority().approvals(opts.status);
|
|
84
|
+
if (isJsonMode(opts))
|
|
85
|
+
return printJson({ data: rows });
|
|
86
|
+
renderTable(rows, [
|
|
87
|
+
{ header: "ID", key: "id", width: 12 },
|
|
88
|
+
{ header: "ACTION", key: "capability_name", width: 28 },
|
|
89
|
+
{
|
|
90
|
+
header: "PRINCIPAL",
|
|
91
|
+
key: (row) => `${row.principal_type}:${row.principal_id}`,
|
|
92
|
+
width: 28,
|
|
93
|
+
},
|
|
94
|
+
{ header: "STATUS", key: "status", width: 12 },
|
|
95
|
+
{ header: "CREATED", key: "inserted_at", width: 24 },
|
|
96
|
+
]);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
handleError(error);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
for (const decision of ["approve", "deny"]) {
|
|
103
|
+
approvals
|
|
104
|
+
.command(`${decision} <id>`)
|
|
105
|
+
.description(`${decision === "approve" ? "Approve" : "Deny"} one exact invocation`)
|
|
106
|
+
.option("--json", "Output JSON")
|
|
107
|
+
.action(async (id, opts) => {
|
|
108
|
+
try {
|
|
109
|
+
const result = await authority().resolveApproval(id, decision);
|
|
110
|
+
if (isJsonMode(opts))
|
|
111
|
+
return printJson({ data: result });
|
|
112
|
+
console.log(`${result.id}: ${result.status}`);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
handleError(error);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const grants = actions
|
|
120
|
+
.command("grants")
|
|
121
|
+
.description("Manage standing action grants");
|
|
122
|
+
grants
|
|
123
|
+
.command("list")
|
|
124
|
+
.option("--status <status>", "Filter by status")
|
|
125
|
+
.option("--json", "Output JSON")
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
try {
|
|
128
|
+
const rows = await authority().grants(opts.status);
|
|
129
|
+
if (isJsonMode(opts))
|
|
130
|
+
return printJson({ data: rows });
|
|
131
|
+
renderTable(rows, [
|
|
132
|
+
{ header: "ID", key: "id", width: 12 },
|
|
133
|
+
{ header: "ACTION", key: "capability_name", width: 28 },
|
|
134
|
+
{
|
|
135
|
+
header: "PRINCIPAL",
|
|
136
|
+
key: (row) => `${row.principal_type}:${row.principal_id}`,
|
|
137
|
+
width: 28,
|
|
138
|
+
},
|
|
139
|
+
{ header: "STATUS", key: "status", width: 12 },
|
|
140
|
+
{
|
|
141
|
+
header: "EXPIRES",
|
|
142
|
+
key: (row) => row.expires_at ?? "never",
|
|
143
|
+
width: 24,
|
|
144
|
+
},
|
|
145
|
+
]);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
handleError(error);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
grants
|
|
152
|
+
.command("create <capability>")
|
|
153
|
+
.requiredOption("--principal-type <type>", "user, api_key, osa, optimal, schedule, opencomputer, mcp, or service")
|
|
154
|
+
.requiredOption("--principal-id <id>", "Exact principal ID")
|
|
155
|
+
.option("--workspace <id>", "Optional workspace restriction")
|
|
156
|
+
.option("--expires-at <iso8601>", "Optional expiration")
|
|
157
|
+
.option("--constraints <json>", "Additional fail-closed constraints", "{}")
|
|
158
|
+
.option("--json", "Output JSON")
|
|
159
|
+
.action(async (capabilityName, opts) => {
|
|
160
|
+
try {
|
|
161
|
+
const client = authority();
|
|
162
|
+
const capability = await client.requireCapability(capabilityName);
|
|
163
|
+
const grant = await client.createGrant({
|
|
164
|
+
capability: {
|
|
165
|
+
name: capability.name,
|
|
166
|
+
fingerprint: capability.fingerprint,
|
|
167
|
+
},
|
|
168
|
+
principal_type: opts.principalType,
|
|
169
|
+
principal_id: opts.principalId,
|
|
170
|
+
...(opts.workspace ? { workspace_id: opts.workspace } : {}),
|
|
171
|
+
...(opts.expiresAt ? { expires_at: opts.expiresAt } : {}),
|
|
172
|
+
constraints: parseJson(opts.constraints),
|
|
173
|
+
});
|
|
174
|
+
if (isJsonMode(opts))
|
|
175
|
+
return printJson({ data: grant });
|
|
176
|
+
console.log(chalk.green(`Grant created: ${grant.id}`));
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
handleError(error);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
grants
|
|
183
|
+
.command("revoke <id>")
|
|
184
|
+
.description("Revoke a standing grant immediately")
|
|
185
|
+
.option("--json", "Output JSON")
|
|
186
|
+
.action(async (id, opts) => {
|
|
187
|
+
try {
|
|
188
|
+
const grant = await authority().revokeGrant(id);
|
|
189
|
+
if (isJsonMode(opts))
|
|
190
|
+
return printJson({ data: grant });
|
|
191
|
+
console.log(chalk.green(`Grant revoked: ${grant.id}`));
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
handleError(error);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
actions
|
|
198
|
+
.command("receipts")
|
|
199
|
+
.description("List immutable action authority receipts")
|
|
200
|
+
.option("--limit <count>", "Maximum rows", "100")
|
|
201
|
+
.option("--json", "Output JSON")
|
|
202
|
+
.action(async (opts) => {
|
|
203
|
+
try {
|
|
204
|
+
const parsedLimit = Number.parseInt(opts.limit ?? "100", 10);
|
|
205
|
+
const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? 100 : parsedLimit;
|
|
206
|
+
const rows = await authority().receipts(limit);
|
|
207
|
+
if (isJsonMode(opts))
|
|
208
|
+
return printJson({ data: rows });
|
|
209
|
+
renderTable(rows, [
|
|
210
|
+
{ header: "TIME", key: "occurred_at", width: 24 },
|
|
211
|
+
{ header: "ACTION", key: "capability_name", width: 28 },
|
|
212
|
+
{ header: "SURFACE", key: "surface", width: 14 },
|
|
213
|
+
{ header: "DECISION", key: "decision", width: 20 },
|
|
214
|
+
{ header: "RECEIPT", key: "id", width: 12 },
|
|
215
|
+
]);
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
handleError(error);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/commands/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAM3C,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,0BAA0B,EAG3B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAM3C,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,0BAA0B,EAG3B,MAAM,qBAAqB,CAAC;AAgB7B,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAiBnE;AA6DD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAKlC;AAYD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC;IAAE,UAAU,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgJ/D;AA0GD,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE;QACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;CACH,GAAG,OAAO,CAAC;IACV,SAAS,EAAE,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC;IACzD,OAAO,EAAE,cAAc,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAqID;AAoED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAojC/C"}
|
package/dist/commands/app.js
CHANGED
|
@@ -12,6 +12,7 @@ import { loadLocalLink } from "./link.js";
|
|
|
12
12
|
import { loadAcceptanceContract, saveReleaseReceipt, verifyApplicationRelease, } from "../app-release.js";
|
|
13
13
|
import { applicationIdempotencyKey, createApplicationOperation, loadApplicationOperation, updateApplicationOperation, } from "../app-operation.js";
|
|
14
14
|
import { handleError, isJsonMode, printJson } from "./util.js";
|
|
15
|
+
import { diagnoseAppDocument } from "../app-document.js";
|
|
15
16
|
export function requireApplicationLink(dir) {
|
|
16
17
|
const link = loadLocalLink(dir);
|
|
17
18
|
if (!link?.deploymentId || !link.name) {
|
|
@@ -45,6 +46,28 @@ function boolValue(value, key) {
|
|
|
45
46
|
const found = record(value)[key];
|
|
46
47
|
return typeof found === "boolean" ? found : undefined;
|
|
47
48
|
}
|
|
49
|
+
function parseJsonObject(value, option) {
|
|
50
|
+
if (!value)
|
|
51
|
+
return {};
|
|
52
|
+
let parsed;
|
|
53
|
+
try {
|
|
54
|
+
parsed = JSON.parse(value);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new UserError(`${option} must be valid JSON.`, `Pass a JSON object, for example ${option} '{"enabled":true}'.`);
|
|
58
|
+
}
|
|
59
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
60
|
+
throw new UserError(`${option} must be a JSON object.`, `Pass an object, not ${Array.isArray(parsed) ? "an array" : typeof parsed}.`);
|
|
61
|
+
}
|
|
62
|
+
return parsed;
|
|
63
|
+
}
|
|
64
|
+
function parseNonNegativeInteger(value, option) {
|
|
65
|
+
const parsed = Number(value);
|
|
66
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
67
|
+
throw new UserError(`${option} must be a non-negative integer.`, `Received ${JSON.stringify(value)}.`);
|
|
68
|
+
}
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
48
71
|
export async function getRelease(client, deploymentId, releaseId) {
|
|
49
72
|
const raw = await client.apiGet(`/api/v1/deployments/${encodeURIComponent(deploymentId)}/releases/${encodeURIComponent(releaseId)}`);
|
|
50
73
|
return deploymentPayload(raw);
|
|
@@ -169,7 +192,8 @@ async function verifyLinkedRelease(client, dir, link, releaseId, contractPath, r
|
|
|
169
192
|
inspection.migration_verified ||
|
|
170
193
|
verificationEvidence?.migration_verified === true;
|
|
171
194
|
inspection.policy_verified =
|
|
172
|
-
inspection.policy_verified ||
|
|
195
|
+
inspection.policy_verified ||
|
|
196
|
+
verificationEvidence?.policy_verified === true;
|
|
173
197
|
const receipt = await verifyApplicationRelease({
|
|
174
198
|
application: link.name,
|
|
175
199
|
environment: link.environment,
|
|
@@ -472,6 +496,324 @@ export function register(program) {
|
|
|
472
496
|
handleError(err);
|
|
473
497
|
}
|
|
474
498
|
});
|
|
499
|
+
const documents = app
|
|
500
|
+
.command("documents")
|
|
501
|
+
.description("Inspect durable generated App Documents");
|
|
502
|
+
documents
|
|
503
|
+
.command("list")
|
|
504
|
+
.description("List durable apps in the selected workspace")
|
|
505
|
+
.option("--workspace <id>", "Workspace ID")
|
|
506
|
+
.option("--json", "Output machine-readable App Documents")
|
|
507
|
+
.action(async (opts) => {
|
|
508
|
+
try {
|
|
509
|
+
const config = loadConfig();
|
|
510
|
+
const workspaceId = opts.workspace ?? config.workspace;
|
|
511
|
+
if (!workspaceId) {
|
|
512
|
+
throw new UserError("A workspace is required to list App Documents.", "Pass --workspace <id> or select a CLI workspace context.");
|
|
513
|
+
}
|
|
514
|
+
const query = new URLSearchParams({ workspace_id: workspaceId });
|
|
515
|
+
const payload = await new MiosaClient(config).apiGet(`/api/v1/builder/apps?${query.toString()}`);
|
|
516
|
+
if (isJsonMode(opts)) {
|
|
517
|
+
printJson({ ok: true, data: payload, error: null });
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
521
|
+
}
|
|
522
|
+
catch (err) {
|
|
523
|
+
handleError(err);
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
documents
|
|
527
|
+
.command("show <id>")
|
|
528
|
+
.description("Show one durable App Document")
|
|
529
|
+
.option("--json", "Output machine-readable App Document")
|
|
530
|
+
.action(async (id, opts) => {
|
|
531
|
+
try {
|
|
532
|
+
const payload = await new MiosaClient(loadConfig()).apiGet(`/api/v1/builder/apps/${encodeURIComponent(id)}`);
|
|
533
|
+
if (isJsonMode(opts)) {
|
|
534
|
+
printJson({ ok: true, data: payload, error: null });
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
538
|
+
}
|
|
539
|
+
catch (err) {
|
|
540
|
+
handleError(err);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
documents
|
|
544
|
+
.command("doctor <id>")
|
|
545
|
+
.description("Verify workspace, venue, declarations, and exact approval")
|
|
546
|
+
.option("--workspace <id>", "Expected workspace ID")
|
|
547
|
+
.option("--json", "Output a stable diagnostic contract")
|
|
548
|
+
.action(async (id, opts) => {
|
|
549
|
+
try {
|
|
550
|
+
const config = loadConfig();
|
|
551
|
+
const client = new MiosaClient(config);
|
|
552
|
+
const [payload, platformDiagnostics] = await Promise.all([
|
|
553
|
+
client.apiGet(`/api/v1/builder/apps/${encodeURIComponent(id)}`),
|
|
554
|
+
client.apiGet(`/api/v1/builder/apps/${encodeURIComponent(id)}/diagnostics`),
|
|
555
|
+
]);
|
|
556
|
+
const result = diagnoseAppDocument(payload, opts.workspace ?? config.workspace, platformDiagnostics);
|
|
557
|
+
if (isJsonMode(opts)) {
|
|
558
|
+
printJson({
|
|
559
|
+
ok: result.ok,
|
|
560
|
+
data: result,
|
|
561
|
+
error: result.ok
|
|
562
|
+
? null
|
|
563
|
+
: {
|
|
564
|
+
code: "APP_DOCUMENT_DIAGNOSTIC_FAILED",
|
|
565
|
+
message: "One or more App Document checks failed.",
|
|
566
|
+
},
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
console.log(JSON.stringify(result, null, 2));
|
|
571
|
+
}
|
|
572
|
+
if (!result.ok)
|
|
573
|
+
process.exitCode = 1;
|
|
574
|
+
}
|
|
575
|
+
catch (err) {
|
|
576
|
+
handleError(err);
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
documents
|
|
580
|
+
.command("approve <id>")
|
|
581
|
+
.description("Approve the current exact app version for release publishing")
|
|
582
|
+
.requiredOption("--release <id>", "Immutable candidate release ID")
|
|
583
|
+
.option("--reason <reason>", "Review reason")
|
|
584
|
+
.option("--json", "Output the exact approval")
|
|
585
|
+
.action(async (id, opts) => {
|
|
586
|
+
try {
|
|
587
|
+
const payload = await new MiosaClient(loadConfig()).apiPost(`/api/v1/builder/apps/${encodeURIComponent(id)}/approvals`, { reason: opts.reason, release_id: opts.release });
|
|
588
|
+
if (isJsonMode(opts)) {
|
|
589
|
+
printJson({ ok: true, data: payload, error: null });
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
593
|
+
}
|
|
594
|
+
catch (err) {
|
|
595
|
+
handleError(err);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
documents
|
|
599
|
+
.command("revoke <id>")
|
|
600
|
+
.description("Revoke one exact-version review approval")
|
|
601
|
+
.requiredOption("--approval <id>", "Approval ID")
|
|
602
|
+
.option("--json", "Output machine-readable result")
|
|
603
|
+
.action(async (id, opts) => {
|
|
604
|
+
try {
|
|
605
|
+
await new MiosaClient(loadConfig()).apiPost(`/api/v1/builder/apps/${encodeURIComponent(id)}/approvals/${encodeURIComponent(opts.approval)}/revoke`, {});
|
|
606
|
+
const result = {
|
|
607
|
+
app_document_id: id,
|
|
608
|
+
approval_id: opts.approval,
|
|
609
|
+
revoked: true,
|
|
610
|
+
};
|
|
611
|
+
if (isJsonMode(opts)) {
|
|
612
|
+
printJson({ ok: true, data: result, error: null });
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
console.log(JSON.stringify(result, null, 2));
|
|
616
|
+
}
|
|
617
|
+
catch (err) {
|
|
618
|
+
handleError(err);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
const data = documents
|
|
622
|
+
.command("data")
|
|
623
|
+
.description("Read and write declared durable app collections");
|
|
624
|
+
data
|
|
625
|
+
.command("list <id> <collection>")
|
|
626
|
+
.description("List records in one declared app collection")
|
|
627
|
+
.option("--limit <count>", "Maximum records", "100")
|
|
628
|
+
.option("--json", "Output machine-readable records")
|
|
629
|
+
.action(async (id, collection, opts) => {
|
|
630
|
+
try {
|
|
631
|
+
const limit = parseNonNegativeInteger(opts.limit, "--limit");
|
|
632
|
+
const payload = await new MiosaClient(loadConfig()).apiGet(`/api/v1/builder/apps/${encodeURIComponent(id)}/data/${encodeURIComponent(collection)}?limit=${limit}`);
|
|
633
|
+
if (isJsonMode(opts)) {
|
|
634
|
+
printJson({ ok: true, data: payload, error: null });
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
638
|
+
}
|
|
639
|
+
catch (err) {
|
|
640
|
+
handleError(err);
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
data
|
|
644
|
+
.command("get <id> <collection> <key>")
|
|
645
|
+
.description("Read one exact app collection record")
|
|
646
|
+
.option("--json", "Output a machine-readable record")
|
|
647
|
+
.action(async (id, collection, key, opts) => {
|
|
648
|
+
try {
|
|
649
|
+
const payload = await new MiosaClient(loadConfig()).apiGet(`/api/v1/builder/apps/${encodeURIComponent(id)}/data/${encodeURIComponent(collection)}/${encodeURIComponent(key)}`);
|
|
650
|
+
if (isJsonMode(opts)) {
|
|
651
|
+
printJson({ ok: true, data: payload, error: null });
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
655
|
+
}
|
|
656
|
+
catch (err) {
|
|
657
|
+
handleError(err);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
data
|
|
661
|
+
.command("put <id> <collection> <key>")
|
|
662
|
+
.description("Create or update one app collection record")
|
|
663
|
+
.requiredOption("--value <json>", "JSON object value")
|
|
664
|
+
.option("--expected-version <number>", "Exact current version")
|
|
665
|
+
.option("--json", "Output the stored record")
|
|
666
|
+
.action(async (id, collection, key, opts) => {
|
|
667
|
+
try {
|
|
668
|
+
const body = {
|
|
669
|
+
value: parseJsonObject(opts.value, "--value"),
|
|
670
|
+
};
|
|
671
|
+
if (opts.expectedVersion !== undefined) {
|
|
672
|
+
body["expected_version"] = parseNonNegativeInteger(opts.expectedVersion, "--expected-version");
|
|
673
|
+
}
|
|
674
|
+
const payload = await new MiosaClient(loadConfig()).apiPut(`/api/v1/builder/apps/${encodeURIComponent(id)}/data/${encodeURIComponent(collection)}/${encodeURIComponent(key)}`, body);
|
|
675
|
+
if (isJsonMode(opts)) {
|
|
676
|
+
printJson({ ok: true, data: payload, error: null });
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
680
|
+
}
|
|
681
|
+
catch (err) {
|
|
682
|
+
handleError(err);
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
data
|
|
686
|
+
.command("delete <id> <collection> <key>")
|
|
687
|
+
.description("Delete one exact app collection record")
|
|
688
|
+
.option("--expected-version <number>", "Exact current version")
|
|
689
|
+
.option("--json", "Output machine-readable result")
|
|
690
|
+
.action(async (id, collection, key, opts) => {
|
|
691
|
+
try {
|
|
692
|
+
const query = opts.expectedVersion === undefined
|
|
693
|
+
? ""
|
|
694
|
+
: `?expected_version=${parseNonNegativeInteger(opts.expectedVersion, "--expected-version")}`;
|
|
695
|
+
await new MiosaClient(loadConfig()).apiDelete(`/api/v1/builder/apps/${encodeURIComponent(id)}/data/${encodeURIComponent(collection)}/${encodeURIComponent(key)}${query}`);
|
|
696
|
+
const result = {
|
|
697
|
+
app_document_id: id,
|
|
698
|
+
collection,
|
|
699
|
+
key,
|
|
700
|
+
deleted: true,
|
|
701
|
+
};
|
|
702
|
+
if (isJsonMode(opts)) {
|
|
703
|
+
printJson({ ok: true, data: result, error: null });
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
console.log(JSON.stringify(result, null, 2));
|
|
707
|
+
}
|
|
708
|
+
catch (err) {
|
|
709
|
+
handleError(err);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
const automations = documents
|
|
713
|
+
.command("automations")
|
|
714
|
+
.description("Operate durable, authority-governed app automation runs");
|
|
715
|
+
automations
|
|
716
|
+
.command("list <id>")
|
|
717
|
+
.description("List automation runs for one app")
|
|
718
|
+
.option("--limit <count>", "Maximum runs", "100")
|
|
719
|
+
.option("--json", "Output machine-readable runs")
|
|
720
|
+
.action(async (id, opts) => {
|
|
721
|
+
try {
|
|
722
|
+
const limit = parseNonNegativeInteger(opts.limit, "--limit");
|
|
723
|
+
const payload = await new MiosaClient(loadConfig()).apiGet(`/api/v1/builder/apps/${encodeURIComponent(id)}/automation-runs?limit=${limit}`);
|
|
724
|
+
if (isJsonMode(opts)) {
|
|
725
|
+
printJson({ ok: true, data: payload, error: null });
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
729
|
+
}
|
|
730
|
+
catch (err) {
|
|
731
|
+
handleError(err);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
automations
|
|
735
|
+
.command("start <id> <automation>")
|
|
736
|
+
.description("Start one reviewed automation")
|
|
737
|
+
.option("--trigger <json>", "Trigger metadata JSON", "{}")
|
|
738
|
+
.option("--json", "Output the durable run")
|
|
739
|
+
.action(async (id, automation, opts) => {
|
|
740
|
+
try {
|
|
741
|
+
const payload = await new MiosaClient(loadConfig()).apiPost(`/api/v1/builder/apps/${encodeURIComponent(id)}/automations/${encodeURIComponent(automation)}/runs`, { trigger: parseJsonObject(opts.trigger, "--trigger") });
|
|
742
|
+
if (isJsonMode(opts)) {
|
|
743
|
+
printJson({ ok: true, data: payload, error: null });
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
747
|
+
}
|
|
748
|
+
catch (err) {
|
|
749
|
+
handleError(err);
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
automations
|
|
753
|
+
.command("claim <id> <run>")
|
|
754
|
+
.description("Claim or resume the current automation step")
|
|
755
|
+
.option("--json", "Output the exact authority-bound claim")
|
|
756
|
+
.action(async (id, run, opts) => {
|
|
757
|
+
try {
|
|
758
|
+
const payload = await new MiosaClient(loadConfig()).apiPost(`/api/v1/builder/apps/${encodeURIComponent(id)}/automation-runs/${encodeURIComponent(run)}/claim`, {});
|
|
759
|
+
if (isJsonMode(opts)) {
|
|
760
|
+
printJson({ ok: true, data: payload, error: null });
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
764
|
+
}
|
|
765
|
+
catch (err) {
|
|
766
|
+
handleError(err);
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
automations
|
|
770
|
+
.command("complete <id> <run>")
|
|
771
|
+
.description("Complete the exact claimed automation step")
|
|
772
|
+
.requiredOption("--cursor <number>", "Claimed step cursor")
|
|
773
|
+
.requiredOption("--idempotency-key <key>", "Claimed idempotency key")
|
|
774
|
+
.option("--output <json>", "Step output JSON object", "{}")
|
|
775
|
+
.option("--json", "Output the updated run")
|
|
776
|
+
.action(async (id, run, opts) => {
|
|
777
|
+
try {
|
|
778
|
+
const payload = await new MiosaClient(loadConfig()).apiPost(`/api/v1/builder/apps/${encodeURIComponent(id)}/automation-runs/${encodeURIComponent(run)}/complete`, {
|
|
779
|
+
cursor: parseNonNegativeInteger(opts.cursor, "--cursor"),
|
|
780
|
+
idempotency_key: opts.idempotencyKey,
|
|
781
|
+
output: parseJsonObject(opts.output, "--output"),
|
|
782
|
+
});
|
|
783
|
+
if (isJsonMode(opts)) {
|
|
784
|
+
printJson({ ok: true, data: payload, error: null });
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
788
|
+
}
|
|
789
|
+
catch (err) {
|
|
790
|
+
handleError(err);
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
automations
|
|
794
|
+
.command("fail <id> <run>")
|
|
795
|
+
.description("Fail the exact claimed automation step")
|
|
796
|
+
.requiredOption("--cursor <number>", "Claimed step cursor")
|
|
797
|
+
.requiredOption("--idempotency-key <key>", "Claimed idempotency key")
|
|
798
|
+
.requiredOption("--reason <reason>", "Failure reason")
|
|
799
|
+
.option("--json", "Output the updated run")
|
|
800
|
+
.action(async (id, run, opts) => {
|
|
801
|
+
try {
|
|
802
|
+
const payload = await new MiosaClient(loadConfig()).apiPost(`/api/v1/builder/apps/${encodeURIComponent(id)}/automation-runs/${encodeURIComponent(run)}/fail`, {
|
|
803
|
+
cursor: parseNonNegativeInteger(opts.cursor, "--cursor"),
|
|
804
|
+
idempotency_key: opts.idempotencyKey,
|
|
805
|
+
reason: opts.reason,
|
|
806
|
+
});
|
|
807
|
+
if (isJsonMode(opts)) {
|
|
808
|
+
printJson({ ok: true, data: payload, error: null });
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
812
|
+
}
|
|
813
|
+
catch (err) {
|
|
814
|
+
handleError(err);
|
|
815
|
+
}
|
|
816
|
+
});
|
|
475
817
|
app
|
|
476
818
|
.command("pull")
|
|
477
819
|
.argument("[path]", "Local app directory", ".")
|