@vertaaux/cli 0.2.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.
- package/README.md +345 -0
- package/dist/auth/ci-token.d.ts +49 -0
- package/dist/auth/ci-token.d.ts.map +1 -0
- package/dist/auth/ci-token.js +83 -0
- package/dist/auth/device-flow.d.ts +66 -0
- package/dist/auth/device-flow.d.ts.map +1 -0
- package/dist/auth/device-flow.js +156 -0
- package/dist/auth/token-store.d.ts +53 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +78 -0
- package/dist/baseline/diff.d.ts +57 -0
- package/dist/baseline/diff.d.ts.map +1 -0
- package/dist/baseline/diff.js +152 -0
- package/dist/baseline/hash.d.ts +54 -0
- package/dist/baseline/hash.d.ts.map +1 -0
- package/dist/baseline/hash.js +66 -0
- package/dist/baseline/manager.d.ts +89 -0
- package/dist/baseline/manager.d.ts.map +1 -0
- package/dist/baseline/manager.js +157 -0
- package/dist/cache/index.d.ts +8 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +7 -0
- package/dist/cache/route-cache.d.ts +119 -0
- package/dist/cache/route-cache.d.ts.map +1 -0
- package/dist/cache/route-cache.js +213 -0
- package/dist/ci/changed-routes.d.ts +95 -0
- package/dist/ci/changed-routes.d.ts.map +1 -0
- package/dist/ci/changed-routes.js +304 -0
- package/dist/ci/github-api.d.ts +68 -0
- package/dist/ci/github-api.d.ts.map +1 -0
- package/dist/ci/github-api.js +138 -0
- package/dist/ci/gitlab-api.d.ts +75 -0
- package/dist/ci/gitlab-api.d.ts.map +1 -0
- package/dist/ci/gitlab-api.js +180 -0
- package/dist/ci/index.d.ts +6 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +4 -0
- package/dist/commands/audit.d.ts +58 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +862 -0
- package/dist/commands/baseline.d.ts +22 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +210 -0
- package/dist/commands/comment.d.ts +14 -0
- package/dist/commands/comment.d.ts.map +1 -0
- package/dist/commands/comment.js +363 -0
- package/dist/commands/diff.d.ts +24 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +196 -0
- package/dist/commands/doctor.d.ts +58 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +338 -0
- package/dist/commands/download.d.ts +12 -0
- package/dist/commands/download.d.ts.map +1 -0
- package/dist/commands/download.js +183 -0
- package/dist/commands/explain.d.ts +62 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +302 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +212 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +222 -0
- package/dist/commands/policy.d.ts +13 -0
- package/dist/commands/policy.d.ts.map +1 -0
- package/dist/commands/policy.js +347 -0
- package/dist/commands/upload.d.ts +12 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +158 -0
- package/dist/config/defaults.d.ts +21 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +49 -0
- package/dist/config/loader.d.ts +66 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +167 -0
- package/dist/config/schema.d.ts +55 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1090 -0
- package/dist/interactive/fix-wizard.d.ts +44 -0
- package/dist/interactive/fix-wizard.d.ts.map +1 -0
- package/dist/interactive/fix-wizard.js +286 -0
- package/dist/interactive/init-wizard.d.ts +32 -0
- package/dist/interactive/init-wizard.d.ts.map +1 -0
- package/dist/interactive/init-wizard.js +193 -0
- package/dist/interactive/prompts.d.ts +62 -0
- package/dist/interactive/prompts.d.ts.map +1 -0
- package/dist/interactive/prompts.js +78 -0
- package/dist/monorepo/detector.d.ts +70 -0
- package/dist/monorepo/detector.d.ts.map +1 -0
- package/dist/monorepo/detector.js +278 -0
- package/dist/monorepo/index.d.ts +9 -0
- package/dist/monorepo/index.d.ts.map +1 -0
- package/dist/monorepo/index.js +8 -0
- package/dist/monorepo/workspace.d.ts +142 -0
- package/dist/monorepo/workspace.d.ts.map +1 -0
- package/dist/monorepo/workspace.js +171 -0
- package/dist/output/envelope.d.ts +21 -0
- package/dist/output/envelope.d.ts.map +1 -0
- package/dist/output/envelope.js +27 -0
- package/dist/output/factory.d.ts +73 -0
- package/dist/output/factory.d.ts.map +1 -0
- package/dist/output/factory.js +60 -0
- package/dist/output/formats.d.ts +11 -0
- package/dist/output/formats.d.ts.map +1 -0
- package/dist/output/formats.js +41 -0
- package/dist/output/html.d.ts +45 -0
- package/dist/output/html.d.ts.map +1 -0
- package/dist/output/html.js +607 -0
- package/dist/output/human.d.ts +41 -0
- package/dist/output/human.d.ts.map +1 -0
- package/dist/output/human.js +274 -0
- package/dist/output/json.d.ts +42 -0
- package/dist/output/json.d.ts.map +1 -0
- package/dist/output/json.js +37 -0
- package/dist/output/junit.d.ts +56 -0
- package/dist/output/junit.d.ts.map +1 -0
- package/dist/output/junit.js +135 -0
- package/dist/output/markdown.d.ts +77 -0
- package/dist/output/markdown.d.ts.map +1 -0
- package/dist/output/markdown.js +411 -0
- package/dist/output/sarif.d.ts +160 -0
- package/dist/output/sarif.d.ts.map +1 -0
- package/dist/output/sarif.js +207 -0
- package/dist/policy/evaluator.d.ts +111 -0
- package/dist/policy/evaluator.d.ts.map +1 -0
- package/dist/policy/evaluator.js +362 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +11 -0
- package/dist/policy/loader.d.ts +97 -0
- package/dist/policy/loader.d.ts.map +1 -0
- package/dist/policy/loader.js +281 -0
- package/dist/policy/schema.d.ts +297 -0
- package/dist/policy/schema.d.ts.map +1 -0
- package/dist/policy/schema.js +230 -0
- package/dist/quality-gate/evaluator.d.ts +58 -0
- package/dist/quality-gate/evaluator.d.ts.map +1 -0
- package/dist/quality-gate/evaluator.js +274 -0
- package/dist/quality-gate/index.d.ts +10 -0
- package/dist/quality-gate/index.d.ts.map +1 -0
- package/dist/quality-gate/index.js +7 -0
- package/dist/quality-gate/types.d.ts +103 -0
- package/dist/quality-gate/types.d.ts.map +1 -0
- package/dist/quality-gate/types.js +23 -0
- package/dist/templates/azure-devops.d.ts +25 -0
- package/dist/templates/azure-devops.d.ts.map +1 -0
- package/dist/templates/azure-devops.js +109 -0
- package/dist/templates/circleci.d.ts +28 -0
- package/dist/templates/circleci.d.ts.map +1 -0
- package/dist/templates/circleci.js +86 -0
- package/dist/templates/github-actions.d.ts +81 -0
- package/dist/templates/github-actions.d.ts.map +1 -0
- package/dist/templates/github-actions.js +393 -0
- package/dist/templates/gitlab-ci.d.ts +26 -0
- package/dist/templates/gitlab-ci.d.ts.map +1 -0
- package/dist/templates/gitlab-ci.js +70 -0
- package/dist/templates/index.d.ts +72 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +112 -0
- package/dist/templates/jenkins.d.ts +26 -0
- package/dist/templates/jenkins.d.ts.map +1 -0
- package/dist/templates/jenkins.js +110 -0
- package/dist/ui/banner.d.ts +31 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +84 -0
- package/dist/ui/diagnostics.d.ts +39 -0
- package/dist/ui/diagnostics.d.ts.map +1 -0
- package/dist/ui/diagnostics.js +153 -0
- package/dist/ui/spinner.d.ts +61 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +101 -0
- package/dist/ui/table.d.ts +63 -0
- package/dist/ui/table.d.ts.map +1 -0
- package/dist/ui/table.js +236 -0
- package/dist/utils/client.d.ts +82 -0
- package/dist/utils/client.d.ts.map +1 -0
- package/dist/utils/client.js +128 -0
- package/dist/utils/detect-env.d.ts +59 -0
- package/dist/utils/detect-env.d.ts.map +1 -0
- package/dist/utils/detect-env.js +115 -0
- package/dist/utils/exit-codes.d.ts +47 -0
- package/dist/utils/exit-codes.d.ts.map +1 -0
- package/dist/utils/exit-codes.js +61 -0
- package/dist/utils/logger.d.ts +87 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +185 -0
- package/dist/utils/sanitize.d.ts +36 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +64 -0
- package/dist/utils/validators.d.ts +41 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +123 -0
- package/package.json +63 -0
- package/schemas/vertaaux.config.schema.json +103 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy module for VertaaUX CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides policy-as-code support for organizations to define
|
|
5
|
+
* quality standards committed to the repository.
|
|
6
|
+
*
|
|
7
|
+
* Implements CICD-17: Policy-as-code support.
|
|
8
|
+
*/
|
|
9
|
+
export { policyJsonSchema, DEFAULT_POLICY, POLICY_TEMPLATES, } from "./schema.js";
|
|
10
|
+
export { loadPolicy, loadPolicyFile, validatePolicy, resolveBranchPolicy, getEffectivePolicy, PolicyValidationError, PolicyLoadError, } from "./loader.js";
|
|
11
|
+
export { evaluatePolicy, applyRuleOverrides, filterExcludedPaths, formatPolicyResult, } from "./evaluator.js";
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy file loader and validator.
|
|
3
|
+
*
|
|
4
|
+
* Loads policy files from standard locations and validates
|
|
5
|
+
* against JSON Schema. Supports branch-specific overrides.
|
|
6
|
+
*
|
|
7
|
+
* Implements CICD-17: Policy-as-code support.
|
|
8
|
+
*/
|
|
9
|
+
import type { PolicyFile } from "./schema.js";
|
|
10
|
+
/**
|
|
11
|
+
* Result of policy loading.
|
|
12
|
+
*/
|
|
13
|
+
export interface PolicyLoadResult {
|
|
14
|
+
/** The loaded policy (or default if none found) */
|
|
15
|
+
policy: PolicyFile;
|
|
16
|
+
/** Path to the policy file (null if using defaults) */
|
|
17
|
+
path: string | null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of policy validation.
|
|
21
|
+
*/
|
|
22
|
+
export interface PolicyValidationResult {
|
|
23
|
+
/** Whether the policy is valid */
|
|
24
|
+
valid: boolean;
|
|
25
|
+
/** Validation error messages (empty if valid) */
|
|
26
|
+
errors: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Error thrown when policy validation fails.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PolicyValidationError extends Error {
|
|
32
|
+
readonly errors: string[];
|
|
33
|
+
constructor(errors: string[], filePath?: string);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Error thrown when policy file cannot be loaded.
|
|
37
|
+
*/
|
|
38
|
+
export declare class PolicyLoadError extends Error {
|
|
39
|
+
readonly cause?: unknown | undefined;
|
|
40
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate a policy object against the JSON Schema.
|
|
44
|
+
*
|
|
45
|
+
* @param policy - Policy object to validate
|
|
46
|
+
* @returns Validation result with errors if invalid
|
|
47
|
+
*/
|
|
48
|
+
export declare function validatePolicy(policy: unknown): PolicyValidationResult;
|
|
49
|
+
/**
|
|
50
|
+
* Load policy file from a specific path.
|
|
51
|
+
*
|
|
52
|
+
* @param filePath - Path to policy file
|
|
53
|
+
* @returns Loaded and validated policy
|
|
54
|
+
* @throws PolicyLoadError if file cannot be read or parsed
|
|
55
|
+
* @throws PolicyValidationError if policy fails validation
|
|
56
|
+
*/
|
|
57
|
+
export declare function loadPolicyFile(filePath: string): Promise<PolicyFile>;
|
|
58
|
+
/**
|
|
59
|
+
* Load policy file from project root.
|
|
60
|
+
*
|
|
61
|
+
* Searches for policy file in standard locations:
|
|
62
|
+
* 1. vertaa.policy.yml
|
|
63
|
+
* 2. vertaa.policy.yaml
|
|
64
|
+
* 3. .vertaa.policy.yml
|
|
65
|
+
* 4. .vertaaux/policy.yml
|
|
66
|
+
*
|
|
67
|
+
* Returns default policy if none found.
|
|
68
|
+
*
|
|
69
|
+
* @param projectRoot - Root directory to search from (defaults to cwd)
|
|
70
|
+
* @returns Loaded policy and path (or null path if using defaults)
|
|
71
|
+
*/
|
|
72
|
+
export declare function loadPolicy(projectRoot?: string): Promise<PolicyLoadResult>;
|
|
73
|
+
/**
|
|
74
|
+
* Resolve policy with branch-specific overrides.
|
|
75
|
+
*
|
|
76
|
+
* Looks for matching branch in policy.branches and merges
|
|
77
|
+
* branch-specific assertions with base assertions.
|
|
78
|
+
*
|
|
79
|
+
* @param policy - Base policy
|
|
80
|
+
* @param branch - Current branch name
|
|
81
|
+
* @returns Policy with branch-specific overrides applied
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveBranchPolicy(policy: PolicyFile, branch: string): PolicyFile;
|
|
84
|
+
/**
|
|
85
|
+
* Get the effective policy for the current context.
|
|
86
|
+
*
|
|
87
|
+
* Convenience function that loads policy and resolves branch overrides.
|
|
88
|
+
*
|
|
89
|
+
* @param options - Loading options
|
|
90
|
+
* @returns Effective policy for the current branch
|
|
91
|
+
*/
|
|
92
|
+
export declare function getEffectivePolicy(options?: {
|
|
93
|
+
projectRoot?: string;
|
|
94
|
+
branch?: string;
|
|
95
|
+
policyPath?: string;
|
|
96
|
+
}): Promise<PolicyLoadResult>;
|
|
97
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/policy/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAkC,MAAM,aAAa,CAAC;AAa9E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,MAAM,EAAE,UAAU,CAAC;IACnB,uDAAuD;IACvD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,kCAAkC;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,iDAAiD;IACjD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,MAAM,EAAE,MAAM,EAAE;gBAAhB,MAAM,EAAE,MAAM,EAAE,EAChC,QAAQ,CAAC,EAAE,MAAM;CAQpB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,KAAK,CAAC,EAAE,OAAO;gBAD/B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AA+BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,sBAAsB,CAWtE;AAoBD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmB1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8BhF;AAyED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,GACb,UAAU,CA+BZ;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAY5B"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy file loader and validator.
|
|
3
|
+
*
|
|
4
|
+
* Loads policy files from standard locations and validates
|
|
5
|
+
* against JSON Schema. Supports branch-specific overrides.
|
|
6
|
+
*
|
|
7
|
+
* Implements CICD-17: Policy-as-code support.
|
|
8
|
+
*/
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import yaml from "yaml";
|
|
12
|
+
import Ajv from "ajv";
|
|
13
|
+
import { policyJsonSchema, DEFAULT_POLICY } from "./schema.js";
|
|
14
|
+
/**
|
|
15
|
+
* Standard policy file locations, searched in order.
|
|
16
|
+
*/
|
|
17
|
+
const POLICY_FILES = [
|
|
18
|
+
"vertaa.policy.yml",
|
|
19
|
+
"vertaa.policy.yaml",
|
|
20
|
+
".vertaa.policy.yml",
|
|
21
|
+
".vertaaux/policy.yml",
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Error thrown when policy validation fails.
|
|
25
|
+
*/
|
|
26
|
+
export class PolicyValidationError extends Error {
|
|
27
|
+
errors;
|
|
28
|
+
constructor(errors, filePath) {
|
|
29
|
+
const errorMessages = errors.map((e) => ` - ${e}`).join("\n");
|
|
30
|
+
super(`Invalid policy file${filePath ? ` (${filePath})` : ""}:\n${errorMessages}`);
|
|
31
|
+
this.errors = errors;
|
|
32
|
+
this.name = "PolicyValidationError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Error thrown when policy file cannot be loaded.
|
|
37
|
+
*/
|
|
38
|
+
export class PolicyLoadError extends Error {
|
|
39
|
+
cause;
|
|
40
|
+
constructor(message, cause) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.cause = cause;
|
|
43
|
+
this.name = "PolicyLoadError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Create Ajv validator instance
|
|
47
|
+
const ajv = new Ajv({ strict: false, allErrors: true });
|
|
48
|
+
const validateSchema = ajv.compile(policyJsonSchema);
|
|
49
|
+
/**
|
|
50
|
+
* Format Ajv errors into human-readable messages.
|
|
51
|
+
*/
|
|
52
|
+
function formatAjvErrors(errors) {
|
|
53
|
+
if (!errors)
|
|
54
|
+
return [];
|
|
55
|
+
return errors.map((e) => {
|
|
56
|
+
const path = e.instancePath || "root";
|
|
57
|
+
const message = e.message || "unknown error";
|
|
58
|
+
// Add more context for common errors
|
|
59
|
+
if (e.keyword === "enum") {
|
|
60
|
+
const allowed = e.params.allowedValues;
|
|
61
|
+
return `${path}: ${message}. Allowed values: ${allowed?.join(", ")}`;
|
|
62
|
+
}
|
|
63
|
+
if (e.keyword === "additionalProperties") {
|
|
64
|
+
const prop = e.params.additionalProperty;
|
|
65
|
+
return `${path}: unknown property '${prop}'`;
|
|
66
|
+
}
|
|
67
|
+
return `${path}: ${message}`;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate a policy object against the JSON Schema.
|
|
72
|
+
*
|
|
73
|
+
* @param policy - Policy object to validate
|
|
74
|
+
* @returns Validation result with errors if invalid
|
|
75
|
+
*/
|
|
76
|
+
export function validatePolicy(policy) {
|
|
77
|
+
const valid = validateSchema(policy);
|
|
78
|
+
if (valid) {
|
|
79
|
+
return { valid: true, errors: [] };
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
valid: false,
|
|
83
|
+
errors: formatAjvErrors(validateSchema.errors),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse YAML content into a policy object.
|
|
88
|
+
*
|
|
89
|
+
* @param content - YAML string content
|
|
90
|
+
* @param filePath - File path for error messages
|
|
91
|
+
* @returns Parsed policy object
|
|
92
|
+
*/
|
|
93
|
+
function parseYaml(content, filePath) {
|
|
94
|
+
try {
|
|
95
|
+
return yaml.parse(content);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
throw new PolicyLoadError(`Failed to parse YAML in ${filePath}: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Load policy file from a specific path.
|
|
103
|
+
*
|
|
104
|
+
* @param filePath - Path to policy file
|
|
105
|
+
* @returns Loaded and validated policy
|
|
106
|
+
* @throws PolicyLoadError if file cannot be read or parsed
|
|
107
|
+
* @throws PolicyValidationError if policy fails validation
|
|
108
|
+
*/
|
|
109
|
+
export async function loadPolicyFile(filePath) {
|
|
110
|
+
const absolutePath = path.resolve(process.cwd(), filePath);
|
|
111
|
+
// Check file exists
|
|
112
|
+
if (!fs.existsSync(absolutePath)) {
|
|
113
|
+
throw new PolicyLoadError(`Policy file not found: ${absolutePath}`);
|
|
114
|
+
}
|
|
115
|
+
// Read and parse
|
|
116
|
+
const content = fs.readFileSync(absolutePath, "utf-8");
|
|
117
|
+
const parsed = parseYaml(content, absolutePath);
|
|
118
|
+
// Validate
|
|
119
|
+
const validation = validatePolicy(parsed);
|
|
120
|
+
if (!validation.valid) {
|
|
121
|
+
throw new PolicyValidationError(validation.errors, absolutePath);
|
|
122
|
+
}
|
|
123
|
+
return parsed;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load policy file from project root.
|
|
127
|
+
*
|
|
128
|
+
* Searches for policy file in standard locations:
|
|
129
|
+
* 1. vertaa.policy.yml
|
|
130
|
+
* 2. vertaa.policy.yaml
|
|
131
|
+
* 3. .vertaa.policy.yml
|
|
132
|
+
* 4. .vertaaux/policy.yml
|
|
133
|
+
*
|
|
134
|
+
* Returns default policy if none found.
|
|
135
|
+
*
|
|
136
|
+
* @param projectRoot - Root directory to search from (defaults to cwd)
|
|
137
|
+
* @returns Loaded policy and path (or null path if using defaults)
|
|
138
|
+
*/
|
|
139
|
+
export async function loadPolicy(projectRoot) {
|
|
140
|
+
const root = projectRoot || process.cwd();
|
|
141
|
+
// Search for policy file in standard locations
|
|
142
|
+
for (const filename of POLICY_FILES) {
|
|
143
|
+
const filePath = path.join(root, filename);
|
|
144
|
+
if (fs.existsSync(filePath)) {
|
|
145
|
+
try {
|
|
146
|
+
const policy = await loadPolicyFile(filePath);
|
|
147
|
+
return { policy, path: filePath };
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
// Re-throw validation and load errors
|
|
151
|
+
if (error instanceof PolicyValidationError ||
|
|
152
|
+
error instanceof PolicyLoadError) {
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
// Wrap unexpected errors
|
|
156
|
+
throw new PolicyLoadError(`Failed to load policy from ${filePath}: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// No policy file found, return defaults
|
|
161
|
+
return { policy: { ...DEFAULT_POLICY }, path: null };
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check if a branch matches a pattern.
|
|
165
|
+
*
|
|
166
|
+
* Supports simple glob patterns:
|
|
167
|
+
* - Exact match: "main"
|
|
168
|
+
* - Wildcard suffix: "release/*"
|
|
169
|
+
* - Wildcard prefix: "* /hotfix"
|
|
170
|
+
* - Full match: "*"
|
|
171
|
+
*
|
|
172
|
+
* @param branch - Branch name to check
|
|
173
|
+
* @param pattern - Pattern to match against
|
|
174
|
+
* @returns Whether the branch matches the pattern
|
|
175
|
+
*/
|
|
176
|
+
function matchBranch(branch, pattern) {
|
|
177
|
+
// Exact match
|
|
178
|
+
if (pattern === branch)
|
|
179
|
+
return true;
|
|
180
|
+
// Full wildcard
|
|
181
|
+
if (pattern === "*")
|
|
182
|
+
return true;
|
|
183
|
+
// Wildcard suffix: "release/*" matches "release/1.0"
|
|
184
|
+
if (pattern.endsWith("/*")) {
|
|
185
|
+
const prefix = pattern.slice(0, -2);
|
|
186
|
+
return branch.startsWith(prefix + "/");
|
|
187
|
+
}
|
|
188
|
+
// Wildcard prefix: "*/hotfix" matches "feature/hotfix"
|
|
189
|
+
if (pattern.startsWith("*/")) {
|
|
190
|
+
const suffix = pattern.slice(2);
|
|
191
|
+
return branch.endsWith("/" + suffix);
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Deep merge two assertion objects.
|
|
197
|
+
*
|
|
198
|
+
* Override values take precedence over base values.
|
|
199
|
+
* Undefined values in override do not overwrite base values.
|
|
200
|
+
*/
|
|
201
|
+
function mergeAssertions(base, override) {
|
|
202
|
+
return {
|
|
203
|
+
...base,
|
|
204
|
+
// Only override defined values
|
|
205
|
+
...(override.overall_score !== undefined && {
|
|
206
|
+
overall_score: override.overall_score,
|
|
207
|
+
}),
|
|
208
|
+
...(override.accessibility_score !== undefined && {
|
|
209
|
+
accessibility_score: override.accessibility_score,
|
|
210
|
+
}),
|
|
211
|
+
...(override.ux_score !== undefined && { ux_score: override.ux_score }),
|
|
212
|
+
...(override.performance_score !== undefined && {
|
|
213
|
+
performance_score: override.performance_score,
|
|
214
|
+
}),
|
|
215
|
+
...(override.fail_on !== undefined && { fail_on: override.fail_on }),
|
|
216
|
+
...(override.max_new_errors !== undefined && {
|
|
217
|
+
max_new_errors: override.max_new_errors,
|
|
218
|
+
}),
|
|
219
|
+
...(override.max_new_warnings !== undefined && {
|
|
220
|
+
max_new_warnings: override.max_new_warnings,
|
|
221
|
+
}),
|
|
222
|
+
...(override.max_new_total !== undefined && {
|
|
223
|
+
max_new_total: override.max_new_total,
|
|
224
|
+
}),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Resolve policy with branch-specific overrides.
|
|
229
|
+
*
|
|
230
|
+
* Looks for matching branch in policy.branches and merges
|
|
231
|
+
* branch-specific assertions with base assertions.
|
|
232
|
+
*
|
|
233
|
+
* @param policy - Base policy
|
|
234
|
+
* @param branch - Current branch name
|
|
235
|
+
* @returns Policy with branch-specific overrides applied
|
|
236
|
+
*/
|
|
237
|
+
export function resolveBranchPolicy(policy, branch) {
|
|
238
|
+
// No branches configured
|
|
239
|
+
if (!policy.branches || !branch) {
|
|
240
|
+
return policy;
|
|
241
|
+
}
|
|
242
|
+
// Find matching branch config
|
|
243
|
+
let matchedConfig;
|
|
244
|
+
let matchedKey;
|
|
245
|
+
for (const [key, config] of Object.entries(policy.branches)) {
|
|
246
|
+
// Use pattern if specified, otherwise use key as exact match
|
|
247
|
+
const pattern = config.pattern || key;
|
|
248
|
+
if (matchBranch(branch, pattern)) {
|
|
249
|
+
matchedConfig = config;
|
|
250
|
+
matchedKey = key;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// No matching branch
|
|
255
|
+
if (!matchedConfig || !matchedConfig.assertions) {
|
|
256
|
+
return policy;
|
|
257
|
+
}
|
|
258
|
+
// Merge assertions
|
|
259
|
+
return {
|
|
260
|
+
...policy,
|
|
261
|
+
assertions: mergeAssertions(policy.assertions, matchedConfig.assertions),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get the effective policy for the current context.
|
|
266
|
+
*
|
|
267
|
+
* Convenience function that loads policy and resolves branch overrides.
|
|
268
|
+
*
|
|
269
|
+
* @param options - Loading options
|
|
270
|
+
* @returns Effective policy for the current branch
|
|
271
|
+
*/
|
|
272
|
+
export async function getEffectivePolicy(options) {
|
|
273
|
+
const { projectRoot, branch, policyPath } = options || {};
|
|
274
|
+
// Load from specific path or search
|
|
275
|
+
const { policy, path: foundPath } = policyPath
|
|
276
|
+
? { policy: await loadPolicyFile(policyPath), path: policyPath }
|
|
277
|
+
: await loadPolicy(projectRoot);
|
|
278
|
+
// Resolve branch overrides if branch is known
|
|
279
|
+
const resolved = branch ? resolveBranchPolicy(policy, branch) : policy;
|
|
280
|
+
return { policy: resolved, path: foundPath };
|
|
281
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy file schema for vertaa.policy.yml.
|
|
3
|
+
*
|
|
4
|
+
* Enables policy-as-code for organizations to define:
|
|
5
|
+
* - Quality thresholds and assertions
|
|
6
|
+
* - Rule severity overrides
|
|
7
|
+
* - Branch-specific policies
|
|
8
|
+
* - Bypass labels for emergency deploys
|
|
9
|
+
*
|
|
10
|
+
* Modeled on Semgrep/ESLint policy patterns.
|
|
11
|
+
*
|
|
12
|
+
* Implements CICD-17: Policy-as-code support.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Policy file structure for vertaa.policy.yml.
|
|
16
|
+
*/
|
|
17
|
+
export interface PolicyFile {
|
|
18
|
+
/** JSON Schema reference for IDE support */
|
|
19
|
+
$schema?: string;
|
|
20
|
+
/** Policy format version */
|
|
21
|
+
version: 1;
|
|
22
|
+
/** Human-readable policy name */
|
|
23
|
+
name?: string;
|
|
24
|
+
/** Policy description */
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Threshold assertions - fail if not met */
|
|
27
|
+
assertions: PolicyAssertions;
|
|
28
|
+
/** Rule-specific customizations */
|
|
29
|
+
rules?: Record<string, RuleOverride>;
|
|
30
|
+
/** Branch-specific policy overrides */
|
|
31
|
+
branches?: Record<string, BranchPolicy>;
|
|
32
|
+
/** Labels that bypass quality gate */
|
|
33
|
+
bypass_labels?: string[];
|
|
34
|
+
/** Paths to exclude from auditing */
|
|
35
|
+
exclude_paths?: string[];
|
|
36
|
+
/** Required minimum CLI version */
|
|
37
|
+
required_version?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Policy assertions that must pass for the gate to pass.
|
|
41
|
+
*/
|
|
42
|
+
export interface PolicyAssertions {
|
|
43
|
+
/** Minimum overall score (0-100) */
|
|
44
|
+
overall_score?: number;
|
|
45
|
+
/** Minimum accessibility score */
|
|
46
|
+
accessibility_score?: number;
|
|
47
|
+
/** Minimum UX score */
|
|
48
|
+
ux_score?: number;
|
|
49
|
+
/** Minimum performance score */
|
|
50
|
+
performance_score?: number;
|
|
51
|
+
/** Fail on issues at or above this severity */
|
|
52
|
+
fail_on?: "error" | "warning" | "info";
|
|
53
|
+
/** Maximum new error-severity issues allowed */
|
|
54
|
+
max_new_errors?: number;
|
|
55
|
+
/** Maximum new warning-severity issues allowed */
|
|
56
|
+
max_new_warnings?: number;
|
|
57
|
+
/** Maximum total new issues allowed */
|
|
58
|
+
max_new_total?: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Rule-specific override configuration.
|
|
62
|
+
*/
|
|
63
|
+
export interface RuleOverride {
|
|
64
|
+
/** Override severity: error, warning, info, or ignore */
|
|
65
|
+
severity: "error" | "warning" | "info" | "ignore";
|
|
66
|
+
/** Reason for override (for audit trail) */
|
|
67
|
+
reason?: string;
|
|
68
|
+
/** Override only applies to these paths (glob patterns) */
|
|
69
|
+
paths?: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Branch-specific policy configuration.
|
|
73
|
+
*/
|
|
74
|
+
export interface BranchPolicy {
|
|
75
|
+
/** Branch pattern (glob) - if not specified, uses the branch name as exact match */
|
|
76
|
+
pattern?: string;
|
|
77
|
+
/** Override assertions for this branch */
|
|
78
|
+
assertions?: Partial<PolicyAssertions>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* JSON Schema for vertaa.policy.yml validation.
|
|
82
|
+
*
|
|
83
|
+
* Used for:
|
|
84
|
+
* - Runtime validation with Ajv
|
|
85
|
+
* - IDE autocompletion and validation
|
|
86
|
+
* - Documentation generation
|
|
87
|
+
*/
|
|
88
|
+
export declare const policyJsonSchema: {
|
|
89
|
+
$schema: string;
|
|
90
|
+
$id: string;
|
|
91
|
+
title: string;
|
|
92
|
+
description: string;
|
|
93
|
+
type: string;
|
|
94
|
+
properties: {
|
|
95
|
+
$schema: {
|
|
96
|
+
type: string;
|
|
97
|
+
description: string;
|
|
98
|
+
};
|
|
99
|
+
version: {
|
|
100
|
+
type: string;
|
|
101
|
+
enum: number[];
|
|
102
|
+
description: string;
|
|
103
|
+
};
|
|
104
|
+
name: {
|
|
105
|
+
type: string;
|
|
106
|
+
description: string;
|
|
107
|
+
};
|
|
108
|
+
description: {
|
|
109
|
+
type: string;
|
|
110
|
+
description: string;
|
|
111
|
+
};
|
|
112
|
+
assertions: {
|
|
113
|
+
type: string;
|
|
114
|
+
description: string;
|
|
115
|
+
properties: {
|
|
116
|
+
overall_score: {
|
|
117
|
+
type: string;
|
|
118
|
+
minimum: number;
|
|
119
|
+
maximum: number;
|
|
120
|
+
description: string;
|
|
121
|
+
};
|
|
122
|
+
accessibility_score: {
|
|
123
|
+
type: string;
|
|
124
|
+
minimum: number;
|
|
125
|
+
maximum: number;
|
|
126
|
+
description: string;
|
|
127
|
+
};
|
|
128
|
+
ux_score: {
|
|
129
|
+
type: string;
|
|
130
|
+
minimum: number;
|
|
131
|
+
maximum: number;
|
|
132
|
+
description: string;
|
|
133
|
+
};
|
|
134
|
+
performance_score: {
|
|
135
|
+
type: string;
|
|
136
|
+
minimum: number;
|
|
137
|
+
maximum: number;
|
|
138
|
+
description: string;
|
|
139
|
+
};
|
|
140
|
+
fail_on: {
|
|
141
|
+
type: string;
|
|
142
|
+
enum: string[];
|
|
143
|
+
description: string;
|
|
144
|
+
};
|
|
145
|
+
max_new_errors: {
|
|
146
|
+
type: string;
|
|
147
|
+
minimum: number;
|
|
148
|
+
description: string;
|
|
149
|
+
};
|
|
150
|
+
max_new_warnings: {
|
|
151
|
+
type: string;
|
|
152
|
+
minimum: number;
|
|
153
|
+
description: string;
|
|
154
|
+
};
|
|
155
|
+
max_new_total: {
|
|
156
|
+
type: string;
|
|
157
|
+
minimum: number;
|
|
158
|
+
description: string;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
additionalProperties: boolean;
|
|
162
|
+
};
|
|
163
|
+
rules: {
|
|
164
|
+
type: string;
|
|
165
|
+
description: string;
|
|
166
|
+
additionalProperties: {
|
|
167
|
+
type: string;
|
|
168
|
+
properties: {
|
|
169
|
+
severity: {
|
|
170
|
+
type: string;
|
|
171
|
+
enum: string[];
|
|
172
|
+
description: string;
|
|
173
|
+
};
|
|
174
|
+
reason: {
|
|
175
|
+
type: string;
|
|
176
|
+
description: string;
|
|
177
|
+
};
|
|
178
|
+
paths: {
|
|
179
|
+
type: string;
|
|
180
|
+
items: {
|
|
181
|
+
type: string;
|
|
182
|
+
};
|
|
183
|
+
description: string;
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
required: string[];
|
|
187
|
+
additionalProperties: boolean;
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
branches: {
|
|
191
|
+
type: string;
|
|
192
|
+
description: string;
|
|
193
|
+
additionalProperties: {
|
|
194
|
+
type: string;
|
|
195
|
+
properties: {
|
|
196
|
+
pattern: {
|
|
197
|
+
type: string;
|
|
198
|
+
description: string;
|
|
199
|
+
};
|
|
200
|
+
assertions: {
|
|
201
|
+
$ref: string;
|
|
202
|
+
description: string;
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
additionalProperties: boolean;
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
bypass_labels: {
|
|
209
|
+
type: string;
|
|
210
|
+
items: {
|
|
211
|
+
type: string;
|
|
212
|
+
};
|
|
213
|
+
description: string;
|
|
214
|
+
};
|
|
215
|
+
exclude_paths: {
|
|
216
|
+
type: string;
|
|
217
|
+
items: {
|
|
218
|
+
type: string;
|
|
219
|
+
};
|
|
220
|
+
description: string;
|
|
221
|
+
};
|
|
222
|
+
required_version: {
|
|
223
|
+
type: string;
|
|
224
|
+
description: string;
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
required: string[];
|
|
228
|
+
additionalProperties: boolean;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Default policy with sensible enterprise defaults.
|
|
232
|
+
*
|
|
233
|
+
* - Only fail on errors (not warnings/info)
|
|
234
|
+
* - Only fail on NEW errors (existing debt allowed)
|
|
235
|
+
* - Common emergency bypass labels
|
|
236
|
+
*/
|
|
237
|
+
export declare const DEFAULT_POLICY: PolicyFile;
|
|
238
|
+
/**
|
|
239
|
+
* Policy templates for different strictness levels.
|
|
240
|
+
*/
|
|
241
|
+
export declare const POLICY_TEMPLATES: {
|
|
242
|
+
/**
|
|
243
|
+
* Basic template - fail only on new errors.
|
|
244
|
+
*/
|
|
245
|
+
basic: {
|
|
246
|
+
version: 1;
|
|
247
|
+
name: string;
|
|
248
|
+
description: string;
|
|
249
|
+
assertions: {
|
|
250
|
+
fail_on: "error";
|
|
251
|
+
max_new_errors: number;
|
|
252
|
+
};
|
|
253
|
+
bypass_labels: string[];
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Strict template - fail on warnings, require minimum scores.
|
|
257
|
+
*/
|
|
258
|
+
strict: {
|
|
259
|
+
version: 1;
|
|
260
|
+
name: string;
|
|
261
|
+
description: string;
|
|
262
|
+
assertions: {
|
|
263
|
+
fail_on: "warning";
|
|
264
|
+
overall_score: number;
|
|
265
|
+
max_new_errors: number;
|
|
266
|
+
max_new_warnings: number;
|
|
267
|
+
};
|
|
268
|
+
branches: {
|
|
269
|
+
main: {
|
|
270
|
+
assertions: {
|
|
271
|
+
overall_score: number;
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
"release/*": {
|
|
275
|
+
pattern: string;
|
|
276
|
+
assertions: {
|
|
277
|
+
overall_score: number;
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
bypass_labels: string[];
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Lenient template - fail only on critical errors.
|
|
285
|
+
*/
|
|
286
|
+
lenient: {
|
|
287
|
+
version: 1;
|
|
288
|
+
name: string;
|
|
289
|
+
description: string;
|
|
290
|
+
assertions: {
|
|
291
|
+
fail_on: "error";
|
|
292
|
+
};
|
|
293
|
+
bypass_labels: string[];
|
|
294
|
+
};
|
|
295
|
+
};
|
|
296
|
+
export type PolicyTemplate = keyof typeof POLICY_TEMPLATES;
|
|
297
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/policy/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,4BAA4B;IAC5B,OAAO,EAAE,CAAC,CAAC;IAEX,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6CAA6C;IAC7C,UAAU,EAAE,gBAAgB,CAAC;IAE7B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAErC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAExC,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,kCAAkC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,gCAAgC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAEvC,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAElD,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0I5B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,UAO5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;OAEG;;;;;;;;;;;IAYH;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BH;;OAEG;;;;;;;;;;CAUiC,CAAC;AAEvC,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,gBAAgB,CAAC"}
|