domainforge 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (481) hide show
  1. package/.cargo/config.toml +6 -0
  2. package/.claude/settings.local.json +18 -0
  3. package/.coderabbit.yml +43 -0
  4. package/.codex/skills/release-management/SKILL.md +151 -0
  5. package/.codex/skills/release-management/agents/openai.yaml +4 -0
  6. package/.github/actions/decrypt-secrets/action.yml +121 -0
  7. package/.github/agents/Coder.agent.md +97 -0
  8. package/.github/agents/DeepResearch.agent.md +61 -0
  9. package/.github/chatmodes/tdd.vibepro.chatmode.md +1183 -0
  10. package/.github/copilot-instructions.md +13 -0
  11. package/.github/dependabot.yml +68 -0
  12. package/.github/workflows/README.md +165 -0
  13. package/.github/workflows/ci.yml +335 -0
  14. package/.github/workflows/dependabot-automerge.yml +114 -0
  15. package/.github/workflows/dependency-review.yml +27 -0
  16. package/.github/workflows/deploy.yml +87 -0
  17. package/.github/workflows/prepare-release.yml +168 -0
  18. package/.github/workflows/release-crates.yml +42 -0
  19. package/.github/workflows/release-npm.yml +137 -0
  20. package/.github/workflows/release-please.yml +29 -0
  21. package/.github/workflows/release-pypi.yml +96 -0
  22. package/.gitkeep +1 -0
  23. package/.release-please-manifest.json +5 -0
  24. package/.sea-registry.toml +10 -0
  25. package/.serena/project.yml +133 -0
  26. package/.sops.yaml +10 -0
  27. package/AGENTS.md +216 -0
  28. package/CHANGELOG.md +400 -0
  29. package/CLAUDE.md +62 -0
  30. package/CONTRIBUTING.md +323 -0
  31. package/Cargo.lock +3612 -0
  32. package/Cargo.toml +12 -0
  33. package/LICENSE +201 -0
  34. package/README.md +660 -0
  35. package/README_PYTHON.md +256 -0
  36. package/README_TYPESCRIPT.md +305 -0
  37. package/README_WASM.md +329 -0
  38. package/RELEASE_NOTES.md +41 -0
  39. package/bun.lock +378 -0
  40. package/bunfig.toml +11 -0
  41. package/check_output.txt +83 -0
  42. package/clippy_output.txt +80 -0
  43. package/commitlint.config.cjs +8 -0
  44. package/deny.toml +42 -0
  45. package/devbox.json +14 -0
  46. package/devbox.lock +76 -0
  47. package/docs/RELEASE_PROCESS.md +360 -0
  48. package/docs/diagnostics.md +161 -0
  49. package/docs/doc_guidelines.md +53 -0
  50. package/docs/explanations/README.md +21 -0
  51. package/docs/explanations/architecture-overview.md +109 -0
  52. package/docs/explanations/cross-language-binding-strategy.md +68 -0
  53. package/docs/explanations/graph-store-design.md +47 -0
  54. package/docs/explanations/performance-benchmarks.md +63 -0
  55. package/docs/explanations/policy-evaluation-logic.md +106 -0
  56. package/docs/explanations/semantic-modeling-concepts.md +109 -0
  57. package/docs/explanations/three-valued-logic.md +66 -0
  58. package/docs/explanations/versioning-strategy.md +45 -0
  59. package/docs/governance.md +168 -0
  60. package/docs/how-tos/README.md +46 -0
  61. package/docs/how-tos/ci-cd-validation.md +93 -0
  62. package/docs/how-tos/create-custom-units.md +125 -0
  63. package/docs/how-tos/define-policies.md +119 -0
  64. package/docs/how-tos/export-to-calm.md +110 -0
  65. package/docs/how-tos/export-to-protobuf.md +312 -0
  66. package/docs/how-tos/extend-grammar.md +133 -0
  67. package/docs/how-tos/generate-rdf-turtle.md +106 -0
  68. package/docs/how-tos/import-from-calm.md +114 -0
  69. package/docs/how-tos/import-from-sbvr.md +249 -0
  70. package/docs/how-tos/install-cli.md +126 -0
  71. package/docs/how-tos/parse-sea-files.md +132 -0
  72. package/docs/how-tos/policy-evaluation-modes.md +30 -0
  73. package/docs/how-tos/run-cross-language-tests.md +115 -0
  74. package/docs/how-tos/troubleshoot-napi-builds.md +55 -0
  75. package/docs/how-tos/use-modules-imports.md +285 -0
  76. package/docs/index.md +13 -0
  77. package/docs/plans/canonical-normalizer.md +121 -0
  78. package/docs/plans/cd_improvement.md +112 -0
  79. package/docs/plans/cli-ast.md +29 -0
  80. package/docs/plans/expression-bindings-and-normalizer-integration.md +174 -0
  81. package/docs/plans/protobuf_advanced_features_plan.md +597 -0
  82. package/docs/plans/protobuf_plan.yml +525 -0
  83. package/docs/plans/refactor_dsl_architecture.md +131 -0
  84. package/docs/plans/release-plan.md +163 -0
  85. package/docs/plans/sea_fmt_implementation_plan.md +516 -0
  86. package/docs/playbooks/README.md +18 -0
  87. package/docs/playbooks/adding-new-primitive.md +68 -0
  88. package/docs/playbooks/debugging-parser-failures.md +42 -0
  89. package/docs/playbooks/local-release-preparation.md +139 -0
  90. package/docs/playbooks/migrating-schema-versions.md +43 -0
  91. package/docs/playbooks/onboarding-contributors.md +64 -0
  92. package/docs/playbooks/releasing-beta.md +86 -0
  93. package/docs/playbooks/secret-management.md +64 -0
  94. package/docs/reference/README.md +199 -0
  95. package/docs/reference/ast-json-api.md +427 -0
  96. package/docs/reference/calm-mapping.md +519 -0
  97. package/docs/reference/cli-commands.md +588 -0
  98. package/docs/reference/configuration.md +202 -0
  99. package/docs/reference/error-codes.md +664 -0
  100. package/docs/reference/generated-artifacts-policy.md +53 -0
  101. package/docs/reference/grammar-spec.md +255 -0
  102. package/docs/reference/primitives-api.md +317 -0
  103. package/docs/reference/protobuf-api.md +426 -0
  104. package/docs/reference/python-api.md +485 -0
  105. package/docs/reference/registry.md +50 -0
  106. package/docs/reference/sea-dsl-ai-cheatsheet.yaml +913 -0
  107. package/docs/reference/security-model.md +74 -0
  108. package/docs/reference/typescript-api.md +508 -0
  109. package/docs/reference/wasm-api.md +420 -0
  110. package/docs/semantic-pack-review.md +144 -0
  111. package/docs/semantic-pack-signing.md +234 -0
  112. package/docs/semantic-packs.md +284 -0
  113. package/docs/specs/ADR-001-sea-dsl-semantic-source-of-truth.md +33 -0
  114. package/docs/specs/ADR-002-projection-first-class-construct.md +50 -0
  115. package/docs/specs/ADR-003-protobuf-projection-target.md +51 -0
  116. package/docs/specs/ADR-004-projection-compatibility-semantics.md +57 -0
  117. package/docs/specs/ADR-005-multi-language-support-strategy.md +112 -0
  118. package/docs/specs/ADR-006-error-handling-strategy.md +115 -0
  119. package/docs/specs/ADR-007-policy-evaluation-engine.md +95 -0
  120. package/docs/specs/ADR-008-knowledge-graph-integration.md +90 -0
  121. package/docs/specs/ADR-009-module-resolution-strategy.md +115 -0
  122. package/docs/specs/ADR-010-unit-system.md +106 -0
  123. package/docs/specs/PRD-001-sea-projection-framework.md +155 -0
  124. package/docs/specs/PRD-002-sea-cli-tooling.md +169 -0
  125. package/docs/specs/PRD-003-dsl-core-capabilities.md +275 -0
  126. package/docs/specs/README.md +62 -0
  127. package/docs/specs/SDS-001-protobuf-projection-engine.md +451 -0
  128. package/docs/specs/SDS-002-sea-core-architecture.md +268 -0
  129. package/docs/specs/SDS-003-parser-semantic-graph.md +377 -0
  130. package/docs/specs/SDS-004-policy-engine-design.md +362 -0
  131. package/docs/specs/SDS-005-knowledge-graph-module.md +364 -0
  132. package/docs/specs/SDS-006-calm-integration.md +367 -0
  133. package/docs/specs/SDS-007-sbvr-import.md +347 -0
  134. package/docs/templates/template_explanation.md +14 -0
  135. package/docs/templates/template_howto.md +21 -0
  136. package/docs/templates/template_playbook.md +21 -0
  137. package/docs/templates/template_reference.md +17 -0
  138. package/docs/templates/template_tutorial.md +24 -0
  139. package/docs/tutorials/README.md +12 -0
  140. package/docs/tutorials/first-sea-model.md +85 -0
  141. package/docs/tutorials/getting-started.md +98 -0
  142. package/docs/tutorials/python-binding-quickstart.md +107 -0
  143. package/docs/tutorials/typescript-binding-quickstart.md +91 -0
  144. package/docs/tutorials/wasm-in-browser.md +75 -0
  145. package/domainforge-core/CHANGELOG.md +138 -0
  146. package/domainforge-core/Cargo.toml +101 -0
  147. package/domainforge-core/MIGRATING.md +32 -0
  148. package/domainforge-core/README.md +197 -0
  149. package/domainforge-core/benchmark_results.txt +51 -0
  150. package/domainforge-core/build.rs +6 -0
  151. package/domainforge-core/deny.toml +31 -0
  152. package/domainforge-core/docs/specs/projections/sbvr_kg_mapping.md +43 -0
  153. package/domainforge-core/examples/basic.sea +7 -0
  154. package/domainforge-core/examples/cli/import_export_workflow.sh +38 -0
  155. package/domainforge-core/examples/cli/validate_example.sh +30 -0
  156. package/domainforge-core/examples/evolution_semantics.sea +31 -0
  157. package/domainforge-core/examples/parser_demo.rs +203 -0
  158. package/domainforge-core/grammar/sea.pest +408 -0
  159. package/domainforge-core/schemas/calm-v1.schema.json +170 -0
  160. package/domainforge-core/schemas/shacl/sea_shapes.ttl +19 -0
  161. package/domainforge-core/src/authority/compiler.rs +309 -0
  162. package/domainforge-core/src/authority/environment.rs +203 -0
  163. package/domainforge-core/src/authority/error.rs +164 -0
  164. package/domainforge-core/src/authority/fact_resolver.rs +224 -0
  165. package/domainforge-core/src/authority/mod.rs +25 -0
  166. package/domainforge-core/src/authority/pack.rs +133 -0
  167. package/domainforge-core/src/authority/policy.rs +224 -0
  168. package/domainforge-core/src/authority/resolver.rs +446 -0
  169. package/domainforge-core/src/authority/trace.rs +217 -0
  170. package/domainforge-core/src/authority/transform.rs +168 -0
  171. package/domainforge-core/src/authority/types.rs +617 -0
  172. package/domainforge-core/src/bin/domainforge.rs +25 -0
  173. package/domainforge-core/src/calm/export.rs +538 -0
  174. package/domainforge-core/src/calm/import.rs +1220 -0
  175. package/domainforge-core/src/calm/mod.rs +9 -0
  176. package/domainforge-core/src/calm/models.rs +108 -0
  177. package/domainforge-core/src/calm/sbvr_import.rs +9 -0
  178. package/domainforge-core/src/cli/authority.rs +149 -0
  179. package/domainforge-core/src/cli/format.rs +85 -0
  180. package/domainforge-core/src/cli/import.rs +133 -0
  181. package/domainforge-core/src/cli/mod.rs +64 -0
  182. package/domainforge-core/src/cli/normalize.rs +180 -0
  183. package/domainforge-core/src/cli/pack.rs +904 -0
  184. package/domainforge-core/src/cli/parse.rs +112 -0
  185. package/domainforge-core/src/cli/project.rs +294 -0
  186. package/domainforge-core/src/cli/registry.rs +41 -0
  187. package/domainforge-core/src/cli/test.rs +12 -0
  188. package/domainforge-core/src/cli/validate.rs +195 -0
  189. package/domainforge-core/src/cli/validate_kg.rs +80 -0
  190. package/domainforge-core/src/concept_id.rs +89 -0
  191. package/domainforge-core/src/error/diagnostics.rs +426 -0
  192. package/domainforge-core/src/error/fuzzy.rs +253 -0
  193. package/domainforge-core/src/error/mod.rs +13 -0
  194. package/domainforge-core/src/formatter/comments.rs +223 -0
  195. package/domainforge-core/src/formatter/config.rs +114 -0
  196. package/domainforge-core/src/formatter/mod.rs +22 -0
  197. package/domainforge-core/src/formatter/printer.rs +906 -0
  198. package/domainforge-core/src/graph/mod.rs +858 -0
  199. package/domainforge-core/src/graph/to_ast.rs +66 -0
  200. package/domainforge-core/src/kg.rs +1476 -0
  201. package/domainforge-core/src/kg_import.rs +251 -0
  202. package/domainforge-core/src/lib.rs +203 -0
  203. package/domainforge-core/src/module/mod.rs +1 -0
  204. package/domainforge-core/src/module/resolver.rs +260 -0
  205. package/domainforge-core/src/parser/ast.rs +2919 -0
  206. package/domainforge-core/src/parser/ast_convert.rs +494 -0
  207. package/domainforge-core/src/parser/ast_schema.rs +491 -0
  208. package/domainforge-core/src/parser/error.rs +291 -0
  209. package/domainforge-core/src/parser/lint.rs +39 -0
  210. package/domainforge-core/src/parser/mod.rs +193 -0
  211. package/domainforge-core/src/parser/printer.rs +702 -0
  212. package/domainforge-core/src/parser/profiles.rs +71 -0
  213. package/domainforge-core/src/parser/string_utils.rs +138 -0
  214. package/domainforge-core/src/patterns.rs +68 -0
  215. package/domainforge-core/src/policy/core.rs +1148 -0
  216. package/domainforge-core/src/policy/expression.rs +399 -0
  217. package/domainforge-core/src/policy/mod.rs +18 -0
  218. package/domainforge-core/src/policy/normalize.rs +1028 -0
  219. package/domainforge-core/src/policy/quantifier.rs +940 -0
  220. package/domainforge-core/src/policy/three_valued.rs +140 -0
  221. package/domainforge-core/src/policy/three_valued_microbench.rs +104 -0
  222. package/domainforge-core/src/policy/type_inference.rs +67 -0
  223. package/domainforge-core/src/policy/violation.rs +36 -0
  224. package/domainforge-core/src/primitives/concept_change.rs +61 -0
  225. package/domainforge-core/src/primitives/entity.rs +224 -0
  226. package/domainforge-core/src/primitives/flow.rs +111 -0
  227. package/domainforge-core/src/primitives/instance.rs +93 -0
  228. package/domainforge-core/src/primitives/mapping_contract.rs +50 -0
  229. package/domainforge-core/src/primitives/metric.rs +79 -0
  230. package/domainforge-core/src/primitives/mod.rs +25 -0
  231. package/domainforge-core/src/primitives/projection_contract.rs +50 -0
  232. package/domainforge-core/src/primitives/quantity.rs +56 -0
  233. package/domainforge-core/src/primitives/relation.rs +68 -0
  234. package/domainforge-core/src/primitives/resource.rs +237 -0
  235. package/domainforge-core/src/primitives/resource_instance.rs +88 -0
  236. package/domainforge-core/src/primitives/role.rs +49 -0
  237. package/domainforge-core/src/projection/buf.rs +404 -0
  238. package/domainforge-core/src/projection/contracts.rs +22 -0
  239. package/domainforge-core/src/projection/engine.rs +19 -0
  240. package/domainforge-core/src/projection/mod.rs +16 -0
  241. package/domainforge-core/src/projection/protobuf.rs +3331 -0
  242. package/domainforge-core/src/projection/registry.rs +43 -0
  243. package/domainforge-core/src/python/authority.rs +253 -0
  244. package/domainforge-core/src/python/error.rs +227 -0
  245. package/domainforge-core/src/python/formatter.rs +86 -0
  246. package/domainforge-core/src/python/graph.rs +366 -0
  247. package/domainforge-core/src/python/mod.rs +9 -0
  248. package/domainforge-core/src/python/policy.rs +651 -0
  249. package/domainforge-core/src/python/primitives.rs +796 -0
  250. package/domainforge-core/src/python/registry.rs +98 -0
  251. package/domainforge-core/src/python/semantic_pack.rs +619 -0
  252. package/domainforge-core/src/python/units.rs +96 -0
  253. package/domainforge-core/src/registry/mod.rs +432 -0
  254. package/domainforge-core/src/registry/tests.rs +210 -0
  255. package/domainforge-core/src/sbvr.rs +744 -0
  256. package/domainforge-core/src/semantic_pack/builder.rs +470 -0
  257. package/domainforge-core/src/semantic_pack/canonical_json.rs +184 -0
  258. package/domainforge-core/src/semantic_pack/diagnostics.rs +214 -0
  259. package/domainforge-core/src/semantic_pack/diff.rs +216 -0
  260. package/domainforge-core/src/semantic_pack/mod.rs +31 -0
  261. package/domainforge-core/src/semantic_pack/pack_set.rs +240 -0
  262. package/domainforge-core/src/semantic_pack/resolver.rs +437 -0
  263. package/domainforge-core/src/semantic_pack/review.rs +125 -0
  264. package/domainforge-core/src/semantic_pack/schema.rs +342 -0
  265. package/domainforge-core/src/semantic_pack/signing.rs +105 -0
  266. package/domainforge-core/src/semantic_pack/validator.rs +368 -0
  267. package/domainforge-core/src/semantic_version.rs +140 -0
  268. package/domainforge-core/src/test_utils.rs +12 -0
  269. package/domainforge-core/src/typescript/authority.rs +184 -0
  270. package/domainforge-core/src/typescript/error.rs +146 -0
  271. package/domainforge-core/src/typescript/formatter.rs +76 -0
  272. package/domainforge-core/src/typescript/graph.rs +391 -0
  273. package/domainforge-core/src/typescript/mod.rs +9 -0
  274. package/domainforge-core/src/typescript/policy.rs +564 -0
  275. package/domainforge-core/src/typescript/primitives.rs +784 -0
  276. package/domainforge-core/src/typescript/registry.rs +88 -0
  277. package/domainforge-core/src/typescript/semantic_pack.rs +470 -0
  278. package/domainforge-core/src/typescript/units.rs +76 -0
  279. package/domainforge-core/src/units/mod.rs +462 -0
  280. package/domainforge-core/src/uuid_module.rs +42 -0
  281. package/domainforge-core/src/validation_error.rs +818 -0
  282. package/domainforge-core/src/validation_result.rs +30 -0
  283. package/domainforge-core/src/wasm/authority.rs +192 -0
  284. package/domainforge-core/src/wasm/error.rs +145 -0
  285. package/domainforge-core/src/wasm/formatter.rs +69 -0
  286. package/domainforge-core/src/wasm/graph.rs +471 -0
  287. package/domainforge-core/src/wasm/mod.rs +16 -0
  288. package/domainforge-core/src/wasm/policy.rs +607 -0
  289. package/domainforge-core/src/wasm/primitives.rs +295 -0
  290. package/domainforge-core/src/wasm/semantic_pack.rs +471 -0
  291. package/domainforge-core/src/wasm/units.rs +62 -0
  292. package/domainforge-core/std/aws.sea +6 -0
  293. package/domainforge-core/std/core.sea +6 -0
  294. package/domainforge-core/std/http.sea +27 -0
  295. package/domainforge-core/tests/aggregation_enhanced_tests.rs +162 -0
  296. package/domainforge-core/tests/aggregation_eval_tests.rs +248 -0
  297. package/domainforge-core/tests/aggregation_integration_tests.rs +379 -0
  298. package/domainforge-core/tests/aggregation_parser_tests.rs +92 -0
  299. package/domainforge-core/tests/aggregation_tests.rs +102 -0
  300. package/domainforge-core/tests/authority_conformance_tests.rs +1173 -0
  301. package/domainforge-core/tests/calm_round_trip_tests.rs +283 -0
  302. package/domainforge-core/tests/calm_schema_validation_tests.rs +137 -0
  303. package/domainforge-core/tests/cast_operator_tests.rs +85 -0
  304. package/domainforge-core/tests/cli_binary_check.rs +37 -0
  305. package/domainforge-core/tests/cli_import_tests.rs +291 -0
  306. package/domainforge-core/tests/cli_path_traversal_tests.rs +124 -0
  307. package/domainforge-core/tests/cli_tests.rs +63 -0
  308. package/domainforge-core/tests/diagnostics_tests.rs +203 -0
  309. package/domainforge-core/tests/dimension_unit_tests.rs +80 -0
  310. package/domainforge-core/tests/entity_tests.rs +69 -0
  311. package/domainforge-core/tests/evolution_semantics_tests.rs +157 -0
  312. package/domainforge-core/tests/flow_tests.rs +78 -0
  313. package/domainforge-core/tests/flow_unit_validation_tests.rs +31 -0
  314. package/domainforge-core/tests/graph_integration_tests.rs +218 -0
  315. package/domainforge-core/tests/graph_tests.rs +626 -0
  316. package/domainforge-core/tests/import_parsing_tests.rs +23 -0
  317. package/domainforge-core/tests/instance_integration_tests.rs +98 -0
  318. package/domainforge-core/tests/instance_parsing_tests.rs +58 -0
  319. package/domainforge-core/tests/instance_tests.rs +61 -0
  320. package/domainforge-core/tests/kg_uri_encoding_tests.rs +53 -0
  321. package/domainforge-core/tests/lint_tests.rs +19 -0
  322. package/domainforge-core/tests/metric_tests.rs +143 -0
  323. package/domainforge-core/tests/module_resolution_tests.rs +100 -0
  324. package/domainforge-core/tests/namespace_registry_tests.rs +247 -0
  325. package/domainforge-core/tests/null_handling_tests.rs +26 -0
  326. package/domainforge-core/tests/parser_ast_v3.rs +53 -0
  327. package/domainforge-core/tests/parser_dimension_registry_tests.rs +20 -0
  328. package/domainforge-core/tests/parser_integration_tests.rs +294 -0
  329. package/domainforge-core/tests/parser_metadata_tests.rs +97 -0
  330. package/domainforge-core/tests/parser_resource_domain_only_graph_test.rs +21 -0
  331. package/domainforge-core/tests/parser_resource_limits_tests.rs +122 -0
  332. package/domainforge-core/tests/parser_tests.rs +512 -0
  333. package/domainforge-core/tests/pattern_semantics_tests.rs +87 -0
  334. package/domainforge-core/tests/phase_14_determinism_tests.rs +166 -0
  335. package/domainforge-core/tests/phase_15_validation_error_tests.rs +136 -0
  336. package/domainforge-core/tests/phase_16_unicode_tests.rs +248 -0
  337. package/domainforge-core/tests/phase_17_export_tests.rs +285 -0
  338. package/domainforge-core/tests/phase_17_round_trip_tests.rs +264 -0
  339. package/domainforge-core/tests/policy_tests.rs +635 -0
  340. package/domainforge-core/tests/primitives_integration_tests.rs +151 -0
  341. package/domainforge-core/tests/print_rdf_xml.rs +14 -0
  342. package/domainforge-core/tests/printer_tests.rs +204 -0
  343. package/domainforge-core/tests/profile_tests.rs +35 -0
  344. package/domainforge-core/tests/projection_contracts_tests.rs +154 -0
  345. package/domainforge-core/tests/protobuf_projection_tests.rs +199 -0
  346. package/domainforge-core/tests/quantity_tests.rs +41 -0
  347. package/domainforge-core/tests/rdf_xml_typed_literal_tests.rs +105 -0
  348. package/domainforge-core/tests/registry_schema_tests.rs +33 -0
  349. package/domainforge-core/tests/resource_tests.rs +50 -0
  350. package/domainforge-core/tests/resource_unit_tests.rs +24 -0
  351. package/domainforge-core/tests/roles_relations_tests.rs +61 -0
  352. package/domainforge-core/tests/round_trip_tests.rs +34 -0
  353. package/domainforge-core/tests/runtime_toggle_tests.rs +70 -0
  354. package/domainforge-core/tests/sbvr_fact_schema_tests.rs +60 -0
  355. package/domainforge-core/tests/sbvr_flow_facts_tests.rs +55 -0
  356. package/domainforge-core/tests/sbvr_parsing_tests.rs +53 -0
  357. package/domainforge-core/tests/semantic_pack_alias_resolution.rs +197 -0
  358. package/domainforge-core/tests/semantic_pack_build.rs +302 -0
  359. package/domainforge-core/tests/semantic_pack_consumer_smoke.rs +150 -0
  360. package/domainforge-core/tests/semantic_pack_pack_set.rs +160 -0
  361. package/domainforge-core/tests/semantic_pack_signing.rs +157 -0
  362. package/domainforge-core/tests/semantic_pack_three_valued.rs +250 -0
  363. package/domainforge-core/tests/semantic_pack_validate.rs +196 -0
  364. package/domainforge-core/tests/std_lib_tests.rs +37 -0
  365. package/domainforge-core/tests/temporal_evaluation_tests.rs +159 -0
  366. package/domainforge-core/tests/temporal_semantics_tests.rs +214 -0
  367. package/domainforge-core/tests/three_valued_quantifiers_tests.rs +164 -0
  368. package/domainforge-core/tests/turtle_entity_export_tests.rs +38 -0
  369. package/domainforge-core/tests/turtle_escaping_tests.rs +53 -0
  370. package/domainforge-core/tests/turtle_resource_export_tests.rs +34 -0
  371. package/domainforge-core/tests/type_inference_tests.rs +40 -0
  372. package/domainforge-core/tests/unicode_validation_tests.rs +169 -0
  373. package/domainforge-core/tests/unit_tests.rs +81 -0
  374. package/domainforge-core/tests/validate_tests.rs +38 -0
  375. package/domainforge-core/tests/validation_unit_mismatch_tests.rs +83 -0
  376. package/domainforge-core/tests/wasm_tests.rs +229 -0
  377. package/domainforge-python/CHANGELOG-python.md +12 -0
  378. package/domainforge-python/MIGRATING.md +24 -0
  379. package/domainforge-python/README.md +256 -0
  380. package/domainforge-python/domainforge/__init__.py +95 -0
  381. package/domainforge-python/domainforge/domainforge.pyi +519 -0
  382. package/domainforge-python/pyproject.toml +36 -0
  383. package/domainforge-typescript/CHANGELOG-typescript.md +12 -0
  384. package/domainforge-typescript/LICENSE +201 -0
  385. package/domainforge-typescript/MIGRATING.md +24 -0
  386. package/domainforge-typescript/README.md +305 -0
  387. package/domainforge-typescript/index.d.ts +452 -0
  388. package/domainforge-typescript/index.js +361 -0
  389. package/domainforge-typescript/package.json +60 -0
  390. package/example.js +61 -0
  391. package/examples/browser.html +366 -0
  392. package/examples/namespaces/finance/cashflow.sea +5 -0
  393. package/examples/namespaces/logistics/core.sea +7 -0
  394. package/examples/observability_metrics.sea +38 -0
  395. package/fixtures/semantic_packs/acme_procurement/domain/entities.sea +39 -0
  396. package/fixtures/semantic_packs/acme_procurement/domain/metrics.sea +11 -0
  397. package/fixtures/semantic_packs/acme_procurement/domain/relations.sea +7 -0
  398. package/fixtures/semantic_packs/acme_procurement/domain/resources.sea +9 -0
  399. package/fixtures/semantic_packs/acme_procurement/review/acme.procurement.semantic-review.jsonl +7 -0
  400. package/fixtures/semantic_packs/acme_procurement/tests/ambiguous_vendor_alias.sea +8 -0
  401. package/fixtures/semantic_packs/acme_procurement/tests/deprecated_vendor_alias.sea +8 -0
  402. package/fixtures/semantic_packs/acme_procurement/tests/invalid_relation.sea +3 -0
  403. package/fixtures/semantic_packs/acme_procurement/tests/proposed_concept.sea +8 -0
  404. package/fixtures/semantic_packs/acme_procurement/tests/rejected_concept.sea +8 -0
  405. package/fixtures/semantic_packs/acme_procurement/tests/unit_mismatch.sea +7 -0
  406. package/fixtures/semantic_packs/acme_procurement/tests/unknown_vendor_policy.sea +8 -0
  407. package/fixtures/semantic_packs/acme_procurement/tests/valid_purchase_policy.sea +8 -0
  408. package/index.d.ts +2 -0
  409. package/index.js +8 -0
  410. package/justfile +200 -0
  411. package/lefthook.yml +13 -0
  412. package/lib/validate_native_exports.d.ts +4 -0
  413. package/lib/validate_native_exports.js +12 -0
  414. package/package.json +22 -0
  415. package/pytest.ini +5 -0
  416. package/python/tests/test_registry.py +75 -0
  417. package/python/tests/test_units.py +18 -0
  418. package/release-please-config.json +49 -0
  419. package/requirements-dev.txt +3 -0
  420. package/requirements.txt +3 -0
  421. package/rust-toolchain.toml +3 -0
  422. package/schemas/ast-v1.schema.json +72 -0
  423. package/schemas/ast-v2.schema.json +1200 -0
  424. package/schemas/ast-v3.schema.json +1200 -0
  425. package/schemas/sea-registry.schema.json +45 -0
  426. package/scripts/build-python.sh +37 -0
  427. package/scripts/build-release.sh +279 -0
  428. package/scripts/build-typescript.sh +13 -0
  429. package/scripts/build-wasm.sh +113 -0
  430. package/scripts/bump-version.sh +245 -0
  431. package/scripts/check_unused_test_imports.py +85 -0
  432. package/scripts/ci_tasks.py +379 -0
  433. package/scripts/clear_debug_test.sh +10 -0
  434. package/scripts/create-github-release.sh +262 -0
  435. package/scripts/create-tag.sh +203 -0
  436. package/scripts/find_and_link_test_binary.sh +70 -0
  437. package/scripts/generate-changelog.sh +271 -0
  438. package/scripts/generate-release-notes.sh +205 -0
  439. package/scripts/lint_release_security.py +96 -0
  440. package/scripts/lint_release_workflows.py +82 -0
  441. package/scripts/lint_workflow_gates.py +113 -0
  442. package/scripts/optimized-wasm-build.sh +61 -0
  443. package/scripts/patch_napi_types.py +62 -0
  444. package/scripts/pre-release-check.sh +289 -0
  445. package/scripts/prepare_rust_debug.sh +52 -0
  446. package/scripts/release.sh +373 -0
  447. package/scripts/resolve_rust_binary.py +230 -0
  448. package/scripts/run_commitlint.sh +29 -0
  449. package/scripts/test-all.sh +77 -0
  450. package/scripts/update_launch_program.py +93 -0
  451. package/secrets/README.md +27 -0
  452. package/secrets/secrets.yaml +21 -0
  453. package/test_integration.py +67 -0
  454. package/tests/test_authority.py +328 -0
  455. package/tests/test_ci_tasks.py +143 -0
  456. package/tests/test_expression.py +256 -0
  457. package/tests/test_golden_payment_flow.py +42 -0
  458. package/tests/test_graph.py +127 -0
  459. package/tests/test_instance.py +136 -0
  460. package/tests/test_parser.py +82 -0
  461. package/tests/test_primitives.py +68 -0
  462. package/tests/test_role_relation_parity.py +56 -0
  463. package/tests/test_runtime_toggle.py +156 -0
  464. package/tests/test_semantic_pack.py +639 -0
  465. package/tests/test_three_valued_eval.py +159 -0
  466. package/tsconfig.json +30 -0
  467. package/typescript-tests/advanced.test.ts +165 -0
  468. package/typescript-tests/authority.test.ts +216 -0
  469. package/typescript-tests/expression.test.ts +228 -0
  470. package/typescript-tests/golden-payment-flow.test.ts +51 -0
  471. package/typescript-tests/graph.test.ts +142 -0
  472. package/typescript-tests/native-binding.test.ts +20 -0
  473. package/typescript-tests/primitives.test.ts +88 -0
  474. package/typescript-tests/registry.test.ts +122 -0
  475. package/typescript-tests/role_relation.test.ts +63 -0
  476. package/typescript-tests/runtime_toggle.test.ts +141 -0
  477. package/typescript-tests/semantic-pack.test.ts +556 -0
  478. package/typescript-tests/three_valued_eval.test.ts +135 -0
  479. package/typescript-tests/units.test.ts +36 -0
  480. package/vitest.config.ts +13 -0
  481. package/wasm_demo.html +225 -0
@@ -0,0 +1,159 @@
1
+ """
2
+ Test three-valued logic evaluation semantics for policy evaluation.
3
+
4
+ This test validates that the EvaluationResult correctly handles:
5
+ - True evaluations (policy satisfied)
6
+ - False evaluations (policy violated)
7
+ - Null evaluations (policy evaluation unknown/indeterminate)
8
+ """
9
+
10
+ import json
11
+ import pytest
12
+ from domainforge import Graph, EvaluationResult, Severity
13
+
14
+
15
+ def test_policy_evaluates_to_true():
16
+ """Test that a satisfied policy returns is_satisfied=True and tristate=True."""
17
+ graph = Graph()
18
+
19
+ # Create a simple policy that always evaluates to true
20
+ policy = {
21
+ "id": "00000000-0000-0000-0000-000000000001",
22
+ "name": "AlwaysTrue",
23
+ "namespace": "test",
24
+ "version": {"major": 1, "minor": 0, "patch": 0},
25
+ "expression": {"Literal": True},
26
+ "modality": "Obligation",
27
+ "kind": "Constraint",
28
+ "priority": 0,
29
+ "rationale": None,
30
+ "tags": [],
31
+ }
32
+
33
+ result = graph.evaluate_policy(json.dumps(policy))
34
+
35
+ assert isinstance(result, EvaluationResult)
36
+ assert result.is_satisfied is True
37
+ assert result.is_satisfied_tristate is True
38
+ assert len(result.violations) == 0
39
+
40
+
41
+ def test_policy_evaluates_to_false():
42
+ """Test that a violated policy returns is_satisfied=False and tristate=False."""
43
+ graph = Graph()
44
+
45
+ # Create a simple policy that always evaluates to false
46
+ policy = {
47
+ "id": "00000000-0000-0000-0000-000000000002",
48
+ "name": "AlwaysFalse",
49
+ "namespace": "test",
50
+ "version": {"major": 1, "minor": 0, "patch": 0},
51
+ "expression": {"Literal": False},
52
+ "modality": "Obligation",
53
+ "kind": "Constraint",
54
+ "priority": 0,
55
+ "rationale": None,
56
+ "tags": [],
57
+ }
58
+
59
+ result = graph.evaluate_policy(json.dumps(policy))
60
+
61
+ assert isinstance(result, EvaluationResult)
62
+ assert result.is_satisfied is False
63
+ assert result.is_satisfied_tristate is False
64
+ assert len(result.violations) == 1
65
+ assert result.violations[0].name == "AlwaysFalse"
66
+ assert result.violations[0].severity == Severity.Error
67
+
68
+
69
+ def test_policy_evaluates_to_null():
70
+ """Test that an unknown/null policy evaluation returns is_satisfied=False and tristate=None."""
71
+ graph = Graph()
72
+
73
+ # Create a policy that references a non-existent entity attribute
74
+ # This should evaluate to NULL when three_valued_logic feature is enabled
75
+ policy = {
76
+ "id": "00000000-0000-0000-0000-000000000003",
77
+ "name": "NullEvaluation",
78
+ "namespace": "test",
79
+ "version": {"major": 1, "minor": 0, "patch": 0},
80
+ "expression": {
81
+ "MemberAccess": {"object": "NonExistentEntity", "member": "someAttribute"}
82
+ },
83
+ "modality": "Obligation",
84
+ "kind": "Constraint",
85
+ "priority": 0,
86
+ "rationale": None,
87
+ "tags": [],
88
+ }
89
+
90
+ result = graph.evaluate_policy(json.dumps(policy))
91
+
92
+ assert isinstance(result, EvaluationResult)
93
+ # When evaluation is NULL, is_satisfied defaults to False for backwards compatibility
94
+ assert result.is_satisfied is False
95
+ # The tristate field should be None to indicate unknown/NULL
96
+ assert result.is_satisfied_tristate is None
97
+ # Violation severity follows the policy modality even when evaluation is NULL
98
+ assert len(result.violations) == 1
99
+ assert (
100
+ "UNKNOWN" in result.violations[0].message
101
+ or "NULL" in result.violations[0].message
102
+ )
103
+ assert result.violations[0].severity == Severity.Error
104
+
105
+
106
+ def test_evaluation_result_repr():
107
+ """Test that EvaluationResult has a useful string representation."""
108
+ graph = Graph()
109
+
110
+ policy = {
111
+ "id": "00000000-0000-0000-0000-000000000004",
112
+ "name": "TestPolicy",
113
+ "namespace": "test",
114
+ "version": {"major": 1, "minor": 0, "patch": 0},
115
+ "expression": {"Literal": True},
116
+ "modality": "Obligation",
117
+ "kind": "Constraint",
118
+ "priority": 0,
119
+ "rationale": None,
120
+ "tags": [],
121
+ }
122
+
123
+ result = graph.evaluate_policy(json.dumps(policy))
124
+ repr_str = repr(result)
125
+
126
+ assert "EvaluationResult" in repr_str
127
+ assert "is_satisfied" in repr_str
128
+ assert "violations" in repr_str
129
+
130
+
131
+ def test_violation_repr():
132
+ """Test that Violation has a useful string representation."""
133
+ graph = Graph()
134
+
135
+ policy = {
136
+ "id": "00000000-0000-0000-0000-000000000005",
137
+ "name": "ViolatedPolicy",
138
+ "namespace": "test",
139
+ "version": {"major": 1, "minor": 0, "patch": 0},
140
+ "expression": {"Literal": False},
141
+ "modality": "Prohibition",
142
+ "kind": "Constraint",
143
+ "priority": 0,
144
+ "rationale": None,
145
+ "tags": [],
146
+ }
147
+
148
+ result = graph.evaluate_policy(json.dumps(policy))
149
+
150
+ assert len(result.violations) > 0
151
+ violation = result.violations[0]
152
+ repr_str = repr(violation)
153
+
154
+ assert "Violation" in repr_str
155
+ assert "ViolatedPolicy" in repr_str
156
+
157
+
158
+ if __name__ == "__main__":
159
+ pytest.main([__file__, "-v"])
package/tsconfig.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": [
7
+ "ES2020"
8
+ ],
9
+ "declaration": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./",
12
+ "strict": true,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "resolveJsonModule": true,
17
+ "types": [
18
+ "node",
19
+ "bun-types",
20
+ "vitest/globals"
21
+ ]
22
+ },
23
+ "include": [
24
+ "typescript-tests/**/*.ts"
25
+ ],
26
+ "exclude": [
27
+ "node_modules",
28
+ "dist"
29
+ ]
30
+ }
@@ -0,0 +1,165 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Entity, Flow, ResourceInstance, Resource } from '../index';
3
+
4
+ describe('Instance Advanced Features', () => {
5
+ it('creates instance with namespace', () => {
6
+ const entity = new Entity('Warehouse', 'logistics');
7
+ const resource = new Resource('Camera', 'units', 'inventory');
8
+
9
+ const instance = new ResourceInstance(resource.id, entity.id, 'inventory');
10
+ expect(instance.namespace).toBe('inventory');
11
+ });
12
+
13
+ it('manages instance attributes', () => {
14
+ const entity = new Entity('Warehouse');
15
+ const resource = new Resource('Camera', 'units');
16
+ const instance = new ResourceInstance(resource.id, entity.id);
17
+
18
+ instance.setAttribute('serial_number', JSON.stringify('CAM-12345'));
19
+ expect(JSON.parse(instance.getAttribute('serial_number')!)).toBe('CAM-12345');
20
+ });
21
+
22
+ it('handles complex instance metadata', () => {
23
+ const entity = new Entity('Warehouse');
24
+ const resource = new Resource('Camera', 'units');
25
+ const instance = new ResourceInstance(resource.id, entity.id);
26
+
27
+ const metadata = {
28
+ serial: 'CAM-12345',
29
+ manufactured: '2025-01-15',
30
+ warranty_expires: '2027-01-15',
31
+ specifications: {
32
+ resolution: '4K',
33
+ fps: 60
34
+ }
35
+ };
36
+
37
+ instance.setAttribute('metadata', JSON.stringify(metadata));
38
+ const retrieved = JSON.parse(instance.getAttribute('metadata')!);
39
+ expect(retrieved.serial).toBe('CAM-12345');
40
+ expect(retrieved.specifications.resolution).toBe('4K');
41
+ });
42
+ });
43
+
44
+ describe('Attribute Edge Cases', () => {
45
+ it('handles null attribute retrieval', () => {
46
+ const entity = new Entity('Test');
47
+ const attr = entity.getAttribute('nonexistent');
48
+ expect(attr).toBeNull();
49
+ });
50
+
51
+ it('handles empty string attributes', () => {
52
+ const entity = new Entity('Test');
53
+ entity.setAttribute('empty', JSON.stringify(''));
54
+ expect(JSON.parse(entity.getAttribute('empty')!)).toBe('');
55
+ });
56
+
57
+ it('handles numeric attributes', () => {
58
+ const resource = new Resource('Item', 'units');
59
+ resource.setAttribute('quantity', JSON.stringify(42));
60
+ resource.setAttribute('price', JSON.stringify(99.99));
61
+
62
+ expect(JSON.parse(resource.getAttribute('quantity')!)).toBe(42);
63
+ expect(JSON.parse(resource.getAttribute('price')!)).toBe(99.99);
64
+ });
65
+
66
+ it('handles boolean attributes', () => {
67
+ const entity = new Entity('Warehouse');
68
+ entity.setAttribute('active', JSON.stringify(true));
69
+ entity.setAttribute('requires_signature', JSON.stringify(false));
70
+
71
+ expect(JSON.parse(entity.getAttribute('active')!)).toBe(true);
72
+ expect(JSON.parse(entity.getAttribute('requires_signature')!)).toBe(false);
73
+ });
74
+
75
+ it('handles array attributes', () => {
76
+ const entity = new Entity('Warehouse');
77
+ const zones = ['A1', 'A2', 'B1', 'B2'];
78
+ entity.setAttribute('zones', JSON.stringify(zones));
79
+
80
+ const retrieved = JSON.parse(entity.getAttribute('zones')!);
81
+ expect(retrieved).toEqual(zones);
82
+ expect(retrieved.length).toBe(4);
83
+ });
84
+ });
85
+
86
+ describe('Flow Attributes', () => {
87
+ it('manages flow attributes', () => {
88
+ const entity1 = new Entity('Warehouse');
89
+ const entity2 = new Entity('Factory');
90
+ const resource = new Resource('Cameras', 'units');
91
+
92
+ const flow = new Flow(resource.id, entity1.id, entity2.id, 100);
93
+ flow.setAttribute('priority', JSON.stringify('high'));
94
+ flow.setAttribute('scheduled_date', JSON.stringify('2025-12-01'));
95
+
96
+ expect(JSON.parse(flow.getAttribute('priority')!)).toBe('high');
97
+ expect(JSON.parse(flow.getAttribute('scheduled_date')!)).toBe('2025-12-01');
98
+ });
99
+
100
+ it('handles decimal quantities correctly', () => {
101
+ const entity1 = new Entity('Warehouse');
102
+ const entity2 = new Entity('Factory');
103
+ const resource = new Resource('Steel', 'kg');
104
+
105
+ const flow = new Flow(resource.id, entity1.id, entity2.id, 1250.75);
106
+ expect(flow.quantity).toBeCloseTo(1250.75, 2);
107
+ });
108
+ });
109
+
110
+ describe('UUID Validation', () => {
111
+ it('accepts valid UUIDs', () => {
112
+ const validUuid = '550e8400-e29b-41d4-a716-446655440000';
113
+ const entity1 = new Entity('Test1');
114
+ const entity2 = new Entity('Test2');
115
+
116
+ // This should not throw
117
+ expect(() => {
118
+ new Flow(validUuid, entity1.id, entity2.id, 100);
119
+ }).not.toThrow();
120
+ });
121
+
122
+ it('rejects malformed UUIDs', () => {
123
+ expect(() => {
124
+ new Flow('not-a-uuid', 'also-not', 'still-not', 100);
125
+ }).toThrow();
126
+ });
127
+
128
+ it('rejects empty string UUIDs', () => {
129
+ expect(() => {
130
+ new Flow('', '', '', 100);
131
+ }).toThrow();
132
+ });
133
+ });
134
+
135
+ describe('Namespace Handling', () => {
136
+ it('entities without namespace have null namespace', () => {
137
+ const entity = new Entity('Test');
138
+ expect(entity.namespace).toBeNull();
139
+ });
140
+
141
+ it('entities with namespace preserve it', () => {
142
+ const entity = new Entity('Test', 'domain');
143
+ expect(entity.namespace).toBe('domain');
144
+ });
145
+
146
+ it('resources without namespace have null namespace', () => {
147
+ const resource = new Resource('Item', 'units');
148
+ expect(resource.namespace).toBeNull();
149
+ });
150
+
151
+ it('resources with namespace preserve it', () => {
152
+ const resource = new Resource('Item', 'units', 'inventory');
153
+ expect(resource.namespace).toBe('inventory');
154
+ });
155
+
156
+ it('instances can have different namespace than resource/entity', () => {
157
+ const entity = new Entity('Warehouse', 'logistics');
158
+ const resource = new Resource('Camera', 'units', 'inventory');
159
+ const instance = new ResourceInstance(resource.id, entity.id, 'tracking');
160
+
161
+ expect(entity.namespace).toBe('logistics');
162
+ expect(resource.namespace).toBe('inventory');
163
+ expect(instance.namespace).toBe('tracking');
164
+ });
165
+ });
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Tests for the new Policy Authority API exports added in this PR.
3
+ *
4
+ * Covers:
5
+ * - Enum exports: FinalDecision, PolicyModality, SourceClass, ClaimLevel
6
+ * - Function: evaluateAuthority
7
+ */
8
+
9
+ import { describe, it, expect } from 'vitest';
10
+ import {
11
+ FinalDecision,
12
+ PolicyModality,
13
+ SourceClass,
14
+ ClaimLevel,
15
+ evaluateAuthority,
16
+ } from '../index.js';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Helpers
20
+ // ---------------------------------------------------------------------------
21
+
22
+ function makeMinimalConfigJson(packs: unknown[] = []): string {
23
+ return JSON.stringify({
24
+ resolver_semantics_version: '0.4',
25
+ specificity_profile: {
26
+ id: 'default',
27
+ dimensions: [],
28
+ scoring_rules: {},
29
+ hash: '',
30
+ },
31
+ unknown_handling: {
32
+ permission: { default: 'escalate' },
33
+ prohibition: { default: 'deny' },
34
+ obligation: { default: 'escalate' },
35
+ override_: { default: 'not_applicable' },
36
+ },
37
+ fact_sources: [],
38
+ fact_transforms: [],
39
+ authority_packs: packs,
40
+ strict_mode: false,
41
+ compatibility_lowering_version: '0.4',
42
+ resolver_version: '0.1',
43
+ });
44
+ }
45
+
46
+ function makeMinimalRequestJson(operation = 'TestAction', resourceType = 'Order'): string {
47
+ return JSON.stringify({
48
+ request_id: 'req-001',
49
+ actor: { id: 'user-1' },
50
+ operation,
51
+ resource: { type: resourceType },
52
+ context: {},
53
+ requested_at: '2026-06-07T00:00:00Z',
54
+ });
55
+ }
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // Enum value tests
59
+ // ---------------------------------------------------------------------------
60
+
61
+ describe('FinalDecision enum', () => {
62
+ it('exports Allow=0, Deny=1, Escalate=2, NotApplicable=3, Reject=4', () => {
63
+ expect(FinalDecision.Allow).toBe(0);
64
+ expect(FinalDecision.Deny).toBe(1);
65
+ expect(FinalDecision.Escalate).toBe(2);
66
+ expect(FinalDecision.NotApplicable).toBe(3);
67
+ expect(FinalDecision.Reject).toBe(4);
68
+ });
69
+
70
+ it('has exactly five members', () => {
71
+ const keys = Object.keys(FinalDecision).filter((k) => isNaN(Number(k)));
72
+ expect(keys).toHaveLength(5);
73
+ });
74
+ });
75
+
76
+ describe('PolicyModality enum', () => {
77
+ it('exports Permission=0, Prohibition=1, Obligation=2, Override=3', () => {
78
+ expect(PolicyModality.Permission).toBe(0);
79
+ expect(PolicyModality.Prohibition).toBe(1);
80
+ expect(PolicyModality.Obligation).toBe(2);
81
+ expect(PolicyModality.Override).toBe(3);
82
+ });
83
+
84
+ it('has exactly four members', () => {
85
+ const keys = Object.keys(PolicyModality).filter((k) => isNaN(Number(k)));
86
+ expect(keys).toHaveLength(4);
87
+ });
88
+ });
89
+
90
+ describe('SourceClass enum', () => {
91
+ it('exports all seven source class values', () => {
92
+ expect(SourceClass.CallerSupplied).toBe(0);
93
+ expect(SourceClass.RuntimeObserved).toBe(1);
94
+ expect(SourceClass.SystemOfRecord).toBe(2);
95
+ expect(SourceClass.Attested).toBe(3);
96
+ expect(SourceClass.ManualApproval).toBe(4);
97
+ expect(SourceClass.Derived).toBe(5);
98
+ expect(SourceClass.UnknownSource).toBe(6);
99
+ });
100
+
101
+ it('has exactly seven members', () => {
102
+ const keys = Object.keys(SourceClass).filter((k) => isNaN(Number(k)));
103
+ expect(keys).toHaveLength(7);
104
+ });
105
+ });
106
+
107
+ describe('ClaimLevel enum', () => {
108
+ it('exports AuditBacked=0, Validated=1, FormallyProven=2', () => {
109
+ expect(ClaimLevel.AuditBacked).toBe(0);
110
+ expect(ClaimLevel.Validated).toBe(1);
111
+ expect(ClaimLevel.FormallyProven).toBe(2);
112
+ });
113
+
114
+ it('has exactly three members', () => {
115
+ const keys = Object.keys(ClaimLevel).filter((k) => isNaN(Number(k)));
116
+ expect(keys).toHaveLength(3);
117
+ });
118
+ });
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // evaluateAuthority
122
+ // ---------------------------------------------------------------------------
123
+
124
+ describe('evaluateAuthority', () => {
125
+ it('is a function', () => {
126
+ expect(typeof evaluateAuthority).toBe('function');
127
+ });
128
+
129
+ it('throws on invalid config JSON', () => {
130
+ expect(() =>
131
+ evaluateAuthority('not valid json', makeMinimalRequestJson()),
132
+ ).toThrow();
133
+ });
134
+
135
+ it('throws on invalid request JSON', () => {
136
+ expect(() =>
137
+ evaluateAuthority(makeMinimalConfigJson(), 'not valid json'),
138
+ ).toThrow();
139
+ });
140
+
141
+ it('throws on invalid facts JSON', () => {
142
+ expect(() =>
143
+ evaluateAuthority(makeMinimalConfigJson(), makeMinimalRequestJson(), 'not valid json'),
144
+ ).toThrow();
145
+ });
146
+
147
+ it('returns an object with traceJson and decisionJson', () => {
148
+ const result = evaluateAuthority(makeMinimalConfigJson(), makeMinimalRequestJson());
149
+ expect(result).toHaveProperty('traceJson');
150
+ expect(result).toHaveProperty('decisionJson');
151
+ expect(typeof result.traceJson).toBe('string');
152
+ expect(typeof result.decisionJson).toBe('string');
153
+ });
154
+
155
+ it('traceJson and decisionJson are valid JSON strings', () => {
156
+ const result = evaluateAuthority(makeMinimalConfigJson(), makeMinimalRequestJson());
157
+ expect(() => JSON.parse(result.traceJson)).not.toThrow();
158
+ expect(() => JSON.parse(result.decisionJson)).not.toThrow();
159
+ });
160
+
161
+ it('returns not_applicable when no packs are configured', () => {
162
+ const result = evaluateAuthority(makeMinimalConfigJson([]), makeMinimalRequestJson());
163
+ const decision = JSON.parse(result.decisionJson);
164
+ // With no packs and no applicable policies, expect not_applicable
165
+ expect(decision).toHaveProperty('final_decision');
166
+ expect(decision.final_decision).toBe('not_applicable');
167
+ });
168
+
169
+ it('accepts optional facts JSON as a JSON array', () => {
170
+ const factsJson = JSON.stringify([]);
171
+ const result = evaluateAuthority(
172
+ makeMinimalConfigJson(),
173
+ makeMinimalRequestJson(),
174
+ factsJson,
175
+ );
176
+ expect(result).toHaveProperty('decisionJson');
177
+ });
178
+
179
+ it('decision contains a final_decision field', () => {
180
+ const result = evaluateAuthority(makeMinimalConfigJson(), makeMinimalRequestJson());
181
+ const decision = JSON.parse(result.decisionJson);
182
+ expect(decision).toHaveProperty('final_decision');
183
+ const validDecisions = ['allow', 'deny', 'escalate', 'not_applicable', 'reject'];
184
+ expect(validDecisions).toContain(decision.final_decision);
185
+ });
186
+
187
+ it('trace contains request_id matching the request', () => {
188
+ const result = evaluateAuthority(makeMinimalConfigJson(), makeMinimalRequestJson());
189
+ const trace = JSON.parse(result.traceJson);
190
+ // Trace should reference the request_id
191
+ const traceStr = JSON.stringify(trace);
192
+ expect(traceStr).toContain('req-001');
193
+ });
194
+
195
+ it('handles different operations in requests', () => {
196
+ const result1 = evaluateAuthority(
197
+ makeMinimalConfigJson(),
198
+ makeMinimalRequestJson('CreateOrder'),
199
+ );
200
+ const result2 = evaluateAuthority(
201
+ makeMinimalConfigJson(),
202
+ makeMinimalRequestJson('DeleteOrder'),
203
+ );
204
+ // Both should return valid results
205
+ expect(() => JSON.parse(result1.decisionJson)).not.toThrow();
206
+ expect(() => JSON.parse(result2.decisionJson)).not.toThrow();
207
+ });
208
+
209
+ it('two calls with identical input produce the same final_decision', () => {
210
+ const config = makeMinimalConfigJson();
211
+ const request = makeMinimalRequestJson();
212
+ const r1 = JSON.parse(evaluateAuthority(config, request).decisionJson);
213
+ const r2 = JSON.parse(evaluateAuthority(config, request).decisionJson);
214
+ expect(r1.final_decision).toBe(r2.final_decision);
215
+ });
216
+ });