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,115 @@
|
|
|
1
|
+
import type { Policy, PolicyId } from "@cedar-policy/cedar-wasm/nodejs";
|
|
2
|
+
export interface AuthorizeInput {
|
|
3
|
+
/** Concatenated Cedar policy text. Mutually exclusive with policiesMap. */
|
|
4
|
+
policies?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Map of policy id -> policy text. Each key becomes the WASM policy_id and
|
|
7
|
+
* surfaces in determining_policies (overridden by an `@id` annotation when
|
|
8
|
+
* present). Use this when the caller knows the source filename per policy.
|
|
9
|
+
*/
|
|
10
|
+
policiesMap?: Record<string, string>;
|
|
11
|
+
principal: string | Record<string, unknown>;
|
|
12
|
+
action: string | Record<string, unknown>;
|
|
13
|
+
resource: string | Record<string, unknown>;
|
|
14
|
+
entities: string;
|
|
15
|
+
schema?: string;
|
|
16
|
+
context?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional store name to disambiguate workspace auto-discovery (10d) at the
|
|
19
|
+
* MCP layer. handleAuthorize itself does not consult the StoreManager; the
|
|
20
|
+
* server.ts handler resolves this and supplies inputs before calling in.
|
|
21
|
+
*/
|
|
22
|
+
store?: string;
|
|
23
|
+
}
|
|
24
|
+
export type AuthorizeDecisionReason = "permit_policy_fired" | "forbid_policy_fired" | "default_deny_no_permit_matched" | "evaluation_error";
|
|
25
|
+
export interface AuthorizeResult {
|
|
26
|
+
decision: "Allow" | "Deny";
|
|
27
|
+
determining_policies: string[];
|
|
28
|
+
errors: string[];
|
|
29
|
+
decision_reason?: AuthorizeDecisionReason;
|
|
30
|
+
format_detected?: string;
|
|
31
|
+
format_note?: string;
|
|
32
|
+
error?: string;
|
|
33
|
+
/**
|
|
34
|
+
* 10d workspace auto-discovery: populated by the server.ts MCP handler when
|
|
35
|
+
* one or more inputs were resolved from a loaded MCP root rather than from
|
|
36
|
+
* inline params. Each subfield names the store that satisfied the missing
|
|
37
|
+
* input. Surfaces so the caller can trace which store the decision used.
|
|
38
|
+
*/
|
|
39
|
+
auto_discovered?: {
|
|
40
|
+
policies_from?: string;
|
|
41
|
+
schema_from?: string;
|
|
42
|
+
entities_from?: string;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build a Record<policyId, Policy> from caller input.
|
|
47
|
+
*
|
|
48
|
+
* Resolution order for each policy's id:
|
|
49
|
+
* 1. The @id("name") annotation on the policy (highest priority)
|
|
50
|
+
* 2. The caller-provided basename (key in policiesMap)
|
|
51
|
+
* 3. positional "policy<index>" fallback
|
|
52
|
+
*
|
|
53
|
+
* For a flat policies string, we split it via policySetTextToParts so each
|
|
54
|
+
* policy gets its own id rather than collapsing into a single anonymous blob.
|
|
55
|
+
*
|
|
56
|
+
* Exported so cedar_authorize_batch can apply the same H1 resolution and
|
|
57
|
+
* surface the same stable IDs as the single-request handler (kickoff-14 14a).
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildStaticPolicies(input: Pick<AuthorizeInput, "policies" | "policiesMap">): {
|
|
60
|
+
record: Record<PolicyId, Policy>;
|
|
61
|
+
} | {
|
|
62
|
+
error: string;
|
|
63
|
+
};
|
|
64
|
+
export declare function handleAuthorize(input: AuthorizeInput): Promise<AuthorizeResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Inputs accepted by the MCP-level authorize entry point. Wider than
|
|
67
|
+
* `AuthorizeInput` because it also accepts the `_ref` shapes the MCP layer
|
|
68
|
+
* resolves before reaching `handleAuthorize`. Kept distinct so the WASM-level
|
|
69
|
+
* handler does not need to know about MCP plumbing.
|
|
70
|
+
*/
|
|
71
|
+
export interface AuthorizeMcpInput {
|
|
72
|
+
policies?: string;
|
|
73
|
+
policy_ref?: string;
|
|
74
|
+
policiesMap?: Record<string, string>;
|
|
75
|
+
principal: string | Record<string, unknown>;
|
|
76
|
+
action: string | Record<string, unknown>;
|
|
77
|
+
resource: string | Record<string, unknown>;
|
|
78
|
+
entities?: string;
|
|
79
|
+
entities_ref?: string;
|
|
80
|
+
schema?: string;
|
|
81
|
+
schema_ref?: string;
|
|
82
|
+
context?: string;
|
|
83
|
+
store?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 10d workspace auto-discovery wrapper for `cedar_authorize`.
|
|
87
|
+
*
|
|
88
|
+
* Resolves missing policies / schema / entities from the loaded MCP roots,
|
|
89
|
+
* then delegates to `handleAuthorize`. A single store backs all three so a
|
|
90
|
+
* call never mixes policies from one workspace with entities from another.
|
|
91
|
+
*
|
|
92
|
+
* Multi-store deployments with no explicit `store` parameter surface an
|
|
93
|
+
* ambiguity error in the `{ error }` envelope. None-loaded falls through to
|
|
94
|
+
* the "policies / entities required" errors that the MCP layer already used.
|
|
95
|
+
*
|
|
96
|
+
* Returns either:
|
|
97
|
+
* - `{ result }` -- the AuthorizeResult, with `auto_discovered` set when any
|
|
98
|
+
* input was sourced from the workspace.
|
|
99
|
+
* - `{ error }` -- a string error suitable for the standard `{ error: ... }`
|
|
100
|
+
* MCP envelope.
|
|
101
|
+
*
|
|
102
|
+
* The server.ts handler wraps this and serializes the result back to MCP.
|
|
103
|
+
* Tests can call it directly after setting up the `storeManager` singleton
|
|
104
|
+
* with `loadFromRoots([...])`.
|
|
105
|
+
*/
|
|
106
|
+
export declare function handleAuthorizeMcp(input: AuthorizeMcpInput, resolveRef: (uri: string) => {
|
|
107
|
+
content: string;
|
|
108
|
+
} | {
|
|
109
|
+
error: string;
|
|
110
|
+
}): Promise<{
|
|
111
|
+
result: AuthorizeResult;
|
|
112
|
+
} | {
|
|
113
|
+
error: string;
|
|
114
|
+
}>;
|
|
115
|
+
//# sourceMappingURL=authorize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/tools/authorize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { isAuthorized, policySetTextToParts, policyToJson } from "@cedar-policy/cedar-wasm/nodejs";
|
|
2
|
+
import { detectFormat, normalizeEntities, normalizePrincipalRef, } from "../utils/format-detector.js";
|
|
3
|
+
import { storeManager } from "../resources/store-manager.js";
|
|
4
|
+
const DENY_RESULT = (error, detection) => ({
|
|
5
|
+
decision: "Deny",
|
|
6
|
+
determining_policies: [],
|
|
7
|
+
errors: [],
|
|
8
|
+
...(detection ? { format_detected: detection.format, format_note: detection.note } : {}),
|
|
9
|
+
error,
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Extract the @id annotation from a single Cedar policy text, if present.
|
|
13
|
+
* Returns undefined when the policy fails to parse OR when no @id is set.
|
|
14
|
+
*/
|
|
15
|
+
function readIdAnnotation(policyText) {
|
|
16
|
+
const parsed = policyToJson(policyText);
|
|
17
|
+
if (parsed.type !== "success")
|
|
18
|
+
return undefined;
|
|
19
|
+
const id = parsed.json.annotations?.id;
|
|
20
|
+
return typeof id === "string" && id.length > 0 ? id : undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Build a Record<policyId, Policy> from caller input.
|
|
24
|
+
*
|
|
25
|
+
* Resolution order for each policy's id:
|
|
26
|
+
* 1. The @id("name") annotation on the policy (highest priority)
|
|
27
|
+
* 2. The caller-provided basename (key in policiesMap)
|
|
28
|
+
* 3. positional "policy<index>" fallback
|
|
29
|
+
*
|
|
30
|
+
* For a flat policies string, we split it via policySetTextToParts so each
|
|
31
|
+
* policy gets its own id rather than collapsing into a single anonymous blob.
|
|
32
|
+
*
|
|
33
|
+
* Exported so cedar_authorize_batch can apply the same H1 resolution and
|
|
34
|
+
* surface the same stable IDs as the single-request handler (kickoff-14 14a).
|
|
35
|
+
*/
|
|
36
|
+
export function buildStaticPolicies(input) {
|
|
37
|
+
const record = {};
|
|
38
|
+
const usedIds = new Set();
|
|
39
|
+
const assignId = (preferredId, fallbackBase) => {
|
|
40
|
+
let id = preferredId;
|
|
41
|
+
if (usedIds.has(id)) {
|
|
42
|
+
// Disambiguate duplicates so the WASM call does not collide.
|
|
43
|
+
let suffix = 2;
|
|
44
|
+
while (usedIds.has(`${fallbackBase}-${suffix}`))
|
|
45
|
+
suffix++;
|
|
46
|
+
id = `${fallbackBase}-${suffix}`;
|
|
47
|
+
}
|
|
48
|
+
usedIds.add(id);
|
|
49
|
+
return id;
|
|
50
|
+
};
|
|
51
|
+
if (input.policiesMap) {
|
|
52
|
+
for (const [basename, text] of Object.entries(input.policiesMap)) {
|
|
53
|
+
const annotation = readIdAnnotation(text);
|
|
54
|
+
const preferred = annotation ?? basename;
|
|
55
|
+
const id = assignId(preferred, basename);
|
|
56
|
+
record[id] = text;
|
|
57
|
+
}
|
|
58
|
+
return { record };
|
|
59
|
+
}
|
|
60
|
+
const text = input.policies ?? "";
|
|
61
|
+
const parts = policySetTextToParts(text);
|
|
62
|
+
if (parts.type === "failure") {
|
|
63
|
+
// Fall through with a single positional entry; downstream isAuthorized
|
|
64
|
+
// will surface the parse error in the standard errors[] channel.
|
|
65
|
+
record["policy0"] = text;
|
|
66
|
+
return { record };
|
|
67
|
+
}
|
|
68
|
+
parts.policies.forEach((policyText, idx) => {
|
|
69
|
+
const annotation = readIdAnnotation(policyText);
|
|
70
|
+
const fallback = `policy${idx}`;
|
|
71
|
+
const preferred = annotation ?? fallback;
|
|
72
|
+
const id = assignId(preferred, fallback);
|
|
73
|
+
record[id] = policyText;
|
|
74
|
+
});
|
|
75
|
+
return { record };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Classify the authorization outcome into one of four reason codes.
|
|
79
|
+
* See AuthorizeDecisionReason for the contract.
|
|
80
|
+
*/
|
|
81
|
+
function classifyDecisionReason(decision, determining, errors, staticPolicies) {
|
|
82
|
+
if (errors.length > 0)
|
|
83
|
+
return "evaluation_error";
|
|
84
|
+
if (decision === "Allow")
|
|
85
|
+
return "permit_policy_fired";
|
|
86
|
+
// Deny path.
|
|
87
|
+
if (determining.length === 0)
|
|
88
|
+
return "default_deny_no_permit_matched";
|
|
89
|
+
// At least one determining policy fired on a Deny -> a forbid policy.
|
|
90
|
+
// Verify defensively by checking the policy's effect; if any determining
|
|
91
|
+
// entry parses as forbid, classify as forbid_policy_fired.
|
|
92
|
+
for (const id of determining) {
|
|
93
|
+
const text = staticPolicies[id];
|
|
94
|
+
if (typeof text !== "string")
|
|
95
|
+
continue;
|
|
96
|
+
const parsed = policyToJson(text);
|
|
97
|
+
if (parsed.type === "success" && parsed.json.effect === "forbid") {
|
|
98
|
+
return "forbid_policy_fired";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Fallback: a determining policy exists on Deny but is not a parseable forbid.
|
|
102
|
+
return "forbid_policy_fired";
|
|
103
|
+
}
|
|
104
|
+
export async function handleAuthorize(input) {
|
|
105
|
+
// Parse entities first so we can run format detection.
|
|
106
|
+
// Also unwrap the AVP SDK entity_list/entityList envelope:
|
|
107
|
+
// Ruby SDK: { entity_list: [...] }
|
|
108
|
+
// Python/JS: { entityList: [...] }
|
|
109
|
+
// Official API: { entityList: [...] }
|
|
110
|
+
// Users sometimes copy the full SDK entities parameter value rather than just the array.
|
|
111
|
+
let rawEntities;
|
|
112
|
+
try {
|
|
113
|
+
const parsed = JSON.parse(input.entities);
|
|
114
|
+
if (Array.isArray(parsed)) {
|
|
115
|
+
rawEntities = parsed;
|
|
116
|
+
}
|
|
117
|
+
else if (typeof parsed === "object" && parsed !== null) {
|
|
118
|
+
const obj = parsed;
|
|
119
|
+
const list = obj["entity_list"] ?? obj["entityList"] ?? obj["EntityList"];
|
|
120
|
+
if (Array.isArray(list)) {
|
|
121
|
+
rawEntities = list;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
throw new Error("not an array");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
throw new Error("not an array");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return DENY_RESULT("entities must be a valid JSON array or an AVP entity_list object");
|
|
133
|
+
}
|
|
134
|
+
// Detect format across all inputs together
|
|
135
|
+
const detection = detectFormat(rawEntities, input.principal, input.action, input.resource);
|
|
136
|
+
// Normalize entities and principal/action/resource to WASM format
|
|
137
|
+
const normalizedEntities = normalizeEntities(rawEntities, detection.format);
|
|
138
|
+
const principalRef = normalizePrincipalRef(input.principal);
|
|
139
|
+
if ("error" in principalRef)
|
|
140
|
+
return DENY_RESULT(principalRef.error, detection);
|
|
141
|
+
const actionRef = normalizePrincipalRef(input.action);
|
|
142
|
+
if ("error" in actionRef)
|
|
143
|
+
return DENY_RESULT(actionRef.error, detection);
|
|
144
|
+
const resourceRef = normalizePrincipalRef(input.resource);
|
|
145
|
+
if ("error" in resourceRef)
|
|
146
|
+
return DENY_RESULT(resourceRef.error, detection);
|
|
147
|
+
if (!input.policies && !input.policiesMap) {
|
|
148
|
+
return DENY_RESULT("policies or policiesMap is required", detection);
|
|
149
|
+
}
|
|
150
|
+
const built = buildStaticPolicies(input);
|
|
151
|
+
if ("error" in built)
|
|
152
|
+
return DENY_RESULT(built.error, detection);
|
|
153
|
+
const staticPolicies = built.record;
|
|
154
|
+
let schema;
|
|
155
|
+
if (input.schema) {
|
|
156
|
+
try {
|
|
157
|
+
schema = JSON.parse(input.schema);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
schema = input.schema;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
let context = {};
|
|
164
|
+
if (input.context) {
|
|
165
|
+
try {
|
|
166
|
+
context = JSON.parse(input.context);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return DENY_RESULT("context must be a valid JSON object", detection);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const call = {
|
|
173
|
+
principal: principalRef,
|
|
174
|
+
action: actionRef,
|
|
175
|
+
resource: resourceRef,
|
|
176
|
+
context,
|
|
177
|
+
policies: { staticPolicies },
|
|
178
|
+
entities: normalizedEntities,
|
|
179
|
+
...(schema ? { schema, validateRequest: true } : {}),
|
|
180
|
+
};
|
|
181
|
+
// per spike-report-wasm-api.md §1: type field is "success"|"failure" for WASM health,
|
|
182
|
+
// decision is "allow"|"deny" for the authorization result
|
|
183
|
+
const answer = isAuthorized(call);
|
|
184
|
+
if (answer.type === "failure") {
|
|
185
|
+
const errorMessages = answer.errors.map((e) => e.message);
|
|
186
|
+
return {
|
|
187
|
+
decision: "Deny",
|
|
188
|
+
determining_policies: [],
|
|
189
|
+
errors: errorMessages,
|
|
190
|
+
decision_reason: "evaluation_error",
|
|
191
|
+
format_detected: detection.format,
|
|
192
|
+
format_note: detection.note,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const { decision, diagnostics } = answer.response;
|
|
196
|
+
const normalizedDecision = decision === "allow" ? "Allow" : "Deny";
|
|
197
|
+
const determining = diagnostics.reason;
|
|
198
|
+
const errorMessages = diagnostics.errors.map((e) => e.error.message);
|
|
199
|
+
return {
|
|
200
|
+
decision: normalizedDecision,
|
|
201
|
+
determining_policies: determining,
|
|
202
|
+
errors: errorMessages,
|
|
203
|
+
decision_reason: classifyDecisionReason(normalizedDecision, determining, errorMessages, staticPolicies),
|
|
204
|
+
format_detected: detection.format,
|
|
205
|
+
format_note: detection.note,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* 10d workspace auto-discovery wrapper for `cedar_authorize`.
|
|
210
|
+
*
|
|
211
|
+
* Resolves missing policies / schema / entities from the loaded MCP roots,
|
|
212
|
+
* then delegates to `handleAuthorize`. A single store backs all three so a
|
|
213
|
+
* call never mixes policies from one workspace with entities from another.
|
|
214
|
+
*
|
|
215
|
+
* Multi-store deployments with no explicit `store` parameter surface an
|
|
216
|
+
* ambiguity error in the `{ error }` envelope. None-loaded falls through to
|
|
217
|
+
* the "policies / entities required" errors that the MCP layer already used.
|
|
218
|
+
*
|
|
219
|
+
* Returns either:
|
|
220
|
+
* - `{ result }` -- the AuthorizeResult, with `auto_discovered` set when any
|
|
221
|
+
* input was sourced from the workspace.
|
|
222
|
+
* - `{ error }` -- a string error suitable for the standard `{ error: ... }`
|
|
223
|
+
* MCP envelope.
|
|
224
|
+
*
|
|
225
|
+
* The server.ts handler wraps this and serializes the result back to MCP.
|
|
226
|
+
* Tests can call it directly after setting up the `storeManager` singleton
|
|
227
|
+
* with `loadFromRoots([...])`.
|
|
228
|
+
*/
|
|
229
|
+
export async function handleAuthorizeMcp(input, resolveRef) {
|
|
230
|
+
const needsAuto = (!input.policies && !input.policy_ref && !input.policiesMap) ||
|
|
231
|
+
(!input.schema && !input.schema_ref) ||
|
|
232
|
+
(!input.entities && !input.entities_ref);
|
|
233
|
+
let autoStore;
|
|
234
|
+
if (needsAuto) {
|
|
235
|
+
if (input.store) {
|
|
236
|
+
if (!storeManager.getStore(input.store)) {
|
|
237
|
+
const available = storeManager.listStoreNames().join(", ") || "none";
|
|
238
|
+
return { error: `Store not found: "${input.store}". Available stores: ${available}.` };
|
|
239
|
+
}
|
|
240
|
+
autoStore = input.store;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
const def = storeManager.getDefaultStore();
|
|
244
|
+
if (def.kind === "single")
|
|
245
|
+
autoStore = def.store.name;
|
|
246
|
+
else if (def.kind === "ambiguous") {
|
|
247
|
+
return { error: `Multiple stores are loaded (${def.names.join(", ")}). Pass store: "<name>" to choose.` };
|
|
248
|
+
}
|
|
249
|
+
// def.kind === "none": leave autoStore undefined and let the
|
|
250
|
+
// "Either X or X_ref is required" branches below fire.
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Resolve policy_ref / policies. The cedar://policies/{store} loop pattern
|
|
254
|
+
// keeps each policy's basename as its determining-policies id rather than
|
|
255
|
+
// collapsing the set into a single blob.
|
|
256
|
+
let policies = input.policies;
|
|
257
|
+
let policiesMap = input.policiesMap;
|
|
258
|
+
let policiesFrom;
|
|
259
|
+
if (!policies && !policiesMap && input.policy_ref) {
|
|
260
|
+
const storeMatch = input.policy_ref.match(/^cedar:\/\/policies\/([^/]+)$/);
|
|
261
|
+
const singleMatch = input.policy_ref.match(/^cedar:\/\/policies\/([^/]+)\/([^/]+)$/);
|
|
262
|
+
if (storeMatch) {
|
|
263
|
+
const storeName = storeMatch[1];
|
|
264
|
+
try {
|
|
265
|
+
const ids = storeManager.listPolicies(storeName);
|
|
266
|
+
policiesMap = {};
|
|
267
|
+
for (const id of ids)
|
|
268
|
+
policiesMap[id] = storeManager.readPolicy(storeName, id);
|
|
269
|
+
}
|
|
270
|
+
catch (e) {
|
|
271
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else if (singleMatch) {
|
|
275
|
+
const storeName = singleMatch[1];
|
|
276
|
+
const policyId = singleMatch[2];
|
|
277
|
+
try {
|
|
278
|
+
policiesMap = { [policyId]: storeManager.readPolicy(storeName, policyId) };
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
const resolved = resolveRef(input.policy_ref);
|
|
286
|
+
if ("error" in resolved)
|
|
287
|
+
return { error: resolved.error };
|
|
288
|
+
policies = resolved.content;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (!policies && !policiesMap && autoStore) {
|
|
292
|
+
try {
|
|
293
|
+
const ids = storeManager.listPolicies(autoStore);
|
|
294
|
+
policiesMap = {};
|
|
295
|
+
for (const id of ids)
|
|
296
|
+
policiesMap[id] = storeManager.readPolicy(autoStore, id);
|
|
297
|
+
policiesFrom = autoStore;
|
|
298
|
+
}
|
|
299
|
+
catch (e) {
|
|
300
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (!policies && !policiesMap)
|
|
304
|
+
return { error: "Either policies or policy_ref is required" };
|
|
305
|
+
let schema = input.schema;
|
|
306
|
+
let schemaFrom;
|
|
307
|
+
if (!schema && input.schema_ref) {
|
|
308
|
+
const resolved = resolveRef(input.schema_ref);
|
|
309
|
+
if ("error" in resolved)
|
|
310
|
+
return { error: resolved.error };
|
|
311
|
+
schema = resolved.content;
|
|
312
|
+
}
|
|
313
|
+
if (!schema && autoStore) {
|
|
314
|
+
try {
|
|
315
|
+
schema = storeManager.readSchema(autoStore);
|
|
316
|
+
schemaFrom = autoStore;
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
// Store has no schema file; schema stays undefined (it is optional).
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
let entities = input.entities;
|
|
323
|
+
let entitiesFrom;
|
|
324
|
+
if (!entities && input.entities_ref) {
|
|
325
|
+
const resolved = resolveRef(input.entities_ref);
|
|
326
|
+
if ("error" in resolved)
|
|
327
|
+
return { error: resolved.error };
|
|
328
|
+
entities = resolved.content;
|
|
329
|
+
}
|
|
330
|
+
if (!entities && autoStore) {
|
|
331
|
+
// Only claim entities_from if the store actually has an entities/
|
|
332
|
+
// subdirectory with files. readAllEntities returns "[]" when the
|
|
333
|
+
// directory is missing, which would otherwise have us lie in
|
|
334
|
+
// auto_discovered.entities_from about the source of zero entities.
|
|
335
|
+
try {
|
|
336
|
+
const entityFiles = storeManager.listEntities(autoStore);
|
|
337
|
+
if (entityFiles.length > 0) {
|
|
338
|
+
entities = storeManager.readAllEntities(autoStore);
|
|
339
|
+
entitiesFrom = autoStore;
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
entities = "[]";
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (e) {
|
|
346
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (!entities)
|
|
350
|
+
return { error: "Either entities or entities_ref is required" };
|
|
351
|
+
const result = await handleAuthorize({
|
|
352
|
+
policies,
|
|
353
|
+
policiesMap,
|
|
354
|
+
principal: input.principal,
|
|
355
|
+
action: input.action,
|
|
356
|
+
resource: input.resource,
|
|
357
|
+
entities,
|
|
358
|
+
schema,
|
|
359
|
+
context: input.context,
|
|
360
|
+
});
|
|
361
|
+
const autoDiscovered = {};
|
|
362
|
+
if (policiesFrom)
|
|
363
|
+
autoDiscovered.policies_from = policiesFrom;
|
|
364
|
+
if (schemaFrom)
|
|
365
|
+
autoDiscovered.schema_from = schemaFrom;
|
|
366
|
+
if (entitiesFrom)
|
|
367
|
+
autoDiscovered.entities_from = entitiesFrom;
|
|
368
|
+
if (Object.keys(autoDiscovered).length > 0) {
|
|
369
|
+
result.auto_discovered = autoDiscovered;
|
|
370
|
+
}
|
|
371
|
+
return { result };
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=authorize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/tools/authorize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface CheckChangeInput {
|
|
2
|
+
old_policy: string;
|
|
3
|
+
new_policy: string;
|
|
4
|
+
}
|
|
5
|
+
export interface PolicyChange {
|
|
6
|
+
field: "effect" | "principal" | "resource" | "action" | "conditions";
|
|
7
|
+
old_value?: string;
|
|
8
|
+
new_value?: string;
|
|
9
|
+
in_place_allowed: boolean;
|
|
10
|
+
reason: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CheckChangeResult {
|
|
13
|
+
can_update_in_place: boolean;
|
|
14
|
+
changes: PolicyChange[];
|
|
15
|
+
recommendation: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function handleCheckChange(input: CheckChangeInput): Promise<CheckChangeResult>;
|
|
19
|
+
//# sourceMappingURL=check-change.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-change.d.ts","sourceRoot":"","sources":["../../src/tools/check-change.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA2CD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsD3F"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { policyToJson } from "@cedar-policy/cedar-wasm/nodejs";
|
|
2
|
+
const IN_PLACE_RULES = {
|
|
3
|
+
effect: {
|
|
4
|
+
allowed: false,
|
|
5
|
+
reason: "Changing effect (permit ↔ forbid) requires deleting and recreating the policy.",
|
|
6
|
+
},
|
|
7
|
+
principal: {
|
|
8
|
+
allowed: false,
|
|
9
|
+
reason: "Changing the principal clause requires deleting and recreating the policy.",
|
|
10
|
+
},
|
|
11
|
+
resource: {
|
|
12
|
+
allowed: false,
|
|
13
|
+
reason: "Changing the resource clause requires deleting and recreating the policy.",
|
|
14
|
+
},
|
|
15
|
+
action: {
|
|
16
|
+
allowed: true,
|
|
17
|
+
reason: "Action clause changes can be applied in-place.",
|
|
18
|
+
},
|
|
19
|
+
conditions: {
|
|
20
|
+
allowed: true,
|
|
21
|
+
reason: "Condition clause (when/unless) changes can be applied in-place.",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
function parsePolicy(text) {
|
|
25
|
+
const result = policyToJson(text);
|
|
26
|
+
if (result.type === "failure") {
|
|
27
|
+
throw new Error(result.errors.map((e) => e.message).join("; "));
|
|
28
|
+
}
|
|
29
|
+
return result.json;
|
|
30
|
+
}
|
|
31
|
+
function stringify(v) {
|
|
32
|
+
return JSON.stringify(v);
|
|
33
|
+
}
|
|
34
|
+
const EMPTY_RESULT = {
|
|
35
|
+
can_update_in_place: false,
|
|
36
|
+
changes: [],
|
|
37
|
+
recommendation: "",
|
|
38
|
+
};
|
|
39
|
+
export async function handleCheckChange(input) {
|
|
40
|
+
let oldJson;
|
|
41
|
+
let newJson;
|
|
42
|
+
try {
|
|
43
|
+
oldJson = parsePolicy(input.old_policy);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
return { ...EMPTY_RESULT, error: `Failed to parse old_policy: ${e instanceof Error ? e.message : String(e)}` };
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
newJson = parsePolicy(input.new_policy);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
return { ...EMPTY_RESULT, error: `Failed to parse new_policy: ${e instanceof Error ? e.message : String(e)}` };
|
|
53
|
+
}
|
|
54
|
+
const changes = [];
|
|
55
|
+
// Compare each field. Effect is a string; others are structured objects.
|
|
56
|
+
const fields = [
|
|
57
|
+
"effect",
|
|
58
|
+
"principal",
|
|
59
|
+
"resource",
|
|
60
|
+
"action",
|
|
61
|
+
"conditions",
|
|
62
|
+
];
|
|
63
|
+
for (const field of fields) {
|
|
64
|
+
const oldVal = field === "effect" ? oldJson.effect : oldJson[field];
|
|
65
|
+
const newVal = field === "effect" ? newJson.effect : newJson[field];
|
|
66
|
+
if (stringify(oldVal) !== stringify(newVal)) {
|
|
67
|
+
const rule = IN_PLACE_RULES[field];
|
|
68
|
+
changes.push({
|
|
69
|
+
field: field,
|
|
70
|
+
old_value: stringify(oldVal),
|
|
71
|
+
new_value: stringify(newVal),
|
|
72
|
+
in_place_allowed: rule.allowed,
|
|
73
|
+
reason: rule.reason,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const can_update_in_place = changes.every((c) => c.in_place_allowed);
|
|
78
|
+
let recommendation;
|
|
79
|
+
if (changes.length === 0) {
|
|
80
|
+
recommendation = "No changes detected.";
|
|
81
|
+
}
|
|
82
|
+
else if (can_update_in_place) {
|
|
83
|
+
recommendation = "All changes can be applied as an in-place policy update.";
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const blocking = changes.filter((c) => !c.in_place_allowed).map((c) => c.field);
|
|
87
|
+
recommendation = `Delete the existing policy and create a new one. The following fields cannot be changed in-place: ${blocking.join(", ")}.`;
|
|
88
|
+
}
|
|
89
|
+
return { can_update_in_place, changes, recommendation };
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=check-change.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-change.js","sourceRoot":"","sources":["../../src/tools/check-change.ts"],"names":[],"mappings":"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"}
|