@orygn/opa-mcp 0.4.0 → 0.5.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.
Files changed (146) hide show
  1. package/CHANGELOG.md +339 -3
  2. package/README.md +71 -72
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +8 -3
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config.d.ts +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +57 -15
  9. package/dist/config.js.map +1 -1
  10. package/dist/lib/bundle-signatures.d.ts +23 -0
  11. package/dist/lib/bundle-signatures.d.ts.map +1 -0
  12. package/dist/lib/bundle-signatures.js +152 -0
  13. package/dist/lib/bundle-signatures.js.map +1 -0
  14. package/dist/lib/child-env.d.ts +9 -2
  15. package/dist/lib/child-env.d.ts.map +1 -1
  16. package/dist/lib/child-env.js +38 -6
  17. package/dist/lib/child-env.js.map +1 -1
  18. package/dist/lib/conftest-cli.d.ts +25 -10
  19. package/dist/lib/conftest-cli.d.ts.map +1 -1
  20. package/dist/lib/conftest-cli.js +152 -33
  21. package/dist/lib/conftest-cli.js.map +1 -1
  22. package/dist/lib/install-id.d.ts.map +1 -1
  23. package/dist/lib/install-id.js +18 -3
  24. package/dist/lib/install-id.js.map +1 -1
  25. package/dist/lib/json-stream.d.ts +26 -0
  26. package/dist/lib/json-stream.d.ts.map +1 -0
  27. package/dist/lib/json-stream.js +69 -0
  28. package/dist/lib/json-stream.js.map +1 -0
  29. package/dist/lib/opa-cli.d.ts +64 -16
  30. package/dist/lib/opa-cli.d.ts.map +1 -1
  31. package/dist/lib/opa-cli.js +98 -28
  32. package/dist/lib/opa-cli.js.map +1 -1
  33. package/dist/lib/opa-paths.d.ts +24 -0
  34. package/dist/lib/opa-paths.d.ts.map +1 -0
  35. package/dist/lib/opa-paths.js +97 -0
  36. package/dist/lib/opa-paths.js.map +1 -0
  37. package/dist/lib/regal-cli.d.ts +16 -1
  38. package/dist/lib/regal-cli.d.ts.map +1 -1
  39. package/dist/lib/regal-cli.js +40 -6
  40. package/dist/lib/regal-cli.js.map +1 -1
  41. package/dist/lib/rego-ast-walker.d.ts.map +1 -1
  42. package/dist/lib/rego-ast-walker.js +141 -17
  43. package/dist/lib/rego-ast-walker.js.map +1 -1
  44. package/dist/lib/rego-counterexample.d.ts +1 -1
  45. package/dist/lib/rego-counterexample.d.ts.map +1 -1
  46. package/dist/lib/rego-counterexample.js +23 -5
  47. package/dist/lib/rego-counterexample.js.map +1 -1
  48. package/dist/lib/rego-ir.d.ts +32 -2
  49. package/dist/lib/rego-ir.d.ts.map +1 -1
  50. package/dist/lib/rego-smt-encoder.d.ts +53 -5
  51. package/dist/lib/rego-smt-encoder.d.ts.map +1 -1
  52. package/dist/lib/rego-smt-encoder.js +192 -26
  53. package/dist/lib/rego-smt-encoder.js.map +1 -1
  54. package/dist/lib/rego-type-inferencer.d.ts +1 -1
  55. package/dist/lib/rego-type-inferencer.d.ts.map +1 -1
  56. package/dist/lib/rego-type-inferencer.js +3 -3
  57. package/dist/lib/rego-type-inferencer.js.map +1 -1
  58. package/dist/lib/rego-verify-engine.d.ts.map +1 -1
  59. package/dist/lib/rego-verify-engine.js +109 -77
  60. package/dist/lib/rego-verify-engine.js.map +1 -1
  61. package/dist/lib/rego-z3.d.ts +10 -0
  62. package/dist/lib/rego-z3.d.ts.map +1 -1
  63. package/dist/lib/rego-z3.js +38 -0
  64. package/dist/lib/rego-z3.js.map +1 -1
  65. package/dist/lib/security.d.ts +8 -0
  66. package/dist/lib/security.d.ts.map +1 -1
  67. package/dist/lib/security.js +130 -54
  68. package/dist/lib/security.js.map +1 -1
  69. package/dist/resources/patterns.d.ts +1 -1
  70. package/dist/resources/patterns.d.ts.map +1 -1
  71. package/dist/resources/patterns.js +40 -12
  72. package/dist/resources/patterns.js.map +1 -1
  73. package/dist/server.d.ts.map +1 -1
  74. package/dist/server.js +10 -2
  75. package/dist/server.js.map +1 -1
  76. package/dist/tools/bundles/build.d.ts.map +1 -1
  77. package/dist/tools/bundles/build.js +12 -4
  78. package/dist/tools/bundles/build.js.map +1 -1
  79. package/dist/tools/bundles/sign.d.ts +9 -2
  80. package/dist/tools/bundles/sign.d.ts.map +1 -1
  81. package/dist/tools/bundles/sign.js +145 -19
  82. package/dist/tools/bundles/sign.js.map +1 -1
  83. package/dist/tools/bundles/verify.d.ts +1 -1
  84. package/dist/tools/bundles/verify.d.ts.map +1 -1
  85. package/dist/tools/bundles/verify.js +58 -19
  86. package/dist/tools/bundles/verify.js.map +1 -1
  87. package/dist/tools/conftest/pull.d.ts.map +1 -1
  88. package/dist/tools/conftest/pull.js +24 -10
  89. package/dist/tools/conftest/pull.js.map +1 -1
  90. package/dist/tools/conftest/push.d.ts.map +1 -1
  91. package/dist/tools/conftest/push.js +17 -7
  92. package/dist/tools/conftest/push.js.map +1 -1
  93. package/dist/tools/conftest/test.d.ts +10 -6
  94. package/dist/tools/conftest/test.d.ts.map +1 -1
  95. package/dist/tools/conftest/test.js +47 -24
  96. package/dist/tools/conftest/test.js.map +1 -1
  97. package/dist/tools/conftest/verify.d.ts +10 -6
  98. package/dist/tools/conftest/verify.d.ts.map +1 -1
  99. package/dist/tools/conftest/verify.js +30 -18
  100. package/dist/tools/conftest/verify.js.map +1 -1
  101. package/dist/tools/evaluation/bench.d.ts +16 -0
  102. package/dist/tools/evaluation/bench.d.ts.map +1 -1
  103. package/dist/tools/evaluation/bench.js +30 -5
  104. package/dist/tools/evaluation/bench.js.map +1 -1
  105. package/dist/tools/evaluation/exec.d.ts +16 -0
  106. package/dist/tools/evaluation/exec.d.ts.map +1 -1
  107. package/dist/tools/evaluation/exec.js +35 -2
  108. package/dist/tools/evaluation/exec.js.map +1 -1
  109. package/dist/tools/evaluation/test-multiroot.d.ts +4 -0
  110. package/dist/tools/evaluation/test-multiroot.d.ts.map +1 -1
  111. package/dist/tools/evaluation/test-multiroot.js +12 -2
  112. package/dist/tools/evaluation/test-multiroot.js.map +1 -1
  113. package/dist/tools/evaluation/test.d.ts +45 -0
  114. package/dist/tools/evaluation/test.d.ts.map +1 -1
  115. package/dist/tools/evaluation/test.js +146 -27
  116. package/dist/tools/evaluation/test.js.map +1 -1
  117. package/dist/tools/helpers/coverage-gaps.d.ts +11 -3
  118. package/dist/tools/helpers/coverage-gaps.d.ts.map +1 -1
  119. package/dist/tools/helpers/coverage-gaps.js +4 -3
  120. package/dist/tools/helpers/coverage-gaps.js.map +1 -1
  121. package/dist/tools/helpers/explain-undefined.d.ts +9 -3
  122. package/dist/tools/helpers/explain-undefined.d.ts.map +1 -1
  123. package/dist/tools/helpers/explain-undefined.js +83 -51
  124. package/dist/tools/helpers/explain-undefined.js.map +1 -1
  125. package/dist/tools/helpers/verify.d.ts.map +1 -1
  126. package/dist/tools/helpers/verify.js +5 -1
  127. package/dist/tools/helpers/verify.js.map +1 -1
  128. package/dist/tools/server-management/_shared.d.ts +15 -4
  129. package/dist/tools/server-management/_shared.d.ts.map +1 -1
  130. package/dist/tools/server-management/_shared.js +73 -12
  131. package/dist/tools/server-management/_shared.js.map +1 -1
  132. package/dist/tools/server-management/data.d.ts.map +1 -1
  133. package/dist/tools/server-management/data.js +88 -23
  134. package/dist/tools/server-management/data.js.map +1 -1
  135. package/dist/tools/server-management/decisions.d.ts.map +1 -1
  136. package/dist/tools/server-management/decisions.js +16 -3
  137. package/dist/tools/server-management/decisions.js.map +1 -1
  138. package/dist/tools/server-management/policies.d.ts.map +1 -1
  139. package/dist/tools/server-management/policies.js +44 -7
  140. package/dist/tools/server-management/policies.js.map +1 -1
  141. package/dist/tools/server-management/status.d.ts.map +1 -1
  142. package/dist/tools/server-management/status.js +80 -13
  143. package/dist/tools/server-management/status.js.map +1 -1
  144. package/dist/types.d.ts +9 -0
  145. package/dist/types.d.ts.map +1 -1
  146. package/package.json +2 -1
@@ -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 -- 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 reasons := rbac.deny_reasons with input as {\"action\": \"read\"}\n \"anonymous request\" in reasons\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 {\n some endpoint in public_endpoints\n matches_endpoint(endpoint)\n}\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\n# Do not name this rule `count`: it would shadow the built-in of the same\n# name, and the call below would resolve to the rule instead.\nrequest_count := count(current_window)\n\nallow if request_count < limit\n\ndeny_reason := sprintf(\n \"rate limit exceeded: %d requests in last %d seconds (limit %d)\",\n [request_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";
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 reasons := rbac.deny_reasons with input as {\"action\": \"read\"}\n \"anonymous request\" in reasons\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# Don't show \"secret\" resources to anyone outside the owner's\n# organization, even admins.\n#\n# Written as a guard the permissive rules consult. A second rule\n# assigning `allow := false` is a conflict in Rego, not an override:\n# both rules produce a value for the same document and evaluation\n# fails with eval_conflict_error. Deny wins by being a precondition,\n# not by being written last.\nhidden_from_other_org if {\n input.resource.classification == \"secret\"\n input.resource.org_id != input.user.org_id\n}\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 not hidden_from_other_org\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 not hidden_from_other_org\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 not hidden_from_other_org\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. A later rule\n cannot override an earlier one by assigning a different value:\n two rules producing different values for the same document is an\n `eval_conflict_error` and evaluation fails. Express a denial as a\n condition the permissive rules must pass, as `hidden_from_other_org`\n does above.\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 \"*\".\n#\n# AWS accepts either a bare string or an array for Statement, Action\n# and Resource, so each is widened to a set before the wildcard test.\n# Testing the array form alone lets the most common admin policy of\n# all, {\"Action\": \"*\", \"Resource\": \"*\"}, through untouched.\nto_set(v) := {v} if is_string(v)\n\nto_set(v) := {x | some x in v} if is_array(v)\n\nstatements(policy) := to_set(policy.Statement) if is_array(policy.Statement)\n\nstatements(policy) := {policy.Statement} if is_object(policy.Statement)\n\ndeny contains msg if {\n resource := input.resource_changes[_]\n resource.type == \"aws_iam_policy\"\n policy := json.unmarshal(resource.change.after.policy)\n some statement in statements(policy)\n statement.Effect == \"Allow\"\n \"*\" in to_set(statement.Action)\n \"*\" in to_set(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- IAM policy documents are string-or-array in several places. Match\n both, or a policy that grants everything slips through.\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 {\n some endpoint in public_endpoints\n matches_endpoint(endpoint)\n}\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\n# Do not name this rule `count`: it would shadow the built-in of the same\n# name, and the call below would resolve to the rule instead.\nrequest_count := count(current_window)\n\nallow if request_count < limit\n\ndeny_reason := sprintf(\n \"rate limit exceeded: %d requests in last %d seconds (limit %d)\",\n [request_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,wwTAoXpB,CAAC"}
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/resources/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,2iWAgZpB,CAAC"}
@@ -103,10 +103,24 @@ import rego.v1
103
103
 
104
104
  default allow := false
105
105
 
106
+ # Don't show "secret" resources to anyone outside the owner's
107
+ # organization, even admins.
108
+ #
109
+ # Written as a guard the permissive rules consult. A second rule
110
+ # assigning \`allow := false\` is a conflict in Rego, not an override:
111
+ # both rules produce a value for the same document and evaluation
112
+ # fails with eval_conflict_error. Deny wins by being a precondition,
113
+ # not by being written last.
114
+ hidden_from_other_org if {
115
+ input.resource.classification == "secret"
116
+ input.resource.org_id != input.user.org_id
117
+ }
118
+
106
119
  # A user can read any resource they own.
107
120
  allow if {
108
121
  input.action == "read"
109
122
  input.resource.owner_id == input.user.id
123
+ not hidden_from_other_org
110
124
  }
111
125
 
112
126
  # A user can read shared resources at their organization.
@@ -114,19 +128,14 @@ allow if {
114
128
  input.action == "read"
115
129
  input.resource.shared
116
130
  input.resource.org_id == input.user.org_id
131
+ not hidden_from_other_org
117
132
  }
118
133
 
119
134
  # Admins can do anything within their organization.
120
135
  allow if {
121
136
  "admin" in input.user.roles
122
137
  input.resource.org_id == input.user.org_id
123
- }
124
-
125
- # Don't show "secret" resources to anyone outside the owner's
126
- # organization, even admins.
127
- allow := false if {
128
- input.resource.classification == "secret"
129
- input.resource.org_id != input.user.org_id
138
+ not hidden_from_other_org
130
139
  }
131
140
  \`\`\`
132
141
 
@@ -160,8 +169,12 @@ test_admin_blocked_from_secret_in_other_org if {
160
169
  \`\`\`
161
170
 
162
171
  **Pitfalls:**
163
- - Multiple \`allow\` rules combine with logical OR. Use explicit
164
- \`allow := false if ...\` to *override* an allow.
172
+ - Multiple \`allow\` rules combine with logical OR. A later rule
173
+ cannot override an earlier one by assigning a different value:
174
+ two rules producing different values for the same document is an
175
+ \`eval_conflict_error\` and evaluation fails. Express a denial as a
176
+ condition the permissive rules must pass, as \`hidden_from_other_org\`
177
+ does above.
165
178
  - Don't compute attributes inside the policy; compute them at the
166
179
  boundary and pass via \`input\`.
167
180
 
@@ -236,14 +249,27 @@ deny contains msg if {
236
249
  }
237
250
 
238
251
  # Reject IAM policies with action "*" on resource "*".
252
+ #
253
+ # AWS accepts either a bare string or an array for Statement, Action
254
+ # and Resource, so each is widened to a set before the wildcard test.
255
+ # Testing the array form alone lets the most common admin policy of
256
+ # all, {"Action": "*", "Resource": "*"}, through untouched.
257
+ to_set(v) := {v} if is_string(v)
258
+
259
+ to_set(v) := {x | some x in v} if is_array(v)
260
+
261
+ statements(policy) := to_set(policy.Statement) if is_array(policy.Statement)
262
+
263
+ statements(policy) := {policy.Statement} if is_object(policy.Statement)
264
+
239
265
  deny contains msg if {
240
266
  resource := input.resource_changes[_]
241
267
  resource.type == "aws_iam_policy"
242
268
  policy := json.unmarshal(resource.change.after.policy)
243
- statement := policy.Statement[_]
269
+ some statement in statements(policy)
244
270
  statement.Effect == "Allow"
245
- "*" in statement.Action
246
- statement.Resource == "*"
271
+ "*" in to_set(statement.Action)
272
+ "*" in to_set(statement.Resource)
247
273
  msg := sprintf("IAM policy %q grants Allow * on *", [resource.address])
248
274
  }
249
275
  \`\`\`
@@ -253,6 +279,8 @@ deny contains msg if {
253
279
  \`terraform plan -json\` schema you target.
254
280
  - \`resource_changes[_].change.after\` may be \`null\` for destroys --
255
281
  guard against it.
282
+ - IAM policy documents are string-or-array in several places. Match
283
+ both, or a policy that grants everything slips through.
256
284
  - For wide-radius changes, use \`opa exec --decision\` against a plan
257
285
  file in CI, not the live API.
258
286
 
@@ -1 +1 @@
1
- {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/resources/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoXvB,CAAC"}
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/resources/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgZvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAYA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAI/E,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAU7D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAiBvC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAuBrD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CvE;AAED;;;;;;;GAOG;AACH,wBAAsB,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAuBpE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAaA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAI/E,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAU7D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAiBvC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAuBrD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CvE;AAED;;;;;;;GAOG;AACH,wBAAsB,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAuBpE"}
package/dist/server.js CHANGED
@@ -8,7 +8,8 @@
8
8
  * IMPORTANT: never write to stdout from anywhere in this process --
9
9
  * stdout is the MCP protocol channel. Use `logger` (file) or stderr.
10
10
  */
11
- import { pathToFileURL } from 'node:url';
11
+ import { realpathSync } from 'node:fs';
12
+ import { fileURLToPath } from 'node:url';
12
13
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
14
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
15
  import { formatHelp, formatStartupBanner, formatVersion, parseCliArgs } from './cli.js';
@@ -144,9 +145,16 @@ function isEntryPoint() {
144
145
  if (!argv1)
145
146
  return false;
146
147
  try {
147
- return import.meta.url === pathToFileURL(argv1).href;
148
+ // Compare real paths. Node resolves symlinks for the module's own URL but
149
+ // leaves process.argv[1] as it was invoked, so a server reached through a
150
+ // link saw two different strings and started nothing: no --version, no
151
+ // --help, and no transport, which a client sees as a process that exits
152
+ // immediately. npm's bin entry is a symlink on macOS and Linux, and
153
+ // installing globally or running through npx goes through it.
154
+ return realpathSync(fileURLToPath(import.meta.url)) === realpathSync(argv1);
148
155
  }
149
156
  catch {
157
+ // A path that cannot be resolved is not this module.
150
158
  return false;
151
159
  }
152
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/tools/bundles/build.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAmE9C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA+F9E"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/tools/bundles/build.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAwE9C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAqG9E"}
@@ -28,14 +28,17 @@ const OpaBundleBuildInput = {
28
28
  .array(z.string())
29
29
  .optional()
30
30
  .describe('Entrypoint refs (required when `target=wasm` or `optimize > 0`).'),
31
- signingKey: z.string().optional().describe('Path to a signing key for inline signing.'),
31
+ signingKey: z
32
+ .string()
33
+ .optional()
34
+ .describe('Path to a PEM private key for signing the built bundle (`--signing-key`). Implies `bundle: true`, which OPA requires for signing.'),
32
35
  signingAlg: z.string().optional().describe('Signing algorithm (e.g. RS256).'),
33
36
  claimsFile: z.string().optional().describe('Path to a claims file for inline signing.'),
34
37
  capabilities: z.string().optional().describe('Path to a capabilities JSON file.'),
35
38
  bundle: z
36
39
  .boolean()
37
40
  .optional()
38
- .describe('Load `paths` as bundle files or root directories (`--bundle`). Required when rebuilding or re-signing an existing bundle.'),
41
+ .describe('Load `paths` as bundle files or root directories (`--bundle`). Implied by `signingKey` and `verificationKey`; set it explicitly to rebuild an existing bundle without signing.'),
39
42
  pruneUnused: z
40
43
  .boolean()
41
44
  .optional()
@@ -51,7 +54,7 @@ const OpaBundleBuildInput = {
51
54
  verificationKey: z
52
55
  .string()
53
56
  .optional()
54
- .describe('Path to a PEM public key (or HMAC secret file) used to re-verify an existing signed bundle during the build (`--verification-key`). Pair with `bundle: true`.'),
57
+ .describe('Path to a PEM public key (or HMAC secret file) used to re-verify an existing signed bundle during the build (`--verification-key`). Implies `bundle: true`, which OPA requires for verification.'),
55
58
  verificationKeyId: z
56
59
  .string()
57
60
  .optional()
@@ -117,7 +120,12 @@ export function registerOpaBundleBuild(server, config) {
117
120
  signingAlg: input.signingAlg,
118
121
  claimsFile: resolvedClaimsFile,
119
122
  capabilities: resolvedCapabilities,
120
- bundle: input.bundle,
123
+ // opa build refuses --signing-key and --verification-key outside
124
+ // bundle mode ("enable bundle mode (ie. --bundle) to verify or sign
125
+ // bundle files or directories"), so either option implies it.
126
+ bundle: input.bundle === true ||
127
+ input.signingKey !== undefined ||
128
+ input.verificationKey !== undefined,
121
129
  pruneUnused: input.pruneUnused,
122
130
  ignore: input.ignore,
123
131
  v1Compatible: input.v1Compatible,
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/tools/bundles/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/tools/bundles/build.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElG,MAAM,mBAAmB,GAAG;IAC1B,KAAK,EAAE,CAAC;SACL,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,kEAAkE,CAAC;IAC/E,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,wEAAwE,CAAC;IACrF,QAAQ,EAAE,CAAC;SACR,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;SACjD,QAAQ,EAAE;SACV,QAAQ,CAAC,gDAAgD,CAAC;IAC7D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IAC3F,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;SACtB,QAAQ,EAAE;SACV,QAAQ,CAAC,gEAAgE,CAAC;IAC7E,WAAW,EAAE,CAAC;SACX,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,kEAAkE,CAAC;IAC/E,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,mIAAmI,CACpI;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC7E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;IACvF,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACjF,MAAM,EAAE,CAAC;SACN,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,gLAAgL,CACjL;IACH,WAAW,EAAE,CAAC;SACX,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,6HAA6H,CAC9H;IACH,MAAM,EAAE,CAAC;SACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CACP,wJAAwJ,CACzJ;IACH,YAAY,EAAE,CAAC;SACZ,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,4GAA4G,CAC7G;IACH,eAAe,EAAE,CAAC;SACf,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,kMAAkM,CACnM;IACH,iBAAiB,EAAE,CAAC;SACjB,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,2EAA2E,CAAC;CACzF,CAAC;AAOF,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,MAAc;IACtE,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;IAE/B,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EACT,wMAAwM;QAC1M,WAAW,EAAE,mBAAmB;QAChC,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI;YACrB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,OAAO,gBAAgB,CAAuB,MAAM,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACrD,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,OAAO,UAAU,CAAC,KAAK,CAAC;YAE5C,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrE,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAE,CAAC;YAE5D,wEAAwE;YACxE,IAAI,kBAAsC,CAAC;YAC3C,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzE,IAAI,CAAC,CAAC,CAAC,EAAE;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC;gBAC1B,kBAAkB,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,kBAAsC,CAAC;YAC3C,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACzE,IAAI,CAAC,CAAC,CAAC,EAAE;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC;gBAC1B,kBAAkB,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,oBAAwC,CAAC;YAC7C,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;gBACvB,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3E,IAAI,CAAC,CAAC,CAAC,EAAE;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC;gBAC1B,oBAAoB,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,uBAA2C,CAAC;YAChD,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9E,IAAI,CAAC,CAAC,CAAC,EAAE;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC;gBAC1B,uBAAuB,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAC5B;gBACE,KAAK,EAAE,WAAW;gBAClB,MAAM,EAAE,UAAU;gBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,UAAU,EAAE,kBAAkB;gBAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,UAAU,EAAE,kBAAkB;gBAC9B,YAAY,EAAE,oBAAoB;gBAClC,iEAAiE;gBACjE,oEAAoE;gBACpE,8DAA8D;gBAC9D,MAAM,EACJ,KAAK,CAAC,MAAM,KAAK,IAAI;oBACrB,KAAK,CAAC,UAAU,KAAK,SAAS;oBAC9B,KAAK,CAAC,eAAe,KAAK,SAAS;gBACrC,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,eAAe,EAAE,uBAAuB;gBACxC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;aAC3C,EACD,MAAM,CACP,CAAC;YAEF,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9D,IAAI,iBAAiB;gBAAE,OAAO,iBAAiB,CAAC;YAEhD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,GAAG,CAAC,cAAc,EAAE,mBAAmB,EAAE;oBAC9C,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE;iBACxE,CAAC,CAAC;YACL,CAAC;YAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;YACxC,OAAO,EAAE,CAAuB;gBAC9B,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,QAAQ,CAAC,IAAI;aACrB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,8 +1,15 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type { Config } from '../../config.js';
3
3
  export interface OpaBundleSignOutput {
4
- signed: boolean;
5
- signaturesPath?: string;
4
+ signed: true;
5
+ /** Absolute path of the `.signatures.json` that was written. */
6
+ signaturesPath: string;
7
+ /** JWT algorithm recorded in the signature header. */
8
+ algorithm: string;
9
+ /** Number of files the signature covers. */
10
+ filesSigned: number;
11
+ keyId?: string;
12
+ scope?: string;
6
13
  }
7
14
  export declare function registerOpaBundleSign(server: McpServer, config: Config): void;
8
15
  //# sourceMappingURL=sign.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../../../src/tools/bundles/sign.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAe9C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAgD7E"}
1
+ {"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../../../src/tools/bundles/sign.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AA+C9C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,IAAI,CAAC;IACb,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAWD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA+J7E"}
@@ -1,25 +1,58 @@
1
- /**
2
- * `opa_bundle_sign` -- sign an existing bundle directory or archive
3
- * via `opa sign`.
4
- */
1
+ import { lstat, readlink, realpath, stat } from 'node:fs/promises';
2
+ import { basename, dirname, join } from 'node:path';
5
3
  import { z } from 'zod';
6
- import { OpaCli } from '../../lib/opa-cli.js';
4
+ import { isKeyOrAlgorithmError, readSignaturesSummary } from '../../lib/bundle-signatures.js';
7
5
  import { err, ok } from '../../lib/errors.js';
6
+ import { OpaCli } from '../../lib/opa-cli.js';
8
7
  import { mapSubprocessFailure, validatePaths, withToolEnvelope } from '../../lib/tool-helpers.js';
8
+ const SIGNATURES_FILE = '.signatures.json';
9
+ /**
10
+ * How far before the call a pre-existing `.signatures.json` may have been
11
+ * modified and still count as written by this call. Filesystems with coarse
12
+ * timestamps (FAT: 2s, HFS+: 1s) can report an unchanged mtime for a rewrite
13
+ * inside the same tick, and a clock only ever compares against itself here.
14
+ */
15
+ const MTIME_SLACK_MS = 2000;
9
16
  const OpaBundleSignInput = {
10
17
  bundle: z
11
18
  .string()
12
19
  .min(1)
13
- .describe('Path to a bundle directory or archive. Must be in an allowed root.'),
14
- signingKey: z.string().min(1).describe('Path to the signing key.'),
15
- signingAlg: z.string().optional().describe('Signing algorithm (e.g. RS256). Default: RS256.'),
16
- claimsFile: z.string().optional().describe('Path to extra claims to include in the signature.'),
20
+ .describe('Path to a bundle directory or `.tar.gz` archive. Must be inside an allowed root.'),
21
+ signingKey: z
22
+ .string()
23
+ .min(1)
24
+ .describe('Path to the PEM private key (RSA or ECDSA), or for HMAC algorithms a file holding the secret. Must be inside an allowed root.'),
25
+ signingAlg: z
26
+ .string()
27
+ .optional()
28
+ .describe('Signing algorithm: RS256 (default), RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, HS256, HS384, HS512.'),
29
+ claimsFile: z
30
+ .string()
31
+ .optional()
32
+ .describe('Path to a JSON file of extra claims to sign, such as {"keyid": "...", "scope": "..."}. Must be inside an allowed root.'),
33
+ outputDir: z
34
+ .string()
35
+ .optional()
36
+ .describe("For an archive, the directory that receives `.signatures.json`; defaults to the archive's own directory. Must exist and be inside an allowed root. Not accepted for a directory bundle, which is signed in place."),
17
37
  };
38
+ /** lstat, so a symlink is reported as itself rather than as its target. */
39
+ async function lstatOrUndefined(path) {
40
+ try {
41
+ return await lstat(path);
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ }
18
47
  export function registerOpaBundleSign(server, config) {
19
48
  const opa = new OpaCli(config);
20
49
  server.registerTool('opa_bundle_sign', {
21
50
  title: 'Sign OPA bundle',
22
- description: 'Sign an OPA bundle with a private key using `opa sign`. Writes a `.signatures.json` next to the bundle directory, or updates the archive in place.',
51
+ description: 'Sign a bundle directory or `.tar.gz` archive with `opa sign`. ' +
52
+ 'A directory is signed in place: `.signatures.json` is written into it and files are recorded as `<directory name>/<file>`, so the signed directory verifies wherever it is placed as long as its name is unchanged, with `opa_bundle_verify` or with `opa build` or `opa run --bundle <name>` from its parent. ' +
53
+ "For an archive the signature is written beside it, into `outputDir` or the archive's own directory, and the archive is not modified; a signed archive comes from `opa_bundle_build` with `signingKey`. " +
54
+ 'The key is a PEM private key (RSA or ECDSA); for HMAC algorithms pass a file holding the secret. Extra claims such as `keyid` and `scope` come from `claimsFile`. ' +
55
+ 'Returns the path written, the algorithm, and the number of files covered.',
23
56
  inputSchema: OpaBundleSignInput,
24
57
  annotations: {
25
58
  readOnlyHint: false,
@@ -32,21 +65,114 @@ export function registerOpaBundleSign(server, config) {
32
65
  const validation = validatePaths([input.bundle, input.signingKey, ...(input.claimsFile ? [input.claimsFile] : [])], config, { mustExist: true });
33
66
  if (!validation.ok)
34
67
  return validation.error;
35
- const result = await opa.sign({
36
- bundle: validation.resolved[0],
37
- signingKey: validation.resolved[1],
38
- signingAlg: input.signingAlg,
39
- claimsFile: input.claimsFile ? validation.resolved[2] : undefined,
40
- }, signal);
68
+ const [resolvedBundle, resolvedKey, resolvedClaims] = validation.resolved;
69
+ // validatePath returns the path as given once its real target is
70
+ // inside an allowed root. OPA's directory walk does not descend a
71
+ // symlink or junction root, so a linked bundle would sign as an empty
72
+ // file list; the real path is what gets signed.
73
+ const realBundle = await realpath(resolvedBundle);
74
+ const isDirectory = (await stat(realBundle)).isDirectory();
75
+ let outputDir;
76
+ if (isDirectory) {
77
+ if (input.outputDir !== undefined) {
78
+ return err('INVALID_INPUT', `outputDir applies to archives only. A directory bundle is signed in place, since OPA reads ${SIGNATURES_FILE} from inside the bundle and cannot use a detached one.`, { details: { bundle: input.bundle } });
79
+ }
80
+ outputDir = realBundle;
81
+ }
82
+ else {
83
+ // The archive's own directory is derived from the path as given,
84
+ // not from the real path: an allowed root that is itself a symlink
85
+ // or a Windows short name (a macOS /var, an 8.3 temp directory)
86
+ // would otherwise fail the syntactic containment check against its
87
+ // own canonical form. Validation resolves the symlink itself.
88
+ const requested = input.outputDir ?? dirname(resolvedBundle);
89
+ const outputValidation = validatePaths([requested], config, { mustExist: true });
90
+ if (!outputValidation.ok)
91
+ return outputValidation.error;
92
+ outputDir = outputValidation.resolved[0];
93
+ if (!(await stat(outputDir)).isDirectory()) {
94
+ return err('INVALID_INPUT', 'outputDir must be an existing directory.', {
95
+ details: { outputDir },
96
+ });
97
+ }
98
+ }
99
+ const signaturesPath = join(outputDir, SIGNATURES_FILE);
100
+ // The directory is inside an allowed root, but the file inside it need
101
+ // not be: a pre-existing `.signatures.json` that is a symlink would
102
+ // have opa write through it to wherever it points.
103
+ const before = await lstatOrUndefined(signaturesPath);
104
+ if (before?.isSymbolicLink()) {
105
+ return err('PATH_NOT_ALLOWED', `${SIGNATURES_FILE} at the output location is a symbolic link; refusing to write through it.`, { details: { signaturesPath } });
106
+ }
107
+ const startedAt = Date.now();
108
+ const signInput = {
109
+ bundle: isDirectory ? basename(realBundle) : realBundle,
110
+ signingKey: resolvedKey,
111
+ outputDir,
112
+ };
113
+ if (isDirectory)
114
+ signInput.cwd = dirname(realBundle);
115
+ if (input.signingAlg !== undefined)
116
+ signInput.signingAlg = input.signingAlg;
117
+ if (resolvedClaims !== undefined)
118
+ signInput.claimsFile = resolvedClaims;
119
+ const result = await opa.sign(signInput, signal);
41
120
  const subprocessFailure = mapSubprocessFailure(result, 'opa');
42
121
  if (subprocessFailure)
43
122
  return subprocessFailure;
123
+ // opa prints its own errors on stdout, so both streams are kept.
124
+ const streams = { stderr: result.stderr.trim(), stdout: result.stdout.trim() };
44
125
  if (result.exitCode !== 0) {
45
- return err('INVALID_BUNDLE', 'opa sign failed.', {
46
- details: { stderr: result.stderr.trim() },
126
+ if (isKeyOrAlgorithmError(`${result.stdout}\n${result.stderr}`)) {
127
+ return err('INVALID_INPUT', 'The signing key or algorithm could not be used.', {
128
+ hint: 'signingKey must be a PEM private key, or for HS256, HS384 and HS512 a file holding the secret, and signingAlg one OPA supports.',
129
+ details: streams,
130
+ });
131
+ }
132
+ return err('INVALID_BUNDLE', 'opa sign failed.', { details: streams });
133
+ }
134
+ // Exit 0 is not the claim; the file is. A signature that was not
135
+ // written, or a stale one from an earlier run, must not be reported
136
+ // as this call's work.
137
+ const after = await lstatOrUndefined(signaturesPath);
138
+ if (after?.isSymbolicLink()) {
139
+ // A link planted between the check above and opa's write has
140
+ // already been followed. Say so, and do not report success.
141
+ const target = await readlink(signaturesPath).catch(() => undefined);
142
+ return err('PATH_NOT_ALLOWED', `${SIGNATURES_FILE} at the output location became a symbolic link while opa ran; the signature may have been written to its target. Not reporting success.`, { details: { signaturesPath, target } });
143
+ }
144
+ const written = after !== undefined &&
145
+ (before === undefined || after.mtimeMs >= startedAt - MTIME_SLACK_MS);
146
+ if (!written) {
147
+ return err('UNKNOWN_ERROR', `opa sign exited 0 but did not write ${SIGNATURES_FILE}.`, {
148
+ details: { signaturesPath, ...streams },
149
+ });
150
+ }
151
+ let summary;
152
+ try {
153
+ summary = await readSignaturesSummary(signaturesPath);
154
+ }
155
+ catch (e) {
156
+ return err('UNKNOWN_ERROR', `opa sign wrote a ${SIGNATURES_FILE} this tool could not read.`, { details: { signaturesPath, error: e instanceof Error ? e.message : String(e) } });
157
+ }
158
+ // A signature over nothing is what an empty directory produces. It
159
+ // verifies nothing and is not worth reporting as success.
160
+ if (summary.filesSigned === 0) {
161
+ return err('INVALID_BUNDLE', 'opa sign covered no files: the bundle is empty.', {
162
+ details: { signaturesPath },
47
163
  });
48
164
  }
49
- return ok({ signed: true });
165
+ const output = {
166
+ signed: true,
167
+ signaturesPath,
168
+ algorithm: summary.algorithm,
169
+ filesSigned: summary.filesSigned,
170
+ };
171
+ if (summary.keyId !== undefined)
172
+ output.keyId = summary.keyId;
173
+ if (summary.scope !== undefined)
174
+ output.scope = summary.scope;
175
+ return ok(output);
50
176
  });
51
177
  });
52
178
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sign.js","sourceRoot":"","sources":["../../../src/tools/bundles/sign.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElG,MAAM,kBAAkB,GAAG;IACzB,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,oEAAoE,CAAC;IACjF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IAClE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IAC7F,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;CAChG,CAAC;AAOF,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAc;IACrE,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;IAE/B,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,oJAAoJ;QACtJ,WAAW,EAAE,kBAAkB;QAC/B,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI;YACrB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QAC1B,OAAO,gBAAgB,CAAsB,MAAM,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,UAAU,GAAG,aAAa,CAC9B,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EACjF,MAAM,EACN,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,OAAO,UAAU,CAAC,KAAK,CAAC;YAE5C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAC3B;gBACE,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAE;gBAC/B,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAE;gBACnC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;aAClE,EACD,MAAM,CACP,CAAC;YAEF,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9D,IAAI,iBAAiB;gBAAE,OAAO,iBAAiB,CAAC;YAEhD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,GAAG,CAAC,gBAAgB,EAAE,kBAAkB,EAAE;oBAC/C,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE;iBAC1C,CAAC,CAAC;YACL,CAAC;YACD,OAAO,EAAE,CAAsB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sign.js","sourceRoot":"","sources":["../../../src/tools/bundles/sign.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type { Config } from '../../config.js';
3
3
  export interface OpaBundleVerifyOutput {
4
4
  bundle: string;
5
- verified: boolean;
5
+ verified: true;
6
6
  }
7
7
  export declare function registerOpaBundleVerify(server: McpServer, config: Config): void;
8
8
  //# sourceMappingURL=verify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/tools/bundles/verify.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAsC9C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAqD/E"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/tools/bundles/verify.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AA6C9C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,IAAI,CAAC;CAChB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAiF/E"}