cedar-mcp-server 1.0.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 (215) hide show
  1. package/.editorconfig +12 -0
  2. package/.github/workflows/ci.yml +31 -0
  3. package/.github/workflows/release.yml +42 -0
  4. package/.nvmrc +1 -0
  5. package/CHANGELOG.md +241 -0
  6. package/CONTRIBUTING.md +83 -0
  7. package/LICENSE +182 -0
  8. package/README.md +1635 -0
  9. package/SECURITY.md +37 -0
  10. package/dist/http-server.d.ts +61 -0
  11. package/dist/http-server.d.ts.map +1 -0
  12. package/dist/http-server.js +194 -0
  13. package/dist/http-server.js.map +1 -0
  14. package/dist/index.d.ts +32 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +270 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/parser/policy-ast.d.ts +49 -0
  19. package/dist/parser/policy-ast.d.ts.map +1 -0
  20. package/dist/parser/policy-ast.js +311 -0
  21. package/dist/parser/policy-ast.js.map +1 -0
  22. package/dist/prompts/index.d.ts +38 -0
  23. package/dist/prompts/index.d.ts.map +1 -0
  24. package/dist/prompts/index.js +172 -0
  25. package/dist/prompts/index.js.map +1 -0
  26. package/dist/resources/ref-resolver.d.ts +23 -0
  27. package/dist/resources/ref-resolver.d.ts.map +1 -0
  28. package/dist/resources/ref-resolver.js +128 -0
  29. package/dist/resources/ref-resolver.js.map +1 -0
  30. package/dist/resources/store-manager.d.ts +64 -0
  31. package/dist/resources/store-manager.d.ts.map +1 -0
  32. package/dist/resources/store-manager.js +221 -0
  33. package/dist/resources/store-manager.js.map +1 -0
  34. package/dist/server.d.ts +18 -0
  35. package/dist/server.d.ts.map +1 -0
  36. package/dist/server.js +539 -0
  37. package/dist/server.js.map +1 -0
  38. package/dist/tools/advise/avp-rules.d.ts +49 -0
  39. package/dist/tools/advise/avp-rules.d.ts.map +1 -0
  40. package/dist/tools/advise/avp-rules.js +59 -0
  41. package/dist/tools/advise/avp-rules.js.map +1 -0
  42. package/dist/tools/advise/cedar-patterns.d.ts +24 -0
  43. package/dist/tools/advise/cedar-patterns.d.ts.map +1 -0
  44. package/dist/tools/advise/cedar-patterns.js +57 -0
  45. package/dist/tools/advise/cedar-patterns.js.map +1 -0
  46. package/dist/tools/advise/context-builder.d.ts +28 -0
  47. package/dist/tools/advise/context-builder.d.ts.map +1 -0
  48. package/dist/tools/advise/context-builder.js +89 -0
  49. package/dist/tools/advise/context-builder.js.map +1 -0
  50. package/dist/tools/advise/gotchas.d.ts +15 -0
  51. package/dist/tools/advise/gotchas.d.ts.map +1 -0
  52. package/dist/tools/advise/gotchas.js +83 -0
  53. package/dist/tools/advise/gotchas.js.map +1 -0
  54. package/dist/tools/advise.d.ts +96 -0
  55. package/dist/tools/advise.d.ts.map +1 -0
  56. package/dist/tools/advise.js +258 -0
  57. package/dist/tools/advise.js.map +1 -0
  58. package/dist/tools/authorize-batch.d.ts +35 -0
  59. package/dist/tools/authorize-batch.d.ts.map +1 -0
  60. package/dist/tools/authorize-batch.js +262 -0
  61. package/dist/tools/authorize-batch.js.map +1 -0
  62. package/dist/tools/authorize.d.ts +115 -0
  63. package/dist/tools/authorize.d.ts.map +1 -0
  64. package/dist/tools/authorize.js +373 -0
  65. package/dist/tools/authorize.js.map +1 -0
  66. package/dist/tools/check-change.d.ts +19 -0
  67. package/dist/tools/check-change.d.ts.map +1 -0
  68. package/dist/tools/check-change.js +91 -0
  69. package/dist/tools/check-change.js.map +1 -0
  70. package/dist/tools/diff-schema.d.ts +103 -0
  71. package/dist/tools/diff-schema.d.ts.map +1 -0
  72. package/dist/tools/diff-schema.js +379 -0
  73. package/dist/tools/diff-schema.js.map +1 -0
  74. package/dist/tools/diff-stores.d.ts +45 -0
  75. package/dist/tools/diff-stores.d.ts.map +1 -0
  76. package/dist/tools/diff-stores.js +222 -0
  77. package/dist/tools/diff-stores.js.map +1 -0
  78. package/dist/tools/explain.d.ts +80 -0
  79. package/dist/tools/explain.d.ts.map +1 -0
  80. package/dist/tools/explain.js +187 -0
  81. package/dist/tools/explain.js.map +1 -0
  82. package/dist/tools/format.d.ts +11 -0
  83. package/dist/tools/format.d.ts.map +1 -0
  84. package/dist/tools/format.js +20 -0
  85. package/dist/tools/format.js.map +1 -0
  86. package/dist/tools/generate-sample.d.ts +28 -0
  87. package/dist/tools/generate-sample.d.ts.map +1 -0
  88. package/dist/tools/generate-sample.js +568 -0
  89. package/dist/tools/generate-sample.js.map +1 -0
  90. package/dist/tools/link-template.d.ts +17 -0
  91. package/dist/tools/link-template.d.ts.map +1 -0
  92. package/dist/tools/link-template.js +78 -0
  93. package/dist/tools/link-template.js.map +1 -0
  94. package/dist/tools/list-template-links.d.ts +16 -0
  95. package/dist/tools/list-template-links.d.ts.map +1 -0
  96. package/dist/tools/list-template-links.js +22 -0
  97. package/dist/tools/list-template-links.js.map +1 -0
  98. package/dist/tools/list-templates.d.ts +16 -0
  99. package/dist/tools/list-templates.d.ts.map +1 -0
  100. package/dist/tools/list-templates.js +36 -0
  101. package/dist/tools/list-templates.js.map +1 -0
  102. package/dist/tools/translate.d.ts +11 -0
  103. package/dist/tools/translate.d.ts.map +1 -0
  104. package/dist/tools/translate.js +53 -0
  105. package/dist/tools/translate.js.map +1 -0
  106. package/dist/tools/validate-entities.d.ts +19 -0
  107. package/dist/tools/validate-entities.d.ts.map +1 -0
  108. package/dist/tools/validate-entities.js +88 -0
  109. package/dist/tools/validate-entities.js.map +1 -0
  110. package/dist/tools/validate-schema.d.ts +22 -0
  111. package/dist/tools/validate-schema.d.ts.map +1 -0
  112. package/dist/tools/validate-schema.js +89 -0
  113. package/dist/tools/validate-schema.js.map +1 -0
  114. package/dist/tools/validate-template.d.ts +18 -0
  115. package/dist/tools/validate-template.d.ts.map +1 -0
  116. package/dist/tools/validate-template.js +59 -0
  117. package/dist/tools/validate-template.js.map +1 -0
  118. package/dist/tools/validate.d.ts +90 -0
  119. package/dist/tools/validate.d.ts.map +1 -0
  120. package/dist/tools/validate.js +351 -0
  121. package/dist/tools/validate.js.map +1 -0
  122. package/dist/utils/format-detector.d.ts +49 -0
  123. package/dist/utils/format-detector.d.ts.map +1 -0
  124. package/dist/utils/format-detector.js +298 -0
  125. package/dist/utils/format-detector.js.map +1 -0
  126. package/examples/README.md +36 -0
  127. package/examples/abac-multi-tenant/README.md +150 -0
  128. package/examples/abac-multi-tenant/entities/users-and-docs.json +33 -0
  129. package/examples/abac-multi-tenant/policies/member-read-internal.cedar +9 -0
  130. package/examples/abac-multi-tenant/policies/owner-full-access.cedar +9 -0
  131. package/examples/abac-multi-tenant/policies/premium-share-guard.cedar +9 -0
  132. package/examples/abac-multi-tenant/policies/private-doc-guard.cedar +13 -0
  133. package/examples/abac-multi-tenant/run.ts +92 -0
  134. package/examples/abac-multi-tenant/schema.json +60 -0
  135. package/examples/api-gateway-path-routing/README.md +154 -0
  136. package/examples/api-gateway-path-routing/entities/users-and-roles.json +20 -0
  137. package/examples/api-gateway-path-routing/policies/admin-full-access.cedar +6 -0
  138. package/examples/api-gateway-path-routing/policies/developer-projects.cedar +14 -0
  139. package/examples/api-gateway-path-routing/policies/viewer-readonly.cedar +10 -0
  140. package/examples/api-gateway-path-routing/run.ts +108 -0
  141. package/examples/api-gateway-path-routing/schema.json +54 -0
  142. package/examples/rbac-document-management/README.md +167 -0
  143. package/examples/rbac-document-management/entities/users-and-docs.json +43 -0
  144. package/examples/rbac-document-management/policies/admin.cedar +6 -0
  145. package/examples/rbac-document-management/policies/editor.cedar +6 -0
  146. package/examples/rbac-document-management/policies/top-secret-forbid.cedar +13 -0
  147. package/examples/rbac-document-management/policies/viewer.cedar +6 -0
  148. package/examples/rbac-document-management/run.ts +87 -0
  149. package/examples/rbac-document-management/schema.json +57 -0
  150. package/package.json +50 -0
  151. package/src/http-server.ts +239 -0
  152. package/src/index.ts +294 -0
  153. package/src/parser/policy-ast.ts +345 -0
  154. package/src/prompts/README.md +3 -0
  155. package/src/prompts/index.ts +217 -0
  156. package/src/resources/ref-resolver.ts +134 -0
  157. package/src/resources/store-manager.ts +248 -0
  158. package/src/server.ts +711 -0
  159. package/src/tools/advise/avp-rules.ts +70 -0
  160. package/src/tools/advise/cedar-patterns.ts +73 -0
  161. package/src/tools/advise/context-builder.ts +109 -0
  162. package/src/tools/advise/gotchas.ts +92 -0
  163. package/src/tools/advise.ts +366 -0
  164. package/src/tools/authorize-batch.ts +345 -0
  165. package/src/tools/authorize.ts +464 -0
  166. package/src/tools/check-change.ts +119 -0
  167. package/src/tools/diff-schema.ts +510 -0
  168. package/src/tools/diff-stores.ts +298 -0
  169. package/src/tools/explain.ts +278 -0
  170. package/src/tools/format.ts +33 -0
  171. package/src/tools/generate-sample.ts +665 -0
  172. package/src/tools/link-template.ts +109 -0
  173. package/src/tools/list-template-links.ts +41 -0
  174. package/src/tools/list-templates.ts +55 -0
  175. package/src/tools/translate.ts +66 -0
  176. package/src/tools/validate-entities.ts +125 -0
  177. package/src/tools/validate-schema.ts +128 -0
  178. package/src/tools/validate-template.ts +72 -0
  179. package/src/tools/validate.ts +459 -0
  180. package/src/utils/format-detector.ts +356 -0
  181. package/test/fixtures/docmgmt.ts +121 -0
  182. package/test/fixtures/multitenant.ts +163 -0
  183. package/test/index.test.ts +96 -0
  184. package/test/integration/e2e/behavior.test.ts +359 -0
  185. package/test/integration/e2e/edge-cases.test.ts +365 -0
  186. package/test/integration/e2e/failure-modes.test.ts +266 -0
  187. package/test/integration/e2e/protocol.test.ts +252 -0
  188. package/test/integration/http-smoke.test.ts +588 -0
  189. package/test/integration/smoke.test.ts +475 -0
  190. package/test/prompts/prompts.test.ts +173 -0
  191. package/test/property/properties.test.ts +234 -0
  192. package/test/resources/ref-resolver.test.ts +186 -0
  193. package/test/resources/store-manager.test.ts +344 -0
  194. package/test/setup.test.ts +7 -0
  195. package/test/tools/advise/avp-rules.test.ts +76 -0
  196. package/test/tools/advise.test.ts +339 -0
  197. package/test/tools/authorize-batch.test.ts +459 -0
  198. package/test/tools/authorize.test.ts +682 -0
  199. package/test/tools/check-change.test.ts +104 -0
  200. package/test/tools/cross-fixture.test.ts +170 -0
  201. package/test/tools/diff-schema.test.ts +355 -0
  202. package/test/tools/diff-stores.test.ts +291 -0
  203. package/test/tools/explain.test.ts +221 -0
  204. package/test/tools/format.test.ts +33 -0
  205. package/test/tools/generate-sample.test.ts +480 -0
  206. package/test/tools/link-template.test.ts +90 -0
  207. package/test/tools/list-templates.test.ts +151 -0
  208. package/test/tools/translate.test.ts +89 -0
  209. package/test/tools/validate-entities.test.ts +178 -0
  210. package/test/tools/validate-schema.test.ts +86 -0
  211. package/test/tools/validate-template.test.ts +89 -0
  212. package/test/tools/validate.test.ts +331 -0
  213. package/test/utils/format-detector.test.ts +518 -0
  214. package/tsconfig.json +17 -0
  215. package/vitest.config.ts +13 -0
@@ -0,0 +1,258 @@
1
+ /**
2
+ * cedar_advise — Cedar policy change planning context preparator.
3
+ *
4
+ * This tool returns deterministic, structured context for the calling LLM to
5
+ * produce a Cedar policy change plan natively. No MCP sampling, no client LLM
6
+ * round-trip. The bundle encodes Cedar/AVP knowledge that does not live in the
7
+ * policy files themselves (pattern classification, AVP UpdatePolicy mutability
8
+ * rules, intent-selected gotchas, sequencing rules) and is what makes the
9
+ * server load-bearing rather than substitutable by Read.
10
+ *
11
+ * Design v2, 2026-05-21: pivoted from sampling-based planner. See
12
+ * projects/cedar-mcp-server/02-technical-design.md "design v2".
13
+ */
14
+ import { checkParseSchema, schemaToJsonWithResolvedTypes } from "@cedar-policy/cedar-wasm/nodejs";
15
+ import { resolveStoreRef, buildStoreContext } from "./advise/context-builder.js";
16
+ import { selectGotchas } from "./advise/gotchas.js";
17
+ import { CEDAR_PATTERNS_SUMMARY } from "./advise/cedar-patterns.js";
18
+ import { AVP_RULES_SUMMARY, AVP_VALIDATION_ERRORS } from "./advise/avp-rules.js";
19
+ import { storeManager } from "../resources/store-manager.js";
20
+ const SEQUENCING_GUIDANCE = [
21
+ "Schema changes that add new entity types, attributes, or actions MUST be deployed BEFORE policies that reference them. AVP validates each policy against the current schema at CreatePolicy/UpdatePolicy time.",
22
+ "Removing an entity type, action, or required attribute is BREAKING for any policy that references it. Update or delete dependent policies first, then remove the schema element.",
23
+ "Changing a required attribute to optional is safe; changing an optional attribute to required can silently skip policies that previously matched (Cedar drops policies that touch a missing required attribute via UnsafeOptionalAttributeAccess).",
24
+ "For renames (entity type, action id, attribute name), there is no atomic rename in AVP. Plan as: add the new name + dual-write policies, migrate consumers, then remove the old name.",
25
+ ];
26
+ const AVP_UPDATE_POLICY_RULES = {
27
+ summary: AVP_RULES_SUMMARY,
28
+ in_place_via_update_policy: [
29
+ "Action scope (action == ... or action in [...])",
30
+ "When/unless condition clauses",
31
+ "Policy name / description metadata",
32
+ ],
33
+ requires_delete_recreate: [
34
+ "Effect (permit ↔ forbid)",
35
+ "Principal scope (head clause)",
36
+ "Resource scope (head clause)",
37
+ "Conversion between static and template-linked policy",
38
+ ],
39
+ new_via_create_policy: [
40
+ "Wholly new policy added to the store (no in-place path applies)",
41
+ ],
42
+ notes: [
43
+ "UpdatePolicy only updates STATIC policies. Template-linked policies use UpdatePolicyTemplate (or relink).",
44
+ "AVP error code for an attempted illegal change is ConflictException / ResourceNotFoundException depending on whether the policy still resolves under the new shape.",
45
+ ],
46
+ };
47
+ const CEDAR_PATTERNS_DETAIL = [
48
+ {
49
+ name: "Membership (RBAC)",
50
+ description: "Principal head clause uses `in Role::\"…\"` or similar group/role parent. Permissions follow group membership.",
51
+ example: 'permit (principal in App::Role::"editor", action in [App::Action::"read"], resource);',
52
+ },
53
+ {
54
+ name: "Relationship (ReBAC)",
55
+ description: "Conditions reference principal's relationship to the resource (often via an attribute on resource like `owners`, `viewers`, `team`).",
56
+ example: 'permit (principal is App::User, action in [App::Action::"read"], resource is App::Doc) when { principal in resource.owners };',
57
+ },
58
+ {
59
+ name: "Discretionary",
60
+ description: "Principal head clause uses `==` to grant access to a specific named entity (no group, no relationship — ad hoc).",
61
+ example: 'permit (principal == App::Service::"ingest", action == App::Action::"write", resource == App::Bucket::"raw");',
62
+ },
63
+ {
64
+ name: "Hybrid",
65
+ description: "Policy combines membership in the head clause with a relationship or ABAC predicate in the condition body. Common in production stores.",
66
+ example: 'permit (principal in App::Role::"editor", action in [App::Action::"write"], resource) when { principal in resource.team };',
67
+ },
68
+ ];
69
+ const NEXT_STEPS_FOR_LLM = `Use this context to produce a Cedar policy change plan. Do not skip these steps:
70
+
71
+ 1. Identify the entity types, attributes, and actions in schema_summary that the user's intent touches. If schema_summary is absent (store_status != "loaded"), state the assumption you are making about the schema and ask the user to confirm. If store_status is "ambiguous", do NOT pick a store silently; ask the user which one from available_stores and re-invoke cedar_advise with an explicit store_ref. If store_status is "not_found" and available_stores is populated, the caller probably mistyped the store name; re-invoke with the corrected name from available_stores. If policy_inventory is empty even though the store loaded, state that the store has no policies yet and confirm with the user before proposing anything other than initial-state policies.
72
+ 2. Pick the most appropriate cedar_patterns_reference pattern for the change. If the store already uses a dominant pattern (see patterns_detected_in_store), prefer it for consistency unless the intent requires otherwise.
73
+ 3. Sequence steps per sequencing_guidance. Schema changes that add a referenced attribute MUST precede policy changes that read it.
74
+ 4. For each step that modifies an existing policy, classify it against avp_update_policy_rules. Effect / principal / resource changes require delete-and-recreate; action and when/unless changes are in-place.
75
+ 5. Address every applicable_gotcha in the plan (either by structuring the snippet to avoid it, or by surfacing it as a warning to the user).
76
+ 6. After drafting Cedar snippets, call cedar_validate on each to confirm syntax + schema-typing before recommending them. Reading a snippet does not tell you whether the Cedar parser accepts it.
77
+ 7. For each modification to an existing policy, call cedar_check_policy_change with the old and new text to confirm the AVP UpdatePolicy classification you assigned.
78
+ 8. If the change spans two stores (current vs. proposed), call cedar_diff_policy_stores to check for behavioral drift before recommending deployment.`;
79
+ /**
80
+ * Build the cedar_advise context bundle.
81
+ *
82
+ * Pure function — no sampler, no LLM round-trip. The calling MCP client's
83
+ * conversation LLM is expected to interpret this bundle and produce the plan.
84
+ */
85
+ export function handleAdvise(input, manager = storeManager) {
86
+ const gotchas = selectGotchas(input.intent).map(gotchaToAdvise);
87
+ const storeView = resolveStoreView(input.store_ref, manager);
88
+ const bundle = {
89
+ tool: "cedar_advise",
90
+ bundle_version: "v2",
91
+ intent: input.intent,
92
+ store_name: storeView.store_name,
93
+ store_status: storeView.store_status,
94
+ schema_summary: storeView.schema_summary,
95
+ policy_inventory: storeView.policy_inventory,
96
+ patterns_detected_in_store: storeView.patterns_detected,
97
+ applicable_gotchas: gotchas,
98
+ avp_update_policy_rules: AVP_UPDATE_POLICY_RULES,
99
+ avp_validation_error_catalog: AVP_VALIDATION_ERRORS.map(e => ({ id: e.id, description: e.description })),
100
+ cedar_patterns_reference: {
101
+ summary: CEDAR_PATTERNS_SUMMARY,
102
+ patterns: CEDAR_PATTERNS_DETAIL,
103
+ },
104
+ sequencing_guidance: SEQUENCING_GUIDANCE,
105
+ next_steps_for_llm: NEXT_STEPS_FOR_LLM,
106
+ };
107
+ if (storeView.available_stores)
108
+ bundle.available_stores = storeView.available_stores;
109
+ if (storeView.auto_discovered)
110
+ bundle.auto_discovered = storeView.auto_discovered;
111
+ return bundle;
112
+ }
113
+ function resolveStoreView(storeRef, manager) {
114
+ if (!storeRef) {
115
+ // Round 4 dogfood (Scenario A): with no store_ref, the calling LLM has no
116
+ // way to learn what stores are loaded short of making a separate tool call
117
+ // and reading `auto_discovered` off the response. Auto-resolve when the
118
+ // resolution is unambiguous; surface candidate names otherwise so the
119
+ // caller can retry with an explicit `store_ref`.
120
+ const names = manager.listStoreNames();
121
+ if (names.length === 0) {
122
+ return { store_status: "not_provided", policy_inventory: [], patterns_detected: [] };
123
+ }
124
+ if (names.length === 1) {
125
+ const onlyStoreName = names[0];
126
+ const ctx = buildStoreContext(onlyStoreName, manager);
127
+ if (!ctx) {
128
+ // 11d audit finding: the single loaded store exists in StoreManager but
129
+ // cannot be grounded (most often: workspace has policies/ but no
130
+ // schema.cedarschema or schema.json, so `buildStoreContext` throws
131
+ // inside readSchema and returns null). Returning `not_found` with the
132
+ // candidate name is self-referential and triggers the next_steps_for_llm
133
+ // "re-invoke with corrected name from available_stores" advice, which
134
+ // loops. Degrade to `not_provided` instead: the bundle still carries
135
+ // the universal Cedar/AVP context, and the LLM treats it as
136
+ // store-less rather than as a typo'd ref.
137
+ return { store_status: "not_provided", policy_inventory: [], patterns_detected: [] };
138
+ }
139
+ return {
140
+ store_name: ctx.store_name,
141
+ store_status: "loaded",
142
+ schema_summary: summarizeSchema(ctx.schema_text),
143
+ policy_inventory: ctx.policy_inventory,
144
+ patterns_detected: countPatterns(ctx.policy_inventory),
145
+ auto_discovered: { store_from: "single_loaded_store" },
146
+ };
147
+ }
148
+ return {
149
+ store_status: "ambiguous",
150
+ policy_inventory: [],
151
+ patterns_detected: [],
152
+ available_stores: names,
153
+ };
154
+ }
155
+ const storeName = resolveStoreRef(storeRef);
156
+ const ctx = buildStoreContext(storeName, manager);
157
+ if (!ctx) {
158
+ const available = manager.listStoreNames();
159
+ const view = {
160
+ store_name: storeName,
161
+ store_status: "not_found",
162
+ policy_inventory: [],
163
+ patterns_detected: [],
164
+ };
165
+ if (available.length > 0)
166
+ view.available_stores = available;
167
+ return view;
168
+ }
169
+ return {
170
+ store_name: ctx.store_name,
171
+ store_status: "loaded",
172
+ schema_summary: summarizeSchema(ctx.schema_text),
173
+ policy_inventory: ctx.policy_inventory,
174
+ patterns_detected: countPatterns(ctx.policy_inventory),
175
+ };
176
+ }
177
+ function summarizeSchema(schemaText) {
178
+ const parsed = parseSchemaInput(schemaText);
179
+ const answer = checkParseSchema(parsed.schema);
180
+ if (answer.type === "failure") {
181
+ return {
182
+ valid: false,
183
+ format: parsed.format,
184
+ namespaces: [],
185
+ entity_type_count: 0,
186
+ action_count: 0,
187
+ raw_text: schemaText,
188
+ errors: answer.errors.map(e => e.message),
189
+ };
190
+ }
191
+ if (parsed.format === "json") {
192
+ const counts = summarizeJsonSchema(parsed.schema);
193
+ return { valid: true, format: parsed.format, raw_text: schemaText, ...counts };
194
+ }
195
+ // For cedarschema text, translate to JSON form to derive structural counts.
196
+ try {
197
+ const jsonAnswer = schemaToJsonWithResolvedTypes(schemaText);
198
+ if (jsonAnswer.type === "success") {
199
+ const counts = summarizeJsonSchema(jsonAnswer.json);
200
+ return { valid: true, format: parsed.format, raw_text: schemaText, ...counts };
201
+ }
202
+ }
203
+ catch {
204
+ // fall through to summary-less success
205
+ }
206
+ return {
207
+ valid: true,
208
+ format: parsed.format,
209
+ namespaces: [],
210
+ entity_type_count: 0,
211
+ action_count: 0,
212
+ raw_text: schemaText,
213
+ };
214
+ }
215
+ function parseSchemaInput(schemaStr) {
216
+ try {
217
+ return { schema: JSON.parse(schemaStr), format: "json" };
218
+ }
219
+ catch {
220
+ return { schema: schemaStr, format: "cedarschema" };
221
+ }
222
+ }
223
+ function summarizeJsonSchema(json) {
224
+ const empty = { namespaces: [], entity_type_count: 0, action_count: 0 };
225
+ if (!json || typeof json !== "object")
226
+ return empty;
227
+ const shape = json;
228
+ const namespaces = Object.keys(shape);
229
+ let entity_type_count = 0;
230
+ let action_count = 0;
231
+ for (const ns of namespaces) {
232
+ const block = shape[ns];
233
+ if (block.entityTypes)
234
+ entity_type_count += Object.keys(block.entityTypes).length;
235
+ if (block.actions)
236
+ action_count += Object.keys(block.actions).length;
237
+ }
238
+ return { namespaces, entity_type_count, action_count };
239
+ }
240
+ function countPatterns(inventory) {
241
+ const counts = new Map();
242
+ for (const entry of inventory) {
243
+ counts.set(entry.pattern, (counts.get(entry.pattern) ?? 0) + 1);
244
+ }
245
+ return Array.from(counts.entries()).map(([pattern, count]) => ({ pattern, count }));
246
+ }
247
+ function gotchaToAdvise(g) {
248
+ const advise = {
249
+ id: g.id,
250
+ severity: g.severity,
251
+ description: g.description,
252
+ };
253
+ if (g.avp_error_category) {
254
+ advise.avp_error_category = g.avp_error_category;
255
+ }
256
+ return advise;
257
+ }
258
+ //# sourceMappingURL=advise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advise.js","sourceRoot":"","sources":["../../src/tools/advise.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export interface AuthorizeBatchInput {
2
+ policies?: string;
3
+ policy_ref?: string;
4
+ /**
5
+ * Map of policy id -> policy text. Each key becomes the WASM policy_id and
6
+ * surfaces in `determining_policies` (overridden by an `@id` annotation when
7
+ * present). The MCP wrapper populates this from `cedar://policies/{store}`
8
+ * refs so determining_policies reports file basenames (`admin`, `editor`)
9
+ * instead of positional placeholders (kickoff-14 14a).
10
+ */
11
+ policiesMap?: Record<string, string>;
12
+ schema?: string;
13
+ schema_ref?: string;
14
+ requests: string;
15
+ entities?: string;
16
+ }
17
+ export interface BatchDecision {
18
+ index: number;
19
+ principal: string;
20
+ action: string;
21
+ resource: string;
22
+ decision: "Allow" | "Deny" | "Error";
23
+ determining_policies?: string[];
24
+ error?: string;
25
+ }
26
+ export interface AuthorizeBatchResult {
27
+ total: number;
28
+ allowed: number;
29
+ denied: number;
30
+ errored: number;
31
+ decisions: BatchDecision[];
32
+ summary: string;
33
+ }
34
+ export declare function handleAuthorizeBatch(input: AuthorizeBatchInput): Promise<AuthorizeBatchResult>;
35
+ //# sourceMappingURL=authorize-batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-batch.d.ts","sourceRoot":"","sources":["../../src/tools/authorize-batch.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAeD,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAmN/B"}
@@ -0,0 +1,262 @@
1
+ import { isAuthorized } from "@cedar-policy/cedar-wasm/nodejs";
2
+ import { detectFormat, normalizeEntities, normalizePrincipalRef, } from "../utils/format-detector.js";
3
+ import { resolveRef } from "../resources/ref-resolver.js";
4
+ import { buildStaticPolicies } from "./authorize.js";
5
+ // ─── Main handler ──────────────────────────────────────────────────────────────
6
+ export async function handleAuthorizeBatch(input) {
7
+ // 1. Resolve policies into a Record<PolicyId, Policy> map so determining_policies
8
+ // returns stable IDs (file basename, @id annotation, or `policy<idx>` fallback)
9
+ // the same way cedar_authorize already does. policiesMap (populated by the MCP
10
+ // wrapper from cedar://policies/{store} refs) wins; inline policies text falls
11
+ // back through buildStaticPolicies' string-split path.
12
+ let policiesText;
13
+ let policiesMap = input.policiesMap;
14
+ if (policiesMap === undefined) {
15
+ if (input.policies) {
16
+ policiesText = input.policies;
17
+ }
18
+ else if (input.policy_ref) {
19
+ const resolved = resolveRef(input.policy_ref);
20
+ if ("error" in resolved) {
21
+ return zeroResult(`Failed to resolve policy_ref: ${resolved.error}`);
22
+ }
23
+ policiesText = resolved.content;
24
+ }
25
+ else {
26
+ return zeroResult("Either policies, policy_ref, or policiesMap is required.");
27
+ }
28
+ }
29
+ const built = buildStaticPolicies({ policies: policiesText, policiesMap });
30
+ if ("error" in built) {
31
+ return zeroResult(built.error);
32
+ }
33
+ const staticPolicies = built.record;
34
+ // 2. Resolve schema (optional)
35
+ let schema;
36
+ if (input.schema_ref) {
37
+ const resolved = resolveRef(input.schema_ref);
38
+ if ("error" in resolved) {
39
+ return zeroResult(`Failed to resolve schema_ref: ${resolved.error}`);
40
+ }
41
+ schema = parseSchema(resolved.content);
42
+ }
43
+ else if (input.schema) {
44
+ schema = parseSchema(input.schema);
45
+ }
46
+ // 3. Parse the shared entities (optional baseline; individual requests may override)
47
+ let sharedEntitiesArray = null;
48
+ if (input.entities) {
49
+ const parsed = parseEntitiesString(input.entities);
50
+ if (parsed === null) {
51
+ return zeroResult("shared entities must be a valid JSON array or AVP entity_list object");
52
+ }
53
+ sharedEntitiesArray = parsed;
54
+ }
55
+ // 4. Parse the requests array
56
+ let rawRequests;
57
+ try {
58
+ const parsed = JSON.parse(input.requests);
59
+ if (!Array.isArray(parsed)) {
60
+ return zeroResult("requests must be a JSON array");
61
+ }
62
+ rawRequests = parsed;
63
+ }
64
+ catch {
65
+ return zeroResult("requests is not valid JSON");
66
+ }
67
+ if (rawRequests.length === 0) {
68
+ return {
69
+ total: 0,
70
+ allowed: 0,
71
+ denied: 0,
72
+ errored: 0,
73
+ decisions: [],
74
+ summary: "0 requests: no requests to evaluate.",
75
+ };
76
+ }
77
+ // 5. Evaluate each request individually
78
+ const decisions = [];
79
+ let allowed = 0;
80
+ let denied = 0;
81
+ let errored = 0;
82
+ for (let i = 0; i < rawRequests.length; i++) {
83
+ const req = rawRequests[i];
84
+ const principalStr = refToString(req.principal);
85
+ const actionStr = refToString(req.action);
86
+ const resourceStr = refToString(req.resource);
87
+ // 5a. Normalize principal / action / resource refs
88
+ const principalRef = normalizePrincipalRef(req.principal);
89
+ if ("error" in principalRef) {
90
+ decisions.push(errorDecision(i, principalStr, actionStr, resourceStr, principalRef.error));
91
+ errored++;
92
+ continue;
93
+ }
94
+ const actionRef = normalizePrincipalRef(req.action);
95
+ if ("error" in actionRef) {
96
+ decisions.push(errorDecision(i, principalStr, actionStr, resourceStr, actionRef.error));
97
+ errored++;
98
+ continue;
99
+ }
100
+ const resourceRef = normalizePrincipalRef(req.resource);
101
+ if ("error" in resourceRef) {
102
+ decisions.push(errorDecision(i, principalStr, actionStr, resourceStr, resourceRef.error));
103
+ errored++;
104
+ continue;
105
+ }
106
+ // 5b. Resolve entities: per-request entities take priority over shared entities.
107
+ let entitiesForCall;
108
+ const perRequestEntitiesRaw = req.entities !== undefined ? req.entities : null;
109
+ if (perRequestEntitiesRaw !== null) {
110
+ const perArr = parseEntitiesValue(perRequestEntitiesRaw);
111
+ if (perArr === null) {
112
+ decisions.push(errorDecision(i, principalStr, actionStr, resourceStr, "Invalid entities: must be a JSON array or AVP entity_list object"));
113
+ errored++;
114
+ continue;
115
+ }
116
+ // Format-detect against the per-request entities
117
+ const detection = detectFormat(perArr, req.principal, req.action, req.resource);
118
+ const normalized = normalizeEntities(perArr, detection.format);
119
+ entitiesForCall = normalized;
120
+ }
121
+ else if (sharedEntitiesArray !== null) {
122
+ // Reuse shared entities — format-detect against this request's refs
123
+ const detection = detectFormat(sharedEntitiesArray, req.principal, req.action, req.resource);
124
+ const normalized = normalizeEntities(sharedEntitiesArray, detection.format);
125
+ entitiesForCall = normalized;
126
+ }
127
+ else {
128
+ // No entities at all — pass empty array (Cedar will evaluate without entity data)
129
+ entitiesForCall = [];
130
+ }
131
+ // 5c. Resolve per-request schema override (rare; falls back to batch schema)
132
+ let callSchema = schema;
133
+ if (req.schema !== undefined) {
134
+ if (typeof req.schema === "string") {
135
+ callSchema = parseSchema(req.schema);
136
+ }
137
+ else {
138
+ callSchema = req.schema;
139
+ }
140
+ }
141
+ // 5d. Parse context
142
+ let context = {};
143
+ if (req.context !== undefined) {
144
+ if (typeof req.context === "string") {
145
+ try {
146
+ context = JSON.parse(req.context);
147
+ }
148
+ catch {
149
+ decisions.push(errorDecision(i, principalStr, actionStr, resourceStr, "context is not valid JSON"));
150
+ errored++;
151
+ continue;
152
+ }
153
+ }
154
+ else if (typeof req.context === "object" && req.context !== null) {
155
+ context = req.context;
156
+ }
157
+ }
158
+ // 5e. Build the authorization call
159
+ const call = {
160
+ principal: principalRef,
161
+ action: actionRef,
162
+ resource: resourceRef,
163
+ context,
164
+ policies: { staticPolicies },
165
+ entities: entitiesForCall,
166
+ ...(callSchema ? { schema: callSchema, validateRequest: true } : {}),
167
+ };
168
+ // 5f. Call Cedar WASM
169
+ const answer = isAuthorized(call);
170
+ if (answer.type === "failure") {
171
+ // Cedar returned a hard failure (e.g. schema validation error, entity deserialization error).
172
+ // This maps to decision "Error" — not a policy Deny.
173
+ const msg = answer.errors.map((e) => e.message).join("; ");
174
+ decisions.push(errorDecision(i, principalStr, actionStr, resourceStr, msg));
175
+ errored++;
176
+ continue;
177
+ }
178
+ const { decision, diagnostics } = answer.response;
179
+ const isAllow = decision === "allow";
180
+ decisions.push({
181
+ index: i,
182
+ principal: principalStr,
183
+ action: actionStr,
184
+ resource: resourceStr,
185
+ decision: isAllow ? "Allow" : "Deny",
186
+ determining_policies: diagnostics.reason,
187
+ });
188
+ if (isAllow) {
189
+ allowed++;
190
+ }
191
+ else {
192
+ denied++;
193
+ }
194
+ }
195
+ const total = rawRequests.length;
196
+ const summary = `${total} request${total === 1 ? "" : "s"}: ${allowed} Allow, ${denied} Deny, ${errored} Error`;
197
+ return { total, allowed, denied, errored, decisions, summary };
198
+ }
199
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
200
+ function parseSchema(raw) {
201
+ try {
202
+ return JSON.parse(raw);
203
+ }
204
+ catch {
205
+ return raw;
206
+ }
207
+ }
208
+ /**
209
+ * Parse entities from a JSON string, unwrapping AVP entity_list envelopes.
210
+ * Returns null on parse failure.
211
+ */
212
+ function parseEntitiesString(raw) {
213
+ let parsed;
214
+ try {
215
+ parsed = JSON.parse(raw);
216
+ }
217
+ catch {
218
+ return null;
219
+ }
220
+ return extractEntityArray(parsed);
221
+ }
222
+ /**
223
+ * Parse entities from an already-parsed value (used for per-request entities
224
+ * that may be a string or an already-parsed array/object).
225
+ */
226
+ function parseEntitiesValue(raw) {
227
+ if (typeof raw === "string") {
228
+ return parseEntitiesString(raw);
229
+ }
230
+ return extractEntityArray(raw);
231
+ }
232
+ /** Unwrap AVP entity_list / entityList / EntityList envelope, or return array as-is. */
233
+ function extractEntityArray(parsed) {
234
+ if (Array.isArray(parsed))
235
+ return parsed;
236
+ if (typeof parsed === "object" && parsed !== null) {
237
+ const obj = parsed;
238
+ const list = obj["entity_list"] ?? obj["entityList"] ?? obj["EntityList"];
239
+ if (Array.isArray(list))
240
+ return list;
241
+ }
242
+ return null;
243
+ }
244
+ function refToString(ref) {
245
+ if (typeof ref === "string")
246
+ return ref;
247
+ return JSON.stringify(ref);
248
+ }
249
+ function errorDecision(index, principal, action, resource, error) {
250
+ return { index, principal, action, resource, decision: "Error", error };
251
+ }
252
+ function zeroResult(error) {
253
+ return {
254
+ total: 0,
255
+ allowed: 0,
256
+ denied: 0,
257
+ errored: 0,
258
+ decisions: [],
259
+ summary: error,
260
+ };
261
+ }
262
+ //# sourceMappingURL=authorize-batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-batch.js","sourceRoot":"","sources":["../../src/tools/authorize-batch.ts"],"names":[],"mappings":"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"}