@intentius/chant-lexicon-cedar 0.44.8
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/README.md +190 -0
- package/dist/avp/ambient.d.ts +54 -0
- package/dist/avp/ambient.d.ts.map +1 -0
- package/dist/avp/client.d.ts +127 -0
- package/dist/avp/client.d.ts.map +1 -0
- package/dist/avp/describe-resources.d.ts +42 -0
- package/dist/avp/describe-resources.d.ts.map +1 -0
- package/dist/avp/embed.d.ts +120 -0
- package/dist/avp/embed.d.ts.map +1 -0
- package/dist/avp/live-export.d.ts +94 -0
- package/dist/avp/live-export.d.ts.map +1 -0
- package/dist/avp/ownership.d.ts +97 -0
- package/dist/avp/ownership.d.ts.map +1 -0
- package/dist/avp/statement.d.ts +22 -0
- package/dist/avp/statement.d.ts.map +1 -0
- package/dist/avp/store.d.ts +82 -0
- package/dist/avp/store.d.ts.map +1 -0
- package/dist/avp/testdata/mock-transport.d.ts +55 -0
- package/dist/avp/testdata/mock-transport.d.ts.map +1 -0
- package/dist/codegen/docs-cli.d.ts +3 -0
- package/dist/codegen/docs-cli.d.ts.map +1 -0
- package/dist/codegen/docs.d.ts +26 -0
- package/dist/codegen/docs.d.ts.map +1 -0
- package/dist/codegen/emit.d.ts +85 -0
- package/dist/codegen/emit.d.ts.map +1 -0
- package/dist/codegen/generate-cli.d.ts +3 -0
- package/dist/codegen/generate-cli.d.ts.map +1 -0
- package/dist/codegen/generate.d.ts +37 -0
- package/dist/codegen/generate.d.ts.map +1 -0
- package/dist/codegen/naming.d.ts +48 -0
- package/dist/codegen/naming.d.ts.map +1 -0
- package/dist/codegen/package.d.ts +10 -0
- package/dist/codegen/package.d.ts.map +1 -0
- package/dist/composites/deny-by-default-set.d.ts +58 -0
- package/dist/composites/deny-by-default-set.d.ts.map +1 -0
- package/dist/composites/index.d.ts +12 -0
- package/dist/composites/index.d.ts.map +1 -0
- package/dist/composites/owner-can-manage.d.ts +48 -0
- package/dist/composites/owner-can-manage.d.ts.map +1 -0
- package/dist/config.d.ts +102 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/coverage.d.ts +59 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/detect.d.ts +18 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/generated/index.d.ts +251 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/runtime.d.ts +2 -0
- package/dist/generated/runtime.d.ts.map +1 -0
- package/dist/import/adapter.d.ts +21 -0
- package/dist/import/adapter.d.ts.map +1 -0
- package/dist/import/clause-text.d.ts +38 -0
- package/dist/import/clause-text.d.ts.map +1 -0
- package/dist/import/generator.d.ts +53 -0
- package/dist/import/generator.d.ts.map +1 -0
- package/dist/import/parser.d.ts +57 -0
- package/dist/import/parser.d.ts.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/init-templates.d.ts +32 -0
- package/dist/init-templates.d.ts.map +1 -0
- package/dist/integrity.json +22 -0
- package/dist/lint/audit-catalog.d.ts +29 -0
- package/dist/lint/audit-catalog.d.ts.map +1 -0
- package/dist/lint/post-synth/cedar-helpers.d.ts +97 -0
- package/dist/lint/post-synth/cedar-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/cedc010.d.ts +17 -0
- package/dist/lint/post-synth/cedc010.d.ts.map +1 -0
- package/dist/lint/post-synth/cedc011.d.ts +17 -0
- package/dist/lint/post-synth/cedc011.d.ts.map +1 -0
- package/dist/lint/post-synth/cedc012.d.ts +21 -0
- package/dist/lint/post-synth/cedc012.d.ts.map +1 -0
- package/dist/lint/post-synth/cedc013.d.ts +20 -0
- package/dist/lint/post-synth/cedc013.d.ts.map +1 -0
- package/dist/lint/post-synth/cedc014.d.ts +19 -0
- package/dist/lint/post-synth/cedc014.d.ts.map +1 -0
- package/dist/lint/post-synth/cede010.d.ts +34 -0
- package/dist/lint/post-synth/cede010.d.ts.map +1 -0
- package/dist/lint/post-synth/cede011.d.ts +22 -0
- package/dist/lint/post-synth/cede011.d.ts.map +1 -0
- package/dist/lint/post-synth/ceds010.d.ts +24 -0
- package/dist/lint/post-synth/ceds010.d.ts.map +1 -0
- package/dist/lint/post-synth/ceds011.d.ts +19 -0
- package/dist/lint/post-synth/ceds011.d.ts.map +1 -0
- package/dist/lint/post-synth/ceds012.d.ts +17 -0
- package/dist/lint/post-synth/ceds012.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts +3 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -0
- package/dist/lint/post-synth/wasm-helpers.d.ts +108 -0
- package/dist/lint/post-synth/wasm-helpers.d.ts.map +1 -0
- package/dist/lint/rules/index.d.ts +10 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/policy-shape.d.ts +31 -0
- package/dist/lint/rules/policy-shape.d.ts.map +1 -0
- package/dist/lsp/completions.d.ts +24 -0
- package/dist/lsp/completions.d.ts.map +1 -0
- package/dist/lsp/hover.d.ts +11 -0
- package/dist/lsp/hover.d.ts.map +1 -0
- package/dist/lsp/registry.d.ts +45 -0
- package/dist/lsp/registry.d.ts.map +1 -0
- package/dist/manifest.json +8 -0
- package/dist/mcp/index.d.ts +34 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/policy-coverage.d.ts +81 -0
- package/dist/mcp/policy-coverage.d.ts.map +1 -0
- package/dist/meta.json +699 -0
- package/dist/okf/index.md +37 -0
- package/dist/okf/rules/CEDC001.md +11 -0
- package/dist/okf/rules/CEDC010.md +11 -0
- package/dist/okf/rules/CEDC011.md +15 -0
- package/dist/okf/rules/CEDC012.md +11 -0
- package/dist/okf/rules/CEDC013.md +15 -0
- package/dist/okf/rules/CEDC014.md +15 -0
- package/dist/okf/rules/CEDE010.md +15 -0
- package/dist/okf/rules/CEDE011.md +15 -0
- package/dist/okf/rules/CEDS010.md +15 -0
- package/dist/okf/rules/CEDS011.md +11 -0
- package/dist/okf/rules/CEDS012.md +15 -0
- package/dist/okf/types/AdminAction.md +14 -0
- package/dist/okf/types/Application.md +14 -0
- package/dist/okf/types/ApproveAction.md +13 -0
- package/dist/okf/types/CommentAction.md +14 -0
- package/dist/okf/types/CreateAction.md +14 -0
- package/dist/okf/types/DeleteAction.md +14 -0
- package/dist/okf/types/Document.md +18 -0
- package/dist/okf/types/Folder.md +15 -0
- package/dist/okf/types/Group.md +14 -0
- package/dist/okf/types/ListAction.md +14 -0
- package/dist/okf/types/Policy.md +29 -0
- package/dist/okf/types/ReadAction.md +14 -0
- package/dist/okf/types/ServiceAccount.md +15 -0
- package/dist/okf/types/ShareAction.md +14 -0
- package/dist/okf/types/Team.md +14 -0
- package/dist/okf/types/User.md +18 -0
- package/dist/okf/types/WriteAction.md +14 -0
- package/dist/package-cli.d.ts +3 -0
- package/dist/package-cli.d.ts.map +1 -0
- package/dist/plugin.d.ts +8 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/rules/cedar-helpers.ts +209 -0
- package/dist/rules/cedc010.ts +80 -0
- package/dist/rules/cedc011.ts +47 -0
- package/dist/rules/cedc012.ts +64 -0
- package/dist/rules/cedc013.ts +68 -0
- package/dist/rules/cedc014.ts +73 -0
- package/dist/rules/cede010.ts +89 -0
- package/dist/rules/cede011.ts +58 -0
- package/dist/rules/ceds010.ts +57 -0
- package/dist/rules/ceds011.ts +42 -0
- package/dist/rules/ceds012.ts +50 -0
- package/dist/rules/policy-shape.ts +148 -0
- package/dist/rules/wasm-helpers.ts +315 -0
- package/dist/serializer.d.ts +138 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/spec/fetch.d.ts +71 -0
- package/dist/spec/fetch.d.ts.map +1 -0
- package/dist/spec/parse.d.ts +113 -0
- package/dist/spec/parse.d.ts.map +1 -0
- package/dist/spec/pin.d.ts +116 -0
- package/dist/spec/pin.d.ts.map +1 -0
- package/dist/spec/pinned-names.json +18 -0
- package/dist/spec/wasm.d.ts +143 -0
- package/dist/spec/wasm.d.ts.map +1 -0
- package/dist/types/index.d.ts +219 -0
- package/dist/validate-cli.d.ts +3 -0
- package/dist/validate-cli.d.ts.map +1 -0
- package/dist/validate.d.ts +25 -0
- package/dist/validate.d.ts.map +1 -0
- package/package.json +75 -0
- package/src/avp/OWNERSHIP.md +125 -0
- package/src/avp/ambient.test.ts +113 -0
- package/src/avp/ambient.ts +124 -0
- package/src/avp/client.ts +310 -0
- package/src/avp/describe-resources.test.ts +316 -0
- package/src/avp/describe-resources.ts +215 -0
- package/src/avp/embed.test.ts +114 -0
- package/src/avp/embed.ts +190 -0
- package/src/avp/live-export.test.ts +232 -0
- package/src/avp/live-export.ts +185 -0
- package/src/avp/ownership.test.ts +101 -0
- package/src/avp/ownership.ts +170 -0
- package/src/avp/statement.ts +50 -0
- package/src/avp/store.ts +152 -0
- package/src/avp/testdata/mock-transport.ts +147 -0
- package/src/codegen/docs-cli.ts +7 -0
- package/src/codegen/docs.ts +873 -0
- package/src/codegen/emit.ts +496 -0
- package/src/codegen/generate-cli.ts +18 -0
- package/src/codegen/generate.test.ts +128 -0
- package/src/codegen/generate.ts +123 -0
- package/src/codegen/naming.ts +101 -0
- package/src/codegen/package.ts +52 -0
- package/src/composites/composites.test.ts +206 -0
- package/src/composites/deny-by-default-set.ts +98 -0
- package/src/composites/index.ts +13 -0
- package/src/composites/owner-can-manage.ts +80 -0
- package/src/config-namespace.test.ts +44 -0
- package/src/config.test.ts +82 -0
- package/src/config.ts +119 -0
- package/src/coverage.test.ts +61 -0
- package/src/coverage.ts +166 -0
- package/src/detect.test.ts +64 -0
- package/src/detect.ts +59 -0
- package/src/generated/index.d.ts +219 -0
- package/src/generated/index.ts +279 -0
- package/src/generated/lexicon-cedar.json +699 -0
- package/src/generated/runtime.ts +2 -0
- package/src/import/adapter.ts +63 -0
- package/src/import/clause-text.ts +178 -0
- package/src/import/generator.test.ts +133 -0
- package/src/import/generator.ts +219 -0
- package/src/import/parser.test.ts +265 -0
- package/src/import/parser.ts +352 -0
- package/src/import/roundtrip.test.ts +127 -0
- package/src/import/testdata/full.cedar +36 -0
- package/src/import/testdata/full.cedar.json +238 -0
- package/src/import/testdata/realistic.cedar +35 -0
- package/src/import/testdata/simple.cedar +6 -0
- package/src/index.ts +94 -0
- package/src/init-templates.test.ts +158 -0
- package/src/init-templates.ts +358 -0
- package/src/lint/audit-catalog.ts +130 -0
- package/src/lint/post-synth/cedar-helpers.ts +209 -0
- package/src/lint/post-synth/cedc010.ts +80 -0
- package/src/lint/post-synth/cedc011.ts +47 -0
- package/src/lint/post-synth/cedc012.ts +64 -0
- package/src/lint/post-synth/cedc013.ts +68 -0
- package/src/lint/post-synth/cedc014.ts +73 -0
- package/src/lint/post-synth/cede010.ts +89 -0
- package/src/lint/post-synth/cede011.ts +58 -0
- package/src/lint/post-synth/ceds010.ts +57 -0
- package/src/lint/post-synth/ceds011.ts +42 -0
- package/src/lint/post-synth/ceds012.ts +50 -0
- package/src/lint/post-synth/index.ts +25 -0
- package/src/lint/post-synth/post-synth.test.ts +474 -0
- package/src/lint/post-synth/wasm-helpers.ts +315 -0
- package/src/lint/rules/index.ts +12 -0
- package/src/lint/rules/policy-shape.test.ts +90 -0
- package/src/lint/rules/policy-shape.ts +148 -0
- package/src/lsp/completions.test.ts +111 -0
- package/src/lsp/completions.ts +55 -0
- package/src/lsp/hover.test.ts +82 -0
- package/src/lsp/hover.ts +75 -0
- package/src/lsp/registry.ts +74 -0
- package/src/mcp/index.ts +103 -0
- package/src/mcp/policy-coverage.test.ts +176 -0
- package/src/mcp/policy-coverage.ts +205 -0
- package/src/package-cli.ts +22 -0
- package/src/plugin.test.ts +115 -0
- package/src/plugin.ts +312 -0
- package/src/serializer.test.ts +502 -0
- package/src/serializer.ts +335 -0
- package/src/skills/chant-cedar-authoring.md +180 -0
- package/src/skills/chant-cedar-avp-embedding.md +125 -0
- package/src/skills/chant-cedar-meta-policy.md +119 -0
- package/src/spec/default-schema.cedarschema +108 -0
- package/src/spec/fetch.ts +107 -0
- package/src/spec/parse.test.ts +123 -0
- package/src/spec/parse.ts +253 -0
- package/src/spec/pin.test.ts +88 -0
- package/src/spec/pin.ts +243 -0
- package/src/spec/pinned-names.json +18 -0
- package/src/spec/wasm.ts +283 -0
- package/src/validate-cli.ts +8 -0
- package/src/validate.ts +85 -0
package/src/spec/wasm.ts
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place `@cedar-policy/cedar-wasm` is called from.
|
|
3
|
+
*
|
|
4
|
+
* Three findings from the 4.12.0 verification (#1648) are encoded here rather
|
|
5
|
+
* than left to each caller to remember:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Only the `/nodejs` flavor.** The root ESM build imports the `.wasm` as
|
|
8
|
+
* an ES module, which Bun cannot start (`wasm.__wbindgen_start is not a
|
|
9
|
+
* function`) and Node only supports behind an experimental warning printed
|
|
10
|
+
* on every run. `/nodejs` loads the binary with `readFileSync` and works
|
|
11
|
+
* under node CJS, node ESM, vitest and bun alike.
|
|
12
|
+
*
|
|
13
|
+
* 2. **`schemaToJsonWithResolvedTypes` takes a string and means it.** A JS
|
|
14
|
+
* object traps the wasm with `memory access out of bounds` — not a failure
|
|
15
|
+
* answer, a memory fault. The `typeof === "string"` guard below is the
|
|
16
|
+
* difference between a readable error and a trap.
|
|
17
|
+
*
|
|
18
|
+
* 3. **The `Answer` union is not the whole error channel.** Malformed input
|
|
19
|
+
* throws a bare serde `Error` from inside the wasm instead of returning
|
|
20
|
+
* `{type:"failure"}`, and the `line 1 column N` in those messages refers to
|
|
21
|
+
* the internal call struct, not to anything the user wrote. Both channels
|
|
22
|
+
* are normalized into one result type here.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { createRequire } from "module";
|
|
26
|
+
import type * as CedarWasm from "@cedar-policy/cedar-wasm/nodejs";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Loaded on first use, not at import.
|
|
30
|
+
*
|
|
31
|
+
* The wasm binary is 4.2 MB and costs ~13 MB RSS to instantiate. Importing
|
|
32
|
+
* this package is something a user's `chant.config.ts` does purely to bring
|
|
33
|
+
* the `cedar` key into `ChantConfig`, and every `chant build` in a project
|
|
34
|
+
* with a policy set loads the serializer — neither touches the validator. A
|
|
35
|
+
* top-level import would charge all of them for it.
|
|
36
|
+
*/
|
|
37
|
+
let wasm: typeof CedarWasm | undefined;
|
|
38
|
+
|
|
39
|
+
function cedar(): typeof CedarWasm {
|
|
40
|
+
if (!wasm) {
|
|
41
|
+
// `require`, not `import()`: the `/nodejs` flavor is CommonJS, and this
|
|
42
|
+
// keeps the call sites synchronous, which is what every consumer here
|
|
43
|
+
// wants. See the flavor note above for why the root ESM build is not an
|
|
44
|
+
// option.
|
|
45
|
+
wasm = createRequire(import.meta.url)("@cedar-policy/cedar-wasm/nodejs") as typeof CedarWasm;
|
|
46
|
+
}
|
|
47
|
+
return wasm;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A namespace body in the resolved schema JSON. */
|
|
51
|
+
export interface ResolvedNamespace {
|
|
52
|
+
commonTypes?: Record<string, ResolvedType>;
|
|
53
|
+
entityTypes?: Record<string, ResolvedEntityType>;
|
|
54
|
+
actions?: Record<string, ResolvedAction>;
|
|
55
|
+
annotations?: Record<string, string>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ResolvedEntityType {
|
|
59
|
+
memberOfTypes?: string[];
|
|
60
|
+
shape?: ResolvedType;
|
|
61
|
+
tags?: ResolvedType;
|
|
62
|
+
enum?: string[];
|
|
63
|
+
annotations?: Record<string, string>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ResolvedAction {
|
|
67
|
+
memberOf?: Array<{ id: string; type?: string }>;
|
|
68
|
+
appliesTo?: {
|
|
69
|
+
principalTypes?: string[];
|
|
70
|
+
resourceTypes?: string[];
|
|
71
|
+
context?: ResolvedType;
|
|
72
|
+
};
|
|
73
|
+
annotations?: Record<string, string>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A type in the *resolved* schema JSON.
|
|
78
|
+
*
|
|
79
|
+
* `schemaToJson` emits `{type:"EntityOrCommon", name}` for every named type,
|
|
80
|
+
* which cannot tell an entity reference from a primitive from a common-type
|
|
81
|
+
* alias. `schemaToJsonWithResolvedTypes` collapses that to `{type:"Entity"}`
|
|
82
|
+
* for entity references and to the primitive name otherwise — except for
|
|
83
|
+
* common types, which stay as a bare qualified `{type:"App::TagSet"}` and are
|
|
84
|
+
* resolved against `commonTypes` by the emitter.
|
|
85
|
+
*/
|
|
86
|
+
export interface ResolvedType {
|
|
87
|
+
type: string;
|
|
88
|
+
name?: string;
|
|
89
|
+
element?: ResolvedType;
|
|
90
|
+
attributes?: Record<string, ResolvedType>;
|
|
91
|
+
required?: boolean;
|
|
92
|
+
enum?: string[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** The `SchemaJson` shape, keyed by namespace (`""` is the empty namespace). */
|
|
96
|
+
export type ResolvedSchemaJson = Record<string, ResolvedNamespace>;
|
|
97
|
+
|
|
98
|
+
export type WasmResult<T> = { ok: true; value: T } | { ok: false; error: string };
|
|
99
|
+
|
|
100
|
+
/** The Cedar *language* version this build of the package implements. */
|
|
101
|
+
export function langVersion(): string {
|
|
102
|
+
return cedar().getCedarLangVersion();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** The `@cedar-policy/cedar-wasm` package version. */
|
|
106
|
+
export function packageVersion(): string {
|
|
107
|
+
return cedar().getCedarVersion();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolve a human-readable `.cedarschema` into fully-qualified schema JSON.
|
|
112
|
+
*
|
|
113
|
+
* Returns a result rather than throwing so a bad project schema reads as a
|
|
114
|
+
* message about the project schema, not as a stack trace out of a wasm module.
|
|
115
|
+
*/
|
|
116
|
+
export function resolveSchema(schemaText: unknown): WasmResult<ResolvedSchemaJson> {
|
|
117
|
+
if (typeof schemaText !== "string") {
|
|
118
|
+
// Guarded, not attempted: a non-string traps the instance rather than
|
|
119
|
+
// returning a failure answer (#1648 §5.4).
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
error: `schemaToJsonWithResolvedTypes takes the human-readable schema as a string; got ${typeof schemaText}`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let answer: unknown;
|
|
127
|
+
try {
|
|
128
|
+
answer = cedar().schemaToJsonWithResolvedTypes(schemaText);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!answer || typeof answer !== "object") {
|
|
134
|
+
return { ok: false, error: "cedar-wasm returned no answer" };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const record = answer as { type?: string; json?: unknown; errors?: unknown };
|
|
138
|
+
if (record.type !== "success") {
|
|
139
|
+
return { ok: false, error: formatWasmErrors(record.errors) };
|
|
140
|
+
}
|
|
141
|
+
if (!record.json || typeof record.json !== "object") {
|
|
142
|
+
return { ok: false, error: "cedar-wasm reported success with no schema JSON" };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return { ok: true, value: record.json as ResolvedSchemaJson };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ── Policy conversion ─────────────────────────────────────────────
|
|
149
|
+
|
|
150
|
+
/** One Cedar policy in Cedar's own JSON policy format. */
|
|
151
|
+
export type PolicyJson = CedarWasm.PolicyJson;
|
|
152
|
+
|
|
153
|
+
/** The two halves `policySetTextToParts` splits a `.cedar` document into. */
|
|
154
|
+
export interface PolicySetParts {
|
|
155
|
+
/** Verbatim source text of each static policy, in source order. */
|
|
156
|
+
policies: string[];
|
|
157
|
+
/** Verbatim source text of each template, in source order. */
|
|
158
|
+
templates: string[];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Run one wasm call and collapse both of its error channels into a result.
|
|
163
|
+
*
|
|
164
|
+
* The `Answer` union is not the whole error channel — malformed input throws a
|
|
165
|
+
* bare serde `Error` from inside the module, and the `line 1 column N` those
|
|
166
|
+
* messages carry points at the internal call struct rather than at anything
|
|
167
|
+
* the user wrote (#1648 §5.3). Both land here as `{ ok: false }`.
|
|
168
|
+
*/
|
|
169
|
+
function wasmCall<T>(
|
|
170
|
+
what: string,
|
|
171
|
+
run: () => unknown,
|
|
172
|
+
extract: (answer: Record<string, unknown>) => T | undefined,
|
|
173
|
+
): WasmResult<T> {
|
|
174
|
+
let answer: unknown;
|
|
175
|
+
try {
|
|
176
|
+
answer = run();
|
|
177
|
+
} catch (err) {
|
|
178
|
+
return { ok: false, error: `${what}: ${err instanceof Error ? err.message : String(err)}` };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (!answer || typeof answer !== "object") {
|
|
182
|
+
return { ok: false, error: `${what}: cedar-wasm returned no answer` };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const record = answer as { type?: string; errors?: unknown };
|
|
186
|
+
if (record.type !== "success") {
|
|
187
|
+
return { ok: false, error: formatWasmErrors(record.errors) };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const value = extract(answer as Record<string, unknown>);
|
|
191
|
+
if (value === undefined) {
|
|
192
|
+
return { ok: false, error: `${what}: cedar-wasm reported success with no result` };
|
|
193
|
+
}
|
|
194
|
+
return { ok: true, value };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Split a `.cedar` document into its policies and its templates.
|
|
199
|
+
*
|
|
200
|
+
* The strings that come back are the **verbatim source** of each policy —
|
|
201
|
+
* annotations, line breaks and all — in source order, which is what lets the
|
|
202
|
+
* importer recover a condition body exactly as it was written rather than as
|
|
203
|
+
* the JSON leg would re-render it. Comments are dropped: they are not part of
|
|
204
|
+
* any grammar the module round-trips.
|
|
205
|
+
*/
|
|
206
|
+
export function splitPolicySet(text: unknown): WasmResult<PolicySetParts> {
|
|
207
|
+
if (typeof text !== "string") {
|
|
208
|
+
return { ok: false, error: `policySetTextToParts takes policy text as a string; got ${typeof text}` };
|
|
209
|
+
}
|
|
210
|
+
return wasmCall("policySetTextToParts", () => cedar().policySetTextToParts(text), (answer) => {
|
|
211
|
+
const { policies, policy_templates: templates } = answer as {
|
|
212
|
+
policies?: unknown;
|
|
213
|
+
policy_templates?: unknown;
|
|
214
|
+
};
|
|
215
|
+
if (!Array.isArray(policies) || !Array.isArray(templates)) return undefined;
|
|
216
|
+
return { policies: policies as string[], templates: templates as string[] };
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Convert one *static* policy (text or JSON) into Cedar's JSON policy format. */
|
|
221
|
+
export function policyToJson(policy: string | PolicyJson): WasmResult<PolicyJson> {
|
|
222
|
+
return wasmCall("policyToJson", () => cedar().policyToJson(policy), (answer) => answer.json as PolicyJson | undefined);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Convert one *template* (text or JSON) into Cedar's JSON policy format.
|
|
227
|
+
*
|
|
228
|
+
* A policy carrying `?principal`/`?resource` is a template, and `policyToJson`
|
|
229
|
+
* refuses it outright ("expected a static policy, got a template containing
|
|
230
|
+
* the slot ?resource") — the two entry points are not interchangeable.
|
|
231
|
+
*/
|
|
232
|
+
export function templateToJson(template: string | PolicyJson): WasmResult<PolicyJson> {
|
|
233
|
+
return wasmCall(
|
|
234
|
+
"templateToJson",
|
|
235
|
+
() => cedar().templateToJson(template),
|
|
236
|
+
(answer) => answer.json as PolicyJson | undefined,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Render one policy's JSON back to Cedar text.
|
|
242
|
+
*
|
|
243
|
+
* Only ever used to recover an *expression* body that has no source text to
|
|
244
|
+
* quote — an imported JSON policy set. The output is single-line and defensively
|
|
245
|
+
* parenthesized (`((context.mfa) == true)`), and `formatPolicies` does not undo
|
|
246
|
+
* that, so it is never the source of a human-facing `.cedar` artifact: those are
|
|
247
|
+
* laid out by the serializer.
|
|
248
|
+
*/
|
|
249
|
+
export function policyToText(policy: PolicyJson): WasmResult<string> {
|
|
250
|
+
return wasmCall("policyToText", () => cedar().policyToText(policy), (answer) => answer.text as string | undefined);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Does this value parse as a Cedar policy set?
|
|
255
|
+
*
|
|
256
|
+
* `checkParsePolicySet` throws — rather than answering `failure` — for a
|
|
257
|
+
* document carrying keys it does not know, which is precisely the shape a
|
|
258
|
+
* foreign lexicon's JSON has, so the throw is a match rejection here.
|
|
259
|
+
*/
|
|
260
|
+
export function parsesAsPolicySet(value: unknown): boolean {
|
|
261
|
+
try {
|
|
262
|
+
return cedar().checkParsePolicySet(value as CedarWasm.PolicySet).type === "success";
|
|
263
|
+
} catch {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Flatten a `DetailedError[]` into one line.
|
|
270
|
+
*
|
|
271
|
+
* `code`, `url` and `severity` are `null` on every error this package emits
|
|
272
|
+
* (#1648 §5.6), so only `message` and `help` carry anything.
|
|
273
|
+
*/
|
|
274
|
+
export function formatWasmErrors(errors: unknown): string {
|
|
275
|
+
if (!Array.isArray(errors) || errors.length === 0) return "cedar-wasm reported a failure with no detail";
|
|
276
|
+
return errors
|
|
277
|
+
.map((e) => {
|
|
278
|
+
if (typeof e === "string") return e;
|
|
279
|
+
const detail = e as { message?: string; help?: string };
|
|
280
|
+
return detail.help ? `${detail.message} (${detail.help})` : String(detail.message ?? e);
|
|
281
|
+
})
|
|
282
|
+
.join("; ");
|
|
283
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { validate } from "./validate";
|
|
3
|
+
import { printValidationResult } from "@intentius/chant/codegen/validate";
|
|
4
|
+
|
|
5
|
+
// `validate` returns a result; printing it is what turns a failed check into a
|
|
6
|
+
// non-zero exit. The scaffold called it and discarded the answer, so a missing
|
|
7
|
+
// registry exited 0.
|
|
8
|
+
printValidationResult(await validate());
|
package/src/validate.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate the generated lexicon-cedar artifacts.
|
|
3
|
+
*
|
|
4
|
+
* The required-name list below is the surface this package publishes when it
|
|
5
|
+
* generates from its own bundled default schema, which is what `prepack`,
|
|
6
|
+
* `just check-lexicons` and CI all do. It is not a claim about a user's
|
|
7
|
+
* project schema — theirs produces their own names, and `coverage()` is the
|
|
8
|
+
* check that answers whether their schema is fully reachable.
|
|
9
|
+
*
|
|
10
|
+
* Listing them explicitly is the point: `src/generated/` is gitignored, so
|
|
11
|
+
* without this list nothing in the repository records what the default schema
|
|
12
|
+
* is supposed to produce, and a codegen change that quietly dropped every
|
|
13
|
+
* action would still pass "the registry parses".
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { dirname } from "path";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
import { validateLexiconArtifacts, type ValidateResult } from "@intentius/chant/codegen/validate";
|
|
19
|
+
|
|
20
|
+
export type { ValidateCheck, ValidateResult } from "@intentius/chant/codegen/validate";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Names the default schema must produce: the policy authoring class, one class
|
|
24
|
+
* per entity type, one per action, and the record type beside each.
|
|
25
|
+
*/
|
|
26
|
+
const REQUIRED_NAMES: string[] = [
|
|
27
|
+
// The authoring surface, present regardless of schema.
|
|
28
|
+
"Policy",
|
|
29
|
+
|
|
30
|
+
// Entity types.
|
|
31
|
+
"Application",
|
|
32
|
+
"Document",
|
|
33
|
+
"Folder",
|
|
34
|
+
"Group",
|
|
35
|
+
"ServiceAccount",
|
|
36
|
+
"Team",
|
|
37
|
+
"User",
|
|
38
|
+
|
|
39
|
+
// Entity attribute records.
|
|
40
|
+
"ApplicationAttributes",
|
|
41
|
+
"DocumentAttributes",
|
|
42
|
+
"FolderAttributes",
|
|
43
|
+
"GroupAttributes",
|
|
44
|
+
"ServiceAccountAttributes",
|
|
45
|
+
"TeamAttributes",
|
|
46
|
+
"UserAttributes",
|
|
47
|
+
|
|
48
|
+
// Actions.
|
|
49
|
+
"AdminAction",
|
|
50
|
+
"ApproveAction",
|
|
51
|
+
"CommentAction",
|
|
52
|
+
"CreateAction",
|
|
53
|
+
"DeleteAction",
|
|
54
|
+
"ListAction",
|
|
55
|
+
"ReadAction",
|
|
56
|
+
"ShareAction",
|
|
57
|
+
"WriteAction",
|
|
58
|
+
|
|
59
|
+
// Action context records.
|
|
60
|
+
"AdminContext",
|
|
61
|
+
"ApproveContext",
|
|
62
|
+
"CommentContext",
|
|
63
|
+
"CreateContext",
|
|
64
|
+
"DeleteContext",
|
|
65
|
+
"ListContext",
|
|
66
|
+
"ReadContext",
|
|
67
|
+
"ShareContext",
|
|
68
|
+
"WriteContext",
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
/** Exposed so tests can assert the list stays above the tier-3 bar. */
|
|
72
|
+
export const requiredNames: readonly string[] = REQUIRED_NAMES;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Validate the generated lexicon-cedar artifacts.
|
|
76
|
+
*/
|
|
77
|
+
export async function validate(opts?: { basePath?: string }): Promise<ValidateResult> {
|
|
78
|
+
const basePath = opts?.basePath ?? dirname(dirname(fileURLToPath(import.meta.url)));
|
|
79
|
+
|
|
80
|
+
return validateLexiconArtifacts({
|
|
81
|
+
lexiconJsonFilename: "lexicon-cedar.json",
|
|
82
|
+
requiredNames: REQUIRED_NAMES,
|
|
83
|
+
basePath,
|
|
84
|
+
});
|
|
85
|
+
}
|