@probelabs/visor 0.1.129 → 0.1.130
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 +23 -0
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/docs/author-permissions.md +20 -0
- package/dist/docs/enterprise-policy.md +1325 -0
- package/dist/docs/index.md +10 -0
- package/dist/docs/scheduler-storage.md +433 -0
- package/dist/docs/scheduler.md +12 -2
- package/dist/enterprise/license/validator.d.ts +39 -0
- package/dist/enterprise/license/validator.d.ts.map +1 -0
- package/dist/enterprise/loader.d.ts +25 -0
- package/dist/enterprise/loader.d.ts.map +1 -0
- package/dist/enterprise/policy/opa-compiler.d.ts +37 -0
- package/dist/enterprise/policy/opa-compiler.d.ts.map +1 -0
- package/dist/enterprise/policy/opa-http-evaluator.d.ts +36 -0
- package/dist/enterprise/policy/opa-http-evaluator.d.ts.map +1 -0
- package/dist/enterprise/policy/opa-policy-engine.d.ts +48 -0
- package/dist/enterprise/policy/opa-policy-engine.d.ts.map +1 -0
- package/dist/enterprise/policy/opa-wasm-evaluator.d.ts +34 -0
- package/dist/enterprise/policy/opa-wasm-evaluator.d.ts.map +1 -0
- package/dist/enterprise/policy/policy-input-builder.d.ts +120 -0
- package/dist/enterprise/policy/policy-input-builder.d.ts.map +1 -0
- package/dist/enterprise/scheduler/knex-store.d.ts +41 -0
- package/dist/enterprise/scheduler/knex-store.d.ts.map +1 -0
- package/dist/examples/README.md +23 -0
- package/dist/examples/enterprise-policy/README.md +344 -0
- package/dist/examples/enterprise-policy/policies/capability_resolve.rego +29 -0
- package/dist/examples/enterprise-policy/policies/capability_resolve_test.rego +230 -0
- package/dist/examples/enterprise-policy/policies/check_execute.rego +71 -0
- package/dist/examples/enterprise-policy/policies/check_execute_test.rego +321 -0
- package/dist/examples/enterprise-policy/policies/deploy_production.rego +33 -0
- package/dist/examples/enterprise-policy/policies/deploy_production_test.rego +29 -0
- package/dist/examples/enterprise-policy/policies/slack_channel_gate.rego +17 -0
- package/dist/examples/enterprise-policy/policies/slack_tool_restrict.rego +16 -0
- package/dist/examples/enterprise-policy/policies/tool_invoke.rego +24 -0
- package/dist/examples/enterprise-policy/policies/tool_invoke_test.rego +227 -0
- package/dist/examples/enterprise-policy/visor.yaml +64 -0
- package/dist/failure-condition-evaluator.d.ts +18 -0
- package/dist/failure-condition-evaluator.d.ts.map +1 -1
- package/dist/frontends/slack-frontend.d.ts +1 -0
- package/dist/frontends/slack-frontend.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +139 -0
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/index.js +12121 -7169
- package/dist/liquid-extensions.d.ts.map +1 -1
- package/dist/output/traces/{run-2026-02-08T18-16-04-160Z.ndjson → run-2026-02-11T16-20-59-999Z.ndjson} +84 -84
- package/dist/{traces/run-2026-02-08T18-16-51-253Z.ndjson → output/traces/run-2026-02-11T16-21-47-711Z.ndjson} +1032 -1032
- package/dist/policy/default-engine.d.ts +17 -0
- package/dist/policy/default-engine.d.ts.map +1 -0
- package/dist/policy/index.d.ts +4 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/policy-check-command.d.ts +65 -0
- package/dist/policy/policy-check-command.d.ts.map +1 -0
- package/dist/policy/types.d.ts +81 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/check-provider.interface.d.ts +2 -0
- package/dist/providers/check-provider.interface.d.ts.map +1 -1
- package/dist/providers/claude-code-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
- package/dist/providers/workflow-check-provider.d.ts.map +1 -1
- package/dist/scheduler/index.d.ts +2 -0
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/schedule-store.d.ts +33 -59
- package/dist/scheduler/schedule-store.d.ts.map +1 -1
- package/dist/scheduler/schedule-tool.d.ts.map +1 -1
- package/dist/scheduler/scheduler.d.ts +24 -3
- package/dist/scheduler/scheduler.d.ts.map +1 -1
- package/dist/scheduler/store/index.d.ts +7 -0
- package/dist/scheduler/store/index.d.ts.map +1 -0
- package/dist/scheduler/store/json-migrator.d.ts +10 -0
- package/dist/scheduler/store/json-migrator.d.ts.map +1 -0
- package/dist/scheduler/store/sqlite-store.d.ts +32 -0
- package/dist/scheduler/store/sqlite-store.d.ts.map +1 -0
- package/dist/scheduler/store/types.d.ts +127 -0
- package/dist/scheduler/store/types.d.ts.map +1 -0
- package/dist/sdk/check-provider-registry-M3Y6JMTW.mjs +28 -0
- package/dist/sdk/check-provider-registry-PANIXYRB.mjs +28 -0
- package/dist/sdk/{chunk-D5KI4YQ4.mjs → chunk-DIND4ZCV.mjs} +2 -2
- package/dist/sdk/{chunk-DGZPPGJJ.mjs → chunk-EUUAQBTW.mjs} +1463 -568
- package/dist/sdk/chunk-EUUAQBTW.mjs.map +1 -0
- package/dist/sdk/{chunk-XDLQ3UNF.mjs → chunk-GEW6LS32.mjs} +2 -2
- package/dist/sdk/{chunk-N7HO6KKC.mjs → chunk-HOKQOO3G.mjs} +11 -6
- package/dist/sdk/chunk-HOKQOO3G.mjs.map +1 -0
- package/dist/sdk/{chunk-XR7XXGL7.mjs → chunk-JL7JXCET.mjs} +2 -2
- package/dist/sdk/{chunk-6W75IMDC.mjs → chunk-LG4AUKHB.mjs} +2 -2
- package/dist/sdk/{chunk-BDGUM6BA.mjs → chunk-S6CD7GFM.mjs} +1463 -568
- package/dist/sdk/chunk-S6CD7GFM.mjs.map +1 -0
- package/dist/sdk/{chunk-PO7X5XI7.mjs → chunk-SZXICFQ3.mjs} +2 -2
- package/dist/sdk/{chunk-HEX3RL32.mjs → chunk-UCMJJ3IM.mjs} +5 -2
- package/dist/sdk/{chunk-HEX3RL32.mjs.map → chunk-UCMJJ3IM.mjs.map} +1 -1
- package/dist/sdk/{chunk-7YSOINAQ.mjs → chunk-UCNT3PDT.mjs} +342 -5
- package/dist/sdk/chunk-UCNT3PDT.mjs.map +1 -0
- package/dist/sdk/{chunk-R5Z7YWPB.mjs → chunk-V2IV3ILA.mjs} +7 -5
- package/dist/sdk/chunk-V2IV3ILA.mjs.map +1 -0
- package/dist/sdk/{chunk-SGS2VMEL.mjs → chunk-VMLORODQ.mjs} +107 -20
- package/dist/sdk/chunk-VMLORODQ.mjs.map +1 -0
- package/dist/sdk/{chunk-2KB35MB7.mjs → chunk-VPC3QSPW.mjs} +2 -2
- package/dist/sdk/{chunk-J5RGJQ53.mjs → chunk-YJRBN3XS.mjs} +2 -2
- package/dist/sdk/{command-executor-DVVXERLR.mjs → command-executor-TOYBBE7S.mjs} +4 -4
- package/dist/sdk/{config-7VTT64SQ.mjs → config-OGOS4ZU4.mjs} +4 -4
- package/dist/sdk/failure-condition-evaluator-HC3M5377.mjs +17 -0
- package/dist/sdk/{github-frontend-3N2NLO66.mjs → github-frontend-E2KJSC3Y.mjs} +7 -7
- package/dist/sdk/{host-ONVMEHAA.mjs → host-EE6EJ2FM.mjs} +4 -4
- package/dist/sdk/lazy-otel-5NH4ZJJM.mjs +24 -0
- package/dist/sdk/{liquid-extensions-5IZLTFSZ.mjs → liquid-extensions-E4EUOCES.mjs} +5 -5
- package/dist/sdk/memory-store-AAPL2MTE.mjs +12 -0
- package/dist/sdk/{metrics-GXQ2EDXA.mjs → metrics-I6A7IHG4.mjs} +3 -3
- package/dist/sdk/{prompt-state-YHGXB2OA.mjs → prompt-state-VAKKC773.mjs} +4 -4
- package/dist/sdk/{renderer-schema-CMXOLNIG.mjs → renderer-schema-HXEW6BRJ.mjs} +3 -3
- package/dist/sdk/{routing-S3Y7T2X3.mjs → routing-OZQWAGAI.mjs} +9 -8
- package/dist/sdk/schedule-tool-handler-B7TMSG6A.mjs +38 -0
- package/dist/sdk/schedule-tool-handler-IEB2VS7O.mjs +38 -0
- package/dist/sdk/sdk.d.mts +134 -4
- package/dist/sdk/sdk.d.ts +134 -4
- package/dist/sdk/sdk.js +2509 -1085
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +14 -14
- package/dist/sdk/{slack-frontend-R3M2CACB.mjs → slack-frontend-LAY45IBR.mjs} +119 -29
- package/dist/sdk/slack-frontend-LAY45IBR.mjs.map +1 -0
- package/dist/sdk/{trace-helpers-YHNPC7MR.mjs → trace-helpers-PP3YHTAM.mjs} +3 -3
- package/dist/sdk/{tui-frontend-S546M7A7.mjs → tui-frontend-T56PZB67.mjs} +25 -16
- package/dist/sdk/tui-frontend-T56PZB67.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-2ET3SFZH.mjs +28 -0
- package/dist/sdk/workflow-check-provider-2ET3SFZH.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-HB4XTD4Z.mjs +28 -0
- package/dist/sdk/workflow-check-provider-HB4XTD4Z.mjs.map +1 -0
- package/dist/sdk/workflow-registry-AAD37XKZ.mjs +12 -0
- package/dist/sdk/workflow-registry-AAD37XKZ.mjs.map +1 -0
- package/dist/slack/client.d.ts +12 -0
- package/dist/slack/client.d.ts.map +1 -1
- package/dist/slack/slack-output-adapter.d.ts.map +1 -1
- package/dist/slack/socket-runner.d.ts.map +1 -1
- package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -1
- package/dist/state-machine/dispatch/policy-gate.d.ts +28 -0
- package/dist/state-machine/dispatch/policy-gate.d.ts.map +1 -0
- package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
- package/dist/state-machine/states/routing.d.ts.map +1 -1
- package/dist/state-machine/states/wave-planning.d.ts.map +1 -1
- package/dist/state-machine-execution-engine.d.ts.map +1 -1
- package/dist/test-runner/core/flow-stage.d.ts.map +1 -1
- package/dist/test-runner/validator.d.ts.map +1 -1
- package/dist/traces/{run-2026-02-08T18-16-04-160Z.ndjson → run-2026-02-11T16-20-59-999Z.ndjson} +84 -84
- package/dist/{output/traces/run-2026-02-08T18-16-51-253Z.ndjson → traces/run-2026-02-11T16-21-47-711Z.ndjson} +1032 -1032
- package/dist/tui/chat-runner.d.ts.map +1 -1
- package/dist/tui/chat-state.d.ts +1 -0
- package/dist/tui/chat-state.d.ts.map +1 -1
- package/dist/tui/chat-tui.d.ts +3 -2
- package/dist/tui/chat-tui.d.ts.map +1 -1
- package/dist/tui/components/chat-box.d.ts +9 -0
- package/dist/tui/components/chat-box.d.ts.map +1 -1
- package/dist/tui/components/input-bar.d.ts +18 -1
- package/dist/tui/components/input-bar.d.ts.map +1 -1
- package/dist/tui/components/status-bar.d.ts +5 -2
- package/dist/tui/components/status-bar.d.ts.map +1 -1
- package/dist/tui/components/trace-viewer.d.ts +1 -0
- package/dist/tui/components/trace-viewer.d.ts.map +1 -1
- package/dist/tui/tui-frontend.d.ts.map +1 -1
- package/dist/types/config.d.ts +107 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/engine.d.ts +5 -0
- package/dist/types/engine.d.ts.map +1 -1
- package/dist/types/execution.d.ts +1 -1
- package/dist/types/execution.d.ts.map +1 -1
- package/package.json +14 -4
- package/dist/sdk/check-provider-registry-ACRGIYOB.mjs +0 -28
- package/dist/sdk/check-provider-registry-VYHKFHK2.mjs +0 -28
- package/dist/sdk/chunk-7YSOINAQ.mjs.map +0 -1
- package/dist/sdk/chunk-BDGUM6BA.mjs.map +0 -1
- package/dist/sdk/chunk-DGZPPGJJ.mjs.map +0 -1
- package/dist/sdk/chunk-N7HO6KKC.mjs.map +0 -1
- package/dist/sdk/chunk-R5Z7YWPB.mjs.map +0 -1
- package/dist/sdk/chunk-SGS2VMEL.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-4WMDF4Q3.mjs +0 -17
- package/dist/sdk/memory-store-3N4AZCYB.mjs +0 -12
- package/dist/sdk/slack-frontend-R3M2CACB.mjs.map +0 -1
- package/dist/sdk/tui-frontend-S546M7A7.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-4F3432ZP.mjs +0 -28
- package/dist/sdk/workflow-check-provider-A44PBPG2.mjs +0 -28
- package/dist/sdk/workflow-registry-ZAYYXLEP.mjs +0 -12
- /package/dist/sdk/{check-provider-registry-ACRGIYOB.mjs.map → check-provider-registry-M3Y6JMTW.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-VYHKFHK2.mjs.map → check-provider-registry-PANIXYRB.mjs.map} +0 -0
- /package/dist/sdk/{chunk-D5KI4YQ4.mjs.map → chunk-DIND4ZCV.mjs.map} +0 -0
- /package/dist/sdk/{chunk-XDLQ3UNF.mjs.map → chunk-GEW6LS32.mjs.map} +0 -0
- /package/dist/sdk/{chunk-XR7XXGL7.mjs.map → chunk-JL7JXCET.mjs.map} +0 -0
- /package/dist/sdk/{chunk-6W75IMDC.mjs.map → chunk-LG4AUKHB.mjs.map} +0 -0
- /package/dist/sdk/{chunk-PO7X5XI7.mjs.map → chunk-SZXICFQ3.mjs.map} +0 -0
- /package/dist/sdk/{chunk-2KB35MB7.mjs.map → chunk-VPC3QSPW.mjs.map} +0 -0
- /package/dist/sdk/{chunk-J5RGJQ53.mjs.map → chunk-YJRBN3XS.mjs.map} +0 -0
- /package/dist/sdk/{command-executor-DVVXERLR.mjs.map → command-executor-TOYBBE7S.mjs.map} +0 -0
- /package/dist/sdk/{config-7VTT64SQ.mjs.map → config-OGOS4ZU4.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-4WMDF4Q3.mjs.map → failure-condition-evaluator-HC3M5377.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-3N2NLO66.mjs.map → github-frontend-E2KJSC3Y.mjs.map} +0 -0
- /package/dist/sdk/{host-ONVMEHAA.mjs.map → host-EE6EJ2FM.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-5IZLTFSZ.mjs.map → lazy-otel-5NH4ZJJM.mjs.map} +0 -0
- /package/dist/sdk/{memory-store-3N4AZCYB.mjs.map → liquid-extensions-E4EUOCES.mjs.map} +0 -0
- /package/dist/sdk/{metrics-GXQ2EDXA.mjs.map → memory-store-AAPL2MTE.mjs.map} +0 -0
- /package/dist/sdk/{prompt-state-YHGXB2OA.mjs.map → metrics-I6A7IHG4.mjs.map} +0 -0
- /package/dist/sdk/{routing-S3Y7T2X3.mjs.map → prompt-state-VAKKC773.mjs.map} +0 -0
- /package/dist/sdk/{renderer-schema-CMXOLNIG.mjs.map → renderer-schema-HXEW6BRJ.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-YHNPC7MR.mjs.map → routing-OZQWAGAI.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-4F3432ZP.mjs.map → schedule-tool-handler-B7TMSG6A.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-A44PBPG2.mjs.map → schedule-tool-handler-IEB2VS7O.mjs.map} +0 -0
- /package/dist/sdk/{workflow-registry-ZAYYXLEP.mjs.map → trace-helpers-PP3YHTAM.mjs.map} +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) ProbeLabs. All rights reserved.
|
|
3
|
+
* Licensed under the Elastic License 2.0; you may not use this file except
|
|
4
|
+
* in compliance with the Elastic License 2.0.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* OPA WASM Evaluator - loads and evaluates OPA policies locally.
|
|
8
|
+
*
|
|
9
|
+
* Supports three input formats:
|
|
10
|
+
* 1. Pre-compiled `.wasm` bundle — loaded directly (fastest startup)
|
|
11
|
+
* 2. `.rego` files or directory — auto-compiled to WASM via `opa build` CLI
|
|
12
|
+
* 3. Directory with `policy.wasm` inside — loaded directly
|
|
13
|
+
*
|
|
14
|
+
* Compilation and caching of .rego files is delegated to {@link OpaCompiler}.
|
|
15
|
+
*
|
|
16
|
+
* Requires:
|
|
17
|
+
* - `@open-policy-agent/opa-wasm` npm package (optional dep)
|
|
18
|
+
* - `opa` CLI on PATH (only when auto-compiling .rego files)
|
|
19
|
+
*/
|
|
20
|
+
export declare class OpaWasmEvaluator {
|
|
21
|
+
private policy;
|
|
22
|
+
private dataDocument;
|
|
23
|
+
private compiler;
|
|
24
|
+
initialize(rulesPath: string | string[]): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Load external data from a JSON file to use as the OPA data document.
|
|
27
|
+
* The loaded data will be passed to `policy.setData()` during evaluation,
|
|
28
|
+
* making it available in Rego via `data.<key>`.
|
|
29
|
+
*/
|
|
30
|
+
loadData(dataPath: string): void;
|
|
31
|
+
evaluate(input: object): Promise<any>;
|
|
32
|
+
shutdown(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=opa-wasm-evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opa-wasm-evaluator.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/enterprise/policy/opa-wasm-evaluator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAkC;IAE5C,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B7D;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IA2B1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAcrC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAehC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) ProbeLabs. All rights reserved.
|
|
3
|
+
* Licensed under the Elastic License 2.0; you may not use this file except
|
|
4
|
+
* in compliance with the Elastic License 2.0.
|
|
5
|
+
*/
|
|
6
|
+
import type { PolicyConfig, StepPolicyOverride } from '../../policy/types';
|
|
7
|
+
/**
|
|
8
|
+
* OPA input document shape (internal to enterprise code).
|
|
9
|
+
* This mirrors what OPA .rego rules expect — OSS code never sees this type.
|
|
10
|
+
*/
|
|
11
|
+
export interface OpaInput {
|
|
12
|
+
scope: string;
|
|
13
|
+
check?: {
|
|
14
|
+
id: string;
|
|
15
|
+
type: string;
|
|
16
|
+
group?: string;
|
|
17
|
+
tags?: string[];
|
|
18
|
+
criticality?: string;
|
|
19
|
+
sandbox?: string;
|
|
20
|
+
policy?: StepPolicyOverride;
|
|
21
|
+
};
|
|
22
|
+
tool?: {
|
|
23
|
+
serverName: string;
|
|
24
|
+
methodName: string;
|
|
25
|
+
transport?: string;
|
|
26
|
+
};
|
|
27
|
+
capability?: {
|
|
28
|
+
allowEdit?: boolean;
|
|
29
|
+
allowBash?: boolean;
|
|
30
|
+
allowedTools?: string[];
|
|
31
|
+
enableDelegate?: boolean;
|
|
32
|
+
sandbox?: string;
|
|
33
|
+
};
|
|
34
|
+
actor: {
|
|
35
|
+
authorAssociation?: string;
|
|
36
|
+
login?: string;
|
|
37
|
+
roles: string[];
|
|
38
|
+
isLocalMode: boolean;
|
|
39
|
+
slack?: {
|
|
40
|
+
userId?: string;
|
|
41
|
+
email?: string;
|
|
42
|
+
channelId?: string;
|
|
43
|
+
channelType?: 'channel' | 'dm' | 'group';
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
repository?: {
|
|
47
|
+
owner?: string;
|
|
48
|
+
name?: string;
|
|
49
|
+
branch?: string;
|
|
50
|
+
baseBranch?: string;
|
|
51
|
+
event?: string;
|
|
52
|
+
action?: string;
|
|
53
|
+
};
|
|
54
|
+
pullRequest?: {
|
|
55
|
+
number?: number;
|
|
56
|
+
labels?: string[];
|
|
57
|
+
draft?: boolean;
|
|
58
|
+
changedFiles?: number;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export interface ActorContext {
|
|
62
|
+
authorAssociation?: string;
|
|
63
|
+
login?: string;
|
|
64
|
+
isLocalMode: boolean;
|
|
65
|
+
slack?: {
|
|
66
|
+
userId?: string;
|
|
67
|
+
email?: string;
|
|
68
|
+
channelId?: string;
|
|
69
|
+
channelType?: 'channel' | 'dm' | 'group';
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export interface RepositoryContext {
|
|
73
|
+
owner?: string;
|
|
74
|
+
name?: string;
|
|
75
|
+
branch?: string;
|
|
76
|
+
baseBranch?: string;
|
|
77
|
+
event?: string;
|
|
78
|
+
action?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface PullRequestContext {
|
|
81
|
+
number?: number;
|
|
82
|
+
labels?: string[];
|
|
83
|
+
draft?: boolean;
|
|
84
|
+
changedFiles?: number;
|
|
85
|
+
}
|
|
86
|
+
export interface CheckContext {
|
|
87
|
+
id: string;
|
|
88
|
+
type: string;
|
|
89
|
+
group?: string;
|
|
90
|
+
tags?: string[];
|
|
91
|
+
criticality?: string;
|
|
92
|
+
sandbox?: string;
|
|
93
|
+
policy?: StepPolicyOverride;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Builds OPA-compatible input documents from engine context.
|
|
97
|
+
*
|
|
98
|
+
* Resolves actor roles from the `policy.roles` config section by matching
|
|
99
|
+
* the actor's authorAssociation and login against role definitions.
|
|
100
|
+
*/
|
|
101
|
+
export declare class PolicyInputBuilder {
|
|
102
|
+
private roles;
|
|
103
|
+
private actor;
|
|
104
|
+
private repository?;
|
|
105
|
+
private pullRequest?;
|
|
106
|
+
constructor(policyConfig: PolicyConfig, actor: ActorContext, repository?: RepositoryContext, pullRequest?: PullRequestContext);
|
|
107
|
+
/** Resolve which roles apply to the current actor. */
|
|
108
|
+
resolveRoles(): string[];
|
|
109
|
+
private buildActor;
|
|
110
|
+
forCheckExecution(check: CheckContext): OpaInput;
|
|
111
|
+
forToolInvocation(serverName: string, methodName: string, transport?: string): OpaInput;
|
|
112
|
+
forCapabilityResolve(checkId: string, capabilities: {
|
|
113
|
+
allowEdit?: boolean;
|
|
114
|
+
allowBash?: boolean;
|
|
115
|
+
allowedTools?: string[];
|
|
116
|
+
enableDelegate?: boolean;
|
|
117
|
+
sandbox?: string;
|
|
118
|
+
}): OpaInput;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=policy-input-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-input-builder.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/enterprise/policy/policy-input-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) ProbeLabs. All rights reserved.
|
|
3
|
+
* Licensed under the Elastic License 2.0; you may not use this file except
|
|
4
|
+
* in compliance with the Elastic License 2.0.
|
|
5
|
+
*/
|
|
6
|
+
import type { Schedule, ScheduleLimits } from '../../scheduler/schedule-store';
|
|
7
|
+
import type { ScheduleStoreBackend, ScheduleStoreStats, StorageConfig, HAConfig } from '../../scheduler/store/types';
|
|
8
|
+
/**
|
|
9
|
+
* Enterprise Knex-backed store for PostgreSQL, MySQL, and MSSQL
|
|
10
|
+
*/
|
|
11
|
+
export declare class KnexStoreBackend implements ScheduleStoreBackend {
|
|
12
|
+
private knex;
|
|
13
|
+
private driver;
|
|
14
|
+
private connection;
|
|
15
|
+
constructor(driver: 'postgresql' | 'mysql' | 'mssql', storageConfig: StorageConfig, _haConfig?: HAConfig);
|
|
16
|
+
initialize(): Promise<void>;
|
|
17
|
+
private buildStandardConnection;
|
|
18
|
+
private buildMssqlConnection;
|
|
19
|
+
private resolveSslConfig;
|
|
20
|
+
private validateSslPath;
|
|
21
|
+
shutdown(): Promise<void>;
|
|
22
|
+
private migrateSchema;
|
|
23
|
+
private getKnex;
|
|
24
|
+
create(schedule: Omit<Schedule, 'id' | 'createdAt' | 'runCount' | 'failureCount' | 'status'>): Promise<Schedule>;
|
|
25
|
+
importSchedule(schedule: Schedule): Promise<void>;
|
|
26
|
+
get(id: string): Promise<Schedule | undefined>;
|
|
27
|
+
update(id: string, patch: Partial<Schedule>): Promise<Schedule | undefined>;
|
|
28
|
+
delete(id: string): Promise<boolean>;
|
|
29
|
+
getByCreator(creatorId: string): Promise<Schedule[]>;
|
|
30
|
+
getActiveSchedules(): Promise<Schedule[]>;
|
|
31
|
+
getDueSchedules(now?: number): Promise<Schedule[]>;
|
|
32
|
+
findByWorkflow(creatorId: string, workflowName: string): Promise<Schedule[]>;
|
|
33
|
+
getAll(): Promise<Schedule[]>;
|
|
34
|
+
getStats(): Promise<ScheduleStoreStats>;
|
|
35
|
+
validateLimits(creatorId: string, isRecurring: boolean, limits: ScheduleLimits): Promise<void>;
|
|
36
|
+
tryAcquireLock(lockId: string, nodeId: string, ttlSeconds: number): Promise<string | null>;
|
|
37
|
+
releaseLock(lockId: string, lockToken: string): Promise<void>;
|
|
38
|
+
renewLock(lockId: string, lockToken: string, ttlSeconds: number): Promise<boolean>;
|
|
39
|
+
flush(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=knex-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knex-store.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/enterprise/scheduler/knex-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,QAAQ,EAET,MAAM,6BAA6B,CAAC;AA+FrC;;GAEG;AACH,qBAAa,gBAAiB,YAAW,oBAAoB;IAC3D,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,UAAU,CAAyB;gBAGzC,MAAM,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,EACxC,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,QAAQ;IAMhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDjC,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,eAAe;IAWjB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAOjB,aAAa;IA4C3B,OAAO,CAAC,OAAO;IAST,MAAM,CACV,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,QAAQ,CAAC,GACpF,OAAO,CAAC,QAAQ,CAAC;IAkBd,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAM9C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAgB3E,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYpC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMpD,kBAAkB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMzC,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAsBlD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAW5E,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAM7B,QAAQ,IAAI,OAAO,CAAC,kBAAkB,CAAC;IA4BvC,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAqCV,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAmC1F,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7D,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAalF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
package/dist/examples/README.md
CHANGED
|
@@ -134,6 +134,9 @@ Example configurations demonstrating various Visor features and use cases.
|
|
|
134
134
|
- **`sandbox-multi-env.yaml`** - Multiple sandbox environments per check
|
|
135
135
|
- **`sandbox-read-only.yaml`** - Read-only sandbox with network isolation
|
|
136
136
|
|
|
137
|
+
### Enterprise Policy Examples (EE)
|
|
138
|
+
- **`enterprise-policy/`** - OPA policy engine with role-based access control **(Enterprise Edition -- requires license, contact hello@probelabs.com)**
|
|
139
|
+
|
|
137
140
|
### Integration Examples
|
|
138
141
|
- **`jira-simple-example.yaml`** - Simple JIRA integration
|
|
139
142
|
- **`jira-single-issue-workflow.yaml`** - Single JIRA issue workflow
|
|
@@ -464,6 +467,26 @@ visor --config examples/workflows/quick-pr-check.yaml --input "pr_type=feature"
|
|
|
464
467
|
visor --config examples/workflows/workflow-composition-example.yaml
|
|
465
468
|
```
|
|
466
469
|
|
|
470
|
+
## Enterprise Policy Engine (EE)
|
|
471
|
+
|
|
472
|
+
> **Enterprise Edition feature.** Requires a Visor EE license.
|
|
473
|
+
> Contact **hello@probelabs.com** for licensing.
|
|
474
|
+
|
|
475
|
+
Role-based access control for checks, MCP tools, and AI capabilities using OPA (Open Policy Agent) policies:
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# Install EE build
|
|
479
|
+
npm install @probelabs/visor@ee
|
|
480
|
+
|
|
481
|
+
# Set license
|
|
482
|
+
export VISOR_LICENSE="<your-jwt-token>"
|
|
483
|
+
|
|
484
|
+
# Run with policy enforcement
|
|
485
|
+
visor --config examples/enterprise-policy/visor.yaml
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
See [`examples/enterprise-policy/README.md`](enterprise-policy/README.md) for full documentation, configuration reference, and Rego policy examples.
|
|
489
|
+
|
|
467
490
|
## 📚 Further Reading
|
|
468
491
|
|
|
469
492
|
- [Main README](../README.md) - Complete Visor documentation
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# OPA Policy Engine (Enterprise Edition)
|
|
2
|
+
|
|
3
|
+
> **This is an Enterprise Edition feature.** A valid Visor EE license is required.
|
|
4
|
+
> To get a license or learn more, contact **hello@probelabs.com**.
|
|
5
|
+
|
|
6
|
+
The OPA (Open Policy Agent) policy engine gives you fine-grained, role-based access control over Visor checks, MCP tools, and AI capabilities. Policies are written in [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) and evaluated locally via WASM or against a remote OPA server.
|
|
7
|
+
|
|
8
|
+
For the full documentation, see [docs/enterprise-policy.md](../../docs/enterprise-policy.md).
|
|
9
|
+
|
|
10
|
+
## What it controls
|
|
11
|
+
|
|
12
|
+
| Scope | What it does |
|
|
13
|
+
|-------|-------------|
|
|
14
|
+
| **Check execution** | Gate which checks can run based on the actor's role |
|
|
15
|
+
| **MCP tool access** | Allow or block specific MCP methods per role |
|
|
16
|
+
| **AI capabilities** | Restrict `allowBash`, `allowEdit`, and tool lists per role |
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
| Dependency | Purpose |
|
|
21
|
+
|-----------|---------|
|
|
22
|
+
| `@probelabs/visor@ee` | Visor Enterprise Edition build |
|
|
23
|
+
| Valid EE license (JWT) | Activates the policy engine |
|
|
24
|
+
| `opa` CLI | Compiles `.rego` files to WASM at startup (local mode) |
|
|
25
|
+
| `@open-policy-agent/opa-wasm` | Evaluates WASM policies in-process (installed automatically with EE build) |
|
|
26
|
+
|
|
27
|
+
### Installing the OPA CLI
|
|
28
|
+
|
|
29
|
+
The OPA CLI is needed to compile `.rego` files into WebAssembly at startup.
|
|
30
|
+
|
|
31
|
+
**macOS:**
|
|
32
|
+
```bash
|
|
33
|
+
brew install opa
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Linux:**
|
|
37
|
+
```bash
|
|
38
|
+
curl -L -o /usr/local/bin/opa \
|
|
39
|
+
https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
|
|
40
|
+
chmod +x /usr/local/bin/opa
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Verify:**
|
|
44
|
+
```bash
|
|
45
|
+
opa version
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> You can skip the OPA CLI if you pre-compile your `.rego` files into a `.wasm` bundle (see [Pre-compiling](#pre-compiling-wasm-bundles) below).
|
|
49
|
+
|
|
50
|
+
## Quick start
|
|
51
|
+
|
|
52
|
+
### 1. Install the EE build
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install @probelabs/visor@ee
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Set your license
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Option A: environment variable
|
|
62
|
+
export VISOR_LICENSE="<your-jwt-token>"
|
|
63
|
+
|
|
64
|
+
# Option B: file in project root
|
|
65
|
+
echo "<your-jwt-token>" > .visor-license
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Add the `policy:` block to your `.visor.yaml`
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
version: "1.0"
|
|
72
|
+
|
|
73
|
+
policy:
|
|
74
|
+
engine: local # 'local' (WASM) or 'remote' (HTTP OPA server)
|
|
75
|
+
rules: ./policies/ # Path to .rego files (local mode)
|
|
76
|
+
fallback: deny # 'allow' or 'deny' when evaluation fails
|
|
77
|
+
timeout: 5000 # Evaluation timeout in ms
|
|
78
|
+
|
|
79
|
+
roles:
|
|
80
|
+
admin:
|
|
81
|
+
author_association: [OWNER]
|
|
82
|
+
users: [cto-username]
|
|
83
|
+
developer:
|
|
84
|
+
author_association: [MEMBER, COLLABORATOR]
|
|
85
|
+
external:
|
|
86
|
+
author_association: [FIRST_TIME_CONTRIBUTOR, FIRST_TIMER, NONE]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 4. Write Rego policies
|
|
90
|
+
|
|
91
|
+
See the `policies/` directory in this example for ready-to-use policies:
|
|
92
|
+
|
|
93
|
+
- **`check_execute.rego`** -- Controls which checks each role can run
|
|
94
|
+
- **`tool_invoke.rego`** -- Blocks destructive MCP methods for non-admins
|
|
95
|
+
- **`capability_resolve.rego`** -- Restricts AI capabilities (bash, file editing) by role
|
|
96
|
+
|
|
97
|
+
### 5. Run
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
visor --config .visor.yaml
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Checks that the actor's role is not authorized for will be skipped with reason `policy_denied`.
|
|
104
|
+
|
|
105
|
+
## Files in this example
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
enterprise-policy/
|
|
109
|
+
visor.yaml # Example .visor.yaml with policy configuration
|
|
110
|
+
policies/
|
|
111
|
+
check_execute.rego # Check execution gating
|
|
112
|
+
tool_invoke.rego # MCP tool access control
|
|
113
|
+
capability_resolve.rego # AI capability restrictions
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Configuration reference
|
|
117
|
+
|
|
118
|
+
### Top-level `policy:` block
|
|
119
|
+
|
|
120
|
+
| Field | Type | Description |
|
|
121
|
+
|-------|------|-------------|
|
|
122
|
+
| `engine` | `local` \| `remote` \| `disabled` | Evaluation backend |
|
|
123
|
+
| `rules` | `string` \| `string[]` | Path to `.rego` files or `.wasm` bundle (local mode) |
|
|
124
|
+
| `url` | `string` | OPA server URL (remote mode) |
|
|
125
|
+
| `fallback` | `allow` \| `deny` \| `warn` | Default decision on evaluation failure |
|
|
126
|
+
| `timeout` | `number` | Evaluation timeout in ms (default: 5000) |
|
|
127
|
+
| `roles` | `map` | Role definitions (see below) |
|
|
128
|
+
|
|
129
|
+
### Role definitions
|
|
130
|
+
|
|
131
|
+
Roles map GitHub author associations, team slugs, or explicit usernames to named roles that your Rego policies reference.
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
roles:
|
|
135
|
+
admin:
|
|
136
|
+
author_association: [OWNER]
|
|
137
|
+
users: [alice, bob]
|
|
138
|
+
developer:
|
|
139
|
+
author_association: [MEMBER, COLLABORATOR]
|
|
140
|
+
external:
|
|
141
|
+
author_association: [FIRST_TIME_CONTRIBUTOR, NONE]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Per-step `policy:` override
|
|
145
|
+
|
|
146
|
+
Individual steps can declare role requirements directly in YAML, without writing Rego:
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
steps:
|
|
150
|
+
deploy-production:
|
|
151
|
+
type: command
|
|
152
|
+
exec: ./deploy.sh production
|
|
153
|
+
policy:
|
|
154
|
+
require: admin # Only admin role can trigger this
|
|
155
|
+
deny: [external] # Explicitly deny external contributors
|
|
156
|
+
rule: visor/deploy/prod # Optional: custom OPA rule path
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Rego policy structure
|
|
160
|
+
|
|
161
|
+
Policies live under `package visor.<scope>` and must export an `allowed` boolean:
|
|
162
|
+
|
|
163
|
+
```rego
|
|
164
|
+
package visor.check.execute
|
|
165
|
+
|
|
166
|
+
default allowed = false
|
|
167
|
+
|
|
168
|
+
allowed {
|
|
169
|
+
input.actor.roles[_] == "admin"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
reason = "access denied" { not allowed }
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Available scopes
|
|
176
|
+
|
|
177
|
+
| Package | Evaluated when |
|
|
178
|
+
|---------|---------------|
|
|
179
|
+
| `visor.check.execute` | Before each check runs |
|
|
180
|
+
| `visor.tool.invoke` | Before each MCP tool call |
|
|
181
|
+
| `visor.capability.resolve` | When assembling AI config |
|
|
182
|
+
|
|
183
|
+
### Input document
|
|
184
|
+
|
|
185
|
+
Your Rego policies receive an `input` document with these fields:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"scope": "check.execute",
|
|
190
|
+
"check": {
|
|
191
|
+
"id": "deploy-production",
|
|
192
|
+
"type": "command",
|
|
193
|
+
"tags": ["deploy"],
|
|
194
|
+
"criticality": "external",
|
|
195
|
+
"policy": { "require": "admin" }
|
|
196
|
+
},
|
|
197
|
+
"actor": {
|
|
198
|
+
"login": "alice",
|
|
199
|
+
"authorAssociation": "MEMBER",
|
|
200
|
+
"roles": ["developer"],
|
|
201
|
+
"isLocalMode": false
|
|
202
|
+
},
|
|
203
|
+
"repository": {
|
|
204
|
+
"owner": "probelabs",
|
|
205
|
+
"name": "visor",
|
|
206
|
+
"branch": "feat/new-feature"
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Writing Rego for Visor
|
|
212
|
+
|
|
213
|
+
### Checking roles
|
|
214
|
+
|
|
215
|
+
Use `input.actor.roles[_]` to check if the actor has a specific role:
|
|
216
|
+
|
|
217
|
+
```rego
|
|
218
|
+
allowed {
|
|
219
|
+
input.actor.roles[_] == "admin"
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Handling per-step YAML requirements
|
|
224
|
+
|
|
225
|
+
When a step declares `policy.require`, your Rego must handle both string and array values:
|
|
226
|
+
|
|
227
|
+
```rego
|
|
228
|
+
# String require (e.g., require: admin)
|
|
229
|
+
allowed {
|
|
230
|
+
required := input.check.policy.require
|
|
231
|
+
is_string(required)
|
|
232
|
+
input.actor.roles[_] == required
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
# Array require (e.g., require: [developer, admin])
|
|
236
|
+
allowed {
|
|
237
|
+
required := input.check.policy.require
|
|
238
|
+
is_array(required)
|
|
239
|
+
required[_] == input.actor.roles[_]
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Local mode bypass
|
|
244
|
+
|
|
245
|
+
When running locally (CLI), you may want to allow all checks:
|
|
246
|
+
|
|
247
|
+
```rego
|
|
248
|
+
allowed {
|
|
249
|
+
input.actor.isLocalMode == true
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### WASM-safe patterns
|
|
254
|
+
|
|
255
|
+
OPA compiles Rego to WebAssembly for fast in-process evaluation. Some patterns are not WASM-safe:
|
|
256
|
+
|
|
257
|
+
```rego
|
|
258
|
+
# BAD: not safe for WASM compilation
|
|
259
|
+
allowed = false {
|
|
260
|
+
not input.actor.roles[_] == "admin"
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
# GOOD: use a helper rule
|
|
264
|
+
is_admin { input.actor.roles[_] == "admin" }
|
|
265
|
+
allowed = false {
|
|
266
|
+
not is_admin
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Testing your policies
|
|
271
|
+
|
|
272
|
+
Use the OPA CLI to test policies before deploying:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# Evaluate with test input
|
|
276
|
+
echo '{"actor":{"roles":["developer"],"isLocalMode":false},"check":{"id":"deploy-staging"}}' | \
|
|
277
|
+
opa eval -d policies/ -i /dev/stdin 'data.visor.check.execute.allowed'
|
|
278
|
+
|
|
279
|
+
# Check for syntax errors
|
|
280
|
+
opa check policies/
|
|
281
|
+
|
|
282
|
+
# Run OPA unit tests (if you have _test.rego files)
|
|
283
|
+
opa test policies/ -v
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Pre-compiling WASM bundles
|
|
287
|
+
|
|
288
|
+
For faster startup (skip compilation at runtime), pre-compile your policies:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Compile all .rego files into a WASM bundle
|
|
292
|
+
opa build -t wasm -e visor -d policies/ -o bundle.tar.gz
|
|
293
|
+
|
|
294
|
+
# Extract the WASM file
|
|
295
|
+
tar -xzf bundle.tar.gz /policy.wasm
|
|
296
|
+
|
|
297
|
+
# Reference the .wasm file in config
|
|
298
|
+
# policy:
|
|
299
|
+
# rules: ./policy.wasm
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
> When compiling with `opa build`, always use `-e visor` as the entrypoint.
|
|
303
|
+
|
|
304
|
+
## Remote OPA server
|
|
305
|
+
|
|
306
|
+
To evaluate against a running OPA server instead of local WASM:
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
policy:
|
|
310
|
+
engine: remote
|
|
311
|
+
url: http://opa:8181
|
|
312
|
+
fallback: deny
|
|
313
|
+
timeout: 3000
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Visor sends POST requests to `${url}/v1/data/visor/<scope>` with `{ "input": ... }`.
|
|
317
|
+
|
|
318
|
+
### Running an OPA server
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# Local server with your policies
|
|
322
|
+
opa run --server --addr :8181 ./policies/
|
|
323
|
+
|
|
324
|
+
# Docker
|
|
325
|
+
docker run -p 8181:8181 \
|
|
326
|
+
-v $(pwd)/policies:/policies \
|
|
327
|
+
openpolicyagent/opa:latest \
|
|
328
|
+
run --server --addr :8181 /policies/
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Without a license
|
|
332
|
+
|
|
333
|
+
If no valid license is found, the policy engine is silently disabled and all checks run as normal (the OSS default). No error is raised.
|
|
334
|
+
|
|
335
|
+
## Further reading
|
|
336
|
+
|
|
337
|
+
- [Full enterprise policy documentation](../../docs/enterprise-policy.md) -- comprehensive guide with troubleshooting
|
|
338
|
+
- [Author permissions (OSS)](../../docs/author-permissions.md) -- simpler, inline permission checks
|
|
339
|
+
- [OPA documentation](https://www.openpolicyagent.org/docs/latest/) -- official OPA docs
|
|
340
|
+
- [Rego playground](https://play.openpolicyagent.org/) -- interactive Rego editor and tester
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
**Questions? Need a license?** Contact **hello@probelabs.com**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# AI capability restriction policy (Visor Enterprise Edition)
|
|
2
|
+
# Controls which AI capabilities (bash, file editing) are available per role.
|
|
3
|
+
# Contact hello@probelabs.com for licensing.
|
|
4
|
+
|
|
5
|
+
package visor.capability.resolve
|
|
6
|
+
|
|
7
|
+
# Helper: actor has developer role
|
|
8
|
+
is_developer { input.actor.roles[_] == "developer" }
|
|
9
|
+
|
|
10
|
+
# Helper: actor has admin role
|
|
11
|
+
is_admin { input.actor.roles[_] == "admin" }
|
|
12
|
+
|
|
13
|
+
# Disable file editing for non-developers
|
|
14
|
+
capabilities["allowEdit"] = false {
|
|
15
|
+
not is_developer
|
|
16
|
+
not is_admin
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Disable bash for external contributors
|
|
20
|
+
capabilities["allowBash"] = false {
|
|
21
|
+
input.actor.roles[_] == "external"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
reason = "edit capability restricted for non-developer/admin roles" {
|
|
25
|
+
capabilities["allowEdit"] == false
|
|
26
|
+
}
|
|
27
|
+
reason = "bash capability restricted for external contributors" {
|
|
28
|
+
capabilities["allowBash"] == false
|
|
29
|
+
}
|