@xano/cli 1.3.1-beta.0 → 1.3.1
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 +5 -269
- package/dist/base-command.d.ts +1 -12
- package/dist/base-command.js +22 -36
- package/dist/commands/branch/set_live/index.d.ts +0 -22
- package/dist/commands/branch/set_live/index.js +1 -60
- package/dist/commands/ephemeral/push/index.js +1 -6
- package/dist/commands/function/create/index.d.ts +0 -15
- package/dist/commands/function/create/index.js +0 -40
- package/dist/commands/function/edit/index.d.ts +0 -15
- package/dist/commands/function/edit/index.js +0 -40
- package/dist/commands/function/run/index.d.ts +1 -0
- package/dist/commands/function/run/index.js +10 -2
- package/dist/commands/release/create/index.js +0 -7
- package/dist/commands/release/deploy/index.d.ts +0 -28
- package/dist/commands/release/deploy/index.js +6 -90
- package/dist/commands/release/import/index.js +1 -5
- package/dist/commands/release/list/index.d.ts +0 -7
- package/dist/commands/release/list/index.js +10 -54
- package/dist/commands/release/push/index.js +1 -19
- package/dist/commands/sandbox/push/index.js +1 -6
- package/dist/commands/tenant/create/index.d.ts +0 -3
- package/dist/commands/tenant/create/index.js +0 -21
- package/dist/commands/tenant/deploy_release/index.d.ts +0 -40
- package/dist/commands/tenant/deploy_release/index.js +4 -186
- package/dist/commands/tenant/edit/index.d.ts +0 -2
- package/dist/commands/tenant/edit/index.js +4 -39
- package/dist/commands/workspace/pull/index.d.ts +0 -10
- package/dist/commands/workspace/pull/index.js +7 -70
- package/dist/commands/workspace/push/index.d.ts +0 -19
- package/dist/commands/workspace/push/index.js +5 -124
- package/dist/utils/document-parser.d.ts +0 -10
- package/dist/utils/document-parser.js +0 -21
- package/dist/utils/multidoc-push.d.ts +2 -55
- package/dist/utils/multidoc-push.js +27 -103
- package/oclif.manifest.json +3658 -6647
- package/package.json +1 -7
- package/dist/commands/policy/catalogue/index.d.ts +0 -15
- package/dist/commands/policy/catalogue/index.js +0 -29
- package/dist/commands/policy/create/index.d.ts +0 -18
- package/dist/commands/policy/create/index.js +0 -39
- package/dist/commands/policy/delete/index.d.ts +0 -19
- package/dist/commands/policy/delete/index.js +0 -61
- package/dist/commands/policy/evaluate/index.d.ts +0 -32
- package/dist/commands/policy/evaluate/index.js +0 -71
- package/dist/commands/policy/list/index.d.ts +0 -14
- package/dist/commands/policy/list/index.js +0 -21
- package/dist/commands/policy/parse/index.d.ts +0 -19
- package/dist/commands/policy/parse/index.js +0 -18
- package/dist/commands/policy/publish/index.d.ts +0 -20
- package/dist/commands/policy/publish/index.js +0 -38
- package/dist/commands/policy/runs/index.d.ts +0 -54
- package/dist/commands/policy/runs/index.js +0 -273
- package/dist/commands/policy/status/index.d.ts +0 -21
- package/dist/commands/policy/status/index.js +0 -54
- package/dist/commands/skills/pull/index.d.ts +0 -30
- package/dist/commands/skills/pull/index.js +0 -118
- package/dist/commands/tenant_deploy_request/bypass/index.d.ts +0 -31
- package/dist/commands/tenant_deploy_request/bypass/index.js +0 -109
- package/dist/commands/tenant_deploy_request/create/index.d.ts +0 -21
- package/dist/commands/tenant_deploy_request/create/index.js +0 -108
- package/dist/commands/tenant_deploy_request/edit/index.d.ts +0 -22
- package/dist/commands/tenant_deploy_request/edit/index.js +0 -103
- package/dist/commands/tenant_deploy_request/get/index.d.ts +0 -25
- package/dist/commands/tenant_deploy_request/get/index.js +0 -116
- package/dist/commands/tenant_deploy_request/list/index.d.ts +0 -20
- package/dist/commands/tenant_deploy_request/list/index.js +0 -122
- package/dist/commands/tenant_deploy_request/revision/index.d.ts +0 -21
- package/dist/commands/tenant_deploy_request/revision/index.js +0 -83
- package/dist/commands/tenant_deploy_request/set_status/index.d.ts +0 -38
- package/dist/commands/tenant_deploy_request/set_status/index.js +0 -159
- package/dist/policy-command.d.ts +0 -90
- package/dist/policy-command.js +0 -94
- package/dist/utils/policy/catalogue.d.ts +0 -7
- package/dist/utils/policy/catalogue.js +0 -72
- package/dist/utils/policy/errors.d.ts +0 -12
- package/dist/utils/policy/errors.js +0 -61
- package/dist/utils/policy/feedback.d.ts +0 -68
- package/dist/utils/policy/feedback.js +0 -165
- package/dist/utils/policy/findings.d.ts +0 -23
- package/dist/utils/policy/findings.js +0 -65
- package/dist/utils/policy/gate.d.ts +0 -161
- package/dist/utils/policy/gate.js +0 -201
- package/dist/utils/policy/goal.d.ts +0 -46
- package/dist/utils/policy/goal.js +0 -95
- package/dist/utils/policy/permission.d.ts +0 -23
- package/dist/utils/policy/permission.js +0 -84
- package/dist/utils/policy/push-gate.d.ts +0 -5
- package/dist/utils/policy/push-gate.js +0 -29
- package/dist/utils/policy/release.d.ts +0 -85
- package/dist/utils/policy/release.js +0 -115
- package/dist/utils/policy/request.d.ts +0 -55
- package/dist/utils/policy/request.js +0 -115
- package/dist/utils/policy/runs.d.ts +0 -30
- package/dist/utils/policy/runs.js +0 -101
- package/dist/utils/policy/status.d.ts +0 -47
- package/dist/utils/policy/status.js +0 -117
- package/dist/utils/policy/types.d.ts +0 -185
- package/dist/utils/policy/types.js +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xano/cli",
|
|
3
3
|
"description": "CLI for Xano's Metadata API",
|
|
4
|
-
"version": "1.3.1
|
|
4
|
+
"version": "1.3.1",
|
|
5
5
|
"author": "Sean Montgomery",
|
|
6
6
|
"bin": {
|
|
7
7
|
"xano": "./bin/run.js"
|
|
@@ -130,12 +130,6 @@
|
|
|
130
130
|
},
|
|
131
131
|
"workspace:git": {
|
|
132
132
|
"description": "Pull workspaces from git repositories"
|
|
133
|
-
},
|
|
134
|
-
"policy": {
|
|
135
|
-
"description": "Author and evaluate workspace policies"
|
|
136
|
-
},
|
|
137
|
-
"skills": {
|
|
138
|
-
"description": "Install agent skills generated by your Xano instance"
|
|
139
133
|
}
|
|
140
134
|
}
|
|
141
135
|
},
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyCatalogue extends PolicyCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
check: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
-
};
|
|
14
|
-
run(): Promise<void>;
|
|
15
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
3
|
-
import { policyCatalogueSummary, selectCatalogueCheck } from '../../../utils/policy/catalogue.js';
|
|
4
|
-
import { listItems } from '../../../utils/policy/request.js';
|
|
5
|
-
export default class PolicyCatalogue extends PolicyCommand {
|
|
6
|
-
static description = 'List built-in policy checks and their parameter schemas';
|
|
7
|
-
static examples = ['$ xano policy catalogue -o json', '$ xano policy catalogue --check object.auth_required'];
|
|
8
|
-
static flags = {
|
|
9
|
-
...PolicyCommand.policyFlags,
|
|
10
|
-
check: Flags.string({ description: 'Show only this check id (an unknown id names the closest matches)' }),
|
|
11
|
-
};
|
|
12
|
-
async run() {
|
|
13
|
-
const { flags } = await this.parse(PolicyCatalogue);
|
|
14
|
-
const { request } = this.policyTarget(flags);
|
|
15
|
-
const result = await request('/check');
|
|
16
|
-
if (flags.check) {
|
|
17
|
-
// `--check` narrows both output modes, so `-o json` stays pipeable for one check too.
|
|
18
|
-
const selected = selectCatalogueCheck(listItems(result), flags.check);
|
|
19
|
-
this.log(flags.output === 'json' ? JSON.stringify(selected, null, 2) : policyCatalogueSummary(selected).join('\n'));
|
|
20
|
-
}
|
|
21
|
-
else if (flags.output === 'json') {
|
|
22
|
-
this.log(JSON.stringify(result, null, 2));
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
for (const line of policyCatalogueSummary(listItems(result)))
|
|
26
|
-
this.log(line);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyCreate extends PolicyCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
goal: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
key: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
param: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
message: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
-
};
|
|
17
|
-
run(): Promise<void>;
|
|
18
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
3
|
-
import { policyFromGoal } from '../../../utils/policy/goal.js';
|
|
4
|
-
import { listAllPolicies } from '../../../utils/policy/request.js';
|
|
5
|
-
export default class PolicyCreate extends PolicyCommand {
|
|
6
|
-
static description = 'Create an independent policy from a platform goal';
|
|
7
|
-
static examples = [
|
|
8
|
-
'$ xano policy create --goal endpoints_need_login -b dev',
|
|
9
|
-
`$ xano policy create --goal no_pii_in_responses --key DATA-020 --param 'fields=["email","ssn"]'`,
|
|
10
|
-
];
|
|
11
|
-
static flags = {
|
|
12
|
-
...PolicyCommand.policyFlags,
|
|
13
|
-
...PolicyCommand.publishFlags,
|
|
14
|
-
goal: Flags.string({ description: 'Goal id from policy catalogue -o json', required: true }),
|
|
15
|
-
key: Flags.string({ description: 'New policy key (default: the goal key with a free numeric suffix if taken)' }),
|
|
16
|
-
param: Flags.string({ description: 'Parameter override: N.path=JSON, 1-based rule number; path=JSON for a single-rule goal', multiple: true }),
|
|
17
|
-
};
|
|
18
|
-
async run() {
|
|
19
|
-
const { flags } = await this.parse(PolicyCreate);
|
|
20
|
-
const target = this.policyTarget(flags);
|
|
21
|
-
const { request } = target;
|
|
22
|
-
const catalogue = await request('/check');
|
|
23
|
-
const goal = catalogue.goals?.find(item => item.id === flags.goal);
|
|
24
|
-
if (!goal)
|
|
25
|
-
this.error(`Unknown goal "${flags.goal}". Run xano policy catalogue -o json to see this instance's goals.`);
|
|
26
|
-
const keys = (await listAllPolicies(request)).map(policy => policy.key);
|
|
27
|
-
// The key is checked against the pattern this instance's catalogue serves.
|
|
28
|
-
const document = policyFromGoal(goal, keys, { key: flags.key, keyRule: catalogue.document?.key, overrides: flags.param });
|
|
29
|
-
const parsed = await this.parseSource(request, { data: document });
|
|
30
|
-
const saved = await request('', 'POST', { data: { source: parsed.source }, ...(flags.message ? { message: flags.message } : {}) });
|
|
31
|
-
if (typeof saved?.id !== 'number')
|
|
32
|
-
this.error('The platform did not return the saved policy. Check xano policy list before retrying.');
|
|
33
|
-
this.logRuleWarnings(parsed);
|
|
34
|
-
if (flags.output === 'json')
|
|
35
|
-
this.log(JSON.stringify(saved, null, 2));
|
|
36
|
-
else
|
|
37
|
-
this.log(`Created ${parsed.policy.key} (Version ${saved.version}) in ${this.where(target)}.`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyDelete extends PolicyCommand {
|
|
3
|
-
static args: {
|
|
4
|
-
policy: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
-
};
|
|
6
|
-
static description: string;
|
|
7
|
-
static examples: string[];
|
|
8
|
-
static flags: {
|
|
9
|
-
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
-
};
|
|
17
|
-
/** `workspace push` is additive, so deleting a policy file leaves the policy in place; this removes it. */
|
|
18
|
-
run(): Promise<void>;
|
|
19
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
3
|
-
import { confirm } from '../../../utils/multidoc-push.js';
|
|
4
|
-
import { listAllPolicies, sameKey } from '../../../utils/policy/request.js';
|
|
5
|
-
export default class PolicyDelete extends PolicyCommand {
|
|
6
|
-
static args = {
|
|
7
|
-
policy: Args.string({
|
|
8
|
-
description: 'Policy key (AUTH-001) or ID to delete',
|
|
9
|
-
required: true,
|
|
10
|
-
}),
|
|
11
|
-
};
|
|
12
|
-
static description = 'Delete a policy from a branch; its Version History is kept. Deleting an active, mandatory policy also needs the workspace:policy update permission.';
|
|
13
|
-
static examples = [
|
|
14
|
-
`$ xano policy delete TMP-DX-001
|
|
15
|
-
Delete policy TMP-DX-001 (ID: 922, Version 2) from workspace 3? Its Version History is kept. (y/N) y
|
|
16
|
-
Deleted policy TMP-DX-001 (ID: 922) from workspace 3.
|
|
17
|
-
`,
|
|
18
|
-
'$ xano policy delete 922 --force',
|
|
19
|
-
'$ xano policy delete TMP-DX-001 -w 3 --force -o json',
|
|
20
|
-
];
|
|
21
|
-
static flags = {
|
|
22
|
-
...PolicyCommand.policyFlags,
|
|
23
|
-
force: Flags.boolean({
|
|
24
|
-
char: 'f',
|
|
25
|
-
default: false,
|
|
26
|
-
description: '[IMPORTANT] NEVER run without explicit user confirmation. Skips the confirmation prompt.',
|
|
27
|
-
}),
|
|
28
|
-
};
|
|
29
|
-
/** `workspace push` is additive, so deleting a policy file leaves the policy in place; this removes it. */
|
|
30
|
-
async run() {
|
|
31
|
-
const { args, flags } = await this.parse(PolicyDelete);
|
|
32
|
-
const target = this.policyTarget(flags);
|
|
33
|
-
const wanted = args.policy.trim();
|
|
34
|
-
if (!wanted)
|
|
35
|
-
this.error('Provide the policy key or ID to delete.');
|
|
36
|
-
const policies = await listAllPolicies(target.request);
|
|
37
|
-
const matched = policies.find((policy) => sameKey(policy.key, wanted))
|
|
38
|
-
?? (/^\d+$/.test(wanted) ? policies.find((policy) => policy.id === Number(wanted)) : undefined);
|
|
39
|
-
if (!matched) {
|
|
40
|
-
const known = policies.map((policy) => policy.key).sort();
|
|
41
|
-
this.error(`No policy "${wanted}" on ${this.where(target)}.${known.length > 0 ? ` This branch has: ${known.join(', ')}.` : ' This branch has no policies.'}`);
|
|
42
|
-
}
|
|
43
|
-
if (!flags.force) {
|
|
44
|
-
// Nobody can answer the prompt: refuse rather than report a cancel as success.
|
|
45
|
-
if (!process.stdin.isTTY)
|
|
46
|
-
this.error('Non-interactive environment detected. Use --force to skip confirmation.');
|
|
47
|
-
const confirmed = await confirm(`Delete policy ${matched.key} (ID: ${matched.id}, Version ${matched.version}) from ${this.where(target)}? Its Version History is kept.`);
|
|
48
|
-
if (!confirmed) {
|
|
49
|
-
this.log('Deletion cancelled.');
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// The policy as listed is what the prompt named: a delete of a policy changed since is refused (`policy_stale`).
|
|
54
|
-
const staleCheck = matched.updated_at ? { last_updated_at: String(matched.updated_at) } : {};
|
|
55
|
-
await target.request(`/${matched.id}`, 'DELETE', undefined, staleCheck);
|
|
56
|
-
if (flags.output === 'json')
|
|
57
|
-
this.log(JSON.stringify({ deleted: true, id: matched.id, key: matched.key }, null, 2));
|
|
58
|
-
else
|
|
59
|
-
this.log(`Deleted policy ${matched.key} (ID: ${matched.id}) from ${this.where(target)}.`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
/** One rule's clear objects in a trial's answer: the first ones and how many there are. */
|
|
3
|
-
type TrialClear = {
|
|
4
|
-
items?: Array<{
|
|
5
|
-
name?: string;
|
|
6
|
-
}>;
|
|
7
|
-
policy_key?: string;
|
|
8
|
-
rule_id?: string;
|
|
9
|
-
total?: number;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* What a trial says it is, then each rule's clear objects: the objects it examined and found
|
|
13
|
-
* nothing on. A trial is never stored, so its answer is all there is to show.
|
|
14
|
-
*/
|
|
15
|
-
export declare function trialLines(key: string, clear: TrialClear[] | undefined): string[];
|
|
16
|
-
export default class PolicyEvaluate extends PolicyCommand {
|
|
17
|
-
static description: string;
|
|
18
|
-
static examples: string[];
|
|
19
|
-
static flags: {
|
|
20
|
-
policy: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
-
'run-detail': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
|
-
summary: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
23
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
|
-
};
|
|
30
|
-
run(): Promise<void>;
|
|
31
|
-
}
|
|
32
|
-
export {};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
3
|
-
import { evaluationEvidence, notStoredLine, policyCheckWarning, policyExitCode, policySummary, } from '../../../utils/policy/feedback.js';
|
|
4
|
-
/** How many clear objects a trial names per rule; the rest are counted. */
|
|
5
|
-
const TRIAL_CLEAR_NAMES = 5;
|
|
6
|
-
/**
|
|
7
|
-
* What a trial says it is, then each rule's clear objects: the objects it examined and found
|
|
8
|
-
* nothing on. A trial is never stored, so its answer is all there is to show.
|
|
9
|
-
*/
|
|
10
|
-
export function trialLines(key, clear) {
|
|
11
|
-
const lines = [`Trial of ${key}: this policy alone, evaluated without storing a run. It is not a report and gates nothing.`];
|
|
12
|
-
if (!clear?.length)
|
|
13
|
-
return lines;
|
|
14
|
-
lines.push('Clear objects (examined, nothing found):');
|
|
15
|
-
for (const rule of clear) {
|
|
16
|
-
const names = (rule.items ?? []).map((item) => item.name ?? '').filter(Boolean).slice(0, TRIAL_CLEAR_NAMES);
|
|
17
|
-
const total = rule.total ?? 0;
|
|
18
|
-
const more = total > names.length ? `${names.length > 0 ? ', ' : ''}${total - names.length} more` : '';
|
|
19
|
-
lines.push(` ${rule.rule_id ?? ''} ${total}${names.length > 0 || more ? ` ${names.join(', ')}${more}` : ''}`);
|
|
20
|
-
}
|
|
21
|
-
return lines;
|
|
22
|
-
}
|
|
23
|
-
export default class PolicyEvaluate extends PolicyCommand {
|
|
24
|
-
static description = 'Evaluate active branch policies and report their findings; blocking findings exit 2. With --policy, try one policy alone, whatever its state, without storing a run';
|
|
25
|
-
static examples = ['$ xano policy evaluate -o json', '$ xano policy evaluate --run-detail', '$ xano policy evaluate --summary -o json', '$ xano policy evaluate --policy AUTH-001'];
|
|
26
|
-
static flags = {
|
|
27
|
-
...PolicyCommand.policyFlags,
|
|
28
|
-
policy: Flags.string({
|
|
29
|
-
description: 'Try this one policy (its key) alone, whatever its state: nothing is stored, and the answer lists each rule\'s clear objects',
|
|
30
|
-
}),
|
|
31
|
-
'run-detail': Flags.boolean({
|
|
32
|
-
default: false,
|
|
33
|
-
description: 'Also print what this run recorded: each policy description and the settings each rule ran with',
|
|
34
|
-
}),
|
|
35
|
-
summary: Flags.boolean({
|
|
36
|
-
default: false,
|
|
37
|
-
description: 'Answer the run summary and its first 50 findings instead of the whole run; `xano policy runs <id>` pages through the rest',
|
|
38
|
-
}),
|
|
39
|
-
};
|
|
40
|
-
async run() {
|
|
41
|
-
const { flags } = await this.parse(PolicyEvaluate);
|
|
42
|
-
if (flags.policy !== undefined && !flags.policy.trim())
|
|
43
|
-
this.error('--policy must name a policy key.');
|
|
44
|
-
const { request } = this.policyTarget(flags);
|
|
45
|
-
// The evaluation answers with its run, so the run's own snapshot names any unnamed rule. The
|
|
46
|
-
// summary answer carries the same snapshot and results, and only the first findings.
|
|
47
|
-
const body = { ...(flags.summary ? { answer: 'summary' } : {}), ...(flags.policy ? { policy: flags.policy } : {}) };
|
|
48
|
-
const result = (await request('/evaluate', 'POST', Object.keys(body).length > 0 ? body : undefined));
|
|
49
|
-
if (flags.output === 'json')
|
|
50
|
-
this.log(JSON.stringify(result, null, 2));
|
|
51
|
-
else {
|
|
52
|
-
for (const line of policySummary(result.policy_check, evaluationEvidence(result)))
|
|
53
|
-
this.log(line);
|
|
54
|
-
// A trial is never stored by design; the "cannot record runs" note is about credentials.
|
|
55
|
-
const notStored = flags.policy ? null : notStoredLine(result);
|
|
56
|
-
if (notStored)
|
|
57
|
-
this.log(notStored);
|
|
58
|
-
if (flags.policy)
|
|
59
|
-
for (const line of trialLines(flags.policy, result.clear))
|
|
60
|
-
this.log(line);
|
|
61
|
-
if (flags['run-detail'])
|
|
62
|
-
this.logRunDetail(result);
|
|
63
|
-
}
|
|
64
|
-
const warning = policyCheckWarning(result.policy_check);
|
|
65
|
-
if (warning)
|
|
66
|
-
this.warn(warning);
|
|
67
|
-
const code = policyExitCode(result.policy_check);
|
|
68
|
-
if (code)
|
|
69
|
-
process.exitCode = code;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyList extends PolicyCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
};
|
|
13
|
-
run(): Promise<void>;
|
|
14
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
import { listItems } from '../../../utils/policy/request.js';
|
|
3
|
-
export default class PolicyList extends PolicyCommand {
|
|
4
|
-
static description = 'List workspace policies and their descriptions';
|
|
5
|
-
static examples = ['$ xano policy list -o json'];
|
|
6
|
-
static flags = { ...PolicyCommand.policyFlags };
|
|
7
|
-
async run() {
|
|
8
|
-
const { flags } = await this.parse(PolicyList);
|
|
9
|
-
const { request } = this.policyTarget(flags);
|
|
10
|
-
const result = await request();
|
|
11
|
-
if (flags.output === 'json') {
|
|
12
|
-
this.log(JSON.stringify(result, null, 2));
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
const policies = listItems(result);
|
|
16
|
-
if (policies.length === 0)
|
|
17
|
-
this.log('No policies found.');
|
|
18
|
-
for (const policy of policies)
|
|
19
|
-
this.log(`${policy.key} ${policy.active ? `Active, ${policy.enforcement === 'mandatory' ? 'Mandatory' : 'Advisory'}` : 'Inactive'} ${policy.title ?? ''} (ID: ${policy.id}, Version ${policy.version})`);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyParse extends PolicyCommand {
|
|
3
|
-
static args: {
|
|
4
|
-
file: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
-
};
|
|
6
|
-
static description: string;
|
|
7
|
-
static examples: string[];
|
|
8
|
-
static flags: {
|
|
9
|
-
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
-
};
|
|
18
|
-
run(): Promise<void>;
|
|
19
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyParse extends PolicyCommand {
|
|
3
|
-
static args = { ...PolicyCommand.sourceArgs };
|
|
4
|
-
static description = 'Validate and format policy XanoScript using the platform parser, with rule warnings against the branch';
|
|
5
|
-
static examples = [
|
|
6
|
-
'$ xano policy parse policies/AUTH-001.xs',
|
|
7
|
-
'$ xano policy parse --file policies/AUTH-001.xs',
|
|
8
|
-
];
|
|
9
|
-
static flags = { ...PolicyCommand.policyFlags, ...PolicyCommand.sourceFlags };
|
|
10
|
-
async run() {
|
|
11
|
-
const { args, flags } = await this.parse(PolicyParse);
|
|
12
|
-
const { request } = this.policyTarget(flags);
|
|
13
|
-
const parsed = await this.parseSource(request, { source: this.readSource(flags, args.file) });
|
|
14
|
-
this.log(flags.output === 'json' ? JSON.stringify(parsed, null, 2) : parsed.source);
|
|
15
|
-
if (flags.output !== 'json')
|
|
16
|
-
this.logRuleWarnings(parsed);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
export default class PolicyPublish extends PolicyCommand {
|
|
3
|
-
static args: {
|
|
4
|
-
file: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
|
-
};
|
|
6
|
-
static description: string;
|
|
7
|
-
static examples: string[];
|
|
8
|
-
static flags: {
|
|
9
|
-
message: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
-
stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
-
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
-
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
-
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
};
|
|
19
|
-
run(): Promise<void>;
|
|
20
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
2
|
-
import { listAllPolicies, sameKey } from '../../../utils/policy/request.js';
|
|
3
|
-
export default class PolicyPublish extends PolicyCommand {
|
|
4
|
-
static args = { ...PolicyCommand.sourceArgs };
|
|
5
|
-
static description = 'Create or update a workspace policy from native XanoScript';
|
|
6
|
-
static examples = [
|
|
7
|
-
'$ xano policy publish policies/AUTH-001.xs',
|
|
8
|
-
'$ xano policy publish --file policies/AUTH-001.xs',
|
|
9
|
-
'$ xano policy publish --file policies/AUTH-001.xs -m "Tightened the scope"',
|
|
10
|
-
];
|
|
11
|
-
static flags = { ...PolicyCommand.policyFlags, ...PolicyCommand.sourceFlags, ...PolicyCommand.publishFlags };
|
|
12
|
-
async run() {
|
|
13
|
-
const { args, flags } = await this.parse(PolicyPublish);
|
|
14
|
-
const target = this.policyTarget(flags);
|
|
15
|
-
const { request } = target;
|
|
16
|
-
const source = this.readSource(flags, args.file);
|
|
17
|
-
// The key picks PUT or POST, so the list is read alongside the parse rather than after it.
|
|
18
|
-
const [parsed, policies] = await Promise.all([this.parseSource(request, { source }), listAllPolicies(request)]);
|
|
19
|
-
// A key that differs only in case names the same policy, which PUT updates, key included.
|
|
20
|
-
const existing = policies.find((policy) => sameKey(policy.key, parsed.policy.key));
|
|
21
|
-
const body = { data: { source: parsed.source } };
|
|
22
|
-
if (flags.message)
|
|
23
|
-
body.message = flags.message;
|
|
24
|
-
const saved = (await request(existing ? `/${existing.id}` : '', existing ? 'PUT' : 'POST', body));
|
|
25
|
-
if (typeof saved?.id !== 'number') {
|
|
26
|
-
this.error('The platform did not return the saved policy. Check `xano policy list` before retrying.');
|
|
27
|
-
}
|
|
28
|
-
this.logRuleWarnings(parsed);
|
|
29
|
-
if (flags.output === 'json') {
|
|
30
|
-
this.log(JSON.stringify(saved, null, 2));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
// A save identical to the stored definition writes nothing: no version, history entry or audit record.
|
|
34
|
-
this.log(saved.unchanged === true
|
|
35
|
-
? `No changes to ${parsed.policy.key} (Version ${saved.version}) in ${this.where(target)}.`
|
|
36
|
-
: `Published ${parsed.policy.key} (Version ${saved.version}) to ${this.where(target)}.`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Interfaces } from '@oclif/core';
|
|
2
|
-
import PolicyCommand from '../../../policy-command.js';
|
|
3
|
-
export default class PolicyRuns extends PolicyCommand {
|
|
4
|
-
static args: {
|
|
5
|
-
run_id: Interfaces.Arg<string | undefined, Record<string, unknown>>;
|
|
6
|
-
};
|
|
7
|
-
static description: string;
|
|
8
|
-
static examples: string[];
|
|
9
|
-
static flags: {
|
|
10
|
-
advisory: Interfaces.BooleanFlag<boolean>;
|
|
11
|
-
all: Interfaces.BooleanFlag<boolean>;
|
|
12
|
-
blocking: Interfaces.BooleanFlag<boolean>;
|
|
13
|
-
kind: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
14
|
-
limit: Interfaces.OptionFlag<number | undefined, Interfaces.CustomOptions>;
|
|
15
|
-
object: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
16
|
-
offset: Interfaces.OptionFlag<number | undefined, Interfaces.CustomOptions>;
|
|
17
|
-
policy: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
18
|
-
recheck: Interfaces.BooleanFlag<boolean>;
|
|
19
|
-
release: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
20
|
-
'release-id': Interfaces.OptionFlag<number | undefined, Interfaces.CustomOptions>;
|
|
21
|
-
rule: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
22
|
-
'run-detail': Interfaces.BooleanFlag<boolean>;
|
|
23
|
-
search: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
24
|
-
severity: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
25
|
-
tag: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
26
|
-
branch: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
27
|
-
output: Interfaces.OptionFlag<string, Interfaces.CustomOptions>;
|
|
28
|
-
workspace: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
29
|
-
config: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
30
|
-
profile: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
31
|
-
verbose: Interfaces.BooleanFlag<boolean>;
|
|
32
|
-
};
|
|
33
|
-
run(): Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* `--all`: every finding that matches, read a page of 500 at a time in the platform's order, as
|
|
36
|
-
* one page. A run of many pages says on stderr what it is reading.
|
|
37
|
-
*/
|
|
38
|
-
private everyFinding;
|
|
39
|
-
/** The retained runs, newest first; the flags that read one run's findings are refused. */
|
|
40
|
-
private listRuns;
|
|
41
|
-
/**
|
|
42
|
-
* `--release <name>`: the release's stored check (`GET release/{id}/policy_run`) and a page of its
|
|
43
|
-
* findings, as a run is read. `--recheck` checks the release again from its archive first. A
|
|
44
|
-
* release with no check says so; under `-o json` it is `{run: null}`.
|
|
45
|
-
*/
|
|
46
|
-
private readRelease;
|
|
47
|
-
/** The release's ID from its name, reading the workspace's releases a page at a time until it is found. */
|
|
48
|
-
private releaseId;
|
|
49
|
-
/**
|
|
50
|
-
* One run's summary and a page of its findings (`path`), or under `-o json` the summary with
|
|
51
|
-
* `findings` and `findings_page`, plus what `extra` adds to it.
|
|
52
|
-
*/
|
|
53
|
-
private reportRun;
|
|
54
|
-
}
|