@githolon/dsl 0.108.7 → 0.110.1

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 (308) 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 +80 -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 +214 -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 +268 -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 +23950 -15776
  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 +550 -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_event_desk_close_test.dart +16 -0
  74. package/dart/test/reception_span_trace_test.dart +23 -0
  75. package/dart/test/replica_readiness_test.dart +156 -0
  76. package/dart/test/runtime_projections_test.dart +92 -0
  77. package/dart/test/runtime_v2_gateway_test.dart +131 -0
  78. package/dart/test/signing_identity_kernel_test.dart +75 -0
  79. package/dart/test/sync_status_preparation_report_test.dart +29 -0
  80. package/dart/test/sync_status_reducer_test.dart +419 -0
  81. package/dart/test/test_harness_test.dart +71 -95
  82. package/dart/test/typed_query_watch_test.dart +170 -0
  83. package/dart/test/typed_watch_registry_test.dart +249 -0
  84. package/dart_lints/README.md +18 -0
  85. package/dart_lints/lib/nomos_lints.dart +70 -0
  86. package/dart_lints/pubspec.lock +580 -0
  87. package/dart_lints/pubspec.yaml +12 -0
  88. package/dart_lints/test/reference_identity_test.dart +75 -0
  89. package/dart_types/CHANGELOG.md +18 -0
  90. package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
  91. package/dart_types/lib/nomos_types.dart +9 -1
  92. package/dart_types/lib/src/admission_decision.dart +37 -0
  93. package/dart_types/lib/src/aggregate_meta.dart +1 -1
  94. package/dart_types/lib/src/approved_model.dart +65 -0
  95. package/dart_types/lib/src/custody.dart +10 -18
  96. package/dart_types/lib/src/error_info.dart +4 -4
  97. package/dart_types/lib/src/errors.dart +29 -29
  98. package/dart_types/lib/src/foreign_ref.dart +62 -33
  99. package/dart_types/lib/src/local_work_rejected.dart +3 -3
  100. package/dart_types/lib/src/nomos_ref.dart +3 -1
  101. package/dart_types/lib/src/principal.dart +2 -2
  102. package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
  103. package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
  104. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
  105. package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
  106. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
  107. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
  108. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
  109. package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
  110. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
  111. package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
  112. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
  113. package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
  114. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
  115. package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
  116. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
  117. package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
  118. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
  119. package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
  120. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
  121. package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
  122. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
  123. package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
  124. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
  125. package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
  126. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
  127. package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
  128. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
  129. package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
  130. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
  131. package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
  132. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
  133. package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
  134. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
  135. package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
  136. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
  137. package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
  138. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
  139. package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
  140. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
  141. package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
  142. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
  143. package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
  144. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
  145. package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
  146. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
  147. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
  148. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
  149. package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
  150. package/dart_types/lib/src/runtime_outcome.dart +133 -0
  151. package/dart_types/lib/src/subscriptions.dart +116 -23
  152. package/dart_types/pubspec.yaml +1 -1
  153. package/dart_types/test/extremum_subscriptions_test.dart +40 -0
  154. package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
  155. package/dart_types/test/nomos_ref_address_test.dart +25 -0
  156. package/dart_types/test/ordered_subscriptions_test.dart +34 -0
  157. package/operation_contract_check.mjs +24 -0
  158. package/package.json +11 -6
  159. package/src/aggregate.ts +70 -10
  160. package/src/application_topology.ts +18 -11
  161. package/src/attested.ts +3 -0
  162. package/src/attested_core.ts +46 -3
  163. package/src/birth_meter_ensure.ts +19 -7
  164. package/src/births.ts +29 -4
  165. package/src/build_package.ts +140 -13
  166. package/src/business_birth.ts +181 -4
  167. package/src/codegen_call_proto.ts +1276 -0
  168. package/src/codegen_call_usda.ts +49 -6
  169. package/src/codegen_dart.ts +83 -44
  170. package/src/codegen_dart_client.ts +458 -800
  171. package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
  172. package/src/codegen_dart_framework_calls.ts +320 -37
  173. package/src/codegen_dart_indexed_variant.ts +159 -0
  174. package/src/codegen_dart_scenario.ts +42 -13
  175. package/src/codegen_proof.ts +3 -3
  176. package/src/codegen_provider_dart.ts +5 -0
  177. package/src/codegen_query_proto.ts +158 -0
  178. package/src/codegen_refusal.ts +189 -0
  179. package/src/codegen_result_proto.ts +931 -0
  180. package/src/codegen_result_usda.ts +4 -0
  181. package/src/codegen_ts.ts +464 -616
  182. package/src/codegen_workspace_access.ts +105 -0
  183. package/src/compatibility_graph.ts +759 -0
  184. package/src/compatibility_usda.ts +264 -0
  185. package/src/compile_package_main.ts +2017 -1195
  186. package/src/custody_placement.ts +156 -0
  187. package/src/custody_placement_usda.ts +91 -0
  188. package/src/decl_shapes.ts +21 -2
  189. package/src/describe_model.ts +1 -0
  190. package/src/directive.ts +59 -2
  191. package/src/drivers.ts +51 -0
  192. package/src/engine_entry.ts +52 -8
  193. package/src/evolve_preview.ts +11 -4
  194. package/src/exists.ts +2 -0
  195. package/src/fields.ts +75 -11
  196. package/src/flow_gate.ts +2 -1
  197. package/src/framework/application_home.ts +170 -18
  198. package/src/framework/attested_receipts.ts +8 -3
  199. package/src/framework/auth_provider_law.ts +169 -9
  200. package/src/framework/birth_certificate_law.ts +4 -0
  201. package/src/framework/capability.ts +34 -3
  202. package/src/framework/child_authentication.ts +346 -0
  203. package/src/framework/console_governance.ts +295 -0
  204. package/src/framework/delegated_roles.ts +301 -0
  205. package/src/framework/domain_lifecycle.ts +26 -13
  206. package/src/framework/founding_genesis.ts +193 -0
  207. package/src/framework/framework_aggregates.ts +1 -1
  208. package/src/framework/genesis.ts +6 -1
  209. package/src/framework/governance_relations.ts +19 -0
  210. package/src/framework/home.ts +5 -734
  211. package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
  212. package/src/framework/model_authority_repair.ts +116 -0
  213. package/src/framework/model_authority_seed.ts +185 -0
  214. package/src/framework/model_transition.ts +211 -0
  215. package/src/framework/owned_custody.ts +1 -1
  216. package/src/framework/principal_enrollment.ts +302 -0
  217. package/src/framework/receiving_group.ts +857 -0
  218. package/src/framework/receiving_group_recovery.ts +314 -0
  219. package/src/framework/relations.ts +4 -8
  220. package/src/framework/signing_identity.ts +242 -95
  221. package/src/framework/source_roster.ts +11 -5
  222. package/src/framework/workspace_access.ts +149 -0
  223. package/src/framework/workspace_invariant.ts +73 -52
  224. package/src/framework/workspaces.ts +407 -40
  225. package/src/framework_call_definitions.ts +32 -3
  226. package/src/generated_client_bundle_boundary.ts +97 -0
  227. package/src/generated_client_names.ts +1 -0
  228. package/src/identity_usda.ts +27 -0
  229. package/src/index.ts +183 -12
  230. package/src/indexed_variant.ts +83 -0
  231. package/src/intent.ts +173 -45
  232. package/src/law_check.ts +8 -5
  233. package/src/law_dependency_index.ts +231 -0
  234. package/src/law_graph.ts +508 -71
  235. package/src/law_graph_usda.ts +170 -24
  236. package/src/law_identity.ts +119 -81
  237. package/src/law_source_map.ts +4 -1
  238. package/src/law_units.ts +498 -0
  239. package/src/law_value_type.ts +7 -3
  240. package/src/member_authentication.ts +302 -0
  241. package/src/null_meta.ts +1 -1
  242. package/src/openusd_compiled_layer.ts +132 -0
  243. package/src/operation_contract_check.ts +31 -0
  244. package/src/ordered_read.ts +2 -1
  245. package/src/package_config.ts +33 -12
  246. package/src/package_dependencies.ts +1 -0
  247. package/src/plan_source_slice.ts +30 -1
  248. package/src/protobuf_field_number.ts +36 -0
  249. package/src/provenance_wire.ts +6 -0
  250. package/src/query.ts +2 -1
  251. package/src/read.ts +50 -0
  252. package/src/relation.ts +4 -1
  253. package/src/relation_schema.ts +15 -2
  254. package/src/report.ts +2 -2
  255. package/src/sqlite_computation_bundle.ts +78 -0
  256. package/src/sqlite_computed.ts +102 -0
  257. package/src/sqlite_counts.ts +154 -0
  258. package/src/sqlite_layout.ts +823 -0
  259. package/src/sqlite_reads.ts +275 -0
  260. package/src/sqlite_samples.ts +185 -0
  261. package/src/stable_id_identity_bridge.ts +1 -1
  262. package/src/stable_ids_for_module.ts +16 -4
  263. package/src/test_call_usda.ts +6 -6
  264. package/src/usda_relationship_integrity.ts +20 -3
  265. package/src/usda_text.ts +21 -1
  266. package/src/value_object.ts +81 -11
  267. package/src/wire.ts +22 -0
  268. package/src/wire_encode.ts +227 -20
  269. package/src/workspace_sharding.ts +15 -6
  270. package/src/workspace_sharing.ts +51 -49
  271. package/src/zod_introspection.ts +2 -0
  272. package/compat_package.mjs +0 -46
  273. package/dart/lib/src/home.dart +0 -15
  274. package/dart/lib/src/runner/offline-install.mjs +0 -15367
  275. package/dart/lib/src/source_trust.dart +0 -51
  276. package/dart/lib/src/webview_bridge.dart +0 -6540
  277. package/dart/lib/src/workspace_name.dart +0 -30
  278. package/dart/test/acquire_session_credentials_test.dart +0 -150
  279. package/dart/test/acquire_session_test.dart +0 -534
  280. package/dart/test/adv_realm_interference_test.dart +0 -600
  281. package/dart/test/cloud_bound_topology_test.dart +0 -168
  282. package/dart/test/cluster_births_test.dart +0 -202
  283. package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
  284. package/dart/test/cluster_local_autosync_test.dart +0 -123
  285. package/dart/test/cluster_scale_test.dart +0 -122
  286. package/dart/test/compat_test.dart +0 -61
  287. package/dart/test/dlq_session_surface_test.dart +0 -222
  288. package/dart/test/first_app_gauntlet_test.dart +0 -386
  289. package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
  290. package/dart/test/four_layer_nested_topology_test.dart +0 -290
  291. package/dart/test/home_parity_test.dart +0 -13
  292. package/dart/test/local_sync_inert_test.dart +0 -107
  293. package/dart/test/node_runner_transport_test.dart +0 -78
  294. package/dart/test/parent_signer_recovery_test.dart +0 -155
  295. package/dart/test/residency_refusal_test.dart +0 -49
  296. package/dart/test/sealing_client_test.dart +0 -181
  297. package/dart/test/session_bound_test.dart +0 -285
  298. package/dart/test/stale_bundle_test.dart +0 -80
  299. package/dart/test/vo_read_typing_test.dart +0 -131
  300. package/dart/test/watch_after_offer_stall_test.dart +0 -100
  301. package/dart/test/webview_bridge_test.dart +0 -1930
  302. package/dart/test/workspace_name_test.dart +0 -24
  303. package/runtime/generated-application-host.js +0 -22860
  304. package/src/codegen_query_usda.ts +0 -214
  305. package/src/compat_manifest.ts +0 -26
  306. package/src/compat_package_main.ts +0 -224
  307. package/src/shape_compat.ts +0 -352
  308. package/src/usd_state.ts +0 -505
@@ -0,0 +1,66 @@
1
+ @internal
2
+ library;
3
+
4
+ import 'dart:io';
5
+
6
+ import 'package:meta/meta.dart' show internal;
7
+
8
+ /// Physical custody owned by a test peer.
9
+ ///
10
+ /// It is an ordinary directory containing bare Git repositories. The test
11
+ /// harness may choose its lifetime, but never serializes the repositories into
12
+ /// a private snapshot or asks Dart to interpret their contents.
13
+ @internal
14
+ final class NmsTestCustody {
15
+ NmsTestCustody._(this.directory);
16
+
17
+ final Directory directory;
18
+
19
+ static Future<NmsTestCustody> create(
20
+ [String prefix = 'nomos-test-peer-']) async =>
21
+ NmsTestCustody._(await Directory.systemTemp.createTemp(prefix));
22
+
23
+ List<String> processArguments(
24
+ String runtimeDirectory, {
25
+ String? trustRootPublicKey,
26
+ }) =>
27
+ <String>[
28
+ '--runtime-bundle=$runtimeDirectory',
29
+ if (trustRootPublicKey != null)
30
+ '--trust-root-public-key=$trustRootPublicKey',
31
+ '--custody=${directory.path}',
32
+ if (Platform.environment['NOMOS_TEST_DIAGNOSTICS'] == '1')
33
+ '--trace=frames',
34
+ ];
35
+
36
+ /// Provision the platform-owned empty Git custody into which the one
37
+ /// parentless genesis offer may write. This is fixture plumbing, not an
38
+ /// application/session lifecycle operation.
39
+ Future<void> provisionWorkspace(String workspace) async {
40
+ if (!RegExp(r'^[A-Za-z0-9._-]{1,160}$').hasMatch(workspace)) {
41
+ throw ArgumentError.value(workspace, 'workspace', 'is not a safe workspace name');
42
+ }
43
+ final repository = Directory('${directory.path}/custody/holon-$workspace.git');
44
+ if (await repository.exists()) return;
45
+ await repository.create(recursive: true);
46
+ Future<void> git(List<String> arguments) async {
47
+ final result = await Process.run('git', arguments);
48
+ if (result.exitCode != 0) {
49
+ throw StateError(
50
+ 'git ${arguments.join(' ')} failed: ${result.stderr}',
51
+ );
52
+ }
53
+ }
54
+ await git(<String>['init', '--bare', '--quiet', repository.path]);
55
+ await git(<String>[
56
+ '--git-dir', repository.path, 'config', 'http.receivepack', 'true',
57
+ ]);
58
+ await git(<String>[
59
+ '--git-dir', repository.path, 'config', 'http.uploadpack', 'true',
60
+ ]);
61
+ }
62
+
63
+ Future<void> dispose() async {
64
+ if (await directory.exists()) await directory.delete(recursive: true);
65
+ }
66
+ }
@@ -0,0 +1,328 @@
1
+ @internal
2
+ library;
3
+
4
+ import 'dart:io';
5
+ import 'dart:convert' show base64Encode;
6
+ import 'dart:math';
7
+ import 'dart:typed_data';
8
+
9
+ import 'package:fixnum/fixnum.dart' show Int64;
10
+ import 'package:meta/meta.dart' show internal;
11
+ import 'package:nomos_types/nomos_kernel_protocol.dart' as protocol;
12
+
13
+ import '../node_runner_transport.dart';
14
+ import '../reception/dart_reception.dart';
15
+ import 'test_custody.dart';
16
+
17
+ @internal
18
+ final class NmsInstalledTestWorkspace {
19
+ const NmsInstalledTestWorkspace({
20
+ required this.workspace,
21
+ required this.controllerHash,
22
+ required this.lawHashes,
23
+ required this.deviceKey,
24
+ required this.domainKeys,
25
+ });
26
+
27
+ final String workspace;
28
+ final String controllerHash;
29
+ final List<String> lawHashes;
30
+ final protocol.SigningKeyPair deviceKey;
31
+ final Set<String> domainKeys;
32
+ }
33
+
34
+ /// A canonical Peer Office hosted by the Node test Platform Shell.
35
+ ///
36
+ /// This class owns fixture setup only. Every operation crosses Runtime v2 and
37
+ /// the kernel's generated Protobuf ABI; it contains no workspace lifecycle,
38
+ /// USDA parser, generic payload map or alternate admission path.
39
+ @internal
40
+ final class NmsTestPeer {
41
+ NmsTestPeer._({
42
+ required this.transport,
43
+ required this.reception,
44
+ required this.custody,
45
+ required this.runtimeDirectory,
46
+ required String entry,
47
+ required String node,
48
+ String? resolveFrom,
49
+ void Function(String line)? onDiagnostic,
50
+ }) : _entry = entry,
51
+ _node = node,
52
+ _resolveFrom = resolveFrom,
53
+ _onDiagnostic = onDiagnostic;
54
+
55
+ /// The live process transport; replaced by [reboot].
56
+ NodeRunnerTransport transport;
57
+
58
+ /// Reception over [transport]; replaced by [reboot].
59
+ DartReception reception;
60
+ final NmsTestCustody custody;
61
+ final String runtimeDirectory;
62
+ final String _entry;
63
+ final String _node;
64
+ final String? _resolveFrom;
65
+ final void Function(String line)? _onDiagnostic;
66
+ final Random _random = Random.secure();
67
+ int _requestSequence = 0;
68
+ int _authoringSequence = 0;
69
+
70
+ static Future<NmsTestPeer> start({
71
+ required String entry,
72
+ required String runtimeDirectory,
73
+ String node = 'node',
74
+ String? resolveFrom,
75
+ void Function(String line)? onDiagnostic,
76
+ }) async {
77
+ final custody = await NmsTestCustody.create();
78
+ NodeRunnerTransport? transport;
79
+ try {
80
+ transport = await NodeRunnerTransport.start(
81
+ entry: entry,
82
+ resolveFrom: resolveFrom,
83
+ node: node,
84
+ arguments: custody.processArguments(runtimeDirectory),
85
+ onDiagnostic: onDiagnostic,
86
+ );
87
+ final reception = DartReception(transport);
88
+ await reception.ready;
89
+ return NmsTestPeer._(
90
+ transport: transport,
91
+ reception: reception,
92
+ custody: custody,
93
+ runtimeDirectory: runtimeDirectory,
94
+ entry: entry,
95
+ node: node,
96
+ resolveFrom: resolveFrom,
97
+ onDiagnostic: onDiagnostic,
98
+ );
99
+ } catch (_) {
100
+ await transport?.dispose();
101
+ await custody.dispose();
102
+ rethrow;
103
+ }
104
+ }
105
+
106
+ protocol.AuthoringOptions _authoring(String actor) {
107
+ _authoringSequence += 1;
108
+ return protocol.AuthoringOptions(
109
+ actor: actor,
110
+ rng: List<double>.generate(64, (_) => _random.nextDouble()),
111
+ deferProjection: false,
112
+ spans: true,
113
+ sequence: Int64(_authoringSequence),
114
+ clock: protocol.CapturedClock(
115
+ physicalMillis: Int64(DateTime.now().toUtc().millisecondsSinceEpoch),
116
+ logical: 0,
117
+ replica: Int64(7),
118
+ ),
119
+ );
120
+ }
121
+
122
+ Future<protocol.CallResponse> _kernel(
123
+ String session,
124
+ protocol.CallRequest request,
125
+ ) async {
126
+ final response = await transport.callKernel(
127
+ session: session,
128
+ request: request,
129
+ credentialUse: protocol.CredentialUse.CREDENTIAL_USE_NONE,
130
+ );
131
+ if (response.hasFailure()) {
132
+ throw StateError('${response.failure.code}: ${response.failure.message}');
133
+ }
134
+ return response;
135
+ }
136
+
137
+ Future<protocol.LawPackageInspection> _inspectLaw(
138
+ Uint8List bytes,
139
+ String label,
140
+ ) async {
141
+ final id = Int64(++_requestSequence);
142
+ final response = await transport.invokeRuntime(
143
+ protocol.RuntimeRequest(
144
+ protocolVersion: 2,
145
+ requestId: id,
146
+ inspectLawPackage: protocol.InspectLawPackageRequest(
147
+ lawUsdz: bytes,
148
+ label: label,
149
+ ),
150
+ ),
151
+ );
152
+ if (response.hasFailure()) {
153
+ throw StateError('${response.failure.code}: ${response.failure.message}');
154
+ }
155
+ if (!response.hasLawPackageInspection() ||
156
+ response.lawPackageInspection.identity.isEmpty) {
157
+ throw StateError(
158
+ 'Peer Office returned ${response.whichOutcome().name} while inspecting $label',
159
+ );
160
+ }
161
+ return response.lawPackageInspection;
162
+ }
163
+
164
+ /// Mint a founding device key on a scratch session BEFORE any custody exists, so the peer can be
165
+ /// booted to trust it (typed boot configuration) ahead of the genesis it will sign.
166
+ Future<protocol.SigningKeyPair> mintFoundingDevice() async {
167
+ final scratch = 'nms-founder-${_random.nextInt(1 << 30).toRadixString(36)}';
168
+ await reception.bindSession(
169
+ workspace: scratch,
170
+ session: scratch,
171
+ );
172
+ return reception.session(scratch).authorKeygen();
173
+ }
174
+
175
+ Future<NmsInstalledTestWorkspace> installWorkspace({
176
+ required String workspace,
177
+ required List<String> lawUsdzPaths,
178
+ String installedBy = 'nomos-test-harness',
179
+ protocol.SigningKeyPair? deviceKey,
180
+ }) async {
181
+ if (lawUsdzPaths.isEmpty) {
182
+ throw ArgumentError.value(
183
+ lawUsdzPaths, 'lawUsdzPaths', 'must not be empty');
184
+ }
185
+ await custody.provisionWorkspace(workspace);
186
+ await reception.bindSession(
187
+ workspace: workspace,
188
+ session: workspace,
189
+ );
190
+ if (deviceKey != null) {
191
+ await reception.session(workspace).refreshCredentials(
192
+ authorSecret: base64Encode(deviceKey.secret),
193
+ );
194
+ }
195
+
196
+ final controller = File('$runtimeDirectory/nomos.law.usdz');
197
+ if (!controller.existsSync()) {
198
+ throw StateError('test runtime has no ${controller.path}');
199
+ }
200
+ final initialized = await _kernel(
201
+ workspace,
202
+ protocol.CallRequest(
203
+ protocolVersion: 1,
204
+ requestId: '$workspace:initialize:${++_requestSequence}',
205
+ offer: protocol.OfferRequest(
206
+ genesis: protocol.GenesisOffer(),
207
+ lawUsdz: await controller.readAsBytes(),
208
+ authoring: _authoring(installedBy),
209
+ ),
210
+ ),
211
+ );
212
+ if (!initialized.hasOffer() || !initialized.offer.hasAdmitted()) {
213
+ throw StateError(
214
+ 'kernel returned ${initialized.whichOutcome().name} for workspace genesis',
215
+ );
216
+ }
217
+ final controllerHash = initialized.offer.admitted.installedLawHash;
218
+ if (controllerHash.isEmpty) {
219
+ throw StateError(
220
+ 'genesis offer did not return its installed controller identity');
221
+ }
222
+
223
+ final hashes = <String>[];
224
+ final domainKeys = <String>{};
225
+ for (final path in lawUsdzPaths) {
226
+ final file = File(path);
227
+ if (!file.existsSync() || !path.endsWith('.law.usdz')) {
228
+ throw StateError('compiled law archive is missing: $path');
229
+ }
230
+ final bytes = await file.readAsBytes();
231
+ final inspection = await _inspectLaw(bytes, file.uri.pathSegments.last);
232
+ final offered = await _kernel(
233
+ workspace,
234
+ protocol.CallRequest(
235
+ protocolVersion: 1,
236
+ requestId: '$workspace:install:${++_requestSequence}',
237
+ offer: protocol.OfferRequest(
238
+ modelLifecycle: protocol.ModelLifecycleIntent(
239
+ operation: protocol
240
+ .ModelLifecycleOperation.MODEL_LIFECYCLE_OPERATION_INSTALL,
241
+ installedBy: installedBy,
242
+ ),
243
+ authoring: _authoring(installedBy),
244
+ lawUsdz: bytes,
245
+ controllerLawHash: controllerHash,
246
+ ),
247
+ ),
248
+ );
249
+ if (!offered.hasOffer() || !offered.offer.hasAdmitted()) {
250
+ final outcome = offered.hasOffer()
251
+ ? offered.offer.whichOutcome().name
252
+ : offered.whichOutcome().name;
253
+ throw StateError('kernel refused installation of $path: $outcome');
254
+ }
255
+ hashes.add(inspection.identity);
256
+ domainKeys.addAll(inspection.domainKeys);
257
+ }
258
+
259
+ final founding =
260
+ deviceKey ?? await reception.session(workspace).authorKeygen();
261
+ await reception.session(workspace).refreshCredentials(
262
+ authorSecret: base64Encode(founding.secret),
263
+ );
264
+ return NmsInstalledTestWorkspace(
265
+ workspace: workspace,
266
+ controllerHash: controllerHash,
267
+ lawHashes: List.unmodifiable(hashes),
268
+ deviceKey: founding,
269
+ domainKeys: Set.unmodifiable(domainKeys),
270
+ );
271
+ }
272
+
273
+ /// Reboot the peer process on the SAME Git custody with [trustRootPublicKey] as its typed
274
+ /// boot configuration, then reopen every workspace this peer installed. The trust root is boot
275
+ /// configuration of the shell, never a kernel variant: a ceremony that signs with a founding
276
+ /// device key first boots the peer to trust that key.
277
+ Future<void> reboot({
278
+ required List<int> trustRootPublicKey,
279
+ Map<String, String> authorSecrets = const {},
280
+ Future<void> Function()? arrangeStoppedCustody,
281
+ }) async {
282
+ if (trustRootPublicKey.length != 32) {
283
+ throw ArgumentError.value(
284
+ trustRootPublicKey.length,
285
+ 'trustRootPublicKey',
286
+ 'must be a 32-byte public key',
287
+ );
288
+ }
289
+ await reception.dispose();
290
+ await transport.dispose();
291
+ await arrangeStoppedCustody?.call();
292
+ final restarted = await NodeRunnerTransport.start(
293
+ entry: _entry,
294
+ resolveFrom: _resolveFrom,
295
+ node: _node,
296
+ arguments: custody.processArguments(
297
+ runtimeDirectory,
298
+ trustRootPublicKey: base64Encode(trustRootPublicKey),
299
+ ),
300
+ onDiagnostic: _onDiagnostic,
301
+ );
302
+ final reopened = DartReception(restarted);
303
+ await reopened.ready;
304
+ transport = restarted;
305
+ reception = reopened;
306
+ for (final entry in authorSecrets.entries) {
307
+ await reception.bindSession(
308
+ workspace: entry.key,
309
+ session: entry.key,
310
+ );
311
+ await reception.session(entry.key).refreshCredentials(
312
+ authorSecret: entry.value,
313
+ );
314
+ }
315
+ }
316
+
317
+ Future<void> dispose() async {
318
+ try {
319
+ await reception.dispose();
320
+ } finally {
321
+ try {
322
+ await transport.dispose();
323
+ } finally {
324
+ await custody.dispose();
325
+ }
326
+ }
327
+ }
328
+ }
@@ -0,0 +1,169 @@
1
+ import 'dart:async';
2
+
3
+ import 'package:nomos_types/nomos_kernel_protocol.dart' as nomos_protocol;
4
+ import 'package:nomos_types/nomos_types.dart'
5
+ show NomosErrorInfo, NomosUnavailable, nomosErrorFromInfo;
6
+
7
+ import 'replica_readiness.dart' show NmsReplicaWake;
8
+
9
+ final class NmsTypedWatchHandle<T> {
10
+ const NmsTypedWatchHandle({required this.id, required this.stream});
11
+
12
+ final String id;
13
+ final Stream<T> stream;
14
+ }
15
+
16
+ /// Correlates generated Runtime v2 watch events with Dart stream listeners.
17
+ /// It neither polls nor evaluates a query; the peer runtime owns both.
18
+ final class NmsTypedWatchRegistry {
19
+ /// [synced] names each workspace whose sync round just completed; a watch
20
+ /// waiting for its copy registers at that moment rather than after a sleep.
21
+ NmsTypedWatchRegistry({Stream<String>? synced}) : _synced = synced;
22
+
23
+ final Stream<String>? _synced;
24
+ final Map<String, _RegisteredWatch> _watches = {};
25
+ int _sequence = 0;
26
+ bool _closed = false;
27
+
28
+ NmsTypedWatchHandle<T> open<T>({
29
+ required String session,
30
+ required T Function(nomos_protocol.WatchChanged) decode,
31
+ required Future<void> Function(String subscriptionId) start,
32
+ required Future<void> Function(String subscriptionId) stop,
33
+ }) {
34
+ if (_closed) throw StateError('Reception watch registry is closed');
35
+ final id = '$session:watch:${++_sequence}';
36
+ late final _TypedWatch<T> watch;
37
+ watch = _TypedWatch<T>(
38
+ synced: _synced,
39
+ decode: decode,
40
+ start: () {
41
+ if (_closed) throw StateError('Reception watch registry is closed');
42
+ _watches[id] = watch;
43
+ return start(id);
44
+ },
45
+ stop: () {
46
+ // After close() the realm close (or the host's transport disposal)
47
+ // releases every peer subscription; a late per-watch unwatch would
48
+ // only race that teardown.
49
+ if (_closed) return Future<void>.value();
50
+ if (_watches.remove(id) == null) return Future<void>.value();
51
+ return stop(id);
52
+ },
53
+ );
54
+ return NmsTypedWatchHandle<T>(id: id, stream: watch.controller.stream);
55
+ }
56
+
57
+ void deliver(nomos_protocol.WatchChanged changed) {
58
+ _watches[changed.subscriptionId]?.deliver(changed);
59
+ }
60
+
61
+ /// Close every watch locally. The reception closes the realm right after,
62
+ /// which releases the peer subscriptions in one round trip; no watch issues
63
+ /// its own unwatch once the registry is closed, so a registration still in
64
+ /// flight at teardown cannot surface as a late "transport is disposed".
65
+ Future<void> close() async {
66
+ if (_closed) return;
67
+ _closed = true;
68
+ final watches = _watches.values.toList(growable: false);
69
+ _watches.clear();
70
+ for (final watch in watches) {
71
+ unawaited(watch.close());
72
+ }
73
+ }
74
+ }
75
+
76
+ abstract interface class _RegisteredWatch {
77
+ void deliver(nomos_protocol.WatchChanged changed);
78
+ Future<void> close();
79
+ }
80
+
81
+ /// One listener owns one peer subscription. Register only after the listener
82
+ /// exists, and order cancellation after registration even when it is in flight.
83
+ /// A single-subscription controller buffers the initial response and pauses.
84
+ final class _TypedWatch<T> implements _RegisteredWatch {
85
+ final Stream<String>? _synced;
86
+ final T Function(nomos_protocol.WatchChanged) _decode;
87
+ final Future<void> Function() _start;
88
+ final Future<void> Function() _stop;
89
+ late final StreamController<T> controller;
90
+ Future<void>? _starting;
91
+ Future<void>? _stopping;
92
+
93
+ _TypedWatch({
94
+ required Stream<String>? synced,
95
+ required T Function(nomos_protocol.WatchChanged) decode,
96
+ required Future<void> Function() start,
97
+ required Future<void> Function() stop,
98
+ }) : _synced = synced,
99
+ _decode = decode,
100
+ _start = start,
101
+ _stop = stop {
102
+ controller = StreamController<T>(
103
+ onListen: () {
104
+ _starting = _startWhenReady().catchError(
105
+ (Object error, StackTrace stack) {
106
+ if (!controller.isClosed) controller.addError(error, stack);
107
+ },
108
+ );
109
+ },
110
+ onCancel: _cancel,
111
+ );
112
+ }
113
+
114
+ /// A workspace that is still opening, syncing or building its read index answers a
115
+ /// retryable [NomosUnavailable]. That is a wait, not a result: the watch registers once
116
+ /// the replica is ready instead of ending its stream on a state that has already passed.
117
+ Future<void> _startWhenReady() async {
118
+ final wake = NmsReplicaWake(_synced);
119
+ try {
120
+ for (var attempt = 0;; attempt++) {
121
+ wake.asking();
122
+ try {
123
+ return await _start();
124
+ } on NomosUnavailable catch (unavailable) {
125
+ if (!unavailable.retryable) rethrow;
126
+ await wake.wait(unavailable, attempt);
127
+ if (controller.isClosed || _stopping != null) return;
128
+ }
129
+ }
130
+ } finally {
131
+ await wake.close();
132
+ }
133
+ }
134
+
135
+ @override
136
+ void deliver(nomos_protocol.WatchChanged changed) {
137
+ if (controller.isClosed) return;
138
+ if (changed.hasFailure()) {
139
+ controller.addError(
140
+ nomosErrorFromInfo(NomosErrorInfo(
141
+ code: changed.failure.code,
142
+ message: changed.failure.message,
143
+ component: changed.failure.component,
144
+ operation: 'watch',
145
+ )),
146
+ );
147
+ return;
148
+ }
149
+ try {
150
+ controller.add(_decode(changed));
151
+ } catch (error, stackTrace) {
152
+ controller.addError(error, stackTrace);
153
+ }
154
+ }
155
+
156
+ Future<void> _cancel() => _stopping ??= () async {
157
+ if (_starting == null) return;
158
+ await _starting;
159
+ await _stop();
160
+ }();
161
+
162
+ @override
163
+ Future<void> close() async {
164
+ // Closing a paused controller may wait for its listener; remote cleanup
165
+ // must not depend on that listener resuming.
166
+ unawaited(controller.close());
167
+ await _cancel();
168
+ }
169
+ }
@@ -0,0 +1,27 @@
1
+ import 'reception/dart_reception.dart' show KernelProgress;
2
+
3
+ /// Read-only Peer Office telemetry for opening one workspace.
4
+ ///
5
+ /// This is presentation state. It cannot enter custody, affect authority, or
6
+ /// choose any lifecycle transition.
7
+ final class ApplicationWorkspaceOpenProgress {
8
+ const ApplicationWorkspaceOpenProgress({
9
+ required this.workspace,
10
+ required this.activeWorkspace,
11
+ required this.operation,
12
+ required this.openOperations,
13
+ required this.startedAt,
14
+ required this.observedAt,
15
+ required this.complete,
16
+ this.kernelProgress,
17
+ });
18
+
19
+ final String workspace;
20
+ final String activeWorkspace;
21
+ final String operation;
22
+ final int openOperations;
23
+ final DateTime startedAt;
24
+ final DateTime observedAt;
25
+ final bool complete;
26
+ final KernelProgress? kernelProgress;
27
+ }
package/dart/pubspec.lock CHANGED
@@ -9,6 +9,14 @@ packages:
9
9
  url: "https://pub.dev"
10
10
  source: hosted
11
11
  version: "100.0.0"
12
+ adaptive_number:
13
+ dependency: transitive
14
+ description:
15
+ name: adaptive_number
16
+ sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
17
+ url: "https://pub.dev"
18
+ source: hosted
19
+ version: "1.0.0"
12
20
  analyzer:
13
21
  dependency: transitive
14
22
  description:
@@ -81,6 +89,14 @@ packages:
81
89
  url: "https://pub.dev"
82
90
  source: hosted
83
91
  version: "3.0.7"
92
+ ed25519_edwards:
93
+ dependency: "direct main"
94
+ description:
95
+ name: ed25519_edwards
96
+ sha256: f3c3b109a0e470ee35f6346a155cab290578660852237fce10df6bbd92758534
97
+ url: "https://pub.dev"
98
+ source: hosted
99
+ version: "0.3.2"
84
100
  file:
85
101
  dependency: transitive
86
102
  description:
@@ -193,13 +209,20 @@ packages:
193
209
  url: "https://pub.dev"
194
210
  source: hosted
195
211
  version: "2.0.2"
212
+ nomos_peer_host:
213
+ dependency: "direct main"
214
+ description:
215
+ path: "../../nomos_peer_host"
216
+ relative: true
217
+ source: path
218
+ version: "0.1.0"
196
219
  nomos_types:
197
220
  dependency: "direct main"
198
221
  description:
199
222
  path: "../dart_types"
200
223
  relative: true
201
224
  source: path
202
- version: "0.10.0"
225
+ version: "0.11.2"
203
226
  package_config:
204
227
  dependency: "direct main"
205
228
  description:
package/dart/pubspec.yaml CHANGED
@@ -7,19 +7,24 @@ repository: https://github.com/Captain-App/nomos2
7
7
  description: >-
8
8
  Nomos 2 Dart client — generated domain values, intent payloads and application
9
9
  lifecycle types over the typed Nomos kernel protocol and USDA custody model.
10
- version: 0.65.3
10
+ version: 0.66.6
11
11
 
12
12
  environment:
13
13
  sdk: ^3.5.0
14
14
 
15
15
  dependencies:
16
+ # Runtime-to-platform capability ports. Contains no runtime implementation.
17
+ nomos_peer_host: ^0.1.0
16
18
  # The pure-data core (wire types, offer codec, NomosReads, schema validation, error
17
19
  # info). nomos_client depends on and re-exports it, so existing imports are unchanged.
18
20
  # For local monorepo dev, pubspec_overrides.yaml points this at ../dart_types.
19
- nomos_types: ^0.10.1
21
+ nomos_types: ^0.11.2
20
22
  fixnum: ^1.1.1
21
23
  json_schema: ^5.2.2
22
24
  crypto: ^3.0.0
25
+ # Pure-Dart RFC 8032 Ed25519: the shell signs the console enrolment request
26
+ # with the device key it already holds (console_enrolment.dart).
27
+ ed25519_edwards: ^0.3.1
23
28
  package_config: ^2.1.0
24
29
  meta: ^1.12.0
25
30
 
@@ -3,5 +3,7 @@
3
3
  # repo. Once nomos_types is published, consumers outside the repo resolve the hosted ^0.1.0;
4
4
  # this file only affects in-repo development.
5
5
  dependency_overrides:
6
+ nomos_peer_host:
7
+ path: ../../nomos_peer_host
6
8
  nomos_types:
7
9
  path: ../dart_types