@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,149 @@
1
+ /** Source-qualified access correspondence. This is law, not a client delivery loop.
2
+ * The source commits its publication and outbound offer together. The recipient
3
+ * keeps an ordering receipt and ordinary Zanzibar edges; no sender gets Home authority.
4
+ */
5
+ import { z } from "zod";
6
+ import { aggregate, instance } from "../aggregate.js";
7
+ import { directive, nomosImplementationDetail, type Directive } from "../directive.js";
8
+ import type { BusinessIntent } from "../intent.js";
9
+ import type { Ports } from "../ctx.js";
10
+ import { Lww } from "../drivers.js";
11
+ import { t } from "../fields.js";
12
+ import { set, withMarker } from "../ops.js";
13
+ import { query } from "../query.js";
14
+ import { readFrameworkDeclaredRows } from "../read.js";
15
+ import { endorsementOf } from "../principal_evidence.js";
16
+ import { RelationTuple, writeTuple, removeTuple } from "./relations.js";
17
+
18
+ declare const nomos: { sha256(input: string): string };
19
+
20
+ export const workspaceAccessPayload = z.object({
21
+ recipient: z.string().regex(/^user:[A-Za-z0-9][A-Za-z0-9_.-]*$/),
22
+ object: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.:/-]*$/),
23
+ relation: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/),
24
+ active: z.boolean(),
25
+ revision: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
26
+ });
27
+ export type WorkspaceAccessPublication = z.infer<typeof workspaceAccessPayload>;
28
+ export type WorkspaceAccessChange = Omit<WorkspaceAccessPublication, "revision">;
29
+
30
+ export const WorkspaceAccessPublication = nomosImplementationDetail(aggregate("WorkspaceAccessPublication", {
31
+ coordinate: t.string().merge(Lww),
32
+ revision: t.int().merge(Lww),
33
+ // Ordering metadata has the same visibility as the public RelationTuple facts;
34
+ // it contains neither device credentials nor encrypted business contents.
35
+ }, { global: true }).public());
36
+ export const workspaceAccessPublication = query("workspaceAccessPublication")
37
+ .key("coordinate").returns(WorkspaceAccessPublication);
38
+
39
+ /** Ordering only. Discovery is the RelationTuple below, not another bookmark index. */
40
+ export const WorkspaceAccessReceipt = nomosImplementationDetail(aggregate("WorkspaceAccessReceipt", {
41
+ coordinate: t.string().merge(Lww),
42
+ revision: t.int().merge(Lww),
43
+ subject: t.string().merge(Lww),
44
+ }, { global: true }).public());
45
+ export const workspaceAccessReceipt = query("workspaceAccessReceipt")
46
+ .key("coordinate").returns(WorkspaceAccessReceipt);
47
+
48
+ /** Home's ordinary Zanzibar discovery read. It has its own nominal identity;
49
+ * it must not collide with generic relation queries installed by other domains. */
50
+ export const receivedWorkspaceAccess = nomosImplementationDetail(query("receivedWorkspaceAccess")
51
+ .key("object").returns(RelationTuple));
52
+
53
+ export function accessCoordinate(recipient: string, object: string): string {
54
+ return nomos.sha256(JSON.stringify([recipient, object]));
55
+ }
56
+ export const RECEIVED_ACCESS_RELATION = "receivedAccess";
57
+ export function receivedAccessObject(recipient: string): string {
58
+ return `received-access:${recipient}`;
59
+ }
60
+
61
+ /** A fresh publication gets a fresh userset address. Revoked leaves are never
62
+ * resurrected (the kernel's remove-wins rule), including a later lawful re-share. */
63
+ export function receivedAccessSubject(source: string, p: WorkspaceAccessPublication): string {
64
+ return `shared:${source}/${p.object}/${p.revision}#${p.relation}`;
65
+ }
66
+
67
+ export const recordReceivedWorkspaceAccess = nomosImplementationDetail(directive("recordReceivedWorkspaceAccess")
68
+ .ensures(RelationTuple)
69
+ .payload(workspaceAccessPayload)
70
+ .plan((p, ctx) => {
71
+ const actor = endorsementOf(ctx.principal().asAttribution())?.principal ?? "";
72
+ if (!actor.startsWith("workspace:")) throw new Error("share requires a verified workspace speaker");
73
+ const source = actor.slice("workspace:".length);
74
+ const coordinate = `${source}/${accessCoordinate(p.recipient, p.object)}`;
75
+ const rows = readFrameworkDeclaredRows(workspaceAccessReceipt, WorkspaceAccessReceipt, { coordinate });
76
+ if (rows.length > 1) throw new Error("duplicate workspace access receipt");
77
+ const previous = rows[0];
78
+ // Old instruments are acknowledged without re-applying their consequences.
79
+ if ((previous?.revision ?? 0) >= p.revision) return [];
80
+ const object = receivedAccessObject(p.recipient);
81
+ const subject = receivedAccessSubject(source, p);
82
+ const at = new Date(ctx.clock().physical).toISOString();
83
+ const receipt = instance(WorkspaceAccessReceipt, `access-receipt:${coordinate}`);
84
+ return [
85
+ ...(previous?.subject ? removeTuple({ object, relation: RECEIVED_ACCESS_RELATION,
86
+ subject: previous.subject, grantedBy: actor, grantedAt: at, revokedBy: actor, revokedAt: at }) : []),
87
+ ...(p.active ? writeTuple({ object, relation: RECEIVED_ACCESS_RELATION, subject,
88
+ grantedBy: actor, grantedAt: at }) : []),
89
+ withMarker(set(receipt, "coordinate", coordinate), "ensures"),
90
+ set(receipt, "revision", p.revision),
91
+ set(receipt, "subject", p.active ? subject : ""),
92
+ ];
93
+ })
94
+ .affectsOptional()
95
+ .alsoEnsuresOptional(WorkspaceAccessReceipt)
96
+ .reads(workspaceAccessReceipt)
97
+ .acceptsVerifiedWorkspaceClaim());
98
+
99
+ /** Attach one typed, durable correspondence to a normal public offer. No session,
100
+ * network, key, clock cache or retry state is introduced by this wrapper. */
101
+ export function publishesWorkspaceAccess<P>(
102
+ action: BusinessIntent<P>,
103
+ change: (facts: P, ctx: Ports) => WorkspaceAccessChange | null,
104
+ recipientWorkspace: (recipient: string) => string,
105
+ receiver?: Directive<WorkspaceAccessPublication>,
106
+ ): BusinessIntent<P>;
107
+ export function publishesWorkspaceAccess<P>(
108
+ action: Directive<P>,
109
+ change: (facts: P, ctx: Ports) => WorkspaceAccessChange | null,
110
+ recipientWorkspace: (recipient: string) => string,
111
+ receiver?: Directive<WorkspaceAccessPublication>,
112
+ ): Directive<P>;
113
+ export function publishesWorkspaceAccess<P>(
114
+ action: Directive<P>,
115
+ change: (facts: P, ctx: Ports) => WorkspaceAccessChange | null,
116
+ recipientWorkspace: (recipient: string) => string,
117
+ receiver: Directive<WorkspaceAccessPublication> = recordReceivedWorkspaceAccess,
118
+ ): Directive<P> {
119
+ const publication = (facts: P, ctx: Ports): WorkspaceAccessPublication => {
120
+ const access = change(facts, ctx);
121
+ if (access === null) throw new Error("this offer has no identified access recipient");
122
+ const coordinate = accessCoordinate(access.recipient, access.object);
123
+ const rows = readFrameworkDeclaredRows(workspaceAccessPublication, WorkspaceAccessPublication, { coordinate });
124
+ if (rows.length > 1) throw new Error("duplicate workspace access publication");
125
+ return workspaceAccessPayload.parse({ ...access, revision: (rows[0]?.revision ?? 0) + 1 });
126
+ };
127
+ return {
128
+ ...action,
129
+ secondaryOutputs: [...(action.secondaryOutputs ?? []), {
130
+ aggregateId: WorkspaceAccessPublication.id, aggregate: WorkspaceAccessPublication, marker: "ensures", optional: true,
131
+ }],
132
+ declaredQueryReads: [...(action.declaredQueryReads ?? []), workspaceAccessPublication],
133
+ plan(facts, ctx) {
134
+ const ops = action.plan(facts, ctx);
135
+ if (change(facts, ctx) === null) return ops;
136
+ const p = publication(facts, ctx);
137
+ const coordinate = accessCoordinate(p.recipient, p.object);
138
+ const counter = instance(WorkspaceAccessPublication, `access-publication:${coordinate}`);
139
+ return [...ops, withMarker(set(counter, "coordinate", coordinate), "ensures"), set(counter, "revision", p.revision)];
140
+ },
141
+ workspaceEffects: [...(action.workspaceEffects ?? []), {
142
+ target: receiver,
143
+ // Payload and destination are evaluated from the same captured ports by the plan encoder.
144
+ destination: { kind: "workspace", address: (facts, ctx) => recipientWorkspace(publication(facts, ctx).recipient) },
145
+ when: (facts, ctx) => change(facts, ctx) !== null,
146
+ payload: publication,
147
+ }],
148
+ };
149
+ }
@@ -35,10 +35,40 @@
35
35
  * workspace scan / projection read / ambient "current world" read — only the declared refs.
36
36
  */
37
37
 
38
+ import type { AggregateHandle, ReadModelRow } from "../aggregate.js";
39
+ import type { Directive } from "../directive.js";
40
+ import type { ValueObject, NominalCase } from "../value_object.js";
38
41
  import type { PointGuardSpec } from "../point_guard.js";
39
42
 
40
43
  /** A TYPED verdict — identical shape to the aggregate invariant (the engine parses both). */
41
- export type WorkspaceInvariantVerdict = { accept: true } | { reject: string };
44
+ export type WorkspaceInvariantVerdict<R = string> = { accept: true } | { reject: R };
45
+ export const accept = (): { accept: true } => ({ accept: true });
46
+ export const reject = <R>(value: R): { reject: R } => ({ reject: value });
47
+
48
+ declare const READ_SNAPSHOT: unique symbol;
49
+ type TypedReadBinding<B extends string, R> = InvariantReadBinding & {
50
+ readonly binding: B;
51
+ readonly [READ_SNAPSHOT]?: R;
52
+ };
53
+ type ReadRow<A> = A extends AggregateHandle<string, infer F> ? ReadModelRow<F> : Record<string, unknown>;
54
+ type ReadBuilder<B extends string, R> = {
55
+ at(id: string): TypedReadBinding<B, R>;
56
+ fromPayload(path: string | readonly string[], options?: { readonly prefix?: string; readonly suffix?: string }): TypedReadBinding<B, R>;
57
+ fromOptionalPayload(path: string | readonly string[], options?: { readonly prefix?: string; readonly suffix?: string }): TypedReadBinding<B, R | undefined>;
58
+ fromTemplate(parts: readonly InvariantReadIdPart[], options?: { readonly optional?: boolean }): TypedReadBinding<B, R | undefined>;
59
+ forEach(path: string | readonly string[], parts: readonly InvariantReadIdPart[], options?: { readonly optional?: boolean }): TypedReadBinding<`${B}${number}`, R | undefined>;
60
+ pre(): ReadBuilder<B, R>;
61
+ post(): ReadBuilder<B, R>;
62
+ };
63
+ type ReadSnapshots<B extends readonly InvariantReadBinding[]> = {
64
+ [R in B[number] as R["binding"]]: R extends TypedReadBinding<string, infer V> ? V : Record<string, unknown>;
65
+ };
66
+ declare const READ_SET_SNAPSHOTS: unique symbol;
67
+ type TypedReadSet<S> = WorkspaceInvariantReads & { readonly [READ_SET_SNAPSHOTS]?: S };
68
+ type SnapshotsOf<R> = typeof READ_SET_SNAPSHOTS extends keyof R
69
+ ? R extends TypedReadSet<infer S> ? S : never
70
+ : Record<string, Record<string, unknown>>;
71
+
42
72
 
43
73
  /**
44
74
  * One DECLARED read: the aggregate TYPE (qualified `domain.Aggregate`) + the concrete instance
@@ -120,22 +150,10 @@ function aggregateName(aggregate: { readonly id: string } | string): string {
120
150
 
121
151
  /** Begin one typed, bounded aggregate read. Prefer an aggregate handle; strings remain available
122
152
  * for framework composition where the declaration is intentionally late-bound. */
123
- export function readRef(
124
- binding: string,
125
- aggregate: { readonly id: string } | string,
126
- ): {
127
- at(id: string): InvariantReadBinding;
128
- fromPayload(path: string | readonly string[], options?: { readonly prefix?: string; readonly suffix?: string }): InvariantReadBinding;
129
- fromOptionalPayload(path: string | readonly string[], options?: { readonly prefix?: string; readonly suffix?: string }): InvariantReadBinding;
130
- fromTemplate(parts: readonly InvariantReadIdPart[], options?: { readonly optional?: boolean }): InvariantReadBinding;
131
- forEach(
132
- path: string | readonly string[],
133
- parts: readonly InvariantReadIdPart[],
134
- options?: { readonly optional?: boolean },
135
- ): InvariantReadBinding;
136
- pre(): ReturnType<typeof readRef>;
137
- post(): ReturnType<typeof readRef>;
138
- } {
153
+ export function readRef<const B extends string, A extends { readonly id: string } | string>(
154
+ binding: B,
155
+ aggregate: A,
156
+ ): ReadBuilder<B, ReadRow<A>> {
139
157
  const build = (state: "pre" | "post") => ({
140
158
  at(id: string): InvariantReadBinding {
141
159
  return { binding, aggregate: aggregateName(aggregate), state, id: { source: "literal", value: id } };
@@ -189,7 +207,7 @@ export function readRef(
189
207
  pre: () => build("pre"),
190
208
  post: () => build("post"),
191
209
  });
192
- return build("post");
210
+ return build("post") as ReadBuilder<B, ReadRow<A>>;
193
211
  }
194
212
 
195
213
  function valueAtPath(value: unknown, path: readonly string[]): unknown {
@@ -247,7 +265,7 @@ export function resolveInvariantReadId(
247
265
 
248
266
  /** Declare a bounded set of generic point reads. The returned callable keeps authoring-time tests
249
267
  * ergonomic, while the non-enumerable metadata is what the compiler lowers into USDA. */
250
- export function readSet(...bindings: readonly InvariantReadBinding[]): WorkspaceInvariantReads {
268
+ export function readSet<const B extends readonly InvariantReadBinding[]>(...bindings: B): TypedReadSet<ReadSnapshots<B>> {
251
269
  const selector = ((ctx: { intent: Record<string, unknown> }) => {
252
270
  const refs: InvariantRef[] = [];
253
271
  for (const binding of bindings) {
@@ -379,7 +397,9 @@ export interface WorkspaceInvariantDecl {
379
397
  /** Typed generic read recipes lowered into USDA. Absent only for not-yet-migrated callbacks. */
380
398
  readonly __nomosReadBindings?: readonly InvariantReadBinding[];
381
399
  /** The executable predicate — ships in the engine bundle, NOT the manifest. */
382
- readonly assert: WorkspaceInvariantAssert;
400
+ readonly assert: (...args: Parameters<WorkspaceInvariantAssert>) => WorkspaceInvariantVerdict<unknown>;
401
+ /** Authenticated nominal output contract; absent preserves the legacy string gate. */
402
+ readonly refusal?: ValueObject<unknown>;
383
403
  /**
384
404
  * THE DECLASSIFY WAIVER (nomosFlowGate rule 4 — architecture/security_model.md): present iff
385
405
  * the author acknowledged that this invariant's refusal MAY correlate with a secret it reads
@@ -390,7 +410,7 @@ export interface WorkspaceInvariantDecl {
390
410
  readonly declassify?: string;
391
411
  /** Framework-owned evaluator whose complete semantics are part of the named kernel ABI.
392
412
  * Tenant-authored invariants omit this and execute their sealed USDA plan. */
393
- readonly __nomosEvaluator?: "birth-quota-v1" | "founder-signer-write-once-v1" | "point-guard-v1";
413
+ readonly __nomosEvaluator?: "birth-quota-v1" | "founder-signer-write-once-v1" | "founder-signer-write-once-v2" | "point-guard-v1";
394
414
  /** Typed point-state law consumed directly by the kernel when evaluator is `point-guard-v1`. */
395
415
  readonly __nomosPointGuard?: PointGuardSpec;
396
416
  /** Framework-only provenance used to keep compiler errors on the tenant-authored surface. */
@@ -404,45 +424,46 @@ export interface WorkspaceInvariantDecl {
404
424
  * The staged builder makes every step REQUIRED at the type level — you cannot register a
405
425
  * half-declared invariant (no `.on`, no `.reads`, or no `.assert`).
406
426
  */
427
+ type InvariantContext<I> = Omit<NonNullable<Parameters<WorkspaceInvariantAssert>[1]>, "intent"> & { intent: I };
428
+ type TypedAssert<I, S, R> = (snapshots: S, ctx: InvariantContext<I>) => WorkspaceInvariantVerdict<R>;
429
+ interface InvariantAssertions<I, S, R = string> {
430
+ assert(predicate: TypedAssert<I, S, R>): WorkspaceInvariantDecl;
431
+ declassify(reason: string): InvariantAssertions<I, S, R>;
432
+ }
433
+ interface InvariantReadsBuilder<I, S> extends InvariantAssertions<I, S> {
434
+ refuses<const N extends string, V>(refusal: ValueObject<V> & { readonly name: N }):
435
+ InvariantAssertions<I, S, NominalCase<N, V>>;
436
+ }
437
+
407
438
  export function workspaceInvariant(id: string): {
408
- on(directiveId: string): {
409
- reads(reads: WorkspaceInvariantReads): {
410
- assert(assert: WorkspaceInvariantAssert): WorkspaceInvariantDecl;
411
- /** Acknowledge an intended secret-correlated refusal (nomosFlowGate rule 4). The reason
412
- * rides the `nomosFlowGate` era key; then chain `.assert(...)` as usual. */
413
- declassify(reason: string): { assert(assert: WorkspaceInvariantAssert): WorkspaceInvariantDecl };
414
- };
415
- };
439
+ on<I>(directive: Directive<I>): { reads<R extends WorkspaceInvariantReads>(reads: R): InvariantReadsBuilder<I, SnapshotsOf<R>> };
440
+ on(directive: string): { reads<R extends WorkspaceInvariantReads>(reads: R): InvariantReadsBuilder<Record<string, unknown>, SnapshotsOf<R>> };
416
441
  } {
417
- const finish = (directiveId: string, reads: WorkspaceInvariantReads, declassify: string | undefined) => ({
418
- assert(assert: WorkspaceInvariantAssert): WorkspaceInvariantDecl {
442
+ const finish = (directiveId: string, reads: WorkspaceInvariantReads, declassify?: string, refusal?: ValueObject<unknown>) => ({
443
+ assert(predicate: WorkspaceInvariantDecl["assert"]): WorkspaceInvariantDecl {
419
444
  const readBindings = nativeReadBindings(reads);
420
445
  return {
421
- id,
422
- on: directiveId,
423
- reads,
446
+ id, on: directiveId, reads,
424
447
  ...(readBindings === undefined ? {} : { __nomosReadBindings: readBindings }),
425
- assert,
426
- ...(declassify !== undefined ? { declassify } : {}),
427
- __isWorkspaceInvariant: true as const,
448
+ assert: predicate,
449
+ ...(refusal === undefined ? {} : { refusal }),
450
+ ...(declassify === undefined ? {} : { declassify }),
451
+ __isWorkspaceInvariant: true,
428
452
  };
429
453
  },
454
+ declassify(reason: string) {
455
+ if (!reason.trim()) throw new Error(`workspaceInvariant('${id}').declassify needs a non-empty reason`);
456
+ return finish(directiveId, reads, reason, refusal);
457
+ },
458
+ refuses(contract: ValueObject<unknown>) {
459
+ return finish(directiveId, reads, declassify, contract);
460
+ },
430
461
  });
462
+ // One erased implementation boundary backs the typed authoring stages. Runtime
463
+ // admission rechecks the law contract; no generic values leak into predicates.
431
464
  return {
432
- on(directiveId: string) {
433
- return {
434
- reads(reads: WorkspaceInvariantReads) {
435
- return {
436
- assert: finish(directiveId, reads, undefined).assert,
437
- declassify(reason: string) {
438
- if (typeof reason !== "string" || reason.trim().length === 0) {
439
- throw new Error(`workspaceInvariant('${id}').declassify(reason) needs a non-empty human reason — it is the audit record for an intended secret-correlated refusal.`);
440
- }
441
- return finish(directiveId, reads, reason);
442
- },
443
- };
444
- },
445
- };
465
+ on(directive: string | Directive<any>) {
466
+ return { reads: (reads: WorkspaceInvariantReads) => finish(typeof directive === "string" ? directive : directive.id, reads) };
446
467
  },
447
- };
468
+ } as ReturnType<typeof workspaceInvariant>;
448
469
  }