@orygn/opa-mcp 0.1.1 → 0.1.3
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/CHANGELOG.md +50 -1
- package/README.md +62 -23
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/lib/errors.d.ts +1 -1
- package/dist/lib/logger.js +2 -2
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/opa-cli.d.ts +3 -3
- package/dist/lib/opa-cli.js +4 -4
- package/dist/lib/opa-client.d.ts +1 -1
- package/dist/lib/regal-cli.d.ts +4 -4
- package/dist/lib/regal-cli.js +5 -5
- package/dist/lib/subprocess.d.ts +1 -1
- package/dist/lib/subprocess.js +2 -2
- package/dist/lib/tool-helpers.d.ts +1 -1
- package/dist/prompts/index.js +6 -6
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/index.d.ts +4 -4
- package/dist/resources/patterns.d.ts +1 -1
- package/dist/resources/patterns.d.ts.map +1 -1
- package/dist/resources/patterns.js +7 -7
- package/dist/resources/style-guide.d.ts +1 -1
- package/dist/resources/style-guide.d.ts.map +1 -1
- package/dist/resources/style-guide.js +3 -3
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -4
- package/dist/server.js.map +1 -1
- package/dist/tools/authoring/capabilities.d.ts +2 -0
- package/dist/tools/authoring/capabilities.d.ts.map +1 -1
- package/dist/tools/authoring/capabilities.js +24 -4
- package/dist/tools/authoring/capabilities.js.map +1 -1
- package/dist/tools/authoring/check.js +3 -3
- package/dist/tools/authoring/check.js.map +1 -1
- package/dist/tools/authoring/deps.js +2 -2
- package/dist/tools/authoring/deps.js.map +1 -1
- package/dist/tools/authoring/format.js +1 -1
- package/dist/tools/authoring/index.d.ts +1 -1
- package/dist/tools/authoring/inspect.js +2 -2
- package/dist/tools/authoring/inspect.js.map +1 -1
- package/dist/tools/authoring/lint.js +1 -1
- package/dist/tools/authoring/parse.js +1 -1
- package/dist/tools/bundles/build.js +1 -1
- package/dist/tools/bundles/index.d.ts +1 -1
- package/dist/tools/bundles/sign.js +1 -1
- package/dist/tools/evaluation/_shared.d.ts +1 -1
- package/dist/tools/evaluation/_shared.js +1 -1
- package/dist/tools/evaluation/bench.js +1 -1
- package/dist/tools/evaluation/compile.d.ts +2 -2
- package/dist/tools/evaluation/compile.js +1 -1
- package/dist/tools/evaluation/compile.js.map +1 -1
- package/dist/tools/evaluation/eval.d.ts +2 -2
- package/dist/tools/evaluation/eval.js +1 -1
- package/dist/tools/evaluation/eval.js.map +1 -1
- package/dist/tools/evaluation/index.d.ts +1 -1
- package/dist/tools/evaluation/test.js +1 -1
- package/dist/tools/helpers/coverage-gaps.d.ts +29 -0
- package/dist/tools/helpers/coverage-gaps.d.ts.map +1 -0
- package/dist/tools/helpers/coverage-gaps.js +125 -0
- package/dist/tools/helpers/coverage-gaps.js.map +1 -0
- package/dist/tools/helpers/describe-policy.js +1 -1
- package/dist/tools/helpers/explain-decision.d.ts +1 -1
- package/dist/tools/helpers/explain-decision.js +1 -1
- package/dist/tools/helpers/explain-decision.js.map +1 -1
- package/dist/tools/helpers/generate-test-skeleton.js +3 -3
- package/dist/tools/helpers/generate-test-skeleton.js.map +1 -1
- package/dist/tools/helpers/index.d.ts +1 -1
- package/dist/tools/helpers/index.d.ts.map +1 -1
- package/dist/tools/helpers/index.js +4 -0
- package/dist/tools/helpers/index.js.map +1 -1
- package/dist/tools/helpers/security-audit.d.ts +21 -0
- package/dist/tools/helpers/security-audit.d.ts.map +1 -0
- package/dist/tools/helpers/security-audit.js +111 -0
- package/dist/tools/helpers/security-audit.js.map +1 -0
- package/dist/tools/helpers/suggest-fix.js +6 -6
- package/dist/tools/helpers/suggest-fix.js.map +1 -1
- package/dist/tools/index.d.ts +9 -6
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/meta/index.d.ts +10 -0
- package/dist/tools/meta/index.d.ts.map +1 -0
- package/dist/tools/meta/index.js +5 -0
- package/dist/tools/meta/index.js.map +1 -0
- package/dist/tools/meta/server-info.d.ts +17 -0
- package/dist/tools/meta/server-info.d.ts.map +1 -0
- package/dist/tools/meta/server-info.js +30 -0
- package/dist/tools/meta/server-info.js.map +1 -0
- package/dist/tools/server-management/data.js +1 -1
- package/dist/tools/server-management/data.js.map +1 -1
- package/dist/tools/server-management/decisions.js +1 -1
- package/dist/tools/server-management/decisions.js.map +1 -1
- package/dist/tools/server-management/index.d.ts +1 -1
- package/dist/tools/server-management/policies.js +1 -1
- package/dist/tools/server-management/policies.js.map +1 -1
- package/dist/tools/server-management/status.js +2 -2
- package/dist/tools/server-management/status.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -17,6 +17,53 @@ not part of the public surface and may change in minor releases.
|
|
|
17
17
|
|
|
18
18
|
## [Unreleased]
|
|
19
19
|
|
|
20
|
+
## [0.1.3] - 2026-05-18
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`rego_coverage_gaps` tool.** Runs `opa test --coverage` and returns a
|
|
25
|
+
per-file breakdown of uncovered line ranges, sorted by coverage ascending
|
|
26
|
+
so the worst-covered files appear first. Accepts an optional `threshold`
|
|
27
|
+
to limit output to files below a target coverage percentage. Surfaces
|
|
28
|
+
`testsPassed`, `testsFailed`, `testsSkipped`, and `overallCoverage` in
|
|
29
|
+
the envelope alongside the gap report.
|
|
30
|
+
|
|
31
|
+
- **`rego_security_audit` tool.** Runs regal lint restricted to the
|
|
32
|
+
`security` and `bugs` categories across one or more policy directories.
|
|
33
|
+
Returns findings grouped by severity (high / medium) with per-finding
|
|
34
|
+
remediation guidance. Designed for fleet-wide periodic sweeps rather
|
|
35
|
+
than per-file style review. Requires regal.
|
|
36
|
+
|
|
37
|
+
- **`mcp_server_info` tool.** Returns the server name, version, resolved
|
|
38
|
+
`opa` and `regal` versions, transport type, and Node.js version in a
|
|
39
|
+
single call. Useful for verifying which server instance an agent is
|
|
40
|
+
talking to and confirming binary paths resolved correctly.
|
|
41
|
+
|
|
42
|
+
- **Claude Code install section** in README with the `claude mcp add --env`
|
|
43
|
+
command. Standing-instructions template (`examples/CLAUDE.md`) and
|
|
44
|
+
PostToolUse hook config (`examples/claude-code-hook.json`) for policy
|
|
45
|
+
repos using Claude Code.
|
|
46
|
+
|
|
47
|
+
- **Node 24 added to CI matrix.** Unit tests now run on Node 20, 22, and 24
|
|
48
|
+
across Ubuntu, macOS, and Windows.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- All em dashes in source comments replaced with `--` (U+002D pairs).
|
|
53
|
+
No behavior change; cosmetic consistency fix.
|
|
54
|
+
|
|
55
|
+
## [0.1.2] - 2026-05-18
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- `rego_capabilities` with `current: true` or a `version` argument now
|
|
60
|
+
returns only builtin names, a count, future keywords, and features by
|
|
61
|
+
default (`names_only: true`). Previously the full spec payload -- type
|
|
62
|
+
signatures, documentation, and metadata for every builtin -- routinely
|
|
63
|
+
exceeded the 100 KB `maxResponseBytes` cap and returned a useless
|
|
64
|
+
`__truncated` envelope. Pass `names_only: false` to retrieve the
|
|
65
|
+
complete payload when type signatures or documentation are needed.
|
|
66
|
+
|
|
20
67
|
## [0.1.1] - 2026-05-09
|
|
21
68
|
|
|
22
69
|
### Fixed
|
|
@@ -145,6 +192,8 @@ wrappers end-to-end. CI matrix: Ubuntu, macOS, and Windows on Node
|
|
|
145
192
|
20 and 22, plus CodeQL security scanning and weekly Dependabot updates
|
|
146
193
|
for npm, GitHub Actions, and Docker base images.
|
|
147
194
|
|
|
148
|
-
[Unreleased]: https://github.com/OrygnsCode/opa-mcp-server/compare/v0.1.
|
|
195
|
+
[Unreleased]: https://github.com/OrygnsCode/opa-mcp-server/compare/v0.1.3...HEAD
|
|
196
|
+
[0.1.3]: https://github.com/OrygnsCode/opa-mcp-server/compare/v0.1.2...v0.1.3
|
|
197
|
+
[0.1.2]: https://github.com/OrygnsCode/opa-mcp-server/releases/tag/v0.1.2
|
|
149
198
|
[0.1.1]: https://github.com/OrygnsCode/opa-mcp-server/releases/tag/v0.1.1
|
|
150
199
|
[0.1.0]: https://github.com/OrygnsCode/opa-mcp-server/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -17,10 +17,10 @@ environment.
|
|
|
17
17
|
+--------------------+ MCP / stdio +-----------------+ spawn / HTTP +------------------+
|
|
18
18
|
| Claude · Cursor · | ------------> | @orygn/opa-mcp | -------------> | opa · regal · |
|
|
19
19
|
| VS Code · ... | <------------ | | <------------- | OPA REST API |
|
|
20
|
-
+--------------------+
|
|
20
|
+
+--------------------+ 35 tools +-----------------+ +------------------+
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
> **Status:** v0.1.
|
|
23
|
+
> **Status:** v0.1.3. Tool surface, error codes, and
|
|
24
24
|
> environment variables follow [SemVer](https://semver.org/) from
|
|
25
25
|
> v0.1.0 forward.
|
|
26
26
|
|
|
@@ -100,20 +100,10 @@ recognize the gap this fills.
|
|
|
100
100
|
The server runs locally over stdio. Pick the install path that matches
|
|
101
101
|
your client.
|
|
102
102
|
|
|
103
|
-
### Claude Desktop
|
|
103
|
+
### Claude Desktop
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
npx -y @smithery/cli install @orygn/opa-mcp --client claude
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Or download `opa-mcp.mcpb` from the
|
|
112
|
-
[latest release](https://github.com/OrygnsCode/opa-mcp-server/releases/latest)
|
|
113
|
-
and double-click it.
|
|
114
|
-
|
|
115
|
-
If you prefer to edit `claude_desktop_config.json` by hand, the snippet
|
|
116
|
-
lives in [`examples/claude-desktop.json`](./examples/claude-desktop.json):
|
|
105
|
+
Edit `claude_desktop_config.json` directly (or copy from
|
|
106
|
+
[`examples/claude-desktop.json`](./examples/claude-desktop.json)):
|
|
117
107
|
|
|
118
108
|
```json
|
|
119
109
|
{
|
|
@@ -136,6 +126,47 @@ lives in [`examples/claude-desktop.json`](./examples/claude-desktop.json):
|
|
|
136
126
|
> [first-time install gotcha](#-first-time-install-gotcha-read-this-if-you-used-npx-or-the-global-install)
|
|
137
127
|
> below. Windows users substitute `C:\\path\\to\\opa.exe`.
|
|
138
128
|
|
|
129
|
+
Or download `opa-mcp.mcpb` from the
|
|
130
|
+
[latest release](https://github.com/OrygnsCode/opa-mcp-server/releases/latest)
|
|
131
|
+
and double-click it.
|
|
132
|
+
|
|
133
|
+
Alternatively, use the Smithery one-liner:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx -y @smithery/cli install @orygn/opa-mcp --client claude
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Claude Code (CLI)
|
|
140
|
+
|
|
141
|
+
Register the server for the current project with `claude mcp add`:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
claude mcp add \
|
|
145
|
+
--env OPA_BINARY=/usr/local/bin/opa \
|
|
146
|
+
--env REGAL_BINARY=/usr/local/bin/regal \
|
|
147
|
+
--env OPA_MCP_ALLOWED_PATHS=/path/to/your/policies \
|
|
148
|
+
opa -- npx -y @orygn/opa-mcp
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This writes the config into `.mcp.json` at your project root and is
|
|
152
|
+
picked up automatically on every `claude` session in that directory.
|
|
153
|
+
Add `--scope user` to register it globally instead.
|
|
154
|
+
|
|
155
|
+
> Replace the paths with your real absolute paths (same caveat as
|
|
156
|
+
> Claude Desktop above). On Windows use `C:\path\to\opa.exe` syntax.
|
|
157
|
+
|
|
158
|
+
**Persistent context and auto-checks for policy repos.**
|
|
159
|
+
If you work in an OPA policy repo regularly, two extra files remove
|
|
160
|
+
repetitive setup from every session:
|
|
161
|
+
|
|
162
|
+
- [`examples/CLAUDE.md`](./examples/CLAUDE.md) -- copy to your repo
|
|
163
|
+
root or `.claude/CLAUDE.md`. Claude Code loads it every session,
|
|
164
|
+
so the agent always knows which tools to use and what conventions apply.
|
|
165
|
+
- [`examples/claude-code-hook.json`](./examples/claude-code-hook.json) --
|
|
166
|
+
merge the `hooks` block into `.claude/settings.json`. Runs `opa check`
|
|
167
|
+
automatically after any `.rego` file is written, so syntax errors
|
|
168
|
+
surface immediately without a manual tool call.
|
|
169
|
+
|
|
139
170
|
### Cursor
|
|
140
171
|
|
|
141
172
|
Drop [`examples/cursor.json`](./examples/cursor.json) into either
|
|
@@ -369,6 +400,14 @@ the tasks agents are actually asked to do.
|
|
|
369
400
|
| `rego_generate_test_skeleton` | Given a policy, generate a `_test.rego` skeleton covering each rule. |
|
|
370
401
|
| `rego_describe_policy` | Summarize what a policy does, its inputs, decisions, and assumptions. |
|
|
371
402
|
| `rego_suggest_fix` | For a failed `rego_check` or `rego_lint`, propose minimal patches. |
|
|
403
|
+
| `rego_coverage_gaps` | Run `opa test --coverage` and return per-file uncovered line ranges, sorted worst first. Use `threshold` to focus on files below a target percentage. |
|
|
404
|
+
| `rego_security_audit` | Run regal lint restricted to `security` and `bugs` categories across a directory. Returns severity-grouped findings with remediation guidance. |
|
|
405
|
+
|
|
406
|
+
### Category F: Meta
|
|
407
|
+
|
|
408
|
+
| Tool | What it does |
|
|
409
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
410
|
+
| `mcp_server_info` | Return server name, version, resolved `opa`/`regal` versions, transport type, and Node.js version in one call. Useful for verifying which server instance the agent is connected to. |
|
|
372
411
|
|
|
373
412
|
## Prompts
|
|
374
413
|
|
|
@@ -452,7 +491,8 @@ Agent: Done. Policy `rbac` is live on staging at $OPA_URL.
|
|
|
452
491
|
│ ├── tools/evaluation/ ─┤ │
|
|
453
492
|
│ ├── tools/bundles/ ─┼─── lib/opa-cli.ts ──┐ │
|
|
454
493
|
│ ├── tools/server-management/ ─┤ │ │
|
|
455
|
-
│ ├── tools/helpers/
|
|
494
|
+
│ ├── tools/helpers/ ─┤ │ │
|
|
495
|
+
│ ├── tools/meta/ ─┘ │ │
|
|
456
496
|
│ │ ▼ │
|
|
457
497
|
│ │ lib/subprocess.ts ──┴── opa │
|
|
458
498
|
│ │ lib/regal-cli.ts ───── regal│
|
|
@@ -554,11 +594,10 @@ upgrade Regal: `brew upgrade regal` or download from the
|
|
|
554
594
|
|
|
555
595
|
**`directory-package-mismatch` violation when linting inline source.**
|
|
556
596
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
real on-disk file when you want canonical signal.
|
|
597
|
+
Since v0.1.1, the server auto-disables this rule for inline-source calls.
|
|
598
|
+
If you see it, you are running an older version -- upgrade to v0.1.1 or
|
|
599
|
+
later. To get canonical signal on this rule, lint via `paths` against the
|
|
600
|
+
real on-disk file instead of passing `source` directly.
|
|
562
601
|
|
|
563
602
|
**Where are the logs?**
|
|
564
603
|
|
|
@@ -588,8 +627,8 @@ npm run build # compile to dist/
|
|
|
588
627
|
```
|
|
589
628
|
|
|
590
629
|
CI runs lint, typecheck, build, and unit tests on every push and PR
|
|
591
|
-
across Ubuntu, macOS, and Windows on Node 20 and
|
|
592
|
-
run on Linux against pinned `opa` and `regal` releases.
|
|
630
|
+
across Ubuntu, macOS, and Windows on Node 20, 22, and 24. Integration
|
|
631
|
+
tests run on Linux against pinned `opa` and `regal` releases.
|
|
593
632
|
|
|
594
633
|
For the full contributor workflow (adding tools, naming conventions,
|
|
595
634
|
logging discipline, release process), see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
package/dist/config.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
15
15
|
/**
|
|
16
16
|
* Allow-listed root directories for file path inputs. Tools that accept
|
|
17
17
|
* filesystem paths reject anything outside these roots. Empty by
|
|
18
|
-
* default
|
|
18
|
+
* default -- file-based tools refuse to read from disk until the
|
|
19
19
|
* operator explicitly opts in via `OPA_MCP_ALLOWED_PATHS`.
|
|
20
20
|
*/
|
|
21
21
|
allowedPaths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Centralized configuration loaded from environment variables.
|
|
3
3
|
*
|
|
4
|
-
* Environment variables are the only configuration surface
|
|
4
|
+
* Environment variables are the only configuration surface -- there is no
|
|
5
5
|
* config file, no flags. This matches how MCP clients (Claude Desktop,
|
|
6
6
|
* Cursor, VS Code) pass config via the `env` object in their JSON.
|
|
7
7
|
*/
|
|
@@ -24,7 +24,7 @@ const ConfigSchema = z.object({
|
|
|
24
24
|
/**
|
|
25
25
|
* Allow-listed root directories for file path inputs. Tools that accept
|
|
26
26
|
* filesystem paths reject anything outside these roots. Empty by
|
|
27
|
-
* default
|
|
27
|
+
* default -- file-based tools refuse to read from disk until the
|
|
28
28
|
* operator explicitly opts in via `OPA_MCP_ALLOWED_PATHS`.
|
|
29
29
|
*/
|
|
30
30
|
allowedPaths: z.array(z.string()).default([]),
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server identity constants shared between the entry point and the
|
|
3
|
+
* mcp_server_info tool. Defined here to avoid a circular import
|
|
4
|
+
* (server.ts -> tools -> meta -> server.ts).
|
|
5
|
+
*/
|
|
6
|
+
export declare const SERVER_NAME = "orygn-opa-mcp";
|
|
7
|
+
export declare const SERVER_VERSION = "0.1.3";
|
|
8
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,WAAW,kBAAkB,CAAC;AAC3C,eAAO,MAAM,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server identity constants shared between the entry point and the
|
|
3
|
+
* mcp_server_info tool. Defined here to avoid a circular import
|
|
4
|
+
* (server.ts -> tools -> meta -> server.ts).
|
|
5
|
+
*/
|
|
6
|
+
export const SERVER_NAME = 'orygn-opa-mcp';
|
|
7
|
+
export const SERVER_VERSION = '0.1.3';
|
|
8
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC"}
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helpers for building structured tool errors.
|
|
3
3
|
*
|
|
4
|
-
* Tools should never throw raw exceptions to the MCP layer
|
|
4
|
+
* Tools should never throw raw exceptions to the MCP layer -- every failure
|
|
5
5
|
* mode returns a `ToolEnvelope` with `ok: false` and a structured `error`.
|
|
6
6
|
*/
|
|
7
7
|
import type { ToolEnvelope, ToolErrorCode } from '../types.js';
|
package/dist/lib/logger.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* File-only logger.
|
|
3
3
|
*
|
|
4
|
-
* Stdout is reserved for MCP protocol traffic
|
|
4
|
+
* Stdout is reserved for MCP protocol traffic -- writing anywhere else
|
|
5
5
|
* would corrupt the JSON-RPC stream. This logger appends to a file with
|
|
6
6
|
* level filtering, and never touches stdout.
|
|
7
7
|
*
|
|
@@ -37,7 +37,7 @@ function write(level, msg, ctx) {
|
|
|
37
37
|
}
|
|
38
38
|
catch {
|
|
39
39
|
// Logging must never throw. If the log file is unreachable, drop the
|
|
40
|
-
// line silently
|
|
40
|
+
// line silently -- better than crashing the server.
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
export const logger = {
|
package/dist/lib/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIzC,MAAM,cAAc,GAA0B;IAC5C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAOF,kDAAkD;AAClD,IAAI,KAA8B,CAAC;AAEnC,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAY;IACnD,KAAK,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,KAAK,CAAC,KAAY,EAAE,GAAW,EAAE,GAA6B;IACrE,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO;IAEnE,MAAM,KAAK,GAAG;QACZ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,KAAK;QACL,GAAG;QACH,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxB,CAAC;IACF,IAAI,CAAC;QACH,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIzC,MAAM,cAAc,GAA0B;IAC5C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAOF,kDAAkD;AAClD,IAAI,KAA8B,CAAC;AAEnC,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAY;IACnD,KAAK,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,KAAK,CAAC,KAAY,EAAE,GAAW,EAAE,GAA6B;IACrE,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO;IAEnE,MAAM,KAAK,GAAG;QACZ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,KAAK;QACL,GAAG;QACH,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxB,CAAC;IACF,IAAI,CAAC;QACH,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,oDAAoD;IACtD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,EAAE,CAAC,GAAW,EAAE,GAA6B,EAAQ,EAAE;QAC1D,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,EAAE,CAAC,GAAW,EAAE,GAA6B,EAAQ,EAAE;QACzD,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,EAAE,CAAC,GAAW,EAAE,GAA6B,EAAQ,EAAE;QACzD,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,KAAK,EAAE,CAAC,GAAW,EAAE,GAA6B,EAAQ,EAAE;QAC1D,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF,CAAC"}
|
package/dist/lib/opa-cli.d.ts
CHANGED
|
@@ -138,7 +138,7 @@ export interface SignInput {
|
|
|
138
138
|
/**
|
|
139
139
|
* Wrapper around the local `opa` binary.
|
|
140
140
|
*
|
|
141
|
-
* Methods do not throw on `opa` errors
|
|
141
|
+
* Methods do not throw on `opa` errors -- non-zero exit codes are
|
|
142
142
|
* surfaced on the returned `SpawnResult` so tools can map them to
|
|
143
143
|
* structured error envelopes at their layer. They DO throw on
|
|
144
144
|
* caller-side bugs (e.g. an empty `paths` array passed where one is
|
|
@@ -154,7 +154,7 @@ export declare class OpaCli {
|
|
|
154
154
|
version(): Promise<string | null>;
|
|
155
155
|
/**
|
|
156
156
|
* Format Rego source. Stdout contains the formatted output. Reports
|
|
157
|
-
* `exitCode: 0` even when no changes are needed
|
|
157
|
+
* `exitCode: 0` even when no changes are needed -- callers compare
|
|
158
158
|
* input vs output to detect a no-op.
|
|
159
159
|
*/
|
|
160
160
|
fmt(input: FmtInput): Promise<SpawnResult>;
|
|
@@ -162,7 +162,7 @@ export declare class OpaCli {
|
|
|
162
162
|
* Type-check Rego. Returns `exitCode: 0` and empty `stdout` when the
|
|
163
163
|
* policy is valid. On failure, `exitCode` is non-zero and the JSON
|
|
164
164
|
* error report is written to **stderr** (this is OPA's actual
|
|
165
|
-
* behavior
|
|
165
|
+
* behavior -- tools must read `stderr`, not `stdout`, for `check`
|
|
166
166
|
* diagnostics). Either inline `source` or one or more `paths` must be
|
|
167
167
|
* provided.
|
|
168
168
|
*/
|
package/dist/lib/opa-cli.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* The `-` (read-from-stdin) convention some opa subcommands document is
|
|
11
11
|
* unreliable on Windows, where `-` is treated as a literal filename.
|
|
12
12
|
*
|
|
13
|
-
* The methods do not parse stdout into typed result objects
|
|
13
|
+
* The methods do not parse stdout into typed result objects -- different
|
|
14
14
|
* tools need different shapes of the same output and a one-size parser
|
|
15
15
|
* would force conversions both ways. Stdout is JSON whenever
|
|
16
16
|
* `--format=json` is set, and tools call `JSON.parse` on it themselves.
|
|
@@ -23,7 +23,7 @@ import { runBinary } from './subprocess.js';
|
|
|
23
23
|
/**
|
|
24
24
|
* Wrapper around the local `opa` binary.
|
|
25
25
|
*
|
|
26
|
-
* Methods do not throw on `opa` errors
|
|
26
|
+
* Methods do not throw on `opa` errors -- non-zero exit codes are
|
|
27
27
|
* surfaced on the returned `SpawnResult` so tools can map them to
|
|
28
28
|
* structured error envelopes at their layer. They DO throw on
|
|
29
29
|
* caller-side bugs (e.g. an empty `paths` array passed where one is
|
|
@@ -48,7 +48,7 @@ export class OpaCli {
|
|
|
48
48
|
// ─── Authoring ───────────────────────────────────────────────────────
|
|
49
49
|
/**
|
|
50
50
|
* Format Rego source. Stdout contains the formatted output. Reports
|
|
51
|
-
* `exitCode: 0` even when no changes are needed
|
|
51
|
+
* `exitCode: 0` even when no changes are needed -- callers compare
|
|
52
52
|
* input vs output to detect a no-op.
|
|
53
53
|
*/
|
|
54
54
|
async fmt(input) {
|
|
@@ -58,7 +58,7 @@ export class OpaCli {
|
|
|
58
58
|
* Type-check Rego. Returns `exitCode: 0` and empty `stdout` when the
|
|
59
59
|
* policy is valid. On failure, `exitCode` is non-zero and the JSON
|
|
60
60
|
* error report is written to **stderr** (this is OPA's actual
|
|
61
|
-
* behavior
|
|
61
|
+
* behavior -- tools must read `stderr`, not `stdout`, for `check`
|
|
62
62
|
* diagnostics). Either inline `source` or one or more `paths` must be
|
|
63
63
|
* provided.
|
|
64
64
|
*/
|
package/dist/lib/opa-client.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface RequestOptions {
|
|
|
29
29
|
body?: unknown;
|
|
30
30
|
/**
|
|
31
31
|
* Raw string body sent verbatim. Used for endpoints that accept
|
|
32
|
-
* non-JSON content
|
|
32
|
+
* non-JSON content -- notably `PUT /v1/policies/{id}` which expects
|
|
33
33
|
* Rego source as `text/plain`.
|
|
34
34
|
*/
|
|
35
35
|
rawBody?: string;
|
package/dist/lib/regal-cli.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export interface LintInput {
|
|
|
39
39
|
/**
|
|
40
40
|
* Wrapper around the local `regal` binary.
|
|
41
41
|
*
|
|
42
|
-
* Like `OpaCli`, methods do not throw on Regal-side errors
|
|
42
|
+
* Like `OpaCli`, methods do not throw on Regal-side errors -- the exit
|
|
43
43
|
* code on the returned `SpawnResult` is the signal. Inline source is
|
|
44
44
|
* always written to a temp file because `regal lint` does not read
|
|
45
45
|
* from stdin.
|
|
@@ -58,9 +58,9 @@ export declare class RegalCli {
|
|
|
58
58
|
* provided.
|
|
59
59
|
*
|
|
60
60
|
* Regal's exit codes:
|
|
61
|
-
* - 0
|
|
62
|
-
* - 3
|
|
63
|
-
* - non-zero other
|
|
61
|
+
* - 0 -- no findings at or above `failLevel`
|
|
62
|
+
* - 3 -- findings present
|
|
63
|
+
* - non-zero other -- Regal-internal failure (config error, etc.)
|
|
64
64
|
*
|
|
65
65
|
* When called with inline `source`, location-bound rules whose
|
|
66
66
|
* verdict depends on the on-disk path (currently
|
package/dist/lib/regal-cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wrapper around the optional `regal` binary (Rego linter, by Styra).
|
|
3
3
|
*
|
|
4
|
-
* Regal is OPTIONAL
|
|
4
|
+
* Regal is OPTIONAL -- only the `rego_lint` tool requires it. Other
|
|
5
5
|
* tools work without Regal installed. If absent, `rego_lint` returns a
|
|
6
6
|
* structured `REGAL_NOT_FOUND` error with an install hint.
|
|
7
7
|
*/
|
|
@@ -21,7 +21,7 @@ export const INLINE_SOURCE_FALSE_POSITIVE_RULES = ['directory-package-mismatch']
|
|
|
21
21
|
/**
|
|
22
22
|
* Wrapper around the local `regal` binary.
|
|
23
23
|
*
|
|
24
|
-
* Like `OpaCli`, methods do not throw on Regal-side errors
|
|
24
|
+
* Like `OpaCli`, methods do not throw on Regal-side errors -- the exit
|
|
25
25
|
* code on the returned `SpawnResult` is the signal. Inline source is
|
|
26
26
|
* always written to a temp file because `regal lint` does not read
|
|
27
27
|
* from stdin.
|
|
@@ -48,9 +48,9 @@ export class RegalCli {
|
|
|
48
48
|
* provided.
|
|
49
49
|
*
|
|
50
50
|
* Regal's exit codes:
|
|
51
|
-
* - 0
|
|
52
|
-
* - 3
|
|
53
|
-
* - non-zero other
|
|
51
|
+
* - 0 -- no findings at or above `failLevel`
|
|
52
|
+
* - 3 -- findings present
|
|
53
|
+
* - non-zero other -- Regal-internal failure (config error, etc.)
|
|
54
54
|
*
|
|
55
55
|
* When called with inline `source`, location-bound rules whose
|
|
56
56
|
* verdict depends on the on-disk path (currently
|
package/dist/lib/subprocess.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface SpawnResult {
|
|
|
19
19
|
durationMs: number;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Run a binary and return its captured output. Never throws
|
|
22
|
+
* Run a binary and return its captured output. Never throws -- failures
|
|
23
23
|
* are reflected in `exitCode` / `timedOut`.
|
|
24
24
|
*/
|
|
25
25
|
export declare function runBinary(binary: string, opts: SpawnOptions): Promise<SpawnResult>;
|
package/dist/lib/subprocess.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subprocess wrapper used by `opa-cli.ts` and `regal-cli.ts`.
|
|
3
3
|
*
|
|
4
|
-
* - Uses argv arrays only (never shell strings)
|
|
4
|
+
* - Uses argv arrays only (never shell strings) -- prevents injection.
|
|
5
5
|
* - Hard timeout per invocation, defaulting to config.subprocessTimeoutMs.
|
|
6
6
|
* - Captures stdout / stderr / exit code separately.
|
|
7
7
|
* - Optional stdin payload for piping source code.
|
|
8
8
|
*/
|
|
9
9
|
import { spawn } from 'node:child_process';
|
|
10
10
|
/**
|
|
11
|
-
* Run a binary and return its captured output. Never throws
|
|
11
|
+
* Run a binary and return its captured output. Never throws -- failures
|
|
12
12
|
* are reflected in `exitCode` / `timedOut`.
|
|
13
13
|
*/
|
|
14
14
|
export async function runBinary(binary, opts) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helpers shared across tool implementations.
|
|
3
3
|
*
|
|
4
|
-
* Each tool follows the same shape
|
|
4
|
+
* Each tool follows the same shape -- validate input, call into a CLI
|
|
5
5
|
* wrapper or HTTP client, map errors to a structured envelope, return
|
|
6
6
|
* the formatted MCP result. The pieces here factor out the parts every
|
|
7
7
|
* tool repeats so each tool file can stay focused on its own logic.
|
package/dist/prompts/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MCP Prompts
|
|
2
|
+
* MCP Prompts -- slash-command-like workflow templates.
|
|
3
3
|
*
|
|
4
4
|
* Each prompt is a stateless instruction set the agent receives when
|
|
5
5
|
* the user invokes it. They orient the agent toward a specific
|
|
@@ -64,7 +64,7 @@ Return a concise review with: pass/fail per item, recommended diffs.`;
|
|
|
64
64
|
const decisionDebuggingWorkflowPrompt = (args) => {
|
|
65
65
|
return `You are debugging an unexpected Rego decision.
|
|
66
66
|
|
|
67
|
-
Query: ${args.query ?? '<not provided
|
|
67
|
+
Query: ${args.query ?? '<not provided -- ask the user>'}
|
|
68
68
|
User's expectation: ${args.expectation ?? '<ask the user what they expected>'}
|
|
69
69
|
|
|
70
70
|
Workflow:
|
|
@@ -77,13 +77,13 @@ Workflow:
|
|
|
77
77
|
3. Re-run with \`rego_explain_decision\` to get a structured trace.
|
|
78
78
|
Identify which rules were evaluated and which fired.
|
|
79
79
|
4. The cause is one of:
|
|
80
|
-
a. **Input mismatch**
|
|
80
|
+
a. **Input mismatch** -- the policy expected a different input shape.
|
|
81
81
|
Use \`rego_describe_policy\` to list the refs the policy reads
|
|
82
82
|
and confirm each is present in the input.
|
|
83
|
-
b. **Rule logic**
|
|
83
|
+
b. **Rule logic** -- a guard fired or didn't fire when it should
|
|
84
84
|
have. Read the trace and explain which rule's body evaluated to
|
|
85
85
|
true/false and why.
|
|
86
|
-
c. **Default decision**
|
|
86
|
+
c. **Default decision** -- no rule produced a value, so the default
|
|
87
87
|
kicked in.
|
|
88
88
|
5. Propose the smallest fix: either an input correction or a policy
|
|
89
89
|
change. If a policy change, run \`rego_check\` and \`rego_test\` on the
|
|
@@ -115,7 +115,7 @@ export function registerPrompts(server, _config) {
|
|
|
115
115
|
source: z
|
|
116
116
|
.string()
|
|
117
117
|
.optional()
|
|
118
|
-
.describe('Rego source to review. Optional
|
|
118
|
+
.describe('Rego source to review. Optional -- agent can ask for it.'),
|
|
119
119
|
},
|
|
120
120
|
}, (args) => ({
|
|
121
121
|
messages: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,MAAM,8BAA8B,GAAG,CAAC,IAGvC,EAAU,EAAE;IACX,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,gBAAgB,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,gCAAgC,CAAC;IAC1E,OAAO;;;;;EAKP,WAAW;;qBAEQ,WAAW;;;;;;;;;;;;;;;gDAegB,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAAC,IAAyB,EAAU,EAAE;IACxE,OAAO;;;EAGP,IAAI,CAAC,MAAM,IAAI,8CAA8C;;;;;;;;;;;;;;;;;;;;;qEAqBM,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,+BAA+B,GAAG,CAAC,IAGxC,EAAU,EAAE;IACX,OAAO;;SAEA,IAAI,CAAC,KAAK,IAAI
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,MAAM,8BAA8B,GAAG,CAAC,IAGvC,EAAU,EAAE;IACX,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,gBAAgB,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,gCAAgC,CAAC;IAC1E,OAAO;;;;;EAKP,WAAW;;qBAEQ,WAAW;;;;;;;;;;;;;;;gDAegB,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAAC,IAAyB,EAAU,EAAE;IACxE,OAAO;;;EAGP,IAAI,CAAC,MAAM,IAAI,8CAA8C;;;;;;;;;;;;;;;;;;;;;qEAqBM,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,+BAA+B,GAAG,CAAC,IAGxC,EAAU,EAAE;IACX,OAAO;;SAEA,IAAI,CAAC,KAAK,IAAI,gCAAgC;sBACjC,IAAI,CAAC,WAAW,IAAI,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;2CAyBlC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,MAAiB,EAAE,OAAe;IAChE,MAAM,CAAC,cAAc,CACnB,4BAA4B,EAC5B;QACE,KAAK,EAAE,4BAA4B;QACnC,WAAW,EACT,uHAAuH;QACzH,UAAU,EAAE;YACV,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YAChF,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;SACvF;KACF,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACT,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,CAAC,IAAI,CAAC,EAAE;aACtE;SACF;KACF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,cAAc,CACnB,yBAAyB,EACzB;QACE,KAAK,EAAE,yBAAyB;QAChC,WAAW,EACT,wHAAwH;QAC1H,UAAU,EAAE;YACV,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,0DAA0D,CAAC;SACxE;KACF,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACT,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,CAAC,IAAI,CAAC,EAAE;aACnE;SACF;KACF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,cAAc,CACnB,6BAA6B,EAC7B;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,2IAA2I;QAC7I,UAAU,EAAE;YACV,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,qDAAqD,CAAC;YAClE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;SACjF;KACF,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACT,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,CAAC,IAAI,CAAC,EAAE;aACvE;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MCP Resources
|
|
2
|
+
* MCP Resources -- read-only references the agent can fetch by URI.
|
|
3
3
|
*
|
|
4
|
-
* - opa://builtins
|
|
5
|
-
* - opa://style-guide
|
|
6
|
-
* - opa://patterns
|
|
4
|
+
* - opa://builtins -- derived at read-time from `opa capabilities`.
|
|
5
|
+
* - opa://style-guide -- curated Rego style guide content.
|
|
6
|
+
* - opa://patterns -- pattern library: RBAC, ABAC, K8s admission,
|
|
7
7
|
* IaC gates, API authz, rate limiting.
|
|
8
8
|
*/
|
|
9
9
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* - A test
|
|
6
6
|
* - Common pitfalls
|
|
7
7
|
*/
|
|
8
|
-
export declare const PATTERNS = "# Rego pattern library\n\nCommon Rego patterns with working examples, tests, and pitfalls. Each\npattern is self-contained
|
|
8
|
+
export declare const PATTERNS = "# Rego pattern library\n\nCommon Rego patterns with working examples, tests, and pitfalls. Each\npattern is self-contained -- copy, adapt, and ship.\n\n---\n\n## 1. Role-based access control (RBAC)\n\n**When to use:** the simplest authorization model. Every user has one\nor more roles; each role grants a set of actions on a set of\nresources. Sufficient for ~80% of internal applications.\n\n```rego\npackage rbac\n\nimport rego.v1\n\ndefault allow := false\n\n# Permissions table -- extend as roles evolve.\npermissions := {\n \"admin\": {\"read\", \"write\", \"delete\", \"manage_users\"},\n \"editor\": {\"read\", \"write\"},\n \"viewer\": {\"read\"},\n}\n\nallow if {\n some role in input.user.roles\n input.action in permissions[role]\n}\n\n# Why was it denied? -- useful for audit logs.\ndeny_reasons contains reason if {\n not allow\n input.user\n reason := sprintf(\n \"user %q has roles %v, none grant %q\",\n [input.user.id, input.user.roles, input.action],\n )\n}\n\ndeny_reasons contains \"anonymous request\" if {\n not allow\n not input.user\n}\n```\n\n**Test:**\n\n```rego\npackage rbac_test\n\nimport rego.v1\nimport data.rbac\n\ntest_admin_can_delete if {\n rbac.allow with input as {\n \"user\": {\"id\": \"alice\", \"roles\": [\"admin\"]},\n \"action\": \"delete\",\n }\n}\n\ntest_viewer_cannot_delete if {\n not rbac.allow with input as {\n \"user\": {\"id\": \"bob\", \"roles\": [\"viewer\"]},\n \"action\": \"delete\",\n }\n}\n\ntest_anonymous_denied if {\n not rbac.allow with input as {\"action\": \"read\"}\n \"anonymous request\" in (rbac.deny_reasons with input as {\"action\": \"read\"})\n}\n```\n\n**Pitfalls:**\n- The `permissions` table grows unbounded. Move to data files\n (`data.permissions`) once you have more than ~20 roles.\n- Roles overlap with groups in real auth systems; map at the boundary\n rather than carrying both.\n\n---\n\n## 2. Attribute-based access control (ABAC)\n\n**When to use:** when \"who\" alone isn't enough -- decisions also depend\non resource attributes (ownership, tenant, sensitivity) and context\n(time of day, source IP).\n\n```rego\npackage abac\n\nimport rego.v1\n\ndefault allow := false\n\n# A user can read any resource they own.\nallow if {\n input.action == \"read\"\n input.resource.owner_id == input.user.id\n}\n\n# A user can read shared resources at their organization.\nallow if {\n input.action == \"read\"\n input.resource.shared\n input.resource.org_id == input.user.org_id\n}\n\n# Admins can do anything within their organization.\nallow if {\n \"admin\" in input.user.roles\n input.resource.org_id == input.user.org_id\n}\n\n# Don't show \"secret\" resources to anyone outside the owner's\n# organization, even admins.\nallow := false if {\n input.resource.classification == \"secret\"\n input.resource.org_id != input.user.org_id\n}\n```\n\n**Test:**\n\n```rego\npackage abac_test\n\nimport rego.v1\nimport data.abac\n\ntest_owner_reads_own if {\n abac.allow with input as {\n \"action\": \"read\",\n \"user\": {\"id\": \"u1\", \"org_id\": \"o1\"},\n \"resource\": {\"owner_id\": \"u1\", \"org_id\": \"o1\"},\n }\n}\n\ntest_admin_blocked_from_secret_in_other_org if {\n not abac.allow with input as {\n \"action\": \"read\",\n \"user\": {\"id\": \"u1\", \"org_id\": \"o1\", \"roles\": [\"admin\"]},\n \"resource\": {\n \"owner_id\": \"u2\",\n \"org_id\": \"o2\",\n \"classification\": \"secret\",\n },\n }\n}\n```\n\n**Pitfalls:**\n- Multiple `allow` rules combine with logical OR. Use explicit\n `allow := false if ...` to *override* an allow.\n- Don't compute attributes inside the policy; compute them at the\n boundary and pass via `input`.\n\n---\n\n## 3. Kubernetes admission control\n\n**When to use:** validate or mutate Kubernetes resources at admission\ntime. Run as a Gatekeeper, OPA-as-a-webhook, or Kyverno-equivalent\npolicy layer.\n\n```rego\npackage k8s.admission\n\nimport rego.v1\n\n# Reject pods without resource limits.\ndeny contains msg if {\n input.request.kind.kind == \"Pod\"\n container := input.request.object.spec.containers[_]\n not container.resources.limits.memory\n msg := sprintf(\n \"Pod %q container %q is missing resources.limits.memory\",\n [input.request.object.metadata.name, container.name],\n )\n}\n\n# Reject privileged containers in production.\ndeny contains msg if {\n input.request.kind.kind == \"Pod\"\n input.request.namespace != \"kube-system\"\n container := input.request.object.spec.containers[_]\n container.securityContext.privileged == true\n msg := sprintf(\n \"privileged containers are not allowed: %q in %q\",\n [container.name, input.request.object.metadata.name],\n )\n}\n```\n\n**Pitfalls:**\n- Use `input.request.object` for the resource being admitted; the\n envelope shape comes from Kubernetes, not your control.\n- For mutations, return a JSON Patch via the `patch` field. Test\n patches with the actual admission webhook in dry-run mode before\n enforcing.\n- Iteration order is undefined; never rely on `containers[0]` to mean\n anything specific.\n\n---\n\n## 4. Infrastructure-as-Code gates (Terraform)\n\n**When to use:** validate Terraform plans before apply. Catch overly\npermissive IAM, public S3 buckets, missing encryption.\n\n```rego\npackage terraform\n\nimport rego.v1\n\n# Reject S3 buckets without server-side encryption.\ndeny contains msg if {\n resource := input.resource_changes[_]\n resource.type == \"aws_s3_bucket\"\n after := resource.change.after\n not after.server_side_encryption_configuration\n msg := sprintf(\n \"S3 bucket %q has no server-side encryption configured\",\n [resource.address],\n )\n}\n\n# Reject IAM policies with action \"*\" on resource \"*\".\ndeny contains msg if {\n resource := input.resource_changes[_]\n resource.type == \"aws_iam_policy\"\n policy := json.unmarshal(resource.change.after.policy)\n statement := policy.Statement[_]\n statement.Effect == \"Allow\"\n \"*\" in statement.Action\n statement.Resource == \"*\"\n msg := sprintf(\"IAM policy %q grants Allow * on *\", [resource.address])\n}\n```\n\n**Pitfalls:**\n- Terraform plan JSON is verbose and version-specific. Pin the\n `terraform plan -json` schema you target.\n- `resource_changes[_].change.after` may be `null` for destroys --\n guard against it.\n- For wide-radius changes, use `opa exec --decision` against a plan\n file in CI, not the live API.\n\n---\n\n## 5. API authorization (HTTP request gating)\n\n**When to use:** at the API gateway / reverse proxy layer, validate\neach request against the caller's identity and the requested\nendpoint.\n\n```rego\npackage api.authz\n\nimport rego.v1\n\ndefault allow := false\n\n# Public endpoints -- no auth required.\npublic_endpoints := {\n {\"method\": \"GET\", \"path\": [\"health\"]},\n {\"method\": \"GET\", \"path\": [\"version\"]},\n}\n\nallow if some _ in public_endpoints; matches_endpoint(_)\n\n# Authenticated reads on resources the user has access to.\nallow if {\n input.method == \"GET\"\n input.user\n user_can_read(input.user, input.path)\n}\n\n# Authenticated writes only with specific scopes.\nallow if {\n input.method in {\"POST\", \"PUT\", \"PATCH\", \"DELETE\"}\n input.user\n \"write\" in input.user.scopes\n user_can_write(input.user, input.path)\n}\n\nmatches_endpoint(spec) if {\n spec.method == input.method\n spec.path == input.path\n}\n\nuser_can_read(user, path) if {\n path[0] == \"users\"\n user.id == path[1]\n}\n\nuser_can_write(user, path) if {\n path[0] == \"users\"\n user.id == path[1]\n}\n```\n\n**Pitfalls:**\n- `input.path` is typically an array (`[\"users\", \"alice\"]`), not a\n string. Build it consistently at the gateway.\n- Path-prefix matching is easy; full pattern matching is not. For\n parameterized routes, decode at the gateway and pass structured\n fields.\n\n---\n\n## 6. Rate limiting (with sliding window data)\n\n**When to use:** allow N requests per principal per window. Lightweight\nlimit enforcement; for high throughput, push to a dedicated rate\nlimiter.\n\n```rego\npackage rate\n\nimport rego.v1\n\n# Configuration: 100 requests per principal per 60-second window.\nlimit := 100\nwindow_seconds := 60\n\n# input.now is a unix timestamp in nanoseconds.\n# data.requests[principal] is an array of nanosecond timestamps.\n\ncurrent_window := requests if {\n requests := [t | some t in data.requests[input.principal]; t > input.now - window_seconds * 1000000000]\n}\n\ncount := count(current_window)\n\nallow if count < limit\n\ndeny_reason := sprintf(\n \"rate limit exceeded: %d requests in last %d seconds (limit %d)\",\n [count, window_seconds, limit],\n) if not allow\n```\n\n**Pitfalls:**\n- `data.requests` grows unbounded unless the writer prunes outside the\n window. Schedule prune on every write.\n- This pattern is *advisory* -- under load, two concurrent decisions\n can both see `count == limit - 1` and both allow. For strict\n limits, use a Lua/Redis token bucket at the gateway and have OPA\n validate the token, not count requests.\n\n---\n\n## Where these patterns came from\n\nEach is distilled from production policy code. The full Rego files,\ntests, and policy data fixtures live in this server's GitHub\nrepository under `tests/fixtures/policies/`.\n\nFor more patterns, see:\n\n- OPA Playground: https://play.openpolicyagent.org/\n- Awesome OPA: https://github.com/anderseknert/awesome-opa\n- Styra DAS pattern library: https://docs.styra.com/das/policies\n";
|
|
9
9
|
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/resources/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/resources/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,ojTA8WpB,CAAC"}
|