@intentius/chant-lexicon-cedar 0.124.30 → 0.124.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/agentcore/embed.js +250 -0
  2. package/dist/agentcore/enforcement.js +81 -0
  3. package/dist/agentcore/scan.js +93 -0
  4. package/dist/avp/ambient.js +100 -0
  5. package/dist/avp/client.js +318 -0
  6. package/dist/avp/describe-resources.js +144 -0
  7. package/dist/avp/embed.js +125 -0
  8. package/dist/avp/live-export.js +151 -0
  9. package/dist/avp/ownership.js +144 -0
  10. package/dist/avp/statement.js +45 -0
  11. package/dist/avp/store.js +105 -0
  12. package/dist/avp/testdata/mock-transport.js +100 -0
  13. package/dist/codegen/docs-cli.js +6 -0
  14. package/dist/codegen/docs.js +133 -0
  15. package/dist/codegen/emit.js +331 -0
  16. package/dist/codegen/generate-cli.js +18 -0
  17. package/dist/codegen/generate.js +122 -0
  18. package/dist/codegen/naming.js +90 -0
  19. package/dist/codegen/package.js +33 -0
  20. package/dist/commands.js +86 -0
  21. package/dist/composites/deny-by-default-set.js +51 -0
  22. package/dist/composites/index.js +9 -0
  23. package/dist/composites/owner-can-manage.js +48 -0
  24. package/dist/config.js +159 -0
  25. package/dist/coverage.js +112 -0
  26. package/dist/detect.js +61 -0
  27. package/dist/dogwood/cli.js +477 -0
  28. package/dist/dogwood/event-schema.js +219 -0
  29. package/dist/dogwood/index.js +32 -0
  30. package/dist/dogwood/macros.js +175 -0
  31. package/dist/dogwood/policy.js +58 -0
  32. package/dist/dogwood/replay-activity.js +313 -0
  33. package/dist/dogwood/replay-op.js +134 -0
  34. package/dist/dogwood/scan.js +234 -0
  35. package/dist/dogwood/serialize.js +199 -0
  36. package/dist/dogwood/temporal.js +354 -0
  37. package/dist/dogwood/trace.js +269 -0
  38. package/dist/dogwood/upstream.js +40 -0
  39. package/dist/dogwood/window.js +82 -0
  40. package/dist/gate-policy-pack.js +189 -0
  41. package/dist/gate-policy.js +168 -0
  42. package/dist/gate-schema.js +122 -0
  43. package/dist/generated/index.js +94 -0
  44. package/dist/generated/runtime.js +2 -0
  45. package/dist/import/adapter.js +54 -0
  46. package/dist/import/clause-text.js +166 -0
  47. package/dist/import/generator.js +178 -0
  48. package/dist/import/parser.js +273 -0
  49. package/dist/index.js +79 -0
  50. package/dist/init-templates.js +330 -0
  51. package/dist/integrity.json +2 -2
  52. package/dist/lint/audit-catalog.js +65 -0
  53. package/dist/lint/audit-lineage.js +23 -0
  54. package/dist/lint/post-synth/cedar-helpers.js +123 -0
  55. package/dist/lint/post-synth/cedc010.js +59 -0
  56. package/dist/lint/post-synth/cedc011.js +29 -0
  57. package/dist/lint/post-synth/cedc012.js +34 -0
  58. package/dist/lint/post-synth/cedc013.js +45 -0
  59. package/dist/lint/post-synth/cedc014.js +54 -0
  60. package/dist/lint/post-synth/cede010.js +51 -0
  61. package/dist/lint/post-synth/cede011.js +36 -0
  62. package/dist/lint/post-synth/ceds010.js +31 -0
  63. package/dist/lint/post-synth/ceds011.js +22 -0
  64. package/dist/lint/post-synth/ceds012.js +31 -0
  65. package/dist/lint/post-synth/dogwood-helpers.js +94 -0
  66. package/dist/lint/post-synth/dwdc010.js +38 -0
  67. package/dist/lint/post-synth/dwdc011.js +34 -0
  68. package/dist/lint/post-synth/dwdc012.js +24 -0
  69. package/dist/lint/post-synth/dwdc013.js +29 -0
  70. package/dist/lint/post-synth/dwde010.js +84 -0
  71. package/dist/lint/post-synth/dwde011.js +67 -0
  72. package/dist/lint/post-synth/dwds010.js +21 -0
  73. package/dist/lint/post-synth/index.js +36 -0
  74. package/dist/lint/post-synth/wasm-helpers.js +234 -0
  75. package/dist/lint/rules/index.js +9 -0
  76. package/dist/lint/rules/policy-shape.js +114 -0
  77. package/dist/lsp/completions.js +52 -0
  78. package/dist/lsp/hover.js +56 -0
  79. package/dist/lsp/registry.d.ts.map +1 -1
  80. package/dist/lsp/registry.js +51 -0
  81. package/dist/manifest.json +1 -1
  82. package/dist/mcp/index.js +82 -0
  83. package/dist/mcp/policy-coverage.js +134 -0
  84. package/dist/op/activities/index.js +16 -0
  85. package/dist/package-cli.js +18 -0
  86. package/dist/plugin.js +304 -0
  87. package/dist/policy-text.js +117 -0
  88. package/dist/schema-artifact.js +66 -0
  89. package/dist/serializer.js +203 -0
  90. package/dist/spec/fetch.js +96 -0
  91. package/dist/spec/parse.js +164 -0
  92. package/dist/spec/pin.js +170 -0
  93. package/dist/spec/wasm.js +194 -0
  94. package/dist/validate-cli.js +7 -0
  95. package/dist/validate.js +74 -0
  96. package/package.json +7 -7
  97. package/src/codegen/package.ts +2 -2
  98. package/src/coverage.ts +2 -2
  99. package/src/import/generator.ts +2 -2
  100. package/src/lsp/registry.ts +2 -1
  101. package/src/spec/fetch.ts +2 -2
@@ -0,0 +1,56 @@
1
+ import { lexiconHover } from "@intentius/chant/lsp/lexicon-providers";
2
+ import { cedarIndex, cedarRegistry } from "./registry.js";
3
+ /**
4
+ * Hover over a generated declaration.
5
+ *
6
+ * Core's default formatter reports CloudFormation-shaped facts (primary
7
+ * identifier, create-only, write-only) a Cedar declaration does not have. The
8
+ * facts that matter here are the Cedar ones: what a `Policy` prop means, which
9
+ * groups an entity type is `in`, and what an action applies to.
10
+ */
11
+ export function hover(ctx) {
12
+ return lexiconHover(ctx, cedarIndex(), formatCedarHover);
13
+ }
14
+ function formatCedarHover(className, indexed) {
15
+ const entry = cedarRegistry()[className];
16
+ if (!entry)
17
+ return undefined;
18
+ const lines = [`**${className}**`, "", `Cedar type: \`${entry.resourceType}\``];
19
+ if (entry.description) {
20
+ lines.push("", entry.description);
21
+ }
22
+ if (entry.resourceType === "Cedar::Policy") {
23
+ lines.push("", "The unit this lexicon serializes — one `.cedar` policy plus its entry in the JSON policy set.", "", "| Prop | Meaning |", "|------|---------|", "| `effect` | `permit` or `forbid`; defaults to `permit` |", "| `principal`, `action`, `resource` | scope constraints — `{}`, `{ eq }`, `{ in }`, `{ is }` |", "| `when`, `unless` | Cedar expression strings, one clause each |", "| `annotations` | emitted as `@key(\"value\")` above the policy |");
24
+ return { contents: lines.join("\n") };
25
+ }
26
+ if (entry.resourceType.includes("::Action::")) {
27
+ if (entry.principalTypes?.length) {
28
+ lines.push("", `**Principals:** ${entry.principalTypes.map((t) => `\`${t}\``).join(", ")}`);
29
+ }
30
+ if (entry.resourceTypes?.length) {
31
+ lines.push("", `**Resources:** ${entry.resourceTypes.map((t) => `\`${t}\``).join(", ")}`);
32
+ }
33
+ const context = Object.entries(entry.properties ?? {});
34
+ if (context.length > 0) {
35
+ lines.push("", "**Context:**");
36
+ for (const [name, spec] of context) {
37
+ lines.push(`- \`${name}\`${spec.required ? "" : "?"} — \`${spec.type}\``);
38
+ }
39
+ }
40
+ return { contents: lines.join("\n") };
41
+ }
42
+ if (entry.memberOfTypes?.length) {
43
+ lines.push("", `**Member of:** ${entry.memberOfTypes.map((t) => `\`${t}\``).join(", ")}`);
44
+ }
45
+ if (entry.enumValues?.length) {
46
+ lines.push("", `**Enum values:** ${entry.enumValues.map((v) => `\`${v}\``).join(", ")}`);
47
+ }
48
+ const attributes = Object.entries(entry.properties ?? {});
49
+ if (attributes.length > 0) {
50
+ lines.push("", indexed.kind === "property" ? "**Fields:**" : "**Attributes:**");
51
+ for (const [name, spec] of attributes) {
52
+ lines.push(`- \`${name}\`${spec.required ? "" : "?"} — \`${spec.type}\``);
53
+ }
54
+ }
55
+ return { contents: lines.join("\n") };
56
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/lsp/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,YAAY,EAAqB,MAAM,wCAAwC,CAAC;AAKzF,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAK/D,yEAAyE;AACzE,wBAAgB,aAAa,IAAI,aAAa,CAI7C;AAED,iFAAiF;AACjF,wBAAgB,UAAU,IAAI,YAAY,CAazC;AAED,2FAA2F;AAC3F,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/lsp/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,YAAY,EAAqB,MAAM,wCAAwC,CAAC;AAKzF,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAK/D,yEAAyE;AACzE,wBAAgB,aAAa,IAAI,aAAa,CAI7C;AAED,iFAAiF;AACjF,wBAAgB,UAAU,IAAI,YAAY,CAazC;AAED,2FAA2F;AAC3F,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The generated registry, adapted to what core's `LexiconIndex` reads.
3
+ *
4
+ * `lexicon-cedar.json` describes every declaration the project's schema
5
+ * produced (#1650): the `Policy` authoring class, one entry per entity type,
6
+ * one per action, and the attribute/context record types beside them. Its
7
+ * property table is keyed `properties`, while `LexiconIndex.getPropertyNames`
8
+ * looks at `propertyConstraints` — the CloudFormation-shaped name the class was
9
+ * written against. Renaming the generated key to match would put a
10
+ * CloudFormation word in a Cedar artifact; translating here does not, and it is
11
+ * the only reason this module exists.
12
+ *
13
+ * The require is lazy and cached. `generate()` writes the registry, so a
14
+ * checkout that has not run it yet must still be able to import this file —
15
+ * the LSP tests skip on exactly that condition.
16
+ */
17
+ import { createRequire } from "module";
18
+ import { moduleSourceUrl } from "@intentius/chant/module-source";
19
+ import { LexiconIndex } from "@intentius/chant/lsp/lexicon-providers";
20
+ import { LEXICON_JSON_FILENAME } from "../codegen/generate.js";
21
+ const require = createRequire(moduleSourceUrl(import.meta.url));
22
+ let cachedRegistry = null;
23
+ let cachedIndex = null;
24
+ /** The raw registry, for the hover formatter's Cedar-specific fields. */
25
+ export function cedarRegistry() {
26
+ if (cachedRegistry)
27
+ return cachedRegistry;
28
+ cachedRegistry = require(`../generated/${LEXICON_JSON_FILENAME}`);
29
+ return cachedRegistry;
30
+ }
31
+ /** The same registry as a `LexiconIndex`, with the property table translated. */
32
+ export function cedarIndex() {
33
+ if (cachedIndex)
34
+ return cachedIndex;
35
+ const entries = {};
36
+ for (const [className, entry] of Object.entries(cedarRegistry())) {
37
+ entries[className] = {
38
+ resourceType: entry.resourceType,
39
+ kind: entry.kind,
40
+ lexicon: entry.lexicon,
41
+ propertyConstraints: entry.properties ?? {},
42
+ };
43
+ }
44
+ cachedIndex = new LexiconIndex(entries);
45
+ return cachedIndex;
46
+ }
47
+ /** Reset the caches. Tests that swap the registry on disk need this; nothing else does. */
48
+ export function resetCedarIndexCache() {
49
+ cachedRegistry = null;
50
+ cachedIndex = null;
51
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cedar",
3
- "version": "0.124.30",
3
+ "version": "0.124.32",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Cedar",
6
6
  "intrinsics": [],
@@ -0,0 +1,82 @@
1
+ /**
2
+ * The cedar lexicon's MCP contributions.
3
+ *
4
+ * Two of the three are the conventional pair every lexicon ships, built from
5
+ * core's shared helpers: `cedar:diff` and `chant://cedar/resource-catalog`.
6
+ * The third is the one only this lexicon can answer — see
7
+ * ./policy-coverage.ts.
8
+ *
9
+ * Names are written as bare verbs and single-segment URIs. Core namespaces both
10
+ * (`cedar:<verb>`, `chant://cedar/<path>`), and applying the prefix is
11
+ * idempotent, so the helpers' pre-namespaced output and the bare `coverage`
12
+ * below both register as exactly one well-formed identifier (chant #1341).
13
+ */
14
+ import { createDiffTool, createCatalogResource } from "@intentius/chant/lexicon-plugin-helpers";
15
+ import { cedarSerializer } from "../serializer.js";
16
+ import { computePolicyCoverage, formatPolicyCoverage } from "./policy-coverage.js";
17
+ /**
18
+ * `cedar:coverage` — which schema declarations the built policy set reaches.
19
+ *
20
+ * Builds the project the same way `chant build` does rather than reading a
21
+ * committed `.cedar` file, so the answer is about the policies in source, not
22
+ * about whatever was last written to disk.
23
+ */
24
+ export const cedarCoverageTool = {
25
+ name: "coverage",
26
+ description: "Report which Cedar schema entity types and actions the project's policy set can apply to, " +
27
+ "which are reachable only from a forbid, and which no policy covers at all.",
28
+ inputSchema: {
29
+ type: "object",
30
+ properties: {
31
+ path: {
32
+ type: "string",
33
+ description: "Path to the infrastructure project directory (defaults to the current directory)",
34
+ },
35
+ format: {
36
+ type: "string",
37
+ enum: ["json", "text"],
38
+ description: "Return the full report as JSON (default) or a human-readable summary",
39
+ },
40
+ },
41
+ },
42
+ async handler(params) {
43
+ const { join } = await import("path");
44
+ const { existsSync } = await import("fs");
45
+ const { build } = await import("@intentius/chant/build");
46
+ const { loadCedarConfig } = await import("../config.js");
47
+ const projectRoot = params.path ?? ".";
48
+ const srcDir = existsSync(join(projectRoot, "src")) ? join(projectRoot, "src") : projectRoot;
49
+ const result = await build(srcDir, [cedarSerializer]);
50
+ if (result.errors.length > 0) {
51
+ return { error: "build failed", details: result.errors.map((e) => String(e)) };
52
+ }
53
+ const output = result.outputs.get("cedar");
54
+ const policySetText = typeof output === "string" ? output : (output?.primary ?? "");
55
+ const report = computePolicyCoverage({
56
+ policySetText,
57
+ projectRoot,
58
+ config: await loadCedarConfig(projectRoot),
59
+ });
60
+ return params.format === "text" ? formatPolicyCoverage(report) : report;
61
+ },
62
+ };
63
+ /** Every MCP tool this lexicon contributes. */
64
+ export function cedarMcpTools() {
65
+ return [
66
+ createDiffTool(cedarSerializer, "Compare the current Cedar policy set against the previous build's output", "cedar"),
67
+ cedarCoverageTool,
68
+ ];
69
+ }
70
+ /**
71
+ * Every MCP resource this lexicon contributes.
72
+ *
73
+ * `createCatalogResource` locates the registry relative to the module URL it is
74
+ * given, resolving `<dir>/generated/lexicon-cedar.json`. That has to be
75
+ * `src/`, not `src/mcp/`, so the caller in plugin.ts passes its own
76
+ * `import.meta.url` rather than this file deriving one by walking up.
77
+ */
78
+ export function cedarMcpResources(pluginUrl) {
79
+ return [
80
+ createCatalogResource(pluginUrl, "Cedar Resource Catalog", "Every declaration generated from the project's Cedar schema — entity types, actions, and the Policy class", "lexicon-cedar.json", "cedar"),
81
+ ];
82
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * "Which policies cover this resource?" — answered from a build (epic #1645).
3
+ *
4
+ * `src/coverage.ts` next door asks a different question: is every schema
5
+ * declaration reachable from the *generated artifacts*. This one asks whether
6
+ * every schema declaration is reachable from the *policy set*, which is the
7
+ * authorization question. An entity type no policy can ever apply to is a
8
+ * resource nothing grants and nothing denies — under Cedar's default-deny it is
9
+ * inert, and that is either the intent or a hole.
10
+ *
11
+ * The answer comes from `getValidRequestEnvsPolicy`, Cedar's own resolver: it
12
+ * takes one policy and the schema and returns every (principal, action,
13
+ * resource) triple the policy could apply to, having already expanded `is`,
14
+ * `in`, action groups, and `appliesTo`. Reimplementing that against the parsed
15
+ * scope would be a second, worse Cedar; this is why the wasm package is a
16
+ * runtime dependency rather than a dev one.
17
+ */
18
+ import { getValidRequestEnvsPolicy, policySetTextToParts, policyToJson, } from "@cedar-policy/cedar-wasm/nodejs";
19
+ import { readSchemaSource } from "../spec/fetch.js";
20
+ import { parseCedarSchema } from "../spec/parse.js";
21
+ /**
22
+ * A policy's id and effect, read from Cedar's own parse rather than from the
23
+ * text.
24
+ *
25
+ * The regex version of this worked on the serializer's output and only on the
26
+ * serializer's output: a hand-formatted policy, an annotation whose value
27
+ * contains the word `forbid`, or an escaped quote inside `@id` each break it.
28
+ * `policyToJson` is already in the package, so there is no reason to guess.
29
+ *
30
+ * `index` supplies the fallback id, because a Cedar policy is not required to
31
+ * annotate one and a report keyed by "" would collapse them together.
32
+ */
33
+ function identify(text, index) {
34
+ const parsed = policyToJson(text);
35
+ if (parsed.type !== "success") {
36
+ return { id: `policy-${index + 1}`, effect: "permit" };
37
+ }
38
+ const annotated = parsed.json.annotations?.id;
39
+ return {
40
+ id: typeof annotated === "string" && annotated.length > 0 ? annotated : `policy-${index + 1}`,
41
+ effect: parsed.json.effect === "forbid" ? "forbid" : "permit",
42
+ };
43
+ }
44
+ /**
45
+ * Report which schema declarations the policy set can reach.
46
+ */
47
+ export function computePolicyCoverage(options) {
48
+ const source = readSchemaSource(options);
49
+ const { decls } = parseCedarSchema(source.text);
50
+ const parts = policySetTextToParts(options.policySetText);
51
+ const policies = parts.type === "success" ? parts.policies : [];
52
+ const parseErrors = parts.type === "success" ? [] : parts.errors.map((e) => e.message);
53
+ const hits = new Map();
54
+ const unresolved = [];
55
+ const inert = [];
56
+ policies.forEach((text, index) => {
57
+ const { id, effect } = identify(text, index);
58
+ const envs = getValidRequestEnvsPolicy(text, source.text);
59
+ if (envs.type !== "success") {
60
+ unresolved.push({ policyId: id, error: envs.error });
61
+ return;
62
+ }
63
+ const reached = [...envs.principals, ...envs.actions, ...envs.resources];
64
+ if (reached.length === 0) {
65
+ inert.push(id);
66
+ return;
67
+ }
68
+ for (const name of reached) {
69
+ const hit = hits.get(name) ?? { ids: [], permitted: false, forbidden: false };
70
+ if (!hit.ids.includes(id))
71
+ hit.ids.push(id);
72
+ if (effect === "permit")
73
+ hit.permitted = true;
74
+ else
75
+ hit.forbidden = true;
76
+ hits.set(name, hit);
77
+ }
78
+ });
79
+ const items = decls
80
+ .map((decl) => {
81
+ const hit = hits.get(decl.typeName);
82
+ return {
83
+ name: decl.typeName,
84
+ kind: decl.kind,
85
+ policies: hit?.ids.length ?? 0,
86
+ policyIds: hit?.ids ?? [],
87
+ permitted: hit?.permitted ?? false,
88
+ forbidden: hit?.forbidden ?? false,
89
+ };
90
+ })
91
+ .sort((a, b) => a.name.localeCompare(b.name));
92
+ const entities = items.filter((i) => i.kind === "entity");
93
+ const actions = items.filter((i) => i.kind === "action");
94
+ return {
95
+ schemaPath: source.path,
96
+ isDefaultSchema: source.isDefault,
97
+ policyCount: policies.length,
98
+ entityTypes: entities.length,
99
+ entityTypesCovered: entities.filter((i) => i.policies > 0).length,
100
+ actions: actions.length,
101
+ actionsCovered: actions.filter((i) => i.policies > 0).length,
102
+ uncovered: items.filter((i) => i.policies === 0).map((i) => i.name),
103
+ forbidOnly: items.filter((i) => i.policies > 0 && !i.permitted).map((i) => i.name),
104
+ items,
105
+ unresolved,
106
+ inert,
107
+ parseErrors,
108
+ };
109
+ }
110
+ /** Human-readable summary, for the CLI-shaped callers. */
111
+ export function formatPolicyCoverage(report) {
112
+ const lines = [
113
+ `Cedar policy coverage — ${report.policyCount} policy/policies against ` +
114
+ `${report.isDefaultSchema ? "the bundled default schema" : report.schemaPath}`,
115
+ ` Entity types: ${report.entityTypesCovered}/${report.entityTypes}`,
116
+ ` Actions: ${report.actionsCovered}/${report.actions}`,
117
+ ];
118
+ for (const error of report.parseErrors) {
119
+ lines.push(` Parse error: ${error}`);
120
+ }
121
+ if (report.uncovered.length > 0) {
122
+ lines.push(` Uncovered: ${report.uncovered.join(", ")}`);
123
+ }
124
+ if (report.forbidOnly.length > 0) {
125
+ lines.push(` Forbid only: ${report.forbidOnly.join(", ")}`);
126
+ }
127
+ if (report.inert.length > 0) {
128
+ lines.push(` Never fires: ${report.inert.join(", ")}`);
129
+ }
130
+ for (const problem of report.unresolved) {
131
+ lines.push(` Unresolved: ${problem.policyId} — ${problem.error}`);
132
+ }
133
+ return lines.join("\n");
134
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * cedar Op activities — resolved by the core activity registry when a
3
+ * project's `chant.config.ts` lists the `cedar` lexicon.
4
+ *
5
+ * The registry keys every exported *function* in this module by its name
6
+ * (`loadActivities` → `collectActivities`), which is why only the activities
7
+ * themselves are exported here. `dogwoodReplay`'s helpers — the input
8
+ * resolver, the verdict comparison, the summary renderer — stay importable
9
+ * from `@intentius/chant-lexicon-cedar/dogwood/replay-activity` rather than
10
+ * being registered as activities nobody would ever name in a step.
11
+ *
12
+ * Contributed the `flyApply` way: a plain async function taking one args
13
+ * object, depending on no runtime beyond node, so the local executor
14
+ * (`packages/core/src/op/local-executor.ts`) calls it directly.
15
+ */
16
+ export { dogwoodReplay, dogwoodReplayReport } from "../../dogwood/replay-activity.js";
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Thin entry point for `npm run bundle` in lexicon-cedar.
4
+ *
5
+ * Unlike the other lexicons this does not generate `src/generated/` first —
6
+ * codegen is schema-driven and per-project, and lands in #1650. Until then
7
+ * the bundle carries the manifest, rules and integrity over an empty registry.
8
+ */
9
+ import { packageLexicon } from "./codegen/package.js";
10
+ import { writeBundleSpec } from "@intentius/chant/codegen/package";
11
+ import { join, dirname } from "path";
12
+ import { fileURLToPath } from "url";
13
+ const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
14
+ const { spec, stats } = await packageLexicon({ verbose: true });
15
+ const distDir = join(pkgDir, "dist");
16
+ writeBundleSpec(spec, distDir);
17
+ console.error(`Packaged ${stats.resources} entities, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
18
+ console.error(`dist/ written to ${distDir}`);