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.
- package/.editorconfig +12 -0
- package/.github/workflows/ci.yml +31 -0
- package/.github/workflows/release.yml +42 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +241 -0
- package/CONTRIBUTING.md +83 -0
- package/LICENSE +182 -0
- package/README.md +1635 -0
- package/SECURITY.md +37 -0
- package/dist/http-server.d.ts +61 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +194 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +270 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/policy-ast.d.ts +49 -0
- package/dist/parser/policy-ast.d.ts.map +1 -0
- package/dist/parser/policy-ast.js +311 -0
- package/dist/parser/policy-ast.js.map +1 -0
- package/dist/prompts/index.d.ts +38 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +172 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/resources/ref-resolver.d.ts +23 -0
- package/dist/resources/ref-resolver.d.ts.map +1 -0
- package/dist/resources/ref-resolver.js +128 -0
- package/dist/resources/ref-resolver.js.map +1 -0
- package/dist/resources/store-manager.d.ts +64 -0
- package/dist/resources/store-manager.d.ts.map +1 -0
- package/dist/resources/store-manager.js +221 -0
- package/dist/resources/store-manager.js.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +539 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/advise/avp-rules.d.ts +49 -0
- package/dist/tools/advise/avp-rules.d.ts.map +1 -0
- package/dist/tools/advise/avp-rules.js +59 -0
- package/dist/tools/advise/avp-rules.js.map +1 -0
- package/dist/tools/advise/cedar-patterns.d.ts +24 -0
- package/dist/tools/advise/cedar-patterns.d.ts.map +1 -0
- package/dist/tools/advise/cedar-patterns.js +57 -0
- package/dist/tools/advise/cedar-patterns.js.map +1 -0
- package/dist/tools/advise/context-builder.d.ts +28 -0
- package/dist/tools/advise/context-builder.d.ts.map +1 -0
- package/dist/tools/advise/context-builder.js +89 -0
- package/dist/tools/advise/context-builder.js.map +1 -0
- package/dist/tools/advise/gotchas.d.ts +15 -0
- package/dist/tools/advise/gotchas.d.ts.map +1 -0
- package/dist/tools/advise/gotchas.js +83 -0
- package/dist/tools/advise/gotchas.js.map +1 -0
- package/dist/tools/advise.d.ts +96 -0
- package/dist/tools/advise.d.ts.map +1 -0
- package/dist/tools/advise.js +258 -0
- package/dist/tools/advise.js.map +1 -0
- package/dist/tools/authorize-batch.d.ts +35 -0
- package/dist/tools/authorize-batch.d.ts.map +1 -0
- package/dist/tools/authorize-batch.js +262 -0
- package/dist/tools/authorize-batch.js.map +1 -0
- package/dist/tools/authorize.d.ts +115 -0
- package/dist/tools/authorize.d.ts.map +1 -0
- package/dist/tools/authorize.js +373 -0
- package/dist/tools/authorize.js.map +1 -0
- package/dist/tools/check-change.d.ts +19 -0
- package/dist/tools/check-change.d.ts.map +1 -0
- package/dist/tools/check-change.js +91 -0
- package/dist/tools/check-change.js.map +1 -0
- package/dist/tools/diff-schema.d.ts +103 -0
- package/dist/tools/diff-schema.d.ts.map +1 -0
- package/dist/tools/diff-schema.js +379 -0
- package/dist/tools/diff-schema.js.map +1 -0
- package/dist/tools/diff-stores.d.ts +45 -0
- package/dist/tools/diff-stores.d.ts.map +1 -0
- package/dist/tools/diff-stores.js +222 -0
- package/dist/tools/diff-stores.js.map +1 -0
- package/dist/tools/explain.d.ts +80 -0
- package/dist/tools/explain.d.ts.map +1 -0
- package/dist/tools/explain.js +187 -0
- package/dist/tools/explain.js.map +1 -0
- package/dist/tools/format.d.ts +11 -0
- package/dist/tools/format.d.ts.map +1 -0
- package/dist/tools/format.js +20 -0
- package/dist/tools/format.js.map +1 -0
- package/dist/tools/generate-sample.d.ts +28 -0
- package/dist/tools/generate-sample.d.ts.map +1 -0
- package/dist/tools/generate-sample.js +568 -0
- package/dist/tools/generate-sample.js.map +1 -0
- package/dist/tools/link-template.d.ts +17 -0
- package/dist/tools/link-template.d.ts.map +1 -0
- package/dist/tools/link-template.js +78 -0
- package/dist/tools/link-template.js.map +1 -0
- package/dist/tools/list-template-links.d.ts +16 -0
- package/dist/tools/list-template-links.d.ts.map +1 -0
- package/dist/tools/list-template-links.js +22 -0
- package/dist/tools/list-template-links.js.map +1 -0
- package/dist/tools/list-templates.d.ts +16 -0
- package/dist/tools/list-templates.d.ts.map +1 -0
- package/dist/tools/list-templates.js +36 -0
- package/dist/tools/list-templates.js.map +1 -0
- package/dist/tools/translate.d.ts +11 -0
- package/dist/tools/translate.d.ts.map +1 -0
- package/dist/tools/translate.js +53 -0
- package/dist/tools/translate.js.map +1 -0
- package/dist/tools/validate-entities.d.ts +19 -0
- package/dist/tools/validate-entities.d.ts.map +1 -0
- package/dist/tools/validate-entities.js +88 -0
- package/dist/tools/validate-entities.js.map +1 -0
- package/dist/tools/validate-schema.d.ts +22 -0
- package/dist/tools/validate-schema.d.ts.map +1 -0
- package/dist/tools/validate-schema.js +89 -0
- package/dist/tools/validate-schema.js.map +1 -0
- package/dist/tools/validate-template.d.ts +18 -0
- package/dist/tools/validate-template.d.ts.map +1 -0
- package/dist/tools/validate-template.js +59 -0
- package/dist/tools/validate-template.js.map +1 -0
- package/dist/tools/validate.d.ts +90 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +351 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/utils/format-detector.d.ts +49 -0
- package/dist/utils/format-detector.d.ts.map +1 -0
- package/dist/utils/format-detector.js +298 -0
- package/dist/utils/format-detector.js.map +1 -0
- package/examples/README.md +36 -0
- package/examples/abac-multi-tenant/README.md +150 -0
- package/examples/abac-multi-tenant/entities/users-and-docs.json +33 -0
- package/examples/abac-multi-tenant/policies/member-read-internal.cedar +9 -0
- package/examples/abac-multi-tenant/policies/owner-full-access.cedar +9 -0
- package/examples/abac-multi-tenant/policies/premium-share-guard.cedar +9 -0
- package/examples/abac-multi-tenant/policies/private-doc-guard.cedar +13 -0
- package/examples/abac-multi-tenant/run.ts +92 -0
- package/examples/abac-multi-tenant/schema.json +60 -0
- package/examples/api-gateway-path-routing/README.md +154 -0
- package/examples/api-gateway-path-routing/entities/users-and-roles.json +20 -0
- package/examples/api-gateway-path-routing/policies/admin-full-access.cedar +6 -0
- package/examples/api-gateway-path-routing/policies/developer-projects.cedar +14 -0
- package/examples/api-gateway-path-routing/policies/viewer-readonly.cedar +10 -0
- package/examples/api-gateway-path-routing/run.ts +108 -0
- package/examples/api-gateway-path-routing/schema.json +54 -0
- package/examples/rbac-document-management/README.md +167 -0
- package/examples/rbac-document-management/entities/users-and-docs.json +43 -0
- package/examples/rbac-document-management/policies/admin.cedar +6 -0
- package/examples/rbac-document-management/policies/editor.cedar +6 -0
- package/examples/rbac-document-management/policies/top-secret-forbid.cedar +13 -0
- package/examples/rbac-document-management/policies/viewer.cedar +6 -0
- package/examples/rbac-document-management/run.ts +87 -0
- package/examples/rbac-document-management/schema.json +57 -0
- package/package.json +50 -0
- package/src/http-server.ts +239 -0
- package/src/index.ts +294 -0
- package/src/parser/policy-ast.ts +345 -0
- package/src/prompts/README.md +3 -0
- package/src/prompts/index.ts +217 -0
- package/src/resources/ref-resolver.ts +134 -0
- package/src/resources/store-manager.ts +248 -0
- package/src/server.ts +711 -0
- package/src/tools/advise/avp-rules.ts +70 -0
- package/src/tools/advise/cedar-patterns.ts +73 -0
- package/src/tools/advise/context-builder.ts +109 -0
- package/src/tools/advise/gotchas.ts +92 -0
- package/src/tools/advise.ts +366 -0
- package/src/tools/authorize-batch.ts +345 -0
- package/src/tools/authorize.ts +464 -0
- package/src/tools/check-change.ts +119 -0
- package/src/tools/diff-schema.ts +510 -0
- package/src/tools/diff-stores.ts +298 -0
- package/src/tools/explain.ts +278 -0
- package/src/tools/format.ts +33 -0
- package/src/tools/generate-sample.ts +665 -0
- package/src/tools/link-template.ts +109 -0
- package/src/tools/list-template-links.ts +41 -0
- package/src/tools/list-templates.ts +55 -0
- package/src/tools/translate.ts +66 -0
- package/src/tools/validate-entities.ts +125 -0
- package/src/tools/validate-schema.ts +128 -0
- package/src/tools/validate-template.ts +72 -0
- package/src/tools/validate.ts +459 -0
- package/src/utils/format-detector.ts +356 -0
- package/test/fixtures/docmgmt.ts +121 -0
- package/test/fixtures/multitenant.ts +163 -0
- package/test/index.test.ts +96 -0
- package/test/integration/e2e/behavior.test.ts +359 -0
- package/test/integration/e2e/edge-cases.test.ts +365 -0
- package/test/integration/e2e/failure-modes.test.ts +266 -0
- package/test/integration/e2e/protocol.test.ts +252 -0
- package/test/integration/http-smoke.test.ts +588 -0
- package/test/integration/smoke.test.ts +475 -0
- package/test/prompts/prompts.test.ts +173 -0
- package/test/property/properties.test.ts +234 -0
- package/test/resources/ref-resolver.test.ts +186 -0
- package/test/resources/store-manager.test.ts +344 -0
- package/test/setup.test.ts +7 -0
- package/test/tools/advise/avp-rules.test.ts +76 -0
- package/test/tools/advise.test.ts +339 -0
- package/test/tools/authorize-batch.test.ts +459 -0
- package/test/tools/authorize.test.ts +682 -0
- package/test/tools/check-change.test.ts +104 -0
- package/test/tools/cross-fixture.test.ts +170 -0
- package/test/tools/diff-schema.test.ts +355 -0
- package/test/tools/diff-stores.test.ts +291 -0
- package/test/tools/explain.test.ts +221 -0
- package/test/tools/format.test.ts +33 -0
- package/test/tools/generate-sample.test.ts +480 -0
- package/test/tools/link-template.test.ts +90 -0
- package/test/tools/list-templates.test.ts +151 -0
- package/test/tools/translate.test.ts +89 -0
- package/test/tools/validate-entities.test.ts +178 -0
- package/test/tools/validate-schema.test.ts +86 -0
- package/test/tools/validate-template.test.ts +89 -0
- package/test/tools/validate.test.ts +331 -0
- package/test/utils/format-detector.test.ts +518 -0
- package/tsconfig.json +17 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for walking the PolicyJson AST returned by policyToJson / templateToJson.
|
|
3
|
+
*
|
|
4
|
+
* AST shape proven in spike (2026-05-19):
|
|
5
|
+
* - principal/action/resource: { op: "All" | "==" | "in", entity?, entities?, slot? }
|
|
6
|
+
* - "in" with single entity → entity key (singular)
|
|
7
|
+
* - "in" with multiple → entities key (plural)
|
|
8
|
+
* - conditions: [{ kind: "when"|"unless", body: ExprTree }]
|
|
9
|
+
* - ExprTree: operator-as-key encoding ("==", "&&", "||", "has", ".", "Var", "Value")
|
|
10
|
+
* - Entity literals in scope: { type, id }
|
|
11
|
+
* - Entity literals in conditions: { "Value": { "__entity": { type, id } } }
|
|
12
|
+
*
|
|
13
|
+
* like operator shape (proven in spike 2026-05-20):
|
|
14
|
+
* - { "like": { "left": Expr, "pattern": PatternElem[] } }
|
|
15
|
+
* - PatternElem = "Wildcard" | { Literal: string }
|
|
16
|
+
* - CRITICAL: pattern is CHARACTER-LEVEL — "/api/v1/*" produces one {Literal} per char,
|
|
17
|
+
* not one {Literal: "/api/v1/"} node. Reconstruct by joining all Literal chars,
|
|
18
|
+
* substituting "Wildcard" positions with the desired value.
|
|
19
|
+
* - Negated like: { "!": { "arg": { "like": { ... } } } }
|
|
20
|
+
* - Cedar wildcard matches any char sequence INCLUDING "/". Depth-limiting works via TWO wildcards:
|
|
21
|
+
* "like X/WILDCARD" matches any depth; "like X/WILDCARD/WILDCARD" also matches — negation limits to one segment.
|
|
22
|
+
*/
|
|
23
|
+
import type { PolicyJson, Clause } from "@cedar-policy/cedar-wasm/nodejs";
|
|
24
|
+
export declare function describePrincipal(principal: PolicyJson["principal"]): string;
|
|
25
|
+
export declare function describeAction(action: PolicyJson["action"]): string;
|
|
26
|
+
export declare function describeResource(resource: PolicyJson["resource"]): string;
|
|
27
|
+
export declare function describeCondition(clause: Clause): string;
|
|
28
|
+
export declare function detectPatterns(json: PolicyJson): string[];
|
|
29
|
+
export type PatternElem = "Wildcard" | {
|
|
30
|
+
Literal: string;
|
|
31
|
+
};
|
|
32
|
+
export interface LikeConstraint {
|
|
33
|
+
variable: "principal" | "resource" | "context";
|
|
34
|
+
attr: string;
|
|
35
|
+
pattern: PatternElem[];
|
|
36
|
+
negated: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reconstructs a string from a PatternElem array.
|
|
40
|
+
* Each Wildcard is replaced by wildcardValue.
|
|
41
|
+
* Pattern is character-level (one Literal node per char) — join them all.
|
|
42
|
+
*/
|
|
43
|
+
export declare function patternToString(pattern: PatternElem[], wildcardValue: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Walks condition bodies and extracts all `like` constraints (positive and negated).
|
|
46
|
+
* Returns constraints keyed by variable.attr so callers can decide which to use.
|
|
47
|
+
*/
|
|
48
|
+
export declare function extractLikeConstraints(conditions: PolicyJson["conditions"]): LikeConstraint[];
|
|
49
|
+
//# sourceMappingURL=policy-ast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-ast.d.ts","sourceRoot":"","sources":["../../src/parser/policy-ast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAQ,MAAM,iCAAiC,CAAC;AAIhF,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,MAAM,CAsB5E;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,MAAM,CAiBnE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,GAAG,MAAM,CAmBzE;AAID,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIxD;AAuFD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CA0CzD;AA2BD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAIrF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,GAAG,cAAc,EAAE,CAM7F"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for walking the PolicyJson AST returned by policyToJson / templateToJson.
|
|
3
|
+
*
|
|
4
|
+
* AST shape proven in spike (2026-05-19):
|
|
5
|
+
* - principal/action/resource: { op: "All" | "==" | "in", entity?, entities?, slot? }
|
|
6
|
+
* - "in" with single entity → entity key (singular)
|
|
7
|
+
* - "in" with multiple → entities key (plural)
|
|
8
|
+
* - conditions: [{ kind: "when"|"unless", body: ExprTree }]
|
|
9
|
+
* - ExprTree: operator-as-key encoding ("==", "&&", "||", "has", ".", "Var", "Value")
|
|
10
|
+
* - Entity literals in scope: { type, id }
|
|
11
|
+
* - Entity literals in conditions: { "Value": { "__entity": { type, id } } }
|
|
12
|
+
*
|
|
13
|
+
* like operator shape (proven in spike 2026-05-20):
|
|
14
|
+
* - { "like": { "left": Expr, "pattern": PatternElem[] } }
|
|
15
|
+
* - PatternElem = "Wildcard" | { Literal: string }
|
|
16
|
+
* - CRITICAL: pattern is CHARACTER-LEVEL — "/api/v1/*" produces one {Literal} per char,
|
|
17
|
+
* not one {Literal: "/api/v1/"} node. Reconstruct by joining all Literal chars,
|
|
18
|
+
* substituting "Wildcard" positions with the desired value.
|
|
19
|
+
* - Negated like: { "!": { "arg": { "like": { ... } } } }
|
|
20
|
+
* - Cedar wildcard matches any char sequence INCLUDING "/". Depth-limiting works via TWO wildcards:
|
|
21
|
+
* "like X/WILDCARD" matches any depth; "like X/WILDCARD/WILDCARD" also matches — negation limits to one segment.
|
|
22
|
+
*/
|
|
23
|
+
// ─── Scope description ───────────────────────────────────────────────────────
|
|
24
|
+
export function describePrincipal(principal) {
|
|
25
|
+
// Check for slot first — applies to both "==" and "in" ops in templates
|
|
26
|
+
if ("slot" in principal) {
|
|
27
|
+
const slot = principal["slot"];
|
|
28
|
+
return `principal bound to slot ${slot}`;
|
|
29
|
+
}
|
|
30
|
+
switch (principal.op) {
|
|
31
|
+
case "All":
|
|
32
|
+
return "any principal";
|
|
33
|
+
case "==": {
|
|
34
|
+
const e = "entity" in principal ? principal.entity : null;
|
|
35
|
+
if (e && "type" in e)
|
|
36
|
+
return `exactly ${e.type}::"${e.id}"`;
|
|
37
|
+
return "exactly (unknown)";
|
|
38
|
+
}
|
|
39
|
+
case "in": {
|
|
40
|
+
const entities = resolveInEntities(principal);
|
|
41
|
+
if (entities.length === 1)
|
|
42
|
+
return `principal in ${formatEntity(entities[0])}`;
|
|
43
|
+
return `principal in [${entities.map(formatEntity).join(", ")}]`;
|
|
44
|
+
}
|
|
45
|
+
default:
|
|
46
|
+
return "principal (unknown constraint)";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function describeAction(action) {
|
|
50
|
+
switch (action.op) {
|
|
51
|
+
case "All":
|
|
52
|
+
return "any action";
|
|
53
|
+
case "==": {
|
|
54
|
+
const e = "entity" in action ? action.entity : null;
|
|
55
|
+
if (e && "type" in e)
|
|
56
|
+
return `action ${formatEntity(e)}`;
|
|
57
|
+
return "exactly (unknown action)";
|
|
58
|
+
}
|
|
59
|
+
case "in": {
|
|
60
|
+
const entities = resolveInEntities(action);
|
|
61
|
+
if (entities.length === 1)
|
|
62
|
+
return `action in ${formatEntity(entities[0])}`;
|
|
63
|
+
return `action in [${entities.map(formatEntity).join(", ")}]`;
|
|
64
|
+
}
|
|
65
|
+
default:
|
|
66
|
+
return "action (unknown constraint)";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export function describeResource(resource) {
|
|
70
|
+
switch (resource.op) {
|
|
71
|
+
case "All":
|
|
72
|
+
return "any resource";
|
|
73
|
+
case "==": {
|
|
74
|
+
const e = "entity" in resource ? resource.entity : null;
|
|
75
|
+
const s = "slot" in resource ? resource.slot : null;
|
|
76
|
+
if (s)
|
|
77
|
+
return `resource bound to slot ${s}`;
|
|
78
|
+
if (e && "type" in e)
|
|
79
|
+
return `exactly ${e.type}::"${e.id}"`;
|
|
80
|
+
return "exactly (unknown)";
|
|
81
|
+
}
|
|
82
|
+
case "in": {
|
|
83
|
+
const entities = resolveInEntities(resource);
|
|
84
|
+
if (entities.length === 1)
|
|
85
|
+
return `resource in ${formatEntity(entities[0])}`;
|
|
86
|
+
return `resource in [${entities.map(formatEntity).join(", ")}]`;
|
|
87
|
+
}
|
|
88
|
+
default:
|
|
89
|
+
return "resource (unknown constraint)";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// ─── Condition rendering ──────────────────────────────────────────────────────
|
|
93
|
+
export function describeCondition(clause) {
|
|
94
|
+
const kindLabel = clause.kind === "when" ? "WHEN" : "UNLESS";
|
|
95
|
+
const bodyDesc = describeExpr(clause.body);
|
|
96
|
+
return `${kindLabel} ${bodyDesc}`;
|
|
97
|
+
}
|
|
98
|
+
function describeExpr(expr) {
|
|
99
|
+
if (typeof expr !== "object" || expr === null)
|
|
100
|
+
return String(expr);
|
|
101
|
+
// Var node: { "Var": "principal" | "action" | "resource" | "context" }
|
|
102
|
+
if ("Var" in expr)
|
|
103
|
+
return String(expr["Var"]);
|
|
104
|
+
// Value node: { "Value": <cedar-value> }
|
|
105
|
+
if ("Value" in expr)
|
|
106
|
+
return formatValue(expr["Value"]);
|
|
107
|
+
// Attribute access: { ".": { left, attr } }
|
|
108
|
+
if ("." in expr) {
|
|
109
|
+
const node = expr["."];
|
|
110
|
+
return `${describeExpr(node.left)}.${node.attr}`;
|
|
111
|
+
}
|
|
112
|
+
// Equality: { "==": { left, right } }
|
|
113
|
+
if ("==" in expr) {
|
|
114
|
+
const node = expr["=="];
|
|
115
|
+
return `${describeExpr(node.left)} == ${describeExpr(node.right)}`;
|
|
116
|
+
}
|
|
117
|
+
// Inequality
|
|
118
|
+
if ("!=" in expr) {
|
|
119
|
+
const node = expr["!="];
|
|
120
|
+
return `${describeExpr(node.left)} != ${describeExpr(node.right)}`;
|
|
121
|
+
}
|
|
122
|
+
// Logical AND: { "&&": { left, right } }
|
|
123
|
+
if ("&&" in expr) {
|
|
124
|
+
const node = expr["&&"];
|
|
125
|
+
return `${describeExpr(node.left)} AND ${describeExpr(node.right)}`;
|
|
126
|
+
}
|
|
127
|
+
// Logical OR: { "||": { left, right } }
|
|
128
|
+
if ("||" in expr) {
|
|
129
|
+
const node = expr["||"];
|
|
130
|
+
return `(${describeExpr(node.left)} OR ${describeExpr(node.right)})`;
|
|
131
|
+
}
|
|
132
|
+
// Has (optional attribute check): { "has": { left, attr } }
|
|
133
|
+
if ("has" in expr) {
|
|
134
|
+
const node = expr["has"];
|
|
135
|
+
return `${describeExpr(node.left)} has '${node.attr}'`;
|
|
136
|
+
}
|
|
137
|
+
// In (membership): { "in": { left, right } }
|
|
138
|
+
if ("in" in expr) {
|
|
139
|
+
const node = expr["in"];
|
|
140
|
+
return `${describeExpr(node.left)} in ${describeExpr(node.right)}`;
|
|
141
|
+
}
|
|
142
|
+
// Set literal: { "Set": Expr[] }
|
|
143
|
+
if ("Set" in expr) {
|
|
144
|
+
const items = expr["Set"];
|
|
145
|
+
return `[${items.map(describeExpr).join(", ")}]`;
|
|
146
|
+
}
|
|
147
|
+
// Negation: { "!": { arg } }
|
|
148
|
+
if ("!" in expr) {
|
|
149
|
+
const node = expr["!"];
|
|
150
|
+
return `NOT(${describeExpr(node.arg)})`;
|
|
151
|
+
}
|
|
152
|
+
// like: { "like": { left: Expr, pattern: PatternElem[] } }
|
|
153
|
+
// Reconstruct pattern with * for wildcards so it reads as Cedar syntax
|
|
154
|
+
if ("like" in expr) {
|
|
155
|
+
const node = expr["like"];
|
|
156
|
+
const patternStr = patternToString(node.pattern, "*");
|
|
157
|
+
return `${describeExpr(node.left)} like "${patternStr}"`;
|
|
158
|
+
}
|
|
159
|
+
// contains() call appears as an ExtFuncCall: { "contains": [left, right] }
|
|
160
|
+
// ExtFuncCall is {} & Record<string, Expr[]> — operator is the key, value is args array
|
|
161
|
+
const keys = Object.keys(expr);
|
|
162
|
+
if (keys.length === 1 && Array.isArray(expr[keys[0]])) {
|
|
163
|
+
const fn = keys[0];
|
|
164
|
+
const args = expr[fn];
|
|
165
|
+
return `${describeExpr(args[0])}.${fn}(${args.slice(1).map(describeExpr).join(", ")})`;
|
|
166
|
+
}
|
|
167
|
+
return "complex condition";
|
|
168
|
+
}
|
|
169
|
+
// ─── Pattern detection ────────────────────────────────────────────────────────
|
|
170
|
+
export function detectPatterns(json) {
|
|
171
|
+
const patterns = [];
|
|
172
|
+
if (json.effect === "forbid")
|
|
173
|
+
patterns.push("forbid_policy");
|
|
174
|
+
// Principal scope patterns
|
|
175
|
+
const principalHasSlot = "slot" in json.principal;
|
|
176
|
+
if (principalHasSlot) {
|
|
177
|
+
patterns.push("template_policy", "slot_principal");
|
|
178
|
+
}
|
|
179
|
+
else if (json.principal.op === "in") {
|
|
180
|
+
patterns.push("role_based_access");
|
|
181
|
+
}
|
|
182
|
+
if (json.principal.op === "All")
|
|
183
|
+
patterns.push("any_principal");
|
|
184
|
+
// Action scope patterns
|
|
185
|
+
if (json.action.op === "All")
|
|
186
|
+
patterns.push("unrestricted_action");
|
|
187
|
+
// Resource scope patterns
|
|
188
|
+
if (json.resource.op === "All")
|
|
189
|
+
patterns.push("unrestricted_resource");
|
|
190
|
+
if (json.resource.op === "==" && "slot" in json.resource) {
|
|
191
|
+
if (!patterns.includes("template_policy"))
|
|
192
|
+
patterns.push("template_policy");
|
|
193
|
+
patterns.push("slot_resource");
|
|
194
|
+
}
|
|
195
|
+
// Condition patterns
|
|
196
|
+
const allConditionText = json.conditions.map((c) => JSON.stringify(c)).join(" ");
|
|
197
|
+
if (json.conditions.some((c) => c.kind === "unless"))
|
|
198
|
+
patterns.push("role_exemption");
|
|
199
|
+
if (allConditionText.includes('"has"'))
|
|
200
|
+
patterns.push("optional_attribute_guard");
|
|
201
|
+
if (allConditionText.includes("contains"))
|
|
202
|
+
patterns.push("attribute_containment_check");
|
|
203
|
+
// Name-based identity: principal.name == "..."
|
|
204
|
+
if (allConditionText.includes('"name"') && allConditionText.includes('"Var":"principal"')) {
|
|
205
|
+
patterns.push("name_based_identity");
|
|
206
|
+
}
|
|
207
|
+
// Attribute-based conditions (when clause present and non-trivial)
|
|
208
|
+
if (json.conditions.length > 0 && !patterns.includes("role_exemption")) {
|
|
209
|
+
patterns.push("attribute_condition");
|
|
210
|
+
}
|
|
211
|
+
return [...new Set(patterns)];
|
|
212
|
+
}
|
|
213
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
214
|
+
/** Handles the entity vs entities asymmetry from policyToJson */
|
|
215
|
+
function resolveInEntities(constraint) {
|
|
216
|
+
if ("entities" in constraint && Array.isArray(constraint["entities"])) {
|
|
217
|
+
return constraint["entities"];
|
|
218
|
+
}
|
|
219
|
+
if ("entity" in constraint && constraint["entity"]) {
|
|
220
|
+
return [constraint["entity"]];
|
|
221
|
+
}
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
function formatEntity(e) {
|
|
225
|
+
if (e && typeof e === "object" && "type" in e && "id" in e) {
|
|
226
|
+
const entity = e;
|
|
227
|
+
return `${entity.type}::"${entity.id}"`;
|
|
228
|
+
}
|
|
229
|
+
return JSON.stringify(e);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Reconstructs a string from a PatternElem array.
|
|
233
|
+
* Each Wildcard is replaced by wildcardValue.
|
|
234
|
+
* Pattern is character-level (one Literal node per char) — join them all.
|
|
235
|
+
*/
|
|
236
|
+
export function patternToString(pattern, wildcardValue) {
|
|
237
|
+
return pattern
|
|
238
|
+
.map((e) => (e === "Wildcard" ? wildcardValue : e.Literal))
|
|
239
|
+
.join("");
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Walks condition bodies and extracts all `like` constraints (positive and negated).
|
|
243
|
+
* Returns constraints keyed by variable.attr so callers can decide which to use.
|
|
244
|
+
*/
|
|
245
|
+
export function extractLikeConstraints(conditions) {
|
|
246
|
+
const result = [];
|
|
247
|
+
for (const clause of conditions) {
|
|
248
|
+
walkLikeExpr(clause.body, false, result);
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
function walkLikeExpr(expr, insideNot, acc) {
|
|
253
|
+
if (typeof expr !== "object" || expr === null)
|
|
254
|
+
return;
|
|
255
|
+
const e = expr;
|
|
256
|
+
if ("&&" in e || "||" in e) {
|
|
257
|
+
const key = "&&" in e ? "&&" : "||";
|
|
258
|
+
const node = e[key];
|
|
259
|
+
walkLikeExpr(node.left, insideNot, acc);
|
|
260
|
+
walkLikeExpr(node.right, insideNot, acc);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if ("!" in e) {
|
|
264
|
+
const node = e["!"];
|
|
265
|
+
walkLikeExpr(node.arg, !insideNot, acc);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if ("like" in e) {
|
|
269
|
+
const node = e["like"];
|
|
270
|
+
const attrAccess = extractAttrFromLike(node.left);
|
|
271
|
+
if (attrAccess) {
|
|
272
|
+
acc.push({
|
|
273
|
+
variable: attrAccess.variable,
|
|
274
|
+
attr: attrAccess.attr,
|
|
275
|
+
pattern: node.pattern,
|
|
276
|
+
negated: insideNot,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function extractAttrFromLike(expr) {
|
|
283
|
+
if (typeof expr !== "object" || expr === null)
|
|
284
|
+
return null;
|
|
285
|
+
const e = expr;
|
|
286
|
+
if ("." in e) {
|
|
287
|
+
const node = e["."];
|
|
288
|
+
const v = node.left?.["Var"];
|
|
289
|
+
if (v === "principal" || v === "resource" || v === "context") {
|
|
290
|
+
return { variable: v, attr: node.attr };
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
function formatValue(v) {
|
|
296
|
+
if (v === null)
|
|
297
|
+
return "null";
|
|
298
|
+
if (typeof v === "string")
|
|
299
|
+
return `"${v}"`;
|
|
300
|
+
if (typeof v === "boolean" || typeof v === "number")
|
|
301
|
+
return String(v);
|
|
302
|
+
// Entity literal inside condition body: { __entity: { type, id } }
|
|
303
|
+
if (typeof v === "object" && v !== null && "__entity" in v) {
|
|
304
|
+
const entity = v["__entity"];
|
|
305
|
+
return formatEntity(entity);
|
|
306
|
+
}
|
|
307
|
+
if (Array.isArray(v))
|
|
308
|
+
return `[${v.map(formatValue).join(", ")}]`;
|
|
309
|
+
return JSON.stringify(v);
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=policy-ast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-ast.js","sourceRoot":"","sources":["../../src/parser/policy-ast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Prompt definitions for cedar-mcp-server.
|
|
3
|
+
*
|
|
4
|
+
* Registration in src/server.ts:
|
|
5
|
+
* import { PROMPT_DEFINITIONS } from "./prompts/index.js";
|
|
6
|
+
* for (const p of PROMPT_DEFINITIONS) {
|
|
7
|
+
* server.prompt(p.name, p.description, p.argsSchema, p.handler);
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* Each PromptDefinition is built via definePrompt(), which captures the Zod
|
|
11
|
+
* raw shape generically so TypeScript preserves the concrete arg types through
|
|
12
|
+
* the handler. The array is typed as PromptDefinition<ZodRawShape> for the
|
|
13
|
+
* export; the SDK's server.prompt() overload accepts the same shape.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import type { GetPromptResult } from "@modelcontextprotocol/sdk/types.js";
|
|
17
|
+
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
18
|
+
import type { ServerRequest, ServerNotification } from "@modelcontextprotocol/sdk/types.js";
|
|
19
|
+
type ZodRawShape = Record<string, z.ZodTypeAny>;
|
|
20
|
+
type ShapeOutput<S extends ZodRawShape> = {
|
|
21
|
+
[K in keyof S]: z.infer<S[K]>;
|
|
22
|
+
};
|
|
23
|
+
type PromptExtra = RequestHandlerExtra<ServerRequest, ServerNotification>;
|
|
24
|
+
/**
|
|
25
|
+
* PromptDefinition is intentionally generic so handler arg types are preserved
|
|
26
|
+
* internally. At the export boundary the array is cast to the widened union
|
|
27
|
+
* via definePrompt() which uses `as unknown as` once, in one place.
|
|
28
|
+
*/
|
|
29
|
+
export interface PromptDefinition<Args extends ZodRawShape = ZodRawShape> {
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
argsSchema: Args;
|
|
33
|
+
handler: (args: ShapeOutput<Args>, extra: PromptExtra) => GetPromptResult | Promise<GetPromptResult>;
|
|
34
|
+
}
|
|
35
|
+
type AnyPromptDefinition = PromptDefinition<any>;
|
|
36
|
+
export declare const PROMPT_DEFINITIONS: AnyPromptDefinition[];
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;AAChD,KAAK,WAAW,CAAC,CAAC,SAAS,WAAW,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAC5E,KAAK,WAAW,GAAG,mBAAmB,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACtG;AAGD,KAAK,mBAAmB,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;AA+KjD,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,EAInD,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Prompt definitions for cedar-mcp-server.
|
|
3
|
+
*
|
|
4
|
+
* Registration in src/server.ts:
|
|
5
|
+
* import { PROMPT_DEFINITIONS } from "./prompts/index.js";
|
|
6
|
+
* for (const p of PROMPT_DEFINITIONS) {
|
|
7
|
+
* server.prompt(p.name, p.description, p.argsSchema, p.handler);
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* Each PromptDefinition is built via definePrompt(), which captures the Zod
|
|
11
|
+
* raw shape generically so TypeScript preserves the concrete arg types through
|
|
12
|
+
* the handler. The array is typed as PromptDefinition<ZodRawShape> for the
|
|
13
|
+
* export; the SDK's server.prompt() overload accepts the same shape.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
function definePrompt(def) {
|
|
17
|
+
return def;
|
|
18
|
+
}
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// 1. cedar-review-policy-diff
|
|
21
|
+
//
|
|
22
|
+
// UX assumption: the user has two named policy stores ("blue" = production,
|
|
23
|
+
// "green" = candidate) and wants a structured review before promoting. They
|
|
24
|
+
// expect the prompt to drive all Cedar tool calls and produce a clear verdict.
|
|
25
|
+
//
|
|
26
|
+
// Falsifiability check: would this be useless? Yes, if it skipped the schema
|
|
27
|
+
// diff step. A promoter who misses schema diff will hit breaking changes only
|
|
28
|
+
// at query time. Fixed: schema diff is an explicit step with BREAKING/
|
|
29
|
+
// NON-BREAKING classification.
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
const reviewPolicyDiff = definePrompt({
|
|
32
|
+
name: "cedar-review-policy-diff",
|
|
33
|
+
description: "Drive a structured Cedar policy store promotion review: diff policies, diff schema, summarize breaking risk, and produce a go/no-go recommendation.",
|
|
34
|
+
argsSchema: {
|
|
35
|
+
blue_store: z.string().describe("Name of the baseline (production) policy store"),
|
|
36
|
+
green_store: z.string().describe("Name of the candidate policy store to review"),
|
|
37
|
+
focus: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Optional: narrows review attention, e.g. 'AVP immutability' or 'forbid rules only'"),
|
|
41
|
+
},
|
|
42
|
+
handler: (args) => {
|
|
43
|
+
const focusNote = args.focus
|
|
44
|
+
? `\n\nFocus area for this review: ${args.focus}. Apply extra scrutiny to anything touching that area.`
|
|
45
|
+
: "";
|
|
46
|
+
const text = `You are reviewing a Cedar policy store promotion from "${args.blue_store}" (baseline) to "${args.green_store}" (candidate).` +
|
|
47
|
+
`${focusNote}` +
|
|
48
|
+
`\n\nWork through the following steps in order.\n\n` +
|
|
49
|
+
`Step 1: Structural diff.\n` +
|
|
50
|
+
`Call cedar_diff_policy_stores with blue="${args.blue_store}" and green="${args.green_store}". ` +
|
|
51
|
+
`List every added, removed, and modified policy. Note the policy IDs and whether each change is additive or restrictive.\n\n` +
|
|
52
|
+
`Step 2: Schema diff.\n` +
|
|
53
|
+
`Call cedar_diff_schema with schemas from both stores (cedar://schema/${args.blue_store} and cedar://schema/${args.green_store}). ` +
|
|
54
|
+
`If the diff is non-trivial (any entity type added, removed, or attribute changed), classify each change as BREAKING or NON-BREAKING. ` +
|
|
55
|
+
`A schema change is BREAKING if existing valid Cedar requests could become invalid or if attribute types narrow.\n\n` +
|
|
56
|
+
`Step 3: Behavioral drift summary.\n` +
|
|
57
|
+
`If behavioral_test_requests are available in either store, note any decisions that differ between blue and green. ` +
|
|
58
|
+
`Flag any new Deny decisions that did not exist in blue as HIGH risk.\n\n` +
|
|
59
|
+
`Step 4: Recommendation.\n` +
|
|
60
|
+
`Produce a plain-English summary covering: (a) structural changes, (b) breaking schema risk items, ` +
|
|
61
|
+
`(c) behavioral drift if present, and (d) a clear PROMOTE / DO NOT PROMOTE / PROMOTE WITH CAUTION verdict with reasoning. ` +
|
|
62
|
+
`No marketing language. Use semicolons instead of dashes for lists. Be specific about which policy IDs drive the verdict.`;
|
|
63
|
+
return {
|
|
64
|
+
messages: [{ role: "user", content: { type: "text", text } }],
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// 2. cedar-explain-denial
|
|
70
|
+
//
|
|
71
|
+
// UX assumption: a developer got an unexpected Deny (or Allow) and wants a
|
|
72
|
+
// plain-English explanation without needing to know which tools to call or
|
|
73
|
+
// in what order.
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
const explainDenial = definePrompt({
|
|
76
|
+
name: "cedar-explain-denial",
|
|
77
|
+
description: "Explain why a Cedar authorization request was allowed or denied, in plain English, by evaluating the request and examining the deciding policies.",
|
|
78
|
+
argsSchema: {
|
|
79
|
+
principal: z.string().describe('Principal entity reference, e.g. MyApp::User::"alice"'),
|
|
80
|
+
action: z.string().describe('Action entity reference, e.g. MyApp::Action::"read"'),
|
|
81
|
+
resource: z.string().describe('Resource entity reference, e.g. MyApp::Document::"doc-1"'),
|
|
82
|
+
store: z.string().describe("Name of the policy store to evaluate against"),
|
|
83
|
+
},
|
|
84
|
+
handler: (args) => {
|
|
85
|
+
const text = `Explain why the following Cedar authorization request was decided the way it was.\n\n` +
|
|
86
|
+
`Principal: ${args.principal}\n` +
|
|
87
|
+
`Action: ${args.action}\n` +
|
|
88
|
+
`Resource: ${args.resource}\n` +
|
|
89
|
+
`Store: ${args.store}\n\n` +
|
|
90
|
+
`Work through the following steps.\n\n` +
|
|
91
|
+
`Step 1: Evaluate.\n` +
|
|
92
|
+
`Call cedar_authorize with:\n` +
|
|
93
|
+
` policy_ref = "cedar://policies/${args.store}"\n` +
|
|
94
|
+
` schema_ref = "cedar://schema/${args.store}"\n` +
|
|
95
|
+
` principal = "${args.principal}"\n` +
|
|
96
|
+
` action = "${args.action}"\n` +
|
|
97
|
+
` resource = "${args.resource}"\n` +
|
|
98
|
+
` entities = load from "cedar://entities/${args.store}" if available, otherwise use []\n\n` +
|
|
99
|
+
`Step 2: Explain deciding policies.\n` +
|
|
100
|
+
`Take the policy IDs returned in determining_policies from Step 1. ` +
|
|
101
|
+
`Call cedar_explain on those policy IDs so you have the human-readable logic for each one.\n\n` +
|
|
102
|
+
`Step 3: Plain-English explanation.\n` +
|
|
103
|
+
`Write a clear explanation covering:\n` +
|
|
104
|
+
` (a) The decision (Allow or Deny) and which policy or policies drove it.\n` +
|
|
105
|
+
` (b) Why this principal, action, and resource matched or did not match each determining policy.\n` +
|
|
106
|
+
` (c) What would need to change for the opposite decision: either a policy edit, an entity attribute change, or a context value.\n\n` +
|
|
107
|
+
`Keep the explanation factual and specific. Avoid jargon beyond standard Cedar terms (permit, forbid, principal, action, resource, context).`;
|
|
108
|
+
return {
|
|
109
|
+
messages: [{ role: "user", content: { type: "text", text } }],
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// 3. cedar-avp-migration-checklist
|
|
115
|
+
//
|
|
116
|
+
// UX assumption: the user is preparing to move a local Cedar policy set into
|
|
117
|
+
// Amazon Verified Permissions and wants a guided checklist to avoid easy-to-miss
|
|
118
|
+
// steps (schema format, single-namespace constraint, entity validation).
|
|
119
|
+
// This is purely informational; no tool calls are issued inside the prompt body.
|
|
120
|
+
//
|
|
121
|
+
// Design for "no required args": namespace is optional. When supplied it is
|
|
122
|
+
// substituted into the checklist where AVP requires a single namespace. When
|
|
123
|
+
// omitted a placeholder is used so the checklist is still complete and actionable.
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
const avpMigrationChecklist = definePrompt({
|
|
126
|
+
name: "cedar-avp-migration-checklist",
|
|
127
|
+
description: "Provide a guided checklist for migrating a local Cedar policy set into Amazon Verified Permissions, covering schema format, namespace constraints, entity validation, and behavioral diff.",
|
|
128
|
+
argsSchema: {
|
|
129
|
+
namespace: z
|
|
130
|
+
.string()
|
|
131
|
+
.optional()
|
|
132
|
+
.describe("Optional: the single Cedar namespace your AVP policy store will use, e.g. MyApp"),
|
|
133
|
+
},
|
|
134
|
+
handler: (args) => {
|
|
135
|
+
const ns = args.namespace ?? "<YourNamespace>";
|
|
136
|
+
const text = `AVP migration checklist for namespace: ${ns}\n\n` +
|
|
137
|
+
`Work through each item before moving policies or schema into Amazon Verified Permissions.\n\n` +
|
|
138
|
+
`1. Schema format detection.\n` +
|
|
139
|
+
`Call cedar_validate_schema on your existing schema file. Note whether it is in Cedar JSON format or .cedarschema (human-readable) format. ` +
|
|
140
|
+
`AVP accepts both, but they have different upload paths. Confirm which format you have before proceeding.\n\n` +
|
|
141
|
+
`2. Single-namespace constraint.\n` +
|
|
142
|
+
`AVP enforces a single namespace per policy store. All entity types, actions, and attributes must live under "${ns}". ` +
|
|
143
|
+
`If your local Cedar schema uses multiple namespaces, flatten them now. cedar_validate_schema will surface any namespace collisions.\n\n` +
|
|
144
|
+
`3. Entity format auto-detection.\n` +
|
|
145
|
+
`Cedar WASM accepts a relaxed entity format; AVP is stricter. Run cedar_validate_entities against your entity set with the schema attached. ` +
|
|
146
|
+
`Fix any entities missing required attributes or using incorrect UID formats before upload.\n\n` +
|
|
147
|
+
`4. Template-linked policies.\n` +
|
|
148
|
+
`If you use policy templates, call cedar_link_template for each template-principal-resource combination to confirm links are valid. ` +
|
|
149
|
+
`AVP supports template-linked policies but each link must reference a template that already exists in the store.\n\n` +
|
|
150
|
+
`5. Schema diff before PutSchema.\n` +
|
|
151
|
+
`If you are updating an existing AVP store schema (not a fresh store), call cedar_diff_schema between your local schema and the current AVP schema. ` +
|
|
152
|
+
`Classify every change as BREAKING or NON-BREAKING before calling PutSchema. ` +
|
|
153
|
+
`AVP does not roll back schema changes automatically; a BREAKING change can silently invalidate existing policies.\n\n` +
|
|
154
|
+
`6. Behavioral diff before traffic shift.\n` +
|
|
155
|
+
`After loading policies into the AVP store, use cedar_diff_policy_stores to compare local (blue) with AVP (green). ` +
|
|
156
|
+
`Run any behavioral test cases you have. Confirm no new Deny decisions appear for requests that should be allowed. ` +
|
|
157
|
+
`Only shift production traffic after this step passes.\n\n` +
|
|
158
|
+
`All steps must pass before tagging the migration as complete.`;
|
|
159
|
+
return {
|
|
160
|
+
messages: [{ role: "user", content: { type: "text", text } }],
|
|
161
|
+
};
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// Export
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
export const PROMPT_DEFINITIONS = [
|
|
168
|
+
reviewPolicyDiff,
|
|
169
|
+
explainDenial,
|
|
170
|
+
avpMigrationChecklist,
|
|
171
|
+
];
|
|
172
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves cedar:// resource references to their content.
|
|
3
|
+
* Allows tools to accept policy_ref / schema_ref as alternatives to inline text.
|
|
4
|
+
*
|
|
5
|
+
* URI patterns:
|
|
6
|
+
* cedar://policies/{store} → all policies in store concatenated
|
|
7
|
+
* cedar://policies/{store}/{id} → single policy content
|
|
8
|
+
* cedar://schema/{store} → schema content
|
|
9
|
+
* cedar://templates/{store} → template ID list as JSON array
|
|
10
|
+
* cedar://templates/{store}/{template_id} → single template content
|
|
11
|
+
* cedar://template-links/{store} → link ID list as JSON array
|
|
12
|
+
* cedar://template-links/{store}/{link_id}→ single template-link JSON content
|
|
13
|
+
* cedar://entities/{store} → merged entity arrays as JSON
|
|
14
|
+
* cedar://entities/{store}/{file_id} → single entity file content
|
|
15
|
+
*/
|
|
16
|
+
export type RefResolution = {
|
|
17
|
+
content: string;
|
|
18
|
+
resolved_from: string;
|
|
19
|
+
} | {
|
|
20
|
+
error: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function resolveRef(ref: string): RefResolution;
|
|
23
|
+
//# sourceMappingURL=ref-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref-resolver.d.ts","sourceRoot":"","sources":["../../src/resources/ref-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,MAAM,aAAa,GACrB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CA+GrD"}
|