@githolon/dsl 0.108.6 → 0.110.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 (307) hide show
  1. package/assets/operation-contract.wasm +0 -0
  2. package/check_package.mjs +12 -15
  3. package/compile_package.mjs +17 -18
  4. package/compile_proof.mjs +16 -1
  5. package/dart/CHANGELOG.md +76 -1
  6. package/dart/README.md +25 -2
  7. package/dart/lib/src/admission_decision.dart +41 -0
  8. package/dart/lib/src/application_framework_calls.dart +52 -2
  9. package/dart/lib/src/application_model_adoption.dart +187 -0
  10. package/dart/lib/src/application_status.dart +73 -0
  11. package/dart/lib/src/console_enrolment.dart +271 -0
  12. package/dart/lib/src/console_http_io.dart +26 -0
  13. package/dart/lib/src/console_http_stub.dart +7 -0
  14. package/dart/lib/src/dev_cloud.dart +69 -22
  15. package/dart/lib/src/generated_call.dart +83 -23
  16. package/dart/lib/src/kernel_primitives.dart +119 -0
  17. package/dart/lib/src/nms_conformance_runtime.dart +1 -1
  18. package/dart/lib/src/nms_generated_runtime.dart +32 -10
  19. package/dart/lib/src/nms_test_environment.dart +1 -1
  20. package/dart/lib/src/node_runner_transport.dart +41 -46
  21. package/dart/lib/src/observed_session_directory.dart +70 -0
  22. package/dart/lib/src/operation_receipts.dart +112 -0
  23. package/dart/lib/src/peer_application_streams.dart +103 -0
  24. package/dart/lib/src/reception/dart_reception.dart +4280 -0
  25. package/dart/lib/src/reception/event_desk.dart +211 -0
  26. package/dart/lib/src/reception/extremum_read.dart +46 -0
  27. package/dart/lib/src/reception/local_copies.dart +371 -0
  28. package/dart/lib/src/reception/peer_office_connection.dart +11 -0
  29. package/dart/lib/src/reception/progress_desk.dart +267 -0
  30. package/dart/lib/src/reception/reception_contract.dart +11 -0
  31. package/dart/lib/src/reception/reception_session.dart +284 -0
  32. package/dart/lib/src/reception/sync_diagnostics.dart +26 -0
  33. package/dart/lib/src/reception/workspace_preparation_report.dart +126 -0
  34. package/dart/lib/src/replica_readiness.dart +123 -0
  35. package/dart/lib/src/runner/node-entry.mjs +23905 -15774
  36. package/dart/lib/src/runtime_v2_gateway.dart +56 -3
  37. package/dart/lib/src/runtime_v2_transport.dart +544 -3
  38. package/dart/lib/src/session_bound.dart +200 -311
  39. package/dart/lib/src/signing_identity_kernel.dart +84 -0
  40. package/dart/lib/src/sync_status_projection.dart +548 -0
  41. package/dart/lib/src/sync_status_reducer.dart +170 -0
  42. package/dart/lib/src/test_harness.dart +809 -1153
  43. package/dart/lib/src/testing/test_custody.dart +66 -0
  44. package/dart/lib/src/testing/test_peer.dart +328 -0
  45. package/dart/lib/src/typed_watch_registry.dart +169 -0
  46. package/dart/lib/src/workspace_open_progress.dart +27 -0
  47. package/dart/pubspec.lock +24 -1
  48. package/dart/pubspec.yaml +7 -2
  49. package/dart/pubspec_overrides.yaml +2 -0
  50. package/dart/test/admission_decision_test.dart +48 -0
  51. package/dart/test/background_model_adoption_test.dart +228 -0
  52. package/dart/test/bundle_version_pairing_test.dart +4 -4
  53. package/dart/test/child_authentication_repair_test.dart +359 -0
  54. package/dart/test/cloud_bound_local_shell_test.dart +119 -0
  55. package/dart/test/console_enrolment_refusal_test.dart +52 -0
  56. package/dart/test/console_enrolment_test.dart +227 -0
  57. package/dart/test/errors_test.dart +5 -5
  58. package/dart/test/event_plane_seam_test.dart +50 -164
  59. package/dart/test/extremum_read_test.dart +58 -0
  60. package/dart/test/fixtures/wedge/wedge-entry.mjs +3 -21
  61. package/dart/test/generated_query_test.dart +32 -0
  62. package/dart/test/harness_phase_timeout_test.dart +18 -23
  63. package/dart/test/kernel_author_after_read_test.dart +242 -0
  64. package/dart/test/kernel_fence_test.dart +137 -0
  65. package/dart/test/local_copies_test.dart +222 -0
  66. package/dart/test/model_adoption_test.dart +198 -0
  67. package/dart/test/node_peer_local_custody_test.dart +153 -0
  68. package/dart/test/offer_authentication_proof_test.dart +352 -52
  69. package/dart/test/operation_compatibility_test.dart +151 -0
  70. package/dart/test/platform_credential_effect_test.dart +386 -0
  71. package/dart/test/receiving_group_open_test.dart +213 -0
  72. package/dart/test/reception/workspace_preparation_report_test.dart +103 -0
  73. package/dart/test/reception_span_trace_test.dart +23 -0
  74. package/dart/test/replica_readiness_test.dart +156 -0
  75. package/dart/test/runtime_projections_test.dart +92 -0
  76. package/dart/test/runtime_v2_gateway_test.dart +131 -0
  77. package/dart/test/signing_identity_kernel_test.dart +75 -0
  78. package/dart/test/sync_status_preparation_report_test.dart +29 -0
  79. package/dart/test/sync_status_reducer_test.dart +419 -0
  80. package/dart/test/test_harness_test.dart +71 -95
  81. package/dart/test/typed_query_watch_test.dart +170 -0
  82. package/dart/test/typed_watch_registry_test.dart +249 -0
  83. package/dart_lints/README.md +18 -0
  84. package/dart_lints/lib/nomos_lints.dart +70 -0
  85. package/dart_lints/pubspec.lock +580 -0
  86. package/dart_lints/pubspec.yaml +12 -0
  87. package/dart_lints/test/reference_identity_test.dart +75 -0
  88. package/dart_types/CHANGELOG.md +18 -0
  89. package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
  90. package/dart_types/lib/nomos_types.dart +9 -1
  91. package/dart_types/lib/src/admission_decision.dart +37 -0
  92. package/dart_types/lib/src/aggregate_meta.dart +1 -1
  93. package/dart_types/lib/src/approved_model.dart +65 -0
  94. package/dart_types/lib/src/custody.dart +10 -18
  95. package/dart_types/lib/src/error_info.dart +4 -4
  96. package/dart_types/lib/src/errors.dart +29 -29
  97. package/dart_types/lib/src/foreign_ref.dart +62 -33
  98. package/dart_types/lib/src/local_work_rejected.dart +3 -3
  99. package/dart_types/lib/src/nomos_ref.dart +3 -1
  100. package/dart_types/lib/src/principal.dart +2 -2
  101. package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
  102. package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
  103. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
  104. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
  105. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
  106. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
  107. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
  108. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
  109. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
  110. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
  111. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
  112. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
  113. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
  114. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
  115. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
  116. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
  117. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
  118. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
  119. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
  120. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
  121. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
  122. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
  123. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
  124. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
  125. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
  126. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
  127. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
  128. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
  129. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
  130. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
  131. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
  132. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
  133. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
  134. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
  135. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
  136. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
  137. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
  138. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
  139. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
  140. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
  141. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
  142. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
  143. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
  144. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
  145. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
  146. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
  147. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
  148. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
  149. package/dart_types/lib/src/runtime_outcome.dart +133 -0
  150. package/dart_types/lib/src/subscriptions.dart +116 -23
  151. package/dart_types/pubspec.yaml +1 -1
  152. package/dart_types/test/extremum_subscriptions_test.dart +40 -0
  153. package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
  154. package/dart_types/test/nomos_ref_address_test.dart +25 -0
  155. package/dart_types/test/ordered_subscriptions_test.dart +34 -0
  156. package/operation_contract_check.mjs +24 -0
  157. package/package.json +11 -6
  158. package/src/aggregate.ts +70 -10
  159. package/src/application_topology.ts +18 -11
  160. package/src/attested.ts +3 -0
  161. package/src/attested_core.ts +46 -3
  162. package/src/birth_meter_ensure.ts +19 -7
  163. package/src/births.ts +29 -4
  164. package/src/build_package.ts +140 -13
  165. package/src/business_birth.ts +181 -4
  166. package/src/codegen_call_proto.ts +1274 -0
  167. package/src/codegen_call_usda.ts +49 -6
  168. package/src/codegen_dart.ts +79 -44
  169. package/src/codegen_dart_client.ts +458 -800
  170. package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
  171. package/src/codegen_dart_framework_calls.ts +320 -37
  172. package/src/codegen_dart_indexed_variant.ts +159 -0
  173. package/src/codegen_dart_scenario.ts +42 -13
  174. package/src/codegen_proof.ts +3 -3
  175. package/src/codegen_provider_dart.ts +5 -0
  176. package/src/codegen_query_proto.ts +158 -0
  177. package/src/codegen_refusal.ts +189 -0
  178. package/src/codegen_result_proto.ts +931 -0
  179. package/src/codegen_result_usda.ts +4 -0
  180. package/src/codegen_ts.ts +464 -616
  181. package/src/codegen_workspace_access.ts +105 -0
  182. package/src/compatibility_graph.ts +759 -0
  183. package/src/compatibility_usda.ts +264 -0
  184. package/src/compile_package_main.ts +2083 -1248
  185. package/src/custody_placement.ts +156 -0
  186. package/src/custody_placement_usda.ts +91 -0
  187. package/src/decl_shapes.ts +21 -2
  188. package/src/describe_model.ts +1 -0
  189. package/src/directive.ts +59 -2
  190. package/src/drivers.ts +51 -0
  191. package/src/engine_entry.ts +52 -8
  192. package/src/evolve_preview.ts +11 -4
  193. package/src/exists.ts +2 -0
  194. package/src/fields.ts +75 -11
  195. package/src/flow_gate.ts +2 -1
  196. package/src/framework/application_home.ts +170 -18
  197. package/src/framework/attested_receipts.ts +8 -3
  198. package/src/framework/auth_provider_law.ts +169 -9
  199. package/src/framework/birth_certificate_law.ts +4 -0
  200. package/src/framework/capability.ts +34 -3
  201. package/src/framework/child_authentication.ts +346 -0
  202. package/src/framework/console_governance.ts +295 -0
  203. package/src/framework/delegated_roles.ts +301 -0
  204. package/src/framework/domain_lifecycle.ts +26 -13
  205. package/src/framework/founding_genesis.ts +193 -0
  206. package/src/framework/framework_aggregates.ts +1 -1
  207. package/src/framework/genesis.ts +6 -1
  208. package/src/framework/governance_relations.ts +19 -0
  209. package/src/framework/home.ts +5 -734
  210. package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
  211. package/src/framework/model_authority_repair.ts +116 -0
  212. package/src/framework/model_authority_seed.ts +185 -0
  213. package/src/framework/model_transition.ts +211 -0
  214. package/src/framework/owned_custody.ts +1 -1
  215. package/src/framework/principal_enrollment.ts +302 -0
  216. package/src/framework/receiving_group.ts +857 -0
  217. package/src/framework/receiving_group_recovery.ts +314 -0
  218. package/src/framework/relations.ts +4 -8
  219. package/src/framework/signing_identity.ts +242 -95
  220. package/src/framework/source_roster.ts +11 -5
  221. package/src/framework/workspace_access.ts +149 -0
  222. package/src/framework/workspace_invariant.ts +73 -52
  223. package/src/framework/workspaces.ts +407 -40
  224. package/src/framework_call_definitions.ts +32 -3
  225. package/src/generated_client_bundle_boundary.ts +97 -0
  226. package/src/generated_client_names.ts +1 -0
  227. package/src/identity_usda.ts +27 -0
  228. package/src/index.ts +183 -12
  229. package/src/indexed_variant.ts +83 -0
  230. package/src/intent.ts +173 -45
  231. package/src/law_check.ts +8 -5
  232. package/src/law_dependency_index.ts +231 -0
  233. package/src/law_graph.ts +508 -71
  234. package/src/law_graph_usda.ts +170 -24
  235. package/src/law_identity.ts +119 -81
  236. package/src/law_source_map.ts +4 -1
  237. package/src/law_units.ts +498 -0
  238. package/src/law_value_type.ts +7 -3
  239. package/src/member_authentication.ts +302 -0
  240. package/src/null_meta.ts +1 -1
  241. package/src/openusd_compiled_layer.ts +132 -0
  242. package/src/operation_contract_check.ts +31 -0
  243. package/src/ordered_read.ts +2 -1
  244. package/src/package_config.ts +33 -12
  245. package/src/package_dependencies.ts +1 -0
  246. package/src/plan_source_slice.ts +30 -1
  247. package/src/protobuf_field_number.ts +36 -0
  248. package/src/provenance_wire.ts +6 -0
  249. package/src/query.ts +2 -1
  250. package/src/read.ts +50 -0
  251. package/src/relation.ts +4 -1
  252. package/src/relation_schema.ts +15 -2
  253. package/src/report.ts +2 -2
  254. package/src/sqlite_computation_bundle.ts +78 -0
  255. package/src/sqlite_computed.ts +102 -0
  256. package/src/sqlite_counts.ts +154 -0
  257. package/src/sqlite_layout.ts +823 -0
  258. package/src/sqlite_reads.ts +275 -0
  259. package/src/sqlite_samples.ts +185 -0
  260. package/src/stable_id_identity_bridge.ts +1 -1
  261. package/src/stable_ids_for_module.ts +16 -4
  262. package/src/test_call_usda.ts +6 -6
  263. package/src/usda_relationship_integrity.ts +20 -3
  264. package/src/usda_text.ts +21 -1
  265. package/src/value_object.ts +81 -11
  266. package/src/wire.ts +22 -0
  267. package/src/wire_encode.ts +227 -20
  268. package/src/workspace_sharding.ts +15 -6
  269. package/src/workspace_sharing.ts +51 -49
  270. package/src/zod_introspection.ts +2 -0
  271. package/compat_package.mjs +0 -46
  272. package/dart/lib/src/home.dart +0 -15
  273. package/dart/lib/src/runner/offline-install.mjs +0 -15367
  274. package/dart/lib/src/source_trust.dart +0 -51
  275. package/dart/lib/src/webview_bridge.dart +0 -6540
  276. package/dart/lib/src/workspace_name.dart +0 -30
  277. package/dart/test/acquire_session_credentials_test.dart +0 -150
  278. package/dart/test/acquire_session_test.dart +0 -534
  279. package/dart/test/adv_realm_interference_test.dart +0 -600
  280. package/dart/test/cloud_bound_topology_test.dart +0 -168
  281. package/dart/test/cluster_births_test.dart +0 -202
  282. package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
  283. package/dart/test/cluster_local_autosync_test.dart +0 -123
  284. package/dart/test/cluster_scale_test.dart +0 -122
  285. package/dart/test/compat_test.dart +0 -61
  286. package/dart/test/dlq_session_surface_test.dart +0 -222
  287. package/dart/test/first_app_gauntlet_test.dart +0 -386
  288. package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
  289. package/dart/test/four_layer_nested_topology_test.dart +0 -290
  290. package/dart/test/home_parity_test.dart +0 -13
  291. package/dart/test/local_sync_inert_test.dart +0 -107
  292. package/dart/test/node_runner_transport_test.dart +0 -78
  293. package/dart/test/parent_signer_recovery_test.dart +0 -155
  294. package/dart/test/residency_refusal_test.dart +0 -49
  295. package/dart/test/sealing_client_test.dart +0 -181
  296. package/dart/test/session_bound_test.dart +0 -285
  297. package/dart/test/stale_bundle_test.dart +0 -80
  298. package/dart/test/vo_read_typing_test.dart +0 -131
  299. package/dart/test/watch_after_offer_stall_test.dart +0 -100
  300. package/dart/test/webview_bridge_test.dart +0 -1930
  301. package/dart/test/workspace_name_test.dart +0 -24
  302. package/runtime/generated-application-host.js +0 -22860
  303. package/src/codegen_query_usda.ts +0 -214
  304. package/src/compat_manifest.ts +0 -26
  305. package/src/compat_package_main.ts +0 -224
  306. package/src/shape_compat.ts +0 -352
  307. package/src/usd_state.ts +0 -505
@@ -0,0 +1,302 @@
1
+ // NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
2
+ // remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
3
+ // wasm32-wasip1 artifact {kernel · projection · embedded QuickJS engine}.
4
+ // If a file isn't this / hosting this / authoring for this / proving this — it's gone.
5
+
6
+ /**
7
+ * framework/principal_enrollment.ts — how the FIRST key of a principal reaches the ledger
8
+ * (identity target model D22: the kernel is the authentication).
9
+ *
10
+ * `admit`'s whole authentication rule is: the signature verifies under key K, K is an active signer of
11
+ * the claimed principal P in parent state (`identity:P#signer@key:<sha256(K)>`, `signing_identity.ts`),
12
+ * and P's scope is the scope the directive's provider declares. A principal is `<scope>:<subject>`,
13
+ * exactly its Zanzibar subject. Its first signer tuple lands one of two ways:
14
+ *
15
+ * - **Enrolled scope.** A principal holding `principalScope:<scope>#enroller` (the tenant's backend, or
16
+ * the console hosting one) verified the provider's token OFF the ledger and writes
17
+ * {@link enrollDevice}. The enroller is recorded as the tuple's `grantedBy`; no token, issuer or
18
+ * `verifiedVia` provenance is law. {@link revokeDevice} is its mirror.
19
+ * - **Sovereign scope.** The principal is `<scope>:<sha256(root key)>` and certifies itself:
20
+ * {@link sovereignSelfCertification} writes the founding tuple, marked
21
+ * `nomos:selfCertifyingPrincipal = "true"` so the kernel admits it iff the signing key's sha256 is
22
+ * the principal's subject.
23
+ *
24
+ * Every further device, either scope, is proof of possession: an active signer of P writes
25
+ * `enrollSigner` for the new key. A principal always revokes its own keys with `revokeSigner`.
26
+ *
27
+ * `enroller` is a framework-global relation on the framework object type `principalScope`, granted and
28
+ * revoked by an admin (`grantEnroller`/`revokeEnroller`, `workspaces.ts`) and copied into a child at
29
+ * birth exactly like `operator` (D15/D18: `readInheritedEnrollers` → `buildGenesisChain`).
30
+ */
31
+ import { z } from "zod";
32
+ import { directive, type RequirableDirective } from "../directive.js";
33
+ import { query } from "../query.js";
34
+ import { readFrameworkDeclaredRows } from "../read.js";
35
+ import { relationType, self, user, key } from "../relation_schema.js";
36
+ import { endorsementOf } from "../principal_evidence.js";
37
+ import {
38
+ authenticatesWith,
39
+ consolePrincipals,
40
+ CONSOLE_PRINCIPAL_SCOPE,
41
+ custodianPrincipals,
42
+ CUSTODIAN_PRINCIPAL_SCOPE,
43
+ isAuthenticationProvider,
44
+ principalScopeOf,
45
+ principalsOf,
46
+ RESERVED_PROVIDER_SCOPES,
47
+ type SovereignProviderRef,
48
+ } from "../member_authentication.js";
49
+ import { PRINCIPAL_SCOPE_ENROLLER_RELATION } from "./governance_relations.js";
50
+ import { RelationTuple, removeTuple, writeTuple } from "./relations.js";
51
+ import { signerObject, SIGNER_RELATION } from "./signing_identity.js";
52
+
53
+ /** The framework object type naming one provider scope: `principalScope:<scope>`. */
54
+ export const PRINCIPAL_SCOPE_OBJECT_TYPE = "principalScope" as const;
55
+
56
+ /** The Zanzibar object on which a scope's enrollers are seated. */
57
+ export function principalScopeObject(scope: string): string {
58
+ return `${PRINCIPAL_SCOPE_OBJECT_TYPE}:${requireProviderScope(scope)}`;
59
+ }
60
+
61
+ const scopePattern = /^[A-Za-z][A-Za-z0-9._-]{0,127}$/;
62
+ const sha256Hex = z.string().regex(/^[0-9a-f]{64}$/, "expected lowercase sha256 hex (a public key hash)");
63
+
64
+ function requireProviderScope(scope: string): string {
65
+ if (typeof scope !== "string" || !scopePattern.test(scope) || RESERVED_PROVIDER_SCOPES.includes(scope)) {
66
+ throw new Error(`'${String(scope)}' is not a provider scope`);
67
+ }
68
+ return scope;
69
+ }
70
+
71
+ /** A provider scope in a payload: bounded, and never a framework subject type. */
72
+ export const providerScopeField = z
73
+ .string()
74
+ .regex(scopePattern, "a provider scope is a bounded identifier")
75
+ .refine((scope) => !RESERVED_PROVIDER_SCOPES.includes(scope), "a reserved scope names no principals");
76
+
77
+ /**
78
+ * The framework governance relations' subject classes (`workspace:self#operator`,
79
+ * `principalScope:<s>#enroller`): `user:` and `key:`, the console's enrolled principals
80
+ * (`console:<subject>`), and the framework's sovereign custodian principals (`custodian:<keyhash>`, the
81
+ * founding admin of a root born by token-free genesis). The framework cannot name a tenant's scopes — law
82
+ * is installed per domain (D21) and the framework's unit is composed with every tenant's — so the only
83
+ * provider scopes its own relations admit are the two the framework itself declares: the console's,
84
+ * whose principals are the operators who install law and the hosted enrollers that act for tenants
85
+ * (D18, D22), and the custodians'. Leaf-only: never a userset or wildcard.
86
+ */
87
+ export const GOVERNANCE_SUBJECTS = Object.freeze([
88
+ user(),
89
+ key(),
90
+ principalsOf(consolePrincipals),
91
+ // Token-free genesis (D22): a root's founding admin is a sovereign custodian principal, and it is the
92
+ // root's first enroller and operator, so the framework's governance relations must admit it.
93
+ principalsOf(custodianPrincipals),
94
+ ]);
95
+
96
+ /** The Zanzibar subject classes {@link GOVERNANCE_SUBJECTS} admits, as a predicate over one subject. */
97
+ export function isGovernanceSubject(subject: string): boolean {
98
+ if (/^user:.+/.test(subject)) return true;
99
+ if (/^key:[0-9a-f]{64}$/.test(subject)) return true;
100
+ const scope = principalScopeOf(subject);
101
+ return scope === CONSOLE_PRINCIPAL_SCOPE || scope === CUSTODIAN_PRINCIPAL_SCOPE;
102
+ }
103
+
104
+ /** `principalScope:<scope>#enroller` — see {@link PRINCIPAL_SCOPE_ENROLLER_RELATION}. */
105
+ export const principalScopeRelations = relationType(PRINCIPAL_SCOPE_OBJECT_TYPE)
106
+ // GLOBAL, like `workspace` and `identity`: the object is addressed by its bare type on every door.
107
+ .asGlobal()
108
+ .relation(PRINCIPAL_SCOPE_ENROLLER_RELATION, { rewrite: self(), allow: [...GOVERNANCE_SUBJECTS] });
109
+
110
+ /**
111
+ * A governance grant names its subject exactly one way: a device key (`keyHash` → `key:<hash>`), a
112
+ * legacy user (`principal` → `user:<uid>`), or a console principal (`consolePrincipal`, the full
113
+ * `console:<subject>`).
114
+ */
115
+ export const governanceSubjectFields = {
116
+ keyHash: sha256Hex.optional(),
117
+ principal: z.string().min(1).optional(),
118
+ consolePrincipal: z
119
+ .string()
120
+ .refine((value) => principalScopeOf(value) === CONSOLE_PRINCIPAL_SCOPE, "a console principal is console:<subject>")
121
+ .optional(),
122
+ } as const;
123
+
124
+ type GovernanceSubjectPayload = {
125
+ keyHash?: string | undefined;
126
+ principal?: string | undefined;
127
+ consolePrincipal?: string | undefined;
128
+ };
129
+
130
+ /** Exactly one subject form is present. */
131
+ export function hasOneGovernanceSubject(payload: GovernanceSubjectPayload): boolean {
132
+ return [payload.keyHash, payload.principal, payload.consolePrincipal].filter((value) => !!value).length === 1;
133
+ }
134
+
135
+ /** The Zanzibar subject a governance grant names. Refuses anything but exactly one well-formed form. */
136
+ export function governanceSubject(payload: GovernanceSubjectPayload): string {
137
+ if (!hasOneGovernanceSubject(payload)) {
138
+ throw new Error("a governance grant names exactly one of keyHash, principal or consolePrincipal");
139
+ }
140
+ if (payload.principal) return `user:${payload.principal}`;
141
+ if (payload.consolePrincipal) {
142
+ if (principalScopeOf(payload.consolePrincipal) !== CONSOLE_PRINCIPAL_SCOPE) {
143
+ throw new Error("a console principal is console:<subject>");
144
+ }
145
+ return payload.consolePrincipal;
146
+ }
147
+ if (!/^[0-9a-f]{64}$/.test(payload.keyHash ?? "")) throw new Error("keyHash is a lowercase sha256 hex");
148
+ return `key:${payload.keyHash}`;
149
+ }
150
+
151
+ /** The payload that names `subject` again — the inverse of {@link governanceSubject}, for birth seeding. */
152
+ export function governanceSubjectPayload(subject: string): GovernanceSubjectPayload {
153
+ if (subject.startsWith("user:")) return { principal: subject.slice("user:".length) };
154
+ if (subject.startsWith("key:")) return { keyHash: subject.slice("key:".length) };
155
+ if (principalScopeOf(subject) === CONSOLE_PRINCIPAL_SCOPE) return { consolePrincipal: subject };
156
+ throw new Error(`'${subject}' is not a governance subject`);
157
+ }
158
+
159
+ function requirePrincipalOfScope(principal: string, scope: string): void {
160
+ if (principalScopeOf(principal) !== requireProviderScope(scope)) {
161
+ throw new Error(`principal-not-in-scope: '${principal}' is not a '${scope}:<subject>' principal`);
162
+ }
163
+ }
164
+
165
+ const enrollmentPayload = z
166
+ .object({
167
+ /** The principal's scope. The enroller is checked on `principalScope:<scope>`, so the plan refuses
168
+ * a principal outside it: an enroller of one scope can never mint another scope's principal. */
169
+ scope: providerScopeField,
170
+ principal: z.string().min(1),
171
+ /** sha256 hex of the device's Ed25519 public key. */
172
+ keyHash: sha256Hex,
173
+ })
174
+ .strict()
175
+ .refine((p) => principalScopeOf(p.principal) === p.scope, {
176
+ message: "principal must be <scope>:<subject> of the named scope",
177
+ path: ["principal"],
178
+ });
179
+
180
+ /**
181
+ * `enrollDevice { scope, principal, keyHash }` — an enroller of `scope` writes
182
+ * `identity:<principal>#signer@key:<keyHash>`: the device-bound session of an enrolled scope. The enroller
183
+ * verified the provider's ID token off the ledger (its OIDC `nonce` must be `keyHash`, and it is
184
+ * accepted once), so nothing of the provider lands here. `grantedBy` records the enroller.
185
+ */
186
+ export const enrollDevice = directive("enrollDevice")
187
+ .ensures(RelationTuple)
188
+ .payload(enrollmentPayload)
189
+ .plan((p, ctx) => {
190
+ requirePrincipalOfScope(p.principal, p.scope);
191
+ return writeTuple({
192
+ object: signerObject(p.principal),
193
+ relation: SIGNER_RELATION,
194
+ subject: `key:${p.keyHash}`,
195
+ grantedBy: ctx.principal().asAttribution(),
196
+ grantedAt: String(ctx.clock().physical),
197
+ });
198
+ })
199
+ .requires(PRINCIPAL_SCOPE_ENROLLER_RELATION, {
200
+ objectFrom: { recordType: PRINCIPAL_SCOPE_OBJECT_TYPE, idField: "scope" },
201
+ });
202
+
203
+ /**
204
+ * `revokeDevice { scope, principal, keyHash }` — an enroller of `scope` revokes one key of one of its
205
+ * scope's principals (remove-wins; later writes by that key are refused at their position). A principal
206
+ * always revokes its own keys itself with `revokeSigner`.
207
+ */
208
+ export const revokeDevice = directive("revokeDevice")
209
+ .ensures(RelationTuple)
210
+ .payload(enrollmentPayload)
211
+ .plan((p, ctx) => {
212
+ requirePrincipalOfScope(p.principal, p.scope);
213
+ const at = String(ctx.clock().physical);
214
+ return removeTuple({
215
+ object: signerObject(p.principal),
216
+ relation: SIGNER_RELATION,
217
+ subject: `key:${p.keyHash}`,
218
+ grantedBy: ctx.principal().asAttribution(),
219
+ grantedAt: at,
220
+ revokedBy: ctx.principal().asAttribution(),
221
+ revokedAt: at,
222
+ });
223
+ })
224
+ .requires(PRINCIPAL_SCOPE_ENROLLER_RELATION, {
225
+ objectFrom: { recordType: PRINCIPAL_SCOPE_OBJECT_TYPE, idField: "scope" },
226
+ });
227
+
228
+ /**
229
+ * The founding signer of a SOVEREIGN principal, certified by its own root key (D22). The directive
230
+ * authenticates with `provider`, so the kernel's ordinary rule already pins the captured principal to
231
+ * that sovereign scope; the `nomos:selfCertifyingPrincipal` marker adds the one self-certification
232
+ * rule — the signing key's sha256 is the principal's subject, and needs no prior signer — and the plan
233
+ * refuses any `keyHash` that is not that subject. The tuple it writes is
234
+ * `identity:<scope>:<keyHash>#signer@key:<keyHash>`.
235
+ *
236
+ * One directive per sovereign scope; `id` defaults to `certifySovereignPrincipal`.
237
+ */
238
+ export function sovereignSelfCertification(
239
+ provider: SovereignProviderRef,
240
+ id = "certifySovereignPrincipal",
241
+ ): RequirableDirective<{ keyHash: string }> {
242
+ if (!isAuthenticationProvider(provider) || provider.kind !== "sovereign") {
243
+ throw new Error("sovereignSelfCertification takes a sovereign provider declared with authenticationProvider");
244
+ }
245
+ const scope = provider.scope;
246
+ return authenticatesWith(
247
+ directive(id)
248
+ .ensures(RelationTuple)
249
+ .payload(z.object({ keyHash: sha256Hex }).strict())
250
+ .plan((p, ctx) => {
251
+ const me = ctx.principal().asAuthoritySubject<string>("certify my sovereign identity with its own root key");
252
+ const principal = endorsementOf(me)?.principal ?? "";
253
+ if (principal !== `${scope}:${p.keyHash}`) {
254
+ throw new Error("sovereign-principal-is-its-root-key-hash");
255
+ }
256
+ return writeTuple({
257
+ object: signerObject(principal),
258
+ relation: SIGNER_RELATION,
259
+ subject: `key:${p.keyHash}`,
260
+ grantedBy: ctx.principal().asAttribution(),
261
+ grantedAt: String(ctx.clock().physical),
262
+ });
263
+ })
264
+ .selfCertifyingPrincipal(),
265
+ provider,
266
+ );
267
+ }
268
+
269
+ /** Every tuple of one relation name, across objects — the enroller seeding read. */
270
+ export const relationTuplesByRelation = query("relationTuplesByRelation")
271
+ .key("relation")
272
+ .returns(RelationTuple);
273
+
274
+ /** One inherited enroller grant: the scope and the subject holding it. */
275
+ export interface InheritedEnroller {
276
+ readonly scope: string;
277
+ readonly subject: string;
278
+ }
279
+
280
+ /**
281
+ * ENROLLER INHERITANCE (D22, as D15 for `operator`): the parent's CURRENT active
282
+ * `principalScope:<scope>#enroller` tuples, read by the birthing plan and seated on the child by one
283
+ * `grantEnroller` genesis step each — copied once at birth, never a live dependency on the parent.
284
+ * Sorted by (scope, subject) so the recipe is a pure function of the tuple set.
285
+ */
286
+ export function readInheritedEnrollers(): readonly InheritedEnroller[] {
287
+ const rows = readFrameworkDeclaredRows(relationTuplesByRelation, RelationTuple, {
288
+ relation: PRINCIPAL_SCOPE_ENROLLER_RELATION,
289
+ });
290
+ const prefix = `${PRINCIPAL_SCOPE_OBJECT_TYPE}:`;
291
+ const out: InheritedEnroller[] = [];
292
+ for (const row of rows) {
293
+ if (row.relation !== PRINCIPAL_SCOPE_ENROLLER_RELATION || !row.object?.startsWith(prefix)) continue;
294
+ const scope = row.object.slice(prefix.length);
295
+ const subjects = row.subjects as Record<string, { status?: string }> | undefined;
296
+ for (const [subject, leaf] of Object.entries(subjects ?? {})) {
297
+ if (leaf?.status === "active") out.push({ scope, subject });
298
+ }
299
+ }
300
+ return out.sort((a, b) =>
301
+ a.scope < b.scope ? -1 : a.scope > b.scope ? 1 : a.subject < b.subject ? -1 : a.subject > b.subject ? 1 : 0);
302
+ }