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,49 @@
1
+ /**
2
+ * AVP UpdatePolicy mutability rules — proven from official docs 2026-05-20:
3
+ * https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_UpdatePolicy.html
4
+ *
5
+ * UpdatePolicy only updates STATIC policies. Template-linked → use UpdatePolicyTemplate.
6
+ */
7
+ export type AvpUpdateMode = "in_place_via_update_policy" | "requires_delete_recreate" | "new_policy_via_create_policy";
8
+ export interface AvpChangeClassification {
9
+ mode: AvpUpdateMode;
10
+ rationale: string;
11
+ }
12
+ /** Classify which AVP API call a given change type requires. */
13
+ export declare function classifyAvpChange(changeField: string): AvpChangeClassification;
14
+ /** Validation error categories AVP raises — pre-detectable during authoring. */
15
+ export declare const AVP_VALIDATION_ERRORS: readonly [{
16
+ readonly id: "UnrecognizedEntityType";
17
+ readonly description: "Policy references an entity type not declared in the schema.";
18
+ }, {
19
+ readonly id: "UnrecognizedActionId";
20
+ readonly description: "Policy references an action not declared in the schema.";
21
+ }, {
22
+ readonly id: "InvalidActionApplication";
23
+ readonly description: "Action does not apply to the specified principal and resource types per the schema appliesTo definition.";
24
+ }, {
25
+ readonly id: "UnexpectedType";
26
+ readonly description: "An operand has the wrong type for the operation (e.g. comparing a String to an entity).";
27
+ }, {
28
+ readonly id: "IncompatibleTypes";
29
+ readonly description: "Types in a Set or if/then/else expression are incompatible.";
30
+ }, {
31
+ readonly id: "MissingAttribute";
32
+ readonly description: "Policy accesses an attribute not declared in the schema. Add the attribute to the schema or use a has guard.";
33
+ }, {
34
+ readonly id: "UnsafeOptionalAttributeAccess";
35
+ readonly description: "Policy accesses an optional attribute without a has guard. This causes Cedar to silently skip the policy for principals/resources missing the attribute.";
36
+ }, {
37
+ readonly id: "ImpossiblePolicy";
38
+ readonly description: "Cedar determined the condition always evaluates to false — the policy can never match any request.";
39
+ }, {
40
+ readonly id: "WrongNumberArguments";
41
+ readonly description: "Extension type function called with wrong number of arguments.";
42
+ }, {
43
+ readonly id: "FunctionArgumentValidationError";
44
+ readonly description: "Argument to an extension type function could not be parsed (e.g. invalid IP address string).";
45
+ }];
46
+ export type AvpValidationErrorId = typeof AVP_VALIDATION_ERRORS[number]["id"];
47
+ /** AVP immutability rules summary — for use in sampling prompts. */
48
+ export declare const AVP_RULES_SUMMARY: string;
49
+ //# sourceMappingURL=avp-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avp-rules.d.ts","sourceRoot":"","sources":["../../../src/tools/advise/avp-rules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,aAAa,GAAG,4BAA4B,GAAG,0BAA0B,GAAG,8BAA8B,CAAC;AAEvH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,uBAAuB,CA6B9E;AAED,gFAAgF;AAChF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWxB,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAE9E,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,QAMtB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * AVP UpdatePolicy mutability rules — proven from official docs 2026-05-20:
3
+ * https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_UpdatePolicy.html
4
+ *
5
+ * UpdatePolicy only updates STATIC policies. Template-linked → use UpdatePolicyTemplate.
6
+ */
7
+ /** Classify which AVP API call a given change type requires. */
8
+ export function classifyAvpChange(changeField) {
9
+ switch (changeField) {
10
+ case "action":
11
+ case "when_clause":
12
+ case "unless_clause":
13
+ case "policy_name":
14
+ return {
15
+ mode: "in_place_via_update_policy",
16
+ rationale: "AVP UpdatePolicy supports modifying actions, when/unless clauses, and policy name in-place.",
17
+ };
18
+ case "effect":
19
+ case "principal":
20
+ case "resource":
21
+ case "policy_type_conversion":
22
+ return {
23
+ mode: "requires_delete_recreate",
24
+ rationale: "AVP UpdatePolicy cannot change effect, principal scope, resource scope, or convert between static and template-linked policies. Delete the existing policy and create a new one.",
25
+ };
26
+ case "new_policy":
27
+ return {
28
+ mode: "new_policy_via_create_policy",
29
+ rationale: "New policy — use AVP CreatePolicy API.",
30
+ };
31
+ default:
32
+ return {
33
+ mode: "in_place_via_update_policy",
34
+ rationale: "Change type unclassified — assume in-place update is possible but verify.",
35
+ };
36
+ }
37
+ }
38
+ /** Validation error categories AVP raises — pre-detectable during authoring. */
39
+ export const AVP_VALIDATION_ERRORS = [
40
+ { id: "UnrecognizedEntityType", description: "Policy references an entity type not declared in the schema." },
41
+ { id: "UnrecognizedActionId", description: "Policy references an action not declared in the schema." },
42
+ { id: "InvalidActionApplication", description: "Action does not apply to the specified principal and resource types per the schema appliesTo definition." },
43
+ { id: "UnexpectedType", description: "An operand has the wrong type for the operation (e.g. comparing a String to an entity)." },
44
+ { id: "IncompatibleTypes", description: "Types in a Set or if/then/else expression are incompatible." },
45
+ { id: "MissingAttribute", description: "Policy accesses an attribute not declared in the schema. Add the attribute to the schema or use a has guard." },
46
+ { id: "UnsafeOptionalAttributeAccess", description: "Policy accesses an optional attribute without a has guard. This causes Cedar to silently skip the policy for principals/resources missing the attribute." },
47
+ { id: "ImpossiblePolicy", description: "Cedar determined the condition always evaluates to false — the policy can never match any request." },
48
+ { id: "WrongNumberArguments", description: "Extension type function called with wrong number of arguments." },
49
+ { id: "FunctionArgumentValidationError", description: "Argument to an extension type function could not be parsed (e.g. invalid IP address string)." },
50
+ ];
51
+ /** AVP immutability rules summary — for use in sampling prompts. */
52
+ export const AVP_RULES_SUMMARY = `
53
+ AVP UpdatePolicy constraints (verified from official API docs):
54
+ MUTABLE via UpdatePolicy: action scope, when/unless conditions, policy name.
55
+ IMMUTABLE (delete+recreate required): effect (permit↔forbid), principal scope, resource scope, static↔template-linked conversion.
56
+ NEW policies: use CreatePolicy API.
57
+ Template-linked policies: use UpdatePolicyTemplate, not UpdatePolicy.
58
+ `.trim();
59
+ //# sourceMappingURL=avp-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avp-rules.js","sourceRoot":"","sources":["../../../src/tools/advise/avp-rules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,gEAAgE;AAChE,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,QAAQ,CAAC;QACd,KAAK,aAAa,CAAC;QACnB,KAAK,eAAe,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO;gBACL,IAAI,EAAE,4BAA4B;gBAClC,SAAS,EAAE,6FAA6F;aACzG,CAAC;QACJ,KAAK,QAAQ,CAAC;QACd,KAAK,WAAW,CAAC;QACjB,KAAK,UAAU,CAAC;QAChB,KAAK,wBAAwB;YAC3B,OAAO;gBACL,IAAI,EAAE,0BAA0B;gBAChC,SAAS,EAAE,kLAAkL;aAC9L,CAAC;QACJ,KAAK,YAAY;YACf,OAAO;gBACL,IAAI,EAAE,8BAA8B;gBACpC,SAAS,EAAE,wCAAwC;aACpD,CAAC;QACJ;YACE,OAAO;gBACL,IAAI,EAAE,4BAA4B;gBAClC,SAAS,EAAE,2EAA2E;aACvF,CAAC;IACN,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,EAAE,EAAE,EAAE,wBAAwB,EAAE,WAAW,EAAE,8DAA8D,EAAE;IAC7G,EAAE,EAAE,EAAE,sBAAsB,EAAE,WAAW,EAAE,yDAAyD,EAAE;IACtG,EAAE,EAAE,EAAE,0BAA0B,EAAE,WAAW,EAAE,0GAA0G,EAAE;IAC3J,EAAE,EAAE,EAAE,gBAAgB,EAAE,WAAW,EAAE,yFAAyF,EAAE;IAChI,EAAE,EAAE,EAAE,mBAAmB,EAAE,WAAW,EAAE,6DAA6D,EAAE;IACvG,EAAE,EAAE,EAAE,kBAAkB,EAAE,WAAW,EAAE,8GAA8G,EAAE;IACvJ,EAAE,EAAE,EAAE,+BAA+B,EAAE,WAAW,EAAE,0JAA0J,EAAE;IAChN,EAAE,EAAE,EAAE,kBAAkB,EAAE,WAAW,EAAE,oGAAoG,EAAE;IAC7I,EAAE,EAAE,EAAE,sBAAsB,EAAE,WAAW,EAAE,gEAAgE,EAAE;IAC7G,EAAE,EAAE,EAAE,iCAAiC,EAAE,WAAW,EAAE,8FAA8F,EAAE;CAC9I,CAAC;AAIX,oEAAoE;AACpE,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;CAMhC,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Cedar design pattern definitions and classifier.
3
+ * Patterns proven from official docs 2026-05-20:
4
+ * https://docs.cedarpolicy.com/overview/patterns.html
5
+ */
6
+ import type { PolicyJson } from "@cedar-policy/cedar-wasm/nodejs";
7
+ export type CedarPattern = "membership" | "relationship" | "discretionary" | "hybrid" | "unknown";
8
+ export interface PatternClassification {
9
+ pattern: CedarPattern;
10
+ confidence: "high" | "medium" | "low";
11
+ evidence: string;
12
+ }
13
+ /**
14
+ * Classify a single policy's primary Cedar pattern from its policyToJson AST.
15
+ *
16
+ * Membership (RBAC): principal in Role::"X" — scope uses "in" with a non-resource entity
17
+ * Relationship (ReBAC): principal in resource.attr — condition body has "in" with resource attribute
18
+ * Discretionary: principal == Service::"specific" — scope uses "==" (specific entity)
19
+ * Hybrid: combination of the above
20
+ */
21
+ export declare function classifyPolicy(json: PolicyJson): PatternClassification;
22
+ /** Cedar patterns summary — for use in sampling prompts. */
23
+ export declare const CEDAR_PATTERNS_SUMMARY: string;
24
+ //# sourceMappingURL=cedar-patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cedar-patterns.d.ts","sourceRoot":"","sources":["../../../src/tools/advise/cedar-patterns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,cAAc,GAAG,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElG,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,qBAAqB,CAgCtE;AAED,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,QAa3B,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Cedar design pattern definitions and classifier.
3
+ * Patterns proven from official docs 2026-05-20:
4
+ * https://docs.cedarpolicy.com/overview/patterns.html
5
+ */
6
+ /**
7
+ * Classify a single policy's primary Cedar pattern from its policyToJson AST.
8
+ *
9
+ * Membership (RBAC): principal in Role::"X" — scope uses "in" with a non-resource entity
10
+ * Relationship (ReBAC): principal in resource.attr — condition body has "in" with resource attribute
11
+ * Discretionary: principal == Service::"specific" — scope uses "==" (specific entity)
12
+ * Hybrid: combination of the above
13
+ */
14
+ export function classifyPolicy(json) {
15
+ const principalOp = json.principal.op;
16
+ const conditionsText = JSON.stringify(json.conditions);
17
+ // Relationship: condition body contains "principal in resource" — ReBAC
18
+ const hasReBAC = conditionsText.includes('"in"') &&
19
+ conditionsText.includes('"Var":"principal"') &&
20
+ conditionsText.includes('"Var":"resource"');
21
+ // Membership: principal scope is "in" (role/group membership, not via condition)
22
+ const isMembership = principalOp === "in" && !hasReBAC;
23
+ // Discretionary: principal scope is "==" (specific entity)
24
+ const isDiscretionary = principalOp === "==";
25
+ if (hasReBAC && isMembership) {
26
+ return { pattern: "hybrid", confidence: "medium", evidence: "principal scope uses 'in' (Membership) and conditions use principal-in-resource pattern (Relationship)" };
27
+ }
28
+ if (hasReBAC) {
29
+ return { pattern: "relationship", confidence: "high", evidence: "condition body contains principal-in-resource relationship check" };
30
+ }
31
+ if (isMembership) {
32
+ return { pattern: "membership", confidence: "high", evidence: `principal scope uses 'in' — group/role membership (RBAC)` };
33
+ }
34
+ if (isDiscretionary) {
35
+ return { pattern: "discretionary", confidence: "high", evidence: `principal scope uses '==' — specific entity grant (Discretionary)` };
36
+ }
37
+ if (principalOp === "All") {
38
+ return { pattern: "unknown", confidence: "low", evidence: "principal is unconstrained in scope — pattern determined entirely by conditions" };
39
+ }
40
+ return { pattern: "unknown", confidence: "low", evidence: `principal op '${principalOp}' not recognized` };
41
+ }
42
+ /** Cedar patterns summary — for use in sampling prompts. */
43
+ export const CEDAR_PATTERNS_SUMMARY = `
44
+ Cedar supports three primary design patterns (official docs):
45
+
46
+ 1. MEMBERSHIP (RBAC): principal in Role::"group" — permissions follow group membership.
47
+ Example: permit(principal in Role::"editor", action in [...], resource);
48
+
49
+ 2. RELATIONSHIP (ReBAC): principal in resource.owners — permissions follow resource relationships.
50
+ Example: permit(principal is User, action in [...], resource is Doc) when { principal in resource.owners };
51
+
52
+ 3. DISCRETIONARY: principal == Service::"specific" — ad-hoc per-entity grants.
53
+ Example: permit(principal == Service::"Service-123", action == Action::"call", resource == Service::"Target");
54
+
55
+ All three can coexist in a policy store. Individual policies should follow one pattern.
56
+ `.trim();
57
+ //# sourceMappingURL=cedar-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cedar-patterns.js","sourceRoot":"","sources":["../../../src/tools/advise/cedar-patterns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,IAAgB;IAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;IACtC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEvD,wEAAwE;IACxE,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9C,cAAc,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAC5C,cAAc,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAE9C,iFAAiF;IACjF,MAAM,YAAY,GAAG,WAAW,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC;IAEvD,2DAA2D;IAC3D,MAAM,eAAe,GAAG,WAAW,KAAK,IAAI,CAAC;IAE7C,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,wGAAwG,EAAE,CAAC;IACzK,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,kEAAkE,EAAE,CAAC;IACvI,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,0DAA0D,EAAE,CAAC;IAC7H,CAAC;IACD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,mEAAmE,EAAE,CAAC;IACzI,CAAC;IACD,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,iFAAiF,EAAE,CAAC;IAChJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,WAAW,kBAAkB,EAAE,CAAC;AAC7G,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;CAarC,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Builds deterministic context from a policy store for cedar_advise sampling prompts.
3
+ * No LLM cost — pure AST walking and schema parsing.
4
+ */
5
+ import { StoreManager } from "../../resources/store-manager.js";
6
+ export interface PolicyInventoryEntry {
7
+ policy_id: string;
8
+ pattern: string;
9
+ pattern_confidence: string;
10
+ summary: string;
11
+ policy_text: string;
12
+ }
13
+ export interface StoreContext {
14
+ store_name: string;
15
+ schema_text: string;
16
+ policy_inventory: PolicyInventoryEntry[];
17
+ policy_count: number;
18
+ }
19
+ /**
20
+ * Build structured context from a named policy store.
21
+ * Returns null if the store doesn't exist or has no content.
22
+ */
23
+ export declare function buildStoreContext(storeName: string, manager?: StoreManager): StoreContext | null;
24
+ /** Resolve a store_ref to a store name. Accepts "mystore", "cedar://policies/mystore", etc. */
25
+ export declare function resolveStoreRef(storeRef: string): string;
26
+ /** Format store context as a prompt section. */
27
+ export declare function formatContextForPrompt(ctx: StoreContext): string;
28
+ //# sourceMappingURL=context-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../../src/tools/advise/context-builder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAgB,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAG9E,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,YAA2B,GAAG,YAAY,GAAG,IAAI,CAgD9G;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMxD;AAMD,gDAAgD;AAChD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAgBhE"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Builds deterministic context from a policy store for cedar_advise sampling prompts.
3
+ * No LLM cost — pure AST walking and schema parsing.
4
+ */
5
+ import { policyToJson } from "@cedar-policy/cedar-wasm/nodejs";
6
+ import { storeManager } from "../../resources/store-manager.js";
7
+ import { classifyPolicy } from "./cedar-patterns.js";
8
+ /**
9
+ * Build structured context from a named policy store.
10
+ * Returns null if the store doesn't exist or has no content.
11
+ */
12
+ export function buildStoreContext(storeName, manager = storeManager) {
13
+ try {
14
+ const schema = manager.readSchema(storeName);
15
+ const inventory = [];
16
+ const policyIds = manager.listPolicies(storeName);
17
+ for (const id of policyIds) {
18
+ const content = manager.readPolicy(storeName, id);
19
+ try {
20
+ const parseResult = policyToJson(content.trim());
21
+ if (parseResult.type === "success") {
22
+ const classification = classifyPolicy(parseResult.json);
23
+ inventory.push({
24
+ policy_id: id,
25
+ pattern: classification.pattern,
26
+ pattern_confidence: classification.confidence,
27
+ summary: buildPolicySummary(id, parseResult.json.effect, classification.evidence),
28
+ policy_text: content.trim(),
29
+ });
30
+ }
31
+ else {
32
+ inventory.push({
33
+ policy_id: id,
34
+ pattern: "unknown",
35
+ pattern_confidence: "low",
36
+ summary: `${id}: parse failed — ${parseResult.errors[0]?.message ?? "unknown error"}`,
37
+ policy_text: content.trim(),
38
+ });
39
+ }
40
+ }
41
+ catch {
42
+ inventory.push({
43
+ policy_id: id,
44
+ pattern: "unknown",
45
+ pattern_confidence: "low",
46
+ summary: `${id}: could not analyze`,
47
+ policy_text: content.trim(),
48
+ });
49
+ }
50
+ }
51
+ return {
52
+ store_name: storeName,
53
+ schema_text: schema,
54
+ policy_inventory: inventory,
55
+ policy_count: policyIds.length,
56
+ };
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ /** Resolve a store_ref to a store name. Accepts "mystore", "cedar://policies/mystore", etc. */
63
+ export function resolveStoreRef(storeRef) {
64
+ if (storeRef.startsWith("cedar://")) {
65
+ const match = storeRef.match(/cedar:\/\/(?:policies|schema)\/([^/]+)/);
66
+ return match?.[1] ?? storeRef;
67
+ }
68
+ return storeRef;
69
+ }
70
+ function buildPolicySummary(id, effect, evidence) {
71
+ return `${id} (${effect}, ${evidence})`;
72
+ }
73
+ /** Format store context as a prompt section. */
74
+ export function formatContextForPrompt(ctx) {
75
+ const lines = [
76
+ `Store: "${ctx.store_name}" (${ctx.policy_count} policies)`,
77
+ "",
78
+ "Schema:",
79
+ ctx.schema_text,
80
+ "",
81
+ "Existing policies:",
82
+ ];
83
+ for (const p of ctx.policy_inventory) {
84
+ lines.push(` - ${p.policy_id}: pattern=${p.pattern} (${p.pattern_confidence} confidence) — ${p.summary}`);
85
+ lines.push(` text: ${p.policy_text}`);
86
+ }
87
+ return lines.join("\n");
88
+ }
89
+ //# sourceMappingURL=context-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../../src/tools/advise/context-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Cedar / AVP gotcha catalog.
3
+ * Drawn from 03-cedar-developer-guide.md and the AVP validation error categories.
4
+ */
5
+ export interface Gotcha {
6
+ id: string;
7
+ severity: "high" | "medium" | "info";
8
+ description: string;
9
+ avp_error_category?: string;
10
+ keywords: string[];
11
+ }
12
+ export declare const GOTCHA_CATALOG: Gotcha[];
13
+ /** Select relevant gotchas by matching intent keywords. */
14
+ export declare function selectGotchas(intent: string, maxCount?: number): Gotcha[];
15
+ //# sourceMappingURL=gotchas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gotchas.d.ts","sourceRoot":"","sources":["../../../src/tools/advise/gotchas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,EAAE,MAAM,EAgElC,CAAC;AAEF,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,EAAE,CAWpE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Cedar / AVP gotcha catalog.
3
+ * Drawn from 03-cedar-developer-guide.md and the AVP validation error categories.
4
+ */
5
+ export const GOTCHA_CATALOG = [
6
+ {
7
+ id: "optional_attribute_guard",
8
+ severity: "high",
9
+ description: "Optional schema attributes MUST be guarded with `entity has attr` before access. Without the guard, Cedar silently skips the policy for any entity missing the attribute — no error, just no match. This is one of the most common silent bugs in Cedar.",
10
+ avp_error_category: "UnsafeOptionalAttributeAccess",
11
+ keywords: ["optional", "has", "attribute", "guard", "email", "verified", "nullable"],
12
+ },
13
+ {
14
+ id: "forbid_overrides_permit",
15
+ severity: "high",
16
+ description: "A single matching `forbid` policy overrides ALL matching `permit` policies. There is no priority or weight system. Use `unless` to create exemptions inside the forbid itself.",
17
+ keywords: ["forbid", "block", "deny", "sensitive", "secret", "top_secret", "restrict"],
18
+ },
19
+ {
20
+ id: "avp_in_place_limitation",
21
+ severity: "high",
22
+ description: "AVP UpdatePolicy cannot change: effect (permit↔forbid), principal scope, or resource scope. These require deleting the old policy and creating a new one. Plan your deployment accordingly.",
23
+ avp_error_category: "ResourceNotFoundException",
24
+ keywords: ["change", "update", "modify", "rename", "role", "principal", "resource", "effect"],
25
+ },
26
+ {
27
+ id: "like_wildcard_crosses_slash",
28
+ severity: "medium",
29
+ description: "Cedar's `like` wildcard `*` matches ANY character sequence including `/`. To limit path depth, combine a positive `like` with a negated `like` for deeper patterns. Example: `resource.path like '/api/v1/*' && !(resource.path like '/api/v1/*/*')`.",
30
+ keywords: ["path", "like", "url", "endpoint", "api", "depth", "wildcard", "route"],
31
+ },
32
+ {
33
+ id: "array_containment_syntax",
34
+ severity: "medium",
35
+ description: "Cedar array containment is left-first: `[\"a\", \"b\"].contains(attr)` — the ARRAY is on the left. Writing `attr in [\"a\", \"b\"]` is an entity-hierarchy check, not a value containment check.",
36
+ keywords: ["contains", "list", "array", "set", "allowlist", "in"],
37
+ },
38
+ {
39
+ id: "schema_first_then_policy",
40
+ severity: "medium",
41
+ description: "Schema changes must be deployed BEFORE policies that reference new attributes or types. AVP validates policies against the current schema at creation/update time. Deploying a policy before its schema change causes UnrecognizedEntityType or MissingAttribute errors.",
42
+ avp_error_category: "MissingAttribute",
43
+ keywords: ["schema", "attribute", "entity", "add", "new", "field"],
44
+ },
45
+ {
46
+ id: "default_deny",
47
+ severity: "info",
48
+ description: "Cedar is default-deny. A request is denied unless at least one `permit` policy explicitly matches AND no `forbid` policy matches. There is no 'allow by default' mode.",
49
+ keywords: ["deny", "block", "default", "access"],
50
+ },
51
+ {
52
+ id: "rebac_migration_data",
53
+ severity: "medium",
54
+ description: "Migrating from RBAC to ReBAC (relationship-based) requires populating relationship attributes on existing resources BEFORE deploying the new policy. Without the data, the policy will deny all access for resources without the relationship attribute.",
55
+ keywords: ["owner", "owners", "relationship", "rebac", "migrate", "per-document", "per-resource"],
56
+ },
57
+ {
58
+ id: "avp_single_namespace",
59
+ severity: "info",
60
+ description: "AVP policy stores support only one namespace per schema. If your Cedar policies use multiple namespaces locally, they cannot be deployed to a single AVP policy store.",
61
+ keywords: ["namespace", "avp", "deploy"],
62
+ },
63
+ {
64
+ id: "action_groups_not_automatic",
65
+ severity: "medium",
66
+ description: "Action group entities must be included in the entity list when evaluating locally. AVP adds them automatically, but local evaluation via WASM (and this tool) does not. Pass action group entities explicitly in your entity list.",
67
+ keywords: ["action", "group", "batch", "evaluate", "test"],
68
+ },
69
+ ];
70
+ /** Select relevant gotchas by matching intent keywords. */
71
+ export function selectGotchas(intent, maxCount = 5) {
72
+ const lower = intent.toLowerCase();
73
+ const scored = GOTCHA_CATALOG.map(g => ({
74
+ gotcha: g,
75
+ score: g.keywords.filter(kw => lower.includes(kw)).length,
76
+ }));
77
+ return scored
78
+ .filter(s => s.score > 0)
79
+ .sort((a, b) => b.score - a.score || (a.gotcha.severity === "high" ? -1 : 1))
80
+ .slice(0, maxCount)
81
+ .map(s => s.gotcha);
82
+ }
83
+ //# sourceMappingURL=gotchas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gotchas.js","sourceRoot":"","sources":["../../../src/tools/advise/gotchas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
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 type { PolicyInventoryEntry } from "./advise/context-builder.js";
15
+ import { StoreManager } from "../resources/store-manager.js";
16
+ export interface AdviseInput {
17
+ intent: string;
18
+ store_ref?: string;
19
+ }
20
+ export interface AdviseGotcha {
21
+ id: string;
22
+ severity: "high" | "medium" | "info";
23
+ description: string;
24
+ avp_error_category?: string;
25
+ }
26
+ export interface SchemaSummary {
27
+ valid: boolean;
28
+ format: "json" | "cedarschema";
29
+ namespaces: string[];
30
+ entity_type_count: number;
31
+ action_count: number;
32
+ raw_text: string;
33
+ errors?: string[];
34
+ }
35
+ export interface PatternDetected {
36
+ pattern: string;
37
+ count: number;
38
+ }
39
+ export interface CedarPatternDescription {
40
+ name: string;
41
+ description: string;
42
+ example: string;
43
+ }
44
+ export interface AvpUpdatePolicyRules {
45
+ summary: string;
46
+ in_place_via_update_policy: string[];
47
+ requires_delete_recreate: string[];
48
+ new_via_create_policy: string[];
49
+ notes: string[];
50
+ }
51
+ export interface AdviseContextBundle {
52
+ tool: "cedar_advise";
53
+ bundle_version: "v2";
54
+ intent: string;
55
+ store_name?: string;
56
+ store_status: "loaded" | "not_provided" | "not_found" | "ambiguous";
57
+ /**
58
+ * Names of every currently loaded store, populated when the resolver could
59
+ * not commit to a single store: `not_found` (caller named an unknown store)
60
+ * and `ambiguous` (no `store_ref` passed but multiple stores are loaded).
61
+ * Lets the calling LLM recover by retrying with an explicit `store_ref`
62
+ * without making another tool call just to learn the candidate names.
63
+ */
64
+ available_stores?: string[];
65
+ /**
66
+ * Populated when the resolver inferred the store rather than honoring an
67
+ * explicit `store_ref`. Currently the only resolution path is
68
+ * `single_loaded_store` (no `store_ref`, exactly one store loaded).
69
+ */
70
+ auto_discovered?: {
71
+ store_from: "single_loaded_store";
72
+ };
73
+ schema_summary?: SchemaSummary;
74
+ policy_inventory: PolicyInventoryEntry[];
75
+ patterns_detected_in_store: PatternDetected[];
76
+ applicable_gotchas: AdviseGotcha[];
77
+ avp_update_policy_rules: AvpUpdatePolicyRules;
78
+ avp_validation_error_catalog: {
79
+ id: string;
80
+ description: string;
81
+ }[];
82
+ cedar_patterns_reference: {
83
+ summary: string;
84
+ patterns: CedarPatternDescription[];
85
+ };
86
+ sequencing_guidance: string[];
87
+ next_steps_for_llm: string;
88
+ }
89
+ /**
90
+ * Build the cedar_advise context bundle.
91
+ *
92
+ * Pure function — no sampler, no LLM round-trip. The calling MCP client's
93
+ * conversation LLM is expected to interpret this bundle and produce the plan.
94
+ */
95
+ export declare function handleAdvise(input: AdviseInput, manager?: StoreManager): AdviseContextBundle;
96
+ //# sourceMappingURL=advise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advise.d.ts","sourceRoot":"","sources":["../../src/tools/advise.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAIxE,OAAO,EAAgB,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B,EAAE,MAAM,EAAE,CAAC;IACrC,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,QAAQ,GAAG,cAAc,GAAG,WAAW,GAAG,WAAW,CAAC;IACpE;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE;QAAE,UAAU,EAAE,qBAAqB,CAAA;KAAE,CAAC;IACxD,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,0BAA0B,EAAE,eAAe,EAAE,CAAC;IAC9C,kBAAkB,EAAE,YAAY,EAAE,CAAC;IACnC,uBAAuB,EAAE,oBAAoB,CAAC;IAC9C,4BAA4B,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpE,wBAAwB,EAAE;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,uBAAuB,EAAE,CAAC;KACrC,CAAC;IACF,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAiED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,YAA2B,GACnC,mBAAmB,CA0BrB"}