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,617 @@
1
+ use chrono::{DateTime, Utc};
2
+ use once_cell::sync::Lazy;
3
+ use serde::{Deserialize, Serialize};
4
+ use std::collections::HashMap;
5
+ use std::fmt;
6
+
7
+ use crate::authority::error::AuthorityError;
8
+
9
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10
+ #[serde(rename_all = "snake_case")]
11
+ pub enum FinalDecision {
12
+ Allow,
13
+ Deny,
14
+ Escalate,
15
+ NotApplicable,
16
+ Reject,
17
+ }
18
+
19
+ impl FinalDecision {
20
+ pub fn precedence_rank(&self) -> u8 {
21
+ match self {
22
+ Self::Reject => 5,
23
+ Self::Deny => 4,
24
+ Self::Escalate => 3,
25
+ Self::Allow => 2,
26
+ Self::NotApplicable => 1,
27
+ }
28
+ }
29
+ }
30
+
31
+ impl std::fmt::Display for FinalDecision {
32
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
33
+ match self {
34
+ Self::Allow => write!(f, "Allow"),
35
+ Self::Deny => write!(f, "Deny"),
36
+ Self::Escalate => write!(f, "Escalate"),
37
+ Self::NotApplicable => write!(f, "NotApplicable"),
38
+ Self::Reject => write!(f, "Reject"),
39
+ }
40
+ }
41
+ }
42
+
43
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
44
+ #[serde(rename_all = "PascalCase")]
45
+ pub enum PolicyModality {
46
+ Permission,
47
+ Prohibition,
48
+ Obligation,
49
+ Override,
50
+ }
51
+
52
+ impl std::fmt::Display for PolicyModality {
53
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
54
+ match self {
55
+ Self::Permission => write!(f, "Permission"),
56
+ Self::Prohibition => write!(f, "Prohibition"),
57
+ Self::Obligation => write!(f, "Obligation"),
58
+ Self::Override => write!(f, "Override"),
59
+ }
60
+ }
61
+ }
62
+
63
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
64
+ #[serde(rename_all = "snake_case")]
65
+ pub enum SourceClass {
66
+ CallerSupplied,
67
+ RuntimeObserved,
68
+ SystemOfRecord,
69
+ Attested,
70
+ ManualApproval,
71
+ Derived,
72
+ UnknownSource,
73
+ }
74
+
75
+ impl std::fmt::Display for SourceClass {
76
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
77
+ match self {
78
+ Self::CallerSupplied => write!(f, "caller_supplied"),
79
+ Self::RuntimeObserved => write!(f, "runtime_observed"),
80
+ Self::SystemOfRecord => write!(f, "system_of_record"),
81
+ Self::Attested => write!(f, "attested"),
82
+ Self::ManualApproval => write!(f, "manual_approval"),
83
+ Self::Derived => write!(f, "derived"),
84
+ Self::UnknownSource => write!(f, "unknown_source"),
85
+ }
86
+ }
87
+ }
88
+
89
+ #[derive(Debug, Clone, Serialize, Deserialize)]
90
+ pub struct AuthorityRequest {
91
+ pub request_id: String,
92
+ pub actor: ActorContext,
93
+ pub operation: String,
94
+ pub resource: ResourceRef,
95
+ #[serde(default)]
96
+ pub context: serde_json::Value,
97
+ pub requested_at: DateTime<Utc>,
98
+ #[serde(skip_serializing_if = "Option::is_none")]
99
+ pub correlation_id: Option<String>,
100
+ #[serde(skip_serializing_if = "Option::is_none")]
101
+ pub risk_class: Option<String>,
102
+ #[serde(default)]
103
+ pub metadata: HashMap<String, serde_json::Value>,
104
+ }
105
+
106
+ impl AuthorityRequest {
107
+ pub fn validate(&self) -> Result<(), AuthorityError> {
108
+ if self.request_id.is_empty() {
109
+ return Err(AuthorityError::invalid_request("request_id is required"));
110
+ }
111
+ if self.actor.id.is_empty() {
112
+ return Err(AuthorityError::invalid_request("actor.id is required"));
113
+ }
114
+ if self.operation.is_empty() {
115
+ return Err(AuthorityError::invalid_request("operation is required"));
116
+ }
117
+ if self.resource.id.is_none() && self.resource.type_.is_none() {
118
+ return Err(AuthorityError::invalid_request(
119
+ "resource must include at least id or type",
120
+ ));
121
+ }
122
+ Ok(())
123
+ }
124
+
125
+ pub fn action_hash_input(&self) -> String {
126
+ format!(
127
+ "{}:{}:{}:{}",
128
+ self.request_id,
129
+ self.actor.id,
130
+ self.operation,
131
+ serde_json::to_string(&self.resource).unwrap_or_default()
132
+ )
133
+ }
134
+ }
135
+
136
+ #[derive(Debug, Clone, Serialize, Deserialize)]
137
+ pub struct ActorContext {
138
+ pub id: String,
139
+ #[serde(default)]
140
+ pub role: Option<String>,
141
+ #[serde(default)]
142
+ pub groups: Vec<String>,
143
+ #[serde(skip_serializing_if = "Option::is_none")]
144
+ pub service_account: Option<String>,
145
+ #[serde(skip_serializing_if = "Option::is_none")]
146
+ pub agent_identity: Option<String>,
147
+ }
148
+
149
+ #[derive(Debug, Clone, Serialize, Deserialize)]
150
+ pub struct ResourceRef {
151
+ #[serde(skip_serializing_if = "Option::is_none")]
152
+ pub id: Option<String>,
153
+ #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
154
+ pub type_: Option<String>,
155
+ #[serde(flatten)]
156
+ pub extra: HashMap<String, serde_json::Value>,
157
+ }
158
+
159
+ #[derive(Debug, Clone, Serialize, Deserialize)]
160
+ pub struct FactEnvelope {
161
+ pub path: String,
162
+ pub value: serde_json::Value,
163
+ pub source_class: SourceClass,
164
+ pub source_id: String,
165
+ pub observed_at: DateTime<Utc>,
166
+ #[serde(skip_serializing_if = "Option::is_none")]
167
+ pub expires_at: Option<DateTime<Utc>>,
168
+ #[serde(skip_serializing_if = "Option::is_none")]
169
+ pub evidence_ref: Option<String>,
170
+ #[serde(skip_serializing_if = "Option::is_none")]
171
+ pub signature: Option<String>,
172
+ #[serde(skip_serializing_if = "Option::is_none")]
173
+ pub confidence: Option<f64>,
174
+ #[serde(skip_serializing_if = "Option::is_none")]
175
+ pub lineage: Option<DerivedFactLineage>,
176
+ }
177
+
178
+ impl FactEnvelope {
179
+ pub fn is_fresh(&self, now: DateTime<Utc>) -> bool {
180
+ match self.expires_at {
181
+ Some(exp) => now < exp,
182
+ None => true,
183
+ }
184
+ }
185
+
186
+ pub fn is_trusted(&self) -> bool {
187
+ !matches!(
188
+ self.source_class,
189
+ SourceClass::CallerSupplied | SourceClass::UnknownSource
190
+ )
191
+ }
192
+
193
+ pub fn is_caller_supplied(&self) -> bool {
194
+ matches!(self.source_class, SourceClass::CallerSupplied)
195
+ }
196
+
197
+ pub fn effective_trust(&self) -> SourceClass {
198
+ if let Some(ref lineage) = self.lineage {
199
+ lineage.effective_trust
200
+ } else {
201
+ self.source_class
202
+ }
203
+ }
204
+ }
205
+
206
+ #[derive(Debug, Clone, Serialize, Deserialize)]
207
+ pub struct DerivedFactLineage {
208
+ pub transform_id: String,
209
+ pub transform_version: String,
210
+ pub transform_hash: String,
211
+ pub input_fact_paths: Vec<String>,
212
+ pub input_source_classes: Vec<SourceClass>,
213
+ pub effective_trust: SourceClass,
214
+ pub trust_upgrade_applied: bool,
215
+ }
216
+
217
+ #[derive(Debug, Clone, Serialize, Deserialize)]
218
+ pub struct FactRequirement {
219
+ pub fact_path: String,
220
+ pub allowed_source_classes: Vec<SourceClass>,
221
+ #[serde(default)]
222
+ pub allowed_source_ids: Vec<String>,
223
+ #[serde(skip_serializing_if = "Option::is_none")]
224
+ pub max_age: Option<chrono::Duration>,
225
+ #[serde(default)]
226
+ pub evidence_ref_required: bool,
227
+ #[serde(default)]
228
+ pub signature_required: bool,
229
+ #[serde(skip_serializing_if = "Option::is_none")]
230
+ pub minimum_confidence: Option<f64>,
231
+ #[serde(skip_serializing_if = "Option::is_none")]
232
+ pub required_transform: Option<String>,
233
+ #[serde(skip_serializing_if = "Option::is_none")]
234
+ pub derived_from_source: Option<Vec<SourceClass>>,
235
+ }
236
+
237
+ impl FactRequirement {
238
+ pub fn is_satisfied_by(&self, envelope: &FactEnvelope, now: &DateTime<Utc>) -> bool {
239
+ if self.fact_path != envelope.path {
240
+ return false;
241
+ }
242
+
243
+ let effective = envelope.effective_trust();
244
+ if !self.allowed_source_classes.contains(&effective) {
245
+ return false;
246
+ }
247
+
248
+ if !self.allowed_source_ids.is_empty()
249
+ && !self.allowed_source_ids.contains(&envelope.source_id)
250
+ {
251
+ return false;
252
+ }
253
+
254
+ if self.evidence_ref_required && envelope.evidence_ref.is_none() {
255
+ return false;
256
+ }
257
+
258
+ if self.signature_required && envelope.signature.is_none() {
259
+ return false;
260
+ }
261
+
262
+ if let Some(min_conf) = self.minimum_confidence {
263
+ match envelope.confidence {
264
+ Some(c) if c >= min_conf => {}
265
+ _ => return false,
266
+ }
267
+ }
268
+
269
+ // Enforce derived_from_source lineage check for derived facts
270
+ if let Some(ref required_parent_sources) = self.derived_from_source {
271
+ if let Some(ref lineage) = envelope.lineage {
272
+ // Every input parent source must be in the allowed set
273
+ for parent_class in &lineage.input_source_classes {
274
+ if !required_parent_sources.contains(parent_class) {
275
+ return false;
276
+ }
277
+ }
278
+ } else if effective == SourceClass::Derived {
279
+ // Derived fact without lineage info cannot satisfy derived_from_source requirement
280
+ return false;
281
+ }
282
+ }
283
+
284
+ // Enforce max_age freshness
285
+ if let Some(max_age) = &self.max_age {
286
+ let oldest_allowed = *now - *max_age;
287
+ if envelope.observed_at < oldest_allowed {
288
+ return false;
289
+ }
290
+ }
291
+
292
+ true
293
+ }
294
+ }
295
+
296
+ #[derive(Debug, Clone, Serialize, Deserialize)]
297
+ pub struct FactSource {
298
+ pub id: String,
299
+ pub source_class: SourceClass,
300
+ pub allowed_paths: Vec<String>,
301
+ pub evidence_required: bool,
302
+ pub signature_required: bool,
303
+ pub max_response_latency_ms: u64,
304
+ #[serde(skip_serializing_if = "Option::is_none")]
305
+ pub health_endpoint: Option<String>,
306
+ #[serde(skip_serializing_if = "Option::is_none")]
307
+ pub credential_ref: Option<String>,
308
+ #[serde(skip_serializing_if = "Option::is_none")]
309
+ pub schema_ref: Option<String>,
310
+ #[serde(skip_serializing_if = "Option::is_none")]
311
+ pub owner: Option<String>,
312
+ #[serde(skip_serializing_if = "Option::is_none")]
313
+ pub recovery_hint: Option<String>,
314
+ }
315
+
316
+ #[derive(Debug, Clone, Serialize, Deserialize)]
317
+ pub struct FactTransform {
318
+ pub id: String,
319
+ pub version: String,
320
+ pub hash: String,
321
+ pub inputs: Vec<TransformInput>,
322
+ pub output: TransformOutput,
323
+ pub purity: PurityFlags,
324
+ pub determinism_tests: Vec<String>,
325
+ }
326
+
327
+ #[derive(Debug, Clone, Serialize, Deserialize)]
328
+ pub struct TransformInput {
329
+ pub fact_path: String,
330
+ pub source_classes: Vec<SourceClass>,
331
+ }
332
+
333
+ #[derive(Debug, Clone, Serialize, Deserialize)]
334
+ pub struct TransformOutput {
335
+ pub fact_path: String,
336
+ }
337
+
338
+ #[derive(Debug, Clone, Serialize, Deserialize, Default)]
339
+ pub struct PurityFlags {
340
+ pub network_access: bool,
341
+ pub filesystem_access: bool,
342
+ pub clock_access: bool,
343
+ pub random_access: bool,
344
+ pub side_effects: bool,
345
+ pub global_state_access: bool,
346
+ }
347
+
348
+ impl PurityFlags {
349
+ pub fn is_pure(&self) -> bool {
350
+ !self.network_access
351
+ && !self.filesystem_access
352
+ && !self.clock_access
353
+ && !self.random_access
354
+ && !self.side_effects
355
+ && !self.global_state_access
356
+ }
357
+ }
358
+
359
+ #[derive(Debug, Clone, Serialize, Deserialize)]
360
+ pub struct SpecificityProfile {
361
+ pub id: String,
362
+ pub dimensions: Vec<String>,
363
+ pub scoring_rules: serde_json::Value,
364
+ pub hash: String,
365
+ }
366
+
367
+ impl SpecificityProfile {
368
+ pub fn default_profile() -> Self {
369
+ Self {
370
+ id: "default".to_string(),
371
+ dimensions: vec![
372
+ "actor".to_string(),
373
+ "role".to_string(),
374
+ "action".to_string(),
375
+ "resource".to_string(),
376
+ "scope".to_string(),
377
+ "condition".to_string(),
378
+ ],
379
+ scoring_rules: serde_json::json!({}),
380
+ hash: "default_v1".to_string(),
381
+ }
382
+ }
383
+ }
384
+
385
+ #[derive(Debug, Clone, Serialize, Deserialize)]
386
+ pub struct SpecificityVector {
387
+ pub dimensions: Vec<(String, u32)>,
388
+ }
389
+
390
+ impl SpecificityVector {
391
+ pub fn new(dimensions: Vec<(String, u32)>) -> Self {
392
+ Self { dimensions }
393
+ }
394
+
395
+ pub fn compare(&self, other: &Self) -> SpecificityComparison {
396
+ let all_dims: std::collections::HashSet<&str> = self
397
+ .dimensions
398
+ .iter()
399
+ .chain(other.dimensions.iter())
400
+ .map(|(name, _)| name.as_str())
401
+ .collect();
402
+
403
+ let get_score = |dims: &[(String, u32)], name: &str| -> u32 {
404
+ dims.iter()
405
+ .find(|(n, _)| n == name)
406
+ .map(|(_, s)| *s)
407
+ .unwrap_or(0)
408
+ };
409
+
410
+ let a_dominates = all_dims
411
+ .iter()
412
+ .all(|name| get_score(&self.dimensions, name) >= get_score(&other.dimensions, name));
413
+ let a_strictly_dominates = all_dims
414
+ .iter()
415
+ .any(|name| get_score(&self.dimensions, name) > get_score(&other.dimensions, name));
416
+
417
+ let b_dominates = all_dims
418
+ .iter()
419
+ .all(|name| get_score(&other.dimensions, name) >= get_score(&self.dimensions, name));
420
+ let b_strictly_dominates = all_dims
421
+ .iter()
422
+ .any(|name| get_score(&other.dimensions, name) > get_score(&self.dimensions, name));
423
+
424
+ match (
425
+ a_dominates,
426
+ a_strictly_dominates,
427
+ b_dominates,
428
+ b_strictly_dominates,
429
+ ) {
430
+ (true, false, true, false) => SpecificityComparison::Equal,
431
+ (true, true, false, _) => SpecificityComparison::AMoreSpecific,
432
+ (false, _, true, true) => SpecificityComparison::BMoreSpecific,
433
+ _ => SpecificityComparison::Incomparable,
434
+ }
435
+ }
436
+ }
437
+
438
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
439
+ pub enum SpecificityComparison {
440
+ AMoreSpecific,
441
+ BMoreSpecific,
442
+ Equal,
443
+ Incomparable,
444
+ }
445
+
446
+ #[derive(Debug, Clone, Serialize, Deserialize)]
447
+ pub struct UnknownHandlingConfig {
448
+ pub permission: UnknownHandlingDefault,
449
+ pub prohibition: UnknownHandlingDefault,
450
+ pub obligation: UnknownHandlingDefault,
451
+ pub override_: UnknownHandlingDefault,
452
+ }
453
+
454
+ #[derive(Debug, Clone, Serialize, Deserialize)]
455
+ pub struct UnknownHandlingDefault {
456
+ pub default: FinalDecision,
457
+ }
458
+
459
+ impl UnknownHandlingConfig {
460
+ pub fn defaults() -> Self {
461
+ Self {
462
+ permission: UnknownHandlingDefault {
463
+ default: FinalDecision::Escalate,
464
+ },
465
+ prohibition: UnknownHandlingDefault {
466
+ default: FinalDecision::Deny,
467
+ },
468
+ obligation: UnknownHandlingDefault {
469
+ default: FinalDecision::Escalate,
470
+ },
471
+ override_: UnknownHandlingDefault {
472
+ default: FinalDecision::NotApplicable,
473
+ },
474
+ }
475
+ }
476
+
477
+ pub fn for_modality(&self, modality: &PolicyModality) -> FinalDecision {
478
+ match modality {
479
+ PolicyModality::Permission => self.permission.default,
480
+ PolicyModality::Prohibition => self.prohibition.default,
481
+ PolicyModality::Obligation => self.obligation.default,
482
+ PolicyModality::Override => self.override_.default,
483
+ }
484
+ }
485
+
486
+ pub fn validate(&self) -> Result<(), AuthorityError> {
487
+ // Spec §7.10: unknown handling must follow modality-aware defaults
488
+ // Permission unknown MUST NOT be Allow, Prohibition unknown MUST NOT be Allow
489
+ if matches!(self.permission.default, FinalDecision::Allow) {
490
+ return Err(AuthorityError::new(
491
+ super::error::AuthorityErrorCode::InvalidAuthorityEnvironment,
492
+ "Unknown permission must not default to Allow",
493
+ ));
494
+ }
495
+ if matches!(self.prohibition.default, FinalDecision::Allow) {
496
+ return Err(AuthorityError::new(
497
+ super::error::AuthorityErrorCode::InvalidAuthorityEnvironment,
498
+ "Unknown prohibition must not default to Allow",
499
+ ));
500
+ }
501
+ Ok(())
502
+ }
503
+ }
504
+
505
+ #[derive(Debug, Clone, Serialize, Deserialize)]
506
+ pub struct AuthorityDecision {
507
+ pub decision_id: String,
508
+ pub request_id: String,
509
+ pub final_decision: FinalDecision,
510
+ pub reason_code: String,
511
+ pub trace_ref: String,
512
+ #[serde(skip_serializing_if = "Option::is_none")]
513
+ pub operator_action_hint: Option<String>,
514
+ }
515
+
516
+ #[derive(Debug, Clone, Serialize, Deserialize)]
517
+ pub struct UnknownDecision {
518
+ pub policy_id: String,
519
+ pub unknown_handling_applied: bool,
520
+ pub unknown_modality: PolicyModality,
521
+ pub unknown_default_result: FinalDecision,
522
+ pub unknown_reason: String,
523
+ pub affected_fact_paths: Vec<String>,
524
+ pub fact_source_ids: Vec<String>,
525
+ pub availability_classification: String,
526
+ #[serde(skip_serializing_if = "Option::is_none")]
527
+ pub operator_action_hint: Option<String>,
528
+ }
529
+
530
+ #[derive(Debug, Clone, Serialize, Deserialize)]
531
+ pub struct FactTrustDecision {
532
+ pub fact_path: String,
533
+ pub required_sources: Vec<SourceClass>,
534
+ pub observed_source: SourceClass,
535
+ pub trusted: bool,
536
+ pub reason: String,
537
+ #[serde(skip_serializing_if = "Option::is_none")]
538
+ pub evidence_ref: Option<String>,
539
+ }
540
+
541
+ #[derive(Debug, Clone, Serialize, Deserialize)]
542
+ pub struct CompatibilityLoweringDecision {
543
+ pub policy_id: String,
544
+ pub original_expression: String,
545
+ pub lowered: bool,
546
+ #[serde(skip_serializing_if = "Option::is_none")]
547
+ pub reason: Option<String>,
548
+ }
549
+
550
+ #[derive(Debug, Clone, Serialize, Deserialize)]
551
+ pub struct ConditionEvaluation {
552
+ pub policy_id: String,
553
+ pub condition_result: ThreeValuedResult,
554
+ #[serde(skip_serializing_if = "Option::is_none")]
555
+ pub unknown_handling_result: Option<FinalDecision>,
556
+ }
557
+
558
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
559
+ pub enum ThreeValuedResult {
560
+ True,
561
+ False,
562
+ Unknown,
563
+ }
564
+
565
+ impl From<crate::policy::ThreeValuedBool> for ThreeValuedResult {
566
+ fn from(v: crate::policy::ThreeValuedBool) -> Self {
567
+ match v {
568
+ crate::policy::ThreeValuedBool::True => ThreeValuedResult::True,
569
+ crate::policy::ThreeValuedBool::False => ThreeValuedResult::False,
570
+ crate::policy::ThreeValuedBool::Null => ThreeValuedResult::Unknown,
571
+ }
572
+ }
573
+ }
574
+
575
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
576
+ pub enum ClaimLevel {
577
+ AuditBacked,
578
+ Validated,
579
+ FormallyProven,
580
+ }
581
+
582
+ impl std::fmt::Display for ClaimLevel {
583
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
584
+ match self {
585
+ Self::AuditBacked => write!(f, "audit_backed"),
586
+ Self::Validated => write!(f, "validated"),
587
+ Self::FormallyProven => write!(f, "formally_proven"),
588
+ }
589
+ }
590
+ }
591
+
592
+ static FACT_PATH_RE: Lazy<regex::Regex> =
593
+ Lazy::new(|| regex::Regex::new(r"^[A-Za-z0-9_.\-]+$").unwrap());
594
+
595
+ pub fn validate_fact_path(path: &str) -> Result<(), AuthorityError> {
596
+ if !FACT_PATH_RE.is_match(path) {
597
+ return Err(AuthorityError::invalid_request(format!(
598
+ "Invalid fact path '{}': must contain only [A-Za-z0-9_.-]",
599
+ path
600
+ )));
601
+ }
602
+ Ok(())
603
+ }
604
+
605
+ pub fn compute_hash(data: &str) -> String {
606
+ use xxhash_rust::xxh64::xxh64;
607
+ format!("{:016x}", xxh64(data.as_bytes(), 0))
608
+ }
609
+
610
+ pub fn compute_deterministic_hash(data: &str) -> String {
611
+ use xxhash_rust::xxh64::xxh64;
612
+ format!("{:016x}", xxh64(data.as_bytes(), 42))
613
+ }
614
+
615
+ pub fn generate_decision_id() -> String {
616
+ uuid::Uuid::new_v4().to_string()
617
+ }
@@ -0,0 +1,25 @@
1
+ use clap::Parser;
2
+ use domainforge_core::cli::{
3
+ authority, format, import, normalize, pack, parse, project, registry, test, validate,
4
+ validate_kg, Cli, Commands,
5
+ };
6
+
7
+ fn main() -> anyhow::Result<()> {
8
+ let cli = Cli::parse();
9
+
10
+ // TODO: Setup logging/tracing based on cli.verbose/quiet
11
+
12
+ match cli.command {
13
+ Commands::Parse(args) => parse::run(args),
14
+ Commands::Validate(args) => validate::run(args),
15
+ Commands::Import(args) => import::run(args),
16
+ Commands::Project(args) => project::run(args),
17
+ Commands::Format(args) => format::run(args),
18
+ Commands::Test(args) => test::run(args),
19
+ Commands::ValidateKg(args) => validate_kg::run(args),
20
+ Commands::Normalize(args) => normalize::run(args),
21
+ Commands::Registry(args) => registry::run(args),
22
+ Commands::Authority(args) => authority::run(args),
23
+ Commands::Pack(args) => pack::run(args),
24
+ }
25
+ }