@githolon/dsl 0.108.7 → 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.
- package/assets/operation-contract.wasm +0 -0
- package/check_package.mjs +12 -15
- package/compile_package.mjs +17 -18
- package/compile_proof.mjs +16 -1
- package/dart/CHANGELOG.md +76 -1
- package/dart/README.md +25 -2
- package/dart/lib/src/admission_decision.dart +41 -0
- package/dart/lib/src/application_framework_calls.dart +52 -2
- package/dart/lib/src/application_model_adoption.dart +187 -0
- package/dart/lib/src/application_status.dart +73 -0
- package/dart/lib/src/console_enrolment.dart +271 -0
- package/dart/lib/src/console_http_io.dart +26 -0
- package/dart/lib/src/console_http_stub.dart +7 -0
- package/dart/lib/src/dev_cloud.dart +69 -22
- package/dart/lib/src/generated_call.dart +83 -23
- package/dart/lib/src/kernel_primitives.dart +119 -0
- package/dart/lib/src/nms_conformance_runtime.dart +1 -1
- package/dart/lib/src/nms_generated_runtime.dart +32 -10
- package/dart/lib/src/nms_test_environment.dart +1 -1
- package/dart/lib/src/node_runner_transport.dart +41 -46
- package/dart/lib/src/observed_session_directory.dart +70 -0
- package/dart/lib/src/operation_receipts.dart +112 -0
- package/dart/lib/src/peer_application_streams.dart +103 -0
- package/dart/lib/src/reception/dart_reception.dart +4280 -0
- package/dart/lib/src/reception/event_desk.dart +211 -0
- package/dart/lib/src/reception/extremum_read.dart +46 -0
- package/dart/lib/src/reception/local_copies.dart +371 -0
- package/dart/lib/src/reception/peer_office_connection.dart +11 -0
- package/dart/lib/src/reception/progress_desk.dart +267 -0
- package/dart/lib/src/reception/reception_contract.dart +11 -0
- package/dart/lib/src/reception/reception_session.dart +284 -0
- package/dart/lib/src/reception/sync_diagnostics.dart +26 -0
- package/dart/lib/src/reception/workspace_preparation_report.dart +126 -0
- package/dart/lib/src/replica_readiness.dart +123 -0
- package/dart/lib/src/runner/node-entry.mjs +23905 -15774
- package/dart/lib/src/runtime_v2_gateway.dart +56 -3
- package/dart/lib/src/runtime_v2_transport.dart +544 -3
- package/dart/lib/src/session_bound.dart +200 -311
- package/dart/lib/src/signing_identity_kernel.dart +84 -0
- package/dart/lib/src/sync_status_projection.dart +548 -0
- package/dart/lib/src/sync_status_reducer.dart +170 -0
- package/dart/lib/src/test_harness.dart +809 -1153
- package/dart/lib/src/testing/test_custody.dart +66 -0
- package/dart/lib/src/testing/test_peer.dart +328 -0
- package/dart/lib/src/typed_watch_registry.dart +169 -0
- package/dart/lib/src/workspace_open_progress.dart +27 -0
- package/dart/pubspec.lock +24 -1
- package/dart/pubspec.yaml +7 -2
- package/dart/pubspec_overrides.yaml +2 -0
- package/dart/test/admission_decision_test.dart +48 -0
- package/dart/test/background_model_adoption_test.dart +228 -0
- package/dart/test/bundle_version_pairing_test.dart +4 -4
- package/dart/test/child_authentication_repair_test.dart +359 -0
- package/dart/test/cloud_bound_local_shell_test.dart +119 -0
- package/dart/test/console_enrolment_refusal_test.dart +52 -0
- package/dart/test/console_enrolment_test.dart +227 -0
- package/dart/test/errors_test.dart +5 -5
- package/dart/test/event_plane_seam_test.dart +50 -164
- package/dart/test/extremum_read_test.dart +58 -0
- package/dart/test/fixtures/wedge/wedge-entry.mjs +3 -21
- package/dart/test/generated_query_test.dart +32 -0
- package/dart/test/harness_phase_timeout_test.dart +18 -23
- package/dart/test/kernel_author_after_read_test.dart +242 -0
- package/dart/test/kernel_fence_test.dart +137 -0
- package/dart/test/local_copies_test.dart +222 -0
- package/dart/test/model_adoption_test.dart +198 -0
- package/dart/test/node_peer_local_custody_test.dart +153 -0
- package/dart/test/offer_authentication_proof_test.dart +352 -52
- package/dart/test/operation_compatibility_test.dart +151 -0
- package/dart/test/platform_credential_effect_test.dart +386 -0
- package/dart/test/receiving_group_open_test.dart +213 -0
- package/dart/test/reception/workspace_preparation_report_test.dart +103 -0
- package/dart/test/reception_span_trace_test.dart +23 -0
- package/dart/test/replica_readiness_test.dart +156 -0
- package/dart/test/runtime_projections_test.dart +92 -0
- package/dart/test/runtime_v2_gateway_test.dart +131 -0
- package/dart/test/signing_identity_kernel_test.dart +75 -0
- package/dart/test/sync_status_preparation_report_test.dart +29 -0
- package/dart/test/sync_status_reducer_test.dart +419 -0
- package/dart/test/test_harness_test.dart +71 -95
- package/dart/test/typed_query_watch_test.dart +170 -0
- package/dart/test/typed_watch_registry_test.dart +249 -0
- package/dart_lints/README.md +18 -0
- package/dart_lints/lib/nomos_lints.dart +70 -0
- package/dart_lints/pubspec.lock +580 -0
- package/dart_lints/pubspec.yaml +12 -0
- package/dart_lints/test/reference_identity_test.dart +75 -0
- package/dart_types/CHANGELOG.md +18 -0
- package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
- package/dart_types/lib/nomos_types.dart +9 -1
- package/dart_types/lib/src/admission_decision.dart +37 -0
- package/dart_types/lib/src/aggregate_meta.dart +1 -1
- package/dart_types/lib/src/approved_model.dart +65 -0
- package/dart_types/lib/src/custody.dart +10 -18
- package/dart_types/lib/src/error_info.dart +4 -4
- package/dart_types/lib/src/errors.dart +29 -29
- package/dart_types/lib/src/foreign_ref.dart +62 -33
- package/dart_types/lib/src/local_work_rejected.dart +3 -3
- package/dart_types/lib/src/nomos_ref.dart +3 -1
- package/dart_types/lib/src/principal.dart +2 -2
- package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
- package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
- package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
- package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
- package/dart_types/lib/src/runtime_outcome.dart +133 -0
- package/dart_types/lib/src/subscriptions.dart +116 -23
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/extremum_subscriptions_test.dart +40 -0
- package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
- package/dart_types/test/nomos_ref_address_test.dart +25 -0
- package/dart_types/test/ordered_subscriptions_test.dart +34 -0
- package/operation_contract_check.mjs +24 -0
- package/package.json +11 -6
- package/src/aggregate.ts +70 -10
- package/src/application_topology.ts +18 -11
- package/src/attested.ts +3 -0
- package/src/attested_core.ts +46 -3
- package/src/birth_meter_ensure.ts +19 -7
- package/src/births.ts +29 -4
- package/src/build_package.ts +140 -13
- package/src/business_birth.ts +181 -4
- package/src/codegen_call_proto.ts +1274 -0
- package/src/codegen_call_usda.ts +49 -6
- package/src/codegen_dart.ts +79 -44
- package/src/codegen_dart_client.ts +458 -800
- package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
- package/src/codegen_dart_framework_calls.ts +320 -37
- package/src/codegen_dart_indexed_variant.ts +159 -0
- package/src/codegen_dart_scenario.ts +42 -13
- package/src/codegen_proof.ts +3 -3
- package/src/codegen_provider_dart.ts +5 -0
- package/src/codegen_query_proto.ts +158 -0
- package/src/codegen_refusal.ts +189 -0
- package/src/codegen_result_proto.ts +931 -0
- package/src/codegen_result_usda.ts +4 -0
- package/src/codegen_ts.ts +464 -616
- package/src/codegen_workspace_access.ts +105 -0
- package/src/compatibility_graph.ts +759 -0
- package/src/compatibility_usda.ts +264 -0
- package/src/compile_package_main.ts +1994 -1189
- package/src/custody_placement.ts +156 -0
- package/src/custody_placement_usda.ts +91 -0
- package/src/decl_shapes.ts +21 -2
- package/src/describe_model.ts +1 -0
- package/src/directive.ts +59 -2
- package/src/drivers.ts +51 -0
- package/src/engine_entry.ts +52 -8
- package/src/evolve_preview.ts +11 -4
- package/src/exists.ts +2 -0
- package/src/fields.ts +75 -11
- package/src/flow_gate.ts +2 -1
- package/src/framework/application_home.ts +170 -18
- package/src/framework/attested_receipts.ts +8 -3
- package/src/framework/auth_provider_law.ts +169 -9
- package/src/framework/birth_certificate_law.ts +4 -0
- package/src/framework/capability.ts +34 -3
- package/src/framework/child_authentication.ts +346 -0
- package/src/framework/console_governance.ts +295 -0
- package/src/framework/delegated_roles.ts +301 -0
- package/src/framework/domain_lifecycle.ts +26 -13
- package/src/framework/founding_genesis.ts +193 -0
- package/src/framework/framework_aggregates.ts +1 -1
- package/src/framework/genesis.ts +6 -1
- package/src/framework/governance_relations.ts +19 -0
- package/src/framework/home.ts +5 -734
- package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
- package/src/framework/model_authority_repair.ts +116 -0
- package/src/framework/model_authority_seed.ts +185 -0
- package/src/framework/model_transition.ts +211 -0
- package/src/framework/owned_custody.ts +1 -1
- package/src/framework/principal_enrollment.ts +302 -0
- package/src/framework/receiving_group.ts +857 -0
- package/src/framework/receiving_group_recovery.ts +314 -0
- package/src/framework/relations.ts +4 -8
- package/src/framework/signing_identity.ts +242 -95
- package/src/framework/source_roster.ts +11 -5
- package/src/framework/workspace_access.ts +149 -0
- package/src/framework/workspace_invariant.ts +73 -52
- package/src/framework/workspaces.ts +407 -40
- package/src/framework_call_definitions.ts +32 -3
- package/src/generated_client_bundle_boundary.ts +97 -0
- package/src/generated_client_names.ts +1 -0
- package/src/identity_usda.ts +27 -0
- package/src/index.ts +183 -12
- package/src/indexed_variant.ts +83 -0
- package/src/intent.ts +173 -45
- package/src/law_check.ts +8 -5
- package/src/law_dependency_index.ts +231 -0
- package/src/law_graph.ts +508 -71
- package/src/law_graph_usda.ts +170 -24
- package/src/law_identity.ts +119 -81
- package/src/law_source_map.ts +4 -1
- package/src/law_units.ts +498 -0
- package/src/law_value_type.ts +7 -3
- package/src/member_authentication.ts +302 -0
- package/src/null_meta.ts +1 -1
- package/src/openusd_compiled_layer.ts +132 -0
- package/src/operation_contract_check.ts +31 -0
- package/src/ordered_read.ts +2 -1
- package/src/package_config.ts +33 -12
- package/src/package_dependencies.ts +1 -0
- package/src/plan_source_slice.ts +30 -1
- package/src/protobuf_field_number.ts +36 -0
- package/src/provenance_wire.ts +6 -0
- package/src/query.ts +2 -1
- package/src/read.ts +50 -0
- package/src/relation.ts +4 -1
- package/src/relation_schema.ts +15 -2
- package/src/report.ts +2 -2
- package/src/sqlite_computation_bundle.ts +78 -0
- package/src/sqlite_computed.ts +102 -0
- package/src/sqlite_counts.ts +154 -0
- package/src/sqlite_layout.ts +823 -0
- package/src/sqlite_reads.ts +275 -0
- package/src/sqlite_samples.ts +185 -0
- package/src/stable_id_identity_bridge.ts +1 -1
- package/src/stable_ids_for_module.ts +16 -4
- package/src/test_call_usda.ts +6 -6
- package/src/usda_relationship_integrity.ts +20 -3
- package/src/usda_text.ts +21 -1
- package/src/value_object.ts +81 -11
- package/src/wire.ts +22 -0
- package/src/wire_encode.ts +227 -20
- package/src/workspace_sharding.ts +15 -6
- package/src/workspace_sharing.ts +51 -49
- package/src/zod_introspection.ts +2 -0
- package/compat_package.mjs +0 -46
- package/dart/lib/src/home.dart +0 -15
- package/dart/lib/src/runner/offline-install.mjs +0 -15367
- package/dart/lib/src/source_trust.dart +0 -51
- package/dart/lib/src/webview_bridge.dart +0 -6540
- package/dart/lib/src/workspace_name.dart +0 -30
- package/dart/test/acquire_session_credentials_test.dart +0 -150
- package/dart/test/acquire_session_test.dart +0 -534
- package/dart/test/adv_realm_interference_test.dart +0 -600
- package/dart/test/cloud_bound_topology_test.dart +0 -168
- package/dart/test/cluster_births_test.dart +0 -202
- package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
- package/dart/test/cluster_local_autosync_test.dart +0 -123
- package/dart/test/cluster_scale_test.dart +0 -122
- package/dart/test/compat_test.dart +0 -61
- package/dart/test/dlq_session_surface_test.dart +0 -222
- package/dart/test/first_app_gauntlet_test.dart +0 -386
- package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
- package/dart/test/four_layer_nested_topology_test.dart +0 -290
- package/dart/test/home_parity_test.dart +0 -13
- package/dart/test/local_sync_inert_test.dart +0 -107
- package/dart/test/node_runner_transport_test.dart +0 -78
- package/dart/test/parent_signer_recovery_test.dart +0 -155
- package/dart/test/residency_refusal_test.dart +0 -49
- package/dart/test/sealing_client_test.dart +0 -181
- package/dart/test/session_bound_test.dart +0 -285
- package/dart/test/stale_bundle_test.dart +0 -80
- package/dart/test/vo_read_typing_test.dart +0 -131
- package/dart/test/watch_after_offer_stall_test.dart +0 -100
- package/dart/test/webview_bridge_test.dart +0 -1930
- package/dart/test/workspace_name_test.dart +0 -24
- package/runtime/generated-application-host.js +0 -22860
- package/src/codegen_query_usda.ts +0 -214
- package/src/compat_manifest.ts +0 -26
- package/src/compat_package_main.ts +0 -224
- package/src/shape_compat.ts +0 -352
- package/src/usd_state.ts +0 -505
package/src/law_graph.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { DomainModule } from "./codegen_dart.js";
|
|
5
5
|
import type { z } from "zod";
|
|
6
6
|
import { finishCount } from "./count.js";
|
|
7
|
+
import { SIGNER_DELEGATION_PREFIX } from "./framework/signing_identity.js";
|
|
7
8
|
import { finishExists } from "./exists.js";
|
|
8
9
|
import { finishExtremum } from "./extremum.js";
|
|
9
10
|
import { finishSum } from "./sum.js";
|
|
@@ -15,9 +16,12 @@ import {
|
|
|
15
16
|
mintStructuralLawSid,
|
|
16
17
|
type LawEntityKind,
|
|
17
18
|
type LawIdentityCarry,
|
|
19
|
+
type LawIdentityEntity,
|
|
18
20
|
type LawIdentityRegistry,
|
|
21
|
+
type LawOperationFieldWire,
|
|
19
22
|
} from "./law_identity.js";
|
|
20
|
-
import type { ReferentialMarker } from "./directive.js";
|
|
23
|
+
import type { Directive, ReferentialMarker } from "./directive.js";
|
|
24
|
+
import type { MemberAuthentication } from "./member_authentication.js";
|
|
21
25
|
import type { CanonicalPred } from "./predicate.js";
|
|
22
26
|
import type { PointGuardPredicate } from "./point_guard.js";
|
|
23
27
|
import {
|
|
@@ -27,7 +31,7 @@ import {
|
|
|
27
31
|
type Rewrite,
|
|
28
32
|
} from "./relation_schema.js";
|
|
29
33
|
import type { StableFieldEvolution, StableIds } from "./stable_ids_types.js";
|
|
30
|
-
import { isBusinessIntent } from "./intent.js";
|
|
34
|
+
import { isBusinessIntent, publicOfferRoute } from "./intent.js";
|
|
31
35
|
import {
|
|
32
36
|
lowerLawValueType,
|
|
33
37
|
type LawConstant,
|
|
@@ -38,7 +42,13 @@ import {
|
|
|
38
42
|
type LawValueType,
|
|
39
43
|
} from "./law_value_type.js";
|
|
40
44
|
import { harvestPrincipalFlows } from "./wire_encode.js";
|
|
41
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
admitsNull,
|
|
47
|
+
type Field,
|
|
48
|
+
type FieldKind,
|
|
49
|
+
type ValueObjectDescriptor,
|
|
50
|
+
type ValueObjectFieldDescriptor,
|
|
51
|
+
} from "./fields.js";
|
|
42
52
|
import type { GeometryKind } from "./value_object.js";
|
|
43
53
|
import type { Driver } from "./drivers.js";
|
|
44
54
|
import {
|
|
@@ -302,6 +312,10 @@ export interface LawStructuralEntity<K extends LawStructuralKind> {
|
|
|
302
312
|
readonly sid: string;
|
|
303
313
|
readonly label: string;
|
|
304
314
|
readonly identityClass: "structural";
|
|
315
|
+
/** Retained transport allocation. Meaning remains the scoped field name + its disclosed lineage. */
|
|
316
|
+
readonly wireKey?: string;
|
|
317
|
+
/** Previously shipped transport allocations accepted during a managed overlap. */
|
|
318
|
+
readonly wireAliases?: readonly string[];
|
|
305
319
|
}
|
|
306
320
|
|
|
307
321
|
export interface LawStructuralRef<K extends LawStructuralKind> {
|
|
@@ -469,7 +483,12 @@ export interface LawTrustSourceSetNode extends LawPolicyBase<"source-set"> {
|
|
|
469
483
|
readonly keysField: LawRef<"field">;
|
|
470
484
|
}
|
|
471
485
|
|
|
472
|
-
export
|
|
486
|
+
export interface LawAuthorizedCustodySourceNode extends LawPolicyBase<"authorized-custody-source"> {}
|
|
487
|
+
|
|
488
|
+
export type LawPolicyNode =
|
|
489
|
+
| LawPinnedTrustSourceNode
|
|
490
|
+
| LawTrustSourceSetNode
|
|
491
|
+
| LawAuthorizedCustodySourceNode;
|
|
473
492
|
|
|
474
493
|
export interface LawForeignReadNode {
|
|
475
494
|
readonly kind: "structural";
|
|
@@ -508,6 +527,7 @@ export interface LawWorkspaceInvariantNode {
|
|
|
508
527
|
readonly entity: LawEntity<"invariant">;
|
|
509
528
|
readonly domain: LawRef<"domain">;
|
|
510
529
|
readonly invariantKind: "workspace";
|
|
530
|
+
readonly refusalType?: LawRef<"type">;
|
|
511
531
|
readonly on: LawRef<"intent">;
|
|
512
532
|
readonly reads?: readonly {
|
|
513
533
|
readonly binding: string;
|
|
@@ -516,7 +536,7 @@ export interface LawWorkspaceInvariantNode {
|
|
|
516
536
|
readonly eachPayloadPath?: readonly string[];
|
|
517
537
|
readonly id: InvariantReadBinding["id"];
|
|
518
538
|
}[];
|
|
519
|
-
readonly evaluator?: "birth-quota-v1" | "founder-signer-write-once-v1" | "point-guard-v1";
|
|
539
|
+
readonly evaluator?: "birth-quota-v1" | "founder-signer-write-once-v1" | "founder-signer-write-once-v2" | "point-guard-v1";
|
|
520
540
|
readonly pointGuard?: {
|
|
521
541
|
readonly aggregate: LawRef<"aggregate">;
|
|
522
542
|
readonly binding: string;
|
|
@@ -549,6 +569,8 @@ export interface LawCapabilityNode {
|
|
|
549
569
|
readonly deadLetter: LawRef<"intent">;
|
|
550
570
|
readonly capability: string;
|
|
551
571
|
readonly endpoint?: string;
|
|
572
|
+
readonly executionPlacement?: "custodian";
|
|
573
|
+
readonly executionCardinality?: "singleton";
|
|
552
574
|
readonly tasks?: LawRef<"read">;
|
|
553
575
|
}
|
|
554
576
|
|
|
@@ -572,6 +594,7 @@ export interface LawIntentAuthorization {
|
|
|
572
594
|
readonly relation: LawTargetRef<"relation">;
|
|
573
595
|
readonly object: string;
|
|
574
596
|
readonly objectFrom?: LawIntentAuthorizationObjectFrom;
|
|
597
|
+
readonly subjectFromAttestedRead?: string;
|
|
575
598
|
}
|
|
576
599
|
|
|
577
600
|
export interface LawIntentNode {
|
|
@@ -597,9 +620,13 @@ export interface LawIntentNode {
|
|
|
597
620
|
readonly acceptsWorkspaceEffect: boolean;
|
|
598
621
|
/** Recovery-only admission: the verified source workspace must be the target's exact birth parent. */
|
|
599
622
|
readonly acceptsVerifiedBirthParentRecovery: boolean;
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
623
|
+
readonly acceptsVerifiedWorkspaceClaim?: boolean;
|
|
624
|
+
/** Authentication selected by law for this exact member. Absence retains the historical
|
|
625
|
+
* default-provider interpretation for existing law. */
|
|
626
|
+
readonly authentication?: MemberAuthentication;
|
|
627
|
+
/** D22 sovereign self-certification: the founding signer tuple this intent writes is admitted iff
|
|
628
|
+
* the signing key's sha256 is the captured principal's subject. */
|
|
629
|
+
readonly selfCertifyingPrincipal?: boolean;
|
|
603
630
|
/** Exact nominal target directives this source intent may author into another workspace. */
|
|
604
631
|
readonly directsWorkspaceEffects: readonly LawTargetRef<"intent">[];
|
|
605
632
|
/** Zanzibar relation required to author this intent. */
|
|
@@ -609,6 +636,8 @@ export interface LawIntentNode {
|
|
|
609
636
|
readonly births: boolean;
|
|
610
637
|
readonly birthRecord?: LawRef<"aggregate">;
|
|
611
638
|
readonly birthPrefix?: string;
|
|
639
|
+
readonly birthDelegations?: LawRef<"field">;
|
|
640
|
+
readonly birthDelegationPrefix?: string;
|
|
612
641
|
/** The law-declared genesis verb that establishes this workspace's birth policy. This is a
|
|
613
642
|
* relationship to executable law, never a compiler/runtime allowance value: the kernel uses it
|
|
614
643
|
* only to require an explicit matching step in child genesis before custody can be created. */
|
|
@@ -644,12 +673,7 @@ export interface LawIntentNode {
|
|
|
644
673
|
readonly effects: readonly LawStructuralRef<"effect">[];
|
|
645
674
|
readonly steps: readonly LawRef<"intent">[];
|
|
646
675
|
readonly refuses: readonly string[];
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
/** The public directive vocabulary carried into typed USDA and generated-client compatibility. */
|
|
650
|
-
export function publicIntentRoute(intent: DomainModule["directives"][number]): string {
|
|
651
|
-
const businessBirth = (intent as { businessBirth?: unknown }).businessBirth;
|
|
652
|
-
return businessBirth === undefined || isBusinessIntent(intent) ? intent.id : "birth";
|
|
676
|
+
readonly domainRefusals?: readonly LawRef<"type">[];
|
|
653
677
|
}
|
|
654
678
|
|
|
655
679
|
/**
|
|
@@ -680,6 +704,7 @@ interface LawReadBase<K extends string> {
|
|
|
680
704
|
readonly of: LawRef<"aggregate">;
|
|
681
705
|
readonly contract: LawRef<"contract">;
|
|
682
706
|
readonly public: boolean;
|
|
707
|
+
readonly authentication?: MemberAuthentication;
|
|
683
708
|
readonly predicate?: LawStructuralRef<"predicate">;
|
|
684
709
|
}
|
|
685
710
|
|
|
@@ -711,6 +736,9 @@ export interface LawOrderedReadNode extends LawReadBase<"ordered"> {
|
|
|
711
736
|
readonly filtered: boolean;
|
|
712
737
|
}
|
|
713
738
|
|
|
739
|
+
/** Declared aggregate-row reads share typed transport, not selection semantics. */
|
|
740
|
+
export type LawRowReadNode = LawQueryReadNode | LawOrderedReadNode;
|
|
741
|
+
|
|
714
742
|
export interface LawSpatialReadNode extends LawReadBase<"spatial"> {
|
|
715
743
|
readonly geometry: LawFieldPathRef;
|
|
716
744
|
}
|
|
@@ -776,6 +804,8 @@ export interface LawRetirement {
|
|
|
776
804
|
}
|
|
777
805
|
|
|
778
806
|
export interface DiscoverLawGraphOptions {
|
|
807
|
+
/** The package's exact declaration/export identity, not a label search. */
|
|
808
|
+
readonly workspaceEffectDomain?: (target: Directive<unknown>) => string;
|
|
779
809
|
readonly intentCarries?: readonly LawIdentityCarry[];
|
|
780
810
|
readonly readCarries?: readonly LawIdentityCarry[];
|
|
781
811
|
readonly source?: (
|
|
@@ -786,6 +816,7 @@ export interface DiscoverLawGraphOptions {
|
|
|
786
816
|
| "intent"
|
|
787
817
|
| "read"
|
|
788
818
|
| "contract"
|
|
819
|
+
| "operation-field"
|
|
789
820
|
| "type"
|
|
790
821
|
| "object-type"
|
|
791
822
|
| "relation"
|
|
@@ -992,6 +1023,7 @@ export function discoverLawGraph(
|
|
|
992
1023
|
}
|
|
993
1024
|
|
|
994
1025
|
const types = [...(module.valueObjects ?? [])].sort((a, b) => compareText(a.name, b.name));
|
|
1026
|
+
const typeDescriptorByName = new Map(types.map((type) => [type.name, type] as const));
|
|
995
1027
|
reconciled = identities.reconcile({
|
|
996
1028
|
kind: "type",
|
|
997
1029
|
parent: domainKey,
|
|
@@ -1008,7 +1040,7 @@ export function discoverLawGraph(
|
|
|
1008
1040
|
),
|
|
1009
1041
|
] as const));
|
|
1010
1042
|
const linkValueObjectField = (node: LawFieldNode, field: Field, owner: string): LawFieldNode => {
|
|
1011
|
-
const valueObject = field.valueObject;
|
|
1043
|
+
const valueObject = field.valueObject ?? field.mapValueVo;
|
|
1012
1044
|
if (valueObject === undefined) return node;
|
|
1013
1045
|
const target = typeEntitiesByLabel.get(valueObject.name);
|
|
1014
1046
|
if (target === undefined) fail(`field '${owner}.${node.entity.label}' targets unknown type '${valueObject.name}'`);
|
|
@@ -1017,6 +1049,27 @@ export function discoverLawGraph(
|
|
|
1017
1049
|
anonymousValueNodes.delete(id);
|
|
1018
1050
|
}
|
|
1019
1051
|
}
|
|
1052
|
+
if (field.mapValueVo !== undefined) {
|
|
1053
|
+
// A map of named values is not an anonymous JSON/map shape. Lower its
|
|
1054
|
+
// canonical descriptor into the graph so every downstream projection
|
|
1055
|
+
// (Protobuf, Dart, TypeScript and USDA) sees the same nested nominal
|
|
1056
|
+
// enums, units, references and objects.
|
|
1057
|
+
const lowered = lowerAnonymousValueGraph(
|
|
1058
|
+
{
|
|
1059
|
+
kind: "map",
|
|
1060
|
+
value: descriptorTypeValue(
|
|
1061
|
+
field.mapValueVo.descriptor,
|
|
1062
|
+
typeDescriptorByName,
|
|
1063
|
+
new Set(),
|
|
1064
|
+
),
|
|
1065
|
+
},
|
|
1066
|
+
node.entity,
|
|
1067
|
+
);
|
|
1068
|
+
for (const structural of lowered.nodes) {
|
|
1069
|
+
anonymousValueNodes.set(structural.entity.id, structural);
|
|
1070
|
+
}
|
|
1071
|
+
return { ...node, value: lowered.root };
|
|
1072
|
+
}
|
|
1020
1073
|
return { ...node, value: ref(target) };
|
|
1021
1074
|
};
|
|
1022
1075
|
for (const aggregate of module.aggregates) {
|
|
@@ -1064,7 +1117,10 @@ export function discoverLawGraph(
|
|
|
1064
1117
|
if (target === undefined) fail(`type '${type.name}' field '${fieldName}' targets unknown type '${field.ref}'`);
|
|
1065
1118
|
value = ref(target);
|
|
1066
1119
|
} else {
|
|
1067
|
-
const lowered = lowerAnonymousValueGraph(
|
|
1120
|
+
const lowered = lowerAnonymousValueGraph(
|
|
1121
|
+
descriptorValue(field, typeDescriptorByName, new Set(), type.name, fieldName),
|
|
1122
|
+
fieldEntity,
|
|
1123
|
+
);
|
|
1068
1124
|
for (const structural of lowered.nodes) anonymousValueNodes.set(structural.entity.id, structural);
|
|
1069
1125
|
value = lowered.root;
|
|
1070
1126
|
}
|
|
@@ -1076,7 +1132,7 @@ export function discoverLawGraph(
|
|
|
1076
1132
|
evolutions: [],
|
|
1077
1133
|
mergeDrivers: [],
|
|
1078
1134
|
required: field.optional !== true,
|
|
1079
|
-
nullable:
|
|
1135
|
+
nullable: field.nullable === true,
|
|
1080
1136
|
encrypted: false,
|
|
1081
1137
|
blindIndexed: false,
|
|
1082
1138
|
};
|
|
@@ -1090,12 +1146,13 @@ export function discoverLawGraph(
|
|
|
1090
1146
|
if (referenced === undefined) fail(`type '${type.name}' variant '${variantName}' targets unknown type '${variant.ref}'`);
|
|
1091
1147
|
target = ref(referenced);
|
|
1092
1148
|
} else {
|
|
1149
|
+
const armOwner = `${type.name}${variantName[0]!.toUpperCase()}${variantName.slice(1)}`;
|
|
1093
1150
|
const value: LawValueType = {
|
|
1094
1151
|
kind: "record",
|
|
1095
1152
|
fields: Object.entries(variant.fields).sort(([a], [b]) => compareText(a, b)).map(([name, field]) => ({
|
|
1096
1153
|
name,
|
|
1097
1154
|
required: field.optional !== true,
|
|
1098
|
-
value: descriptorValue(field),
|
|
1155
|
+
value: descriptorValue(field, typeDescriptorByName, new Set(), armOwner, name),
|
|
1099
1156
|
})),
|
|
1100
1157
|
};
|
|
1101
1158
|
const lowered = lowerAnonymousValueGraph(value, typeEntity);
|
|
@@ -1195,7 +1252,16 @@ export function discoverLawGraph(
|
|
|
1195
1252
|
// A workspace-effect-only intent has no local aggregate consequence. Its nominal target
|
|
1196
1253
|
// aggregate belongs to the destination package; retain that as a dependency export instead
|
|
1197
1254
|
// of fabricating a local audit row merely to satisfy the older directive-shaped IR.
|
|
1198
|
-
|
|
1255
|
+
const effect = intent.workspaceEffects.find(
|
|
1256
|
+
(candidate) => candidate.target.aggregateId === aggregateId,
|
|
1257
|
+
)!;
|
|
1258
|
+
const owner = options.workspaceEffectDomain?.(effect.target);
|
|
1259
|
+
return {
|
|
1260
|
+
kind: "dependency-export",
|
|
1261
|
+
entityKind: "aggregate",
|
|
1262
|
+
label: aggregateId,
|
|
1263
|
+
...(owner === undefined ? {} : { domain: owner }),
|
|
1264
|
+
};
|
|
1199
1265
|
}
|
|
1200
1266
|
const birth = (intent as { businessBirth?: { aggregateId?: unknown; domain?: unknown } }).businessBirth;
|
|
1201
1267
|
if (birth?.aggregateId === aggregateId && typeof birth.domain === "string") {
|
|
@@ -1205,6 +1271,55 @@ export function discoverLawGraph(
|
|
|
1205
1271
|
};
|
|
1206
1272
|
const intentNodes: LawIntentNode[] = intents.map((intent) => {
|
|
1207
1273
|
const intentEntity = intentEntities.get(intent.id)!;
|
|
1274
|
+
const liveOperationFieldNames = new Set<string>();
|
|
1275
|
+
const lowerPayloadContract = (
|
|
1276
|
+
value: LawValueType,
|
|
1277
|
+
contract: LawEntity<"contract">,
|
|
1278
|
+
scope: "accepts" | "publicAccepts",
|
|
1279
|
+
): ReturnType<typeof lowerAnonymousContractFields> => {
|
|
1280
|
+
// A field's scoped name is its semantic declaration. The identity ledger keeps
|
|
1281
|
+
// its prior names/tombstone; this additional binding retains only the Protobuf
|
|
1282
|
+
// allocation already spoken by clients. Schema fingerprints remain structural.
|
|
1283
|
+
const provisional = lowerAnonymousContractFields(value, contract);
|
|
1284
|
+
const provisionalById = new Map(provisional.nodes.map((node) => [node.entity.id, node]));
|
|
1285
|
+
const fields = provisional.fields.map((fieldRef): LawAnonymousValueFieldNode => {
|
|
1286
|
+
const field = provisionalById.get(fieldRef.id);
|
|
1287
|
+
if (field?.kind !== "structural" || field.structuralKind !== "value-field") {
|
|
1288
|
+
fail(`directive '${intent.id}' has an invalid top-level ${scope} field`);
|
|
1289
|
+
}
|
|
1290
|
+
return field;
|
|
1291
|
+
});
|
|
1292
|
+
const labels = fields.map((field) => field.name);
|
|
1293
|
+
for (const label of labels) liveOperationFieldNames.add(label);
|
|
1294
|
+
const preferredOperationFieldWire = Object.fromEntries(
|
|
1295
|
+
fields.map((field) => [
|
|
1296
|
+
field.name,
|
|
1297
|
+
{ protobuf: { canonical: field.entity.sid } },
|
|
1298
|
+
]),
|
|
1299
|
+
);
|
|
1300
|
+
const fieldLedger = identities.reconcile({
|
|
1301
|
+
kind: "operation-field",
|
|
1302
|
+
parent: intentEntity.id,
|
|
1303
|
+
labels,
|
|
1304
|
+
preferredOperationFieldWire,
|
|
1305
|
+
// `accepts` and the optional public projection are lowered separately but
|
|
1306
|
+
// share one operation namespace. Retire only after their union is known.
|
|
1307
|
+
retireAbsent: false,
|
|
1308
|
+
});
|
|
1309
|
+
registry = fieldLedger.registry;
|
|
1310
|
+
return lowerAnonymousContractFields(value, contract, (name) => {
|
|
1311
|
+
const key = fieldLedger.resolved[name];
|
|
1312
|
+
const field = key === undefined ? undefined : registry.entities[key];
|
|
1313
|
+
if (
|
|
1314
|
+
field?.kind !== "operation-field" ||
|
|
1315
|
+
field.status !== "active" ||
|
|
1316
|
+
field.operationFieldWire === undefined
|
|
1317
|
+
) {
|
|
1318
|
+
fail(`directive '${intent.id}' has no active wire allocation for ${scope} field '${name}'`);
|
|
1319
|
+
}
|
|
1320
|
+
return field.operationFieldWire.protobuf;
|
|
1321
|
+
});
|
|
1322
|
+
};
|
|
1208
1323
|
const businessBirth = (intent as {
|
|
1209
1324
|
businessBirth?: { publicPayloadSchema?: z.ZodTypeAny; owned?: boolean };
|
|
1210
1325
|
}).businessBirth;
|
|
@@ -1263,9 +1378,10 @@ export function discoverLawGraph(
|
|
|
1263
1378
|
) {
|
|
1264
1379
|
frameworkCapabilities.add("owned-authoring");
|
|
1265
1380
|
}
|
|
1266
|
-
const payloadShape =
|
|
1381
|
+
const payloadShape = lowerPayloadContract(
|
|
1267
1382
|
internalPayloadContract(tenantPayloadContract, frameworkCapabilities),
|
|
1268
1383
|
payloadContractEntity,
|
|
1384
|
+
"accepts",
|
|
1269
1385
|
);
|
|
1270
1386
|
for (const node of payloadShape.nodes) anonymousValueNodes.set(node.entity.id, node);
|
|
1271
1387
|
payloadContractNodes.push({
|
|
@@ -1284,9 +1400,10 @@ export function discoverLawGraph(
|
|
|
1284
1400
|
`${intent.id}#publicAccepts`,
|
|
1285
1401
|
options.source?.("intent", intent.id, module.name),
|
|
1286
1402
|
);
|
|
1287
|
-
const publicPayloadShape =
|
|
1403
|
+
const publicPayloadShape = lowerPayloadContract(
|
|
1288
1404
|
lowerLawValueType(businessBirth.publicPayloadSchema),
|
|
1289
1405
|
publicPayloadContractEntity,
|
|
1406
|
+
"publicAccepts",
|
|
1290
1407
|
);
|
|
1291
1408
|
for (const node of publicPayloadShape.nodes) anonymousValueNodes.set(node.entity.id, node);
|
|
1292
1409
|
payloadContractNodes.push({
|
|
@@ -1296,6 +1413,12 @@ export function discoverLawGraph(
|
|
|
1296
1413
|
fields: publicPayloadShape.fields,
|
|
1297
1414
|
});
|
|
1298
1415
|
}
|
|
1416
|
+
const finalizedOperationFields = identities.reconcile({
|
|
1417
|
+
kind: "operation-field",
|
|
1418
|
+
parent: intentEntity.id,
|
|
1419
|
+
labels: [...liveOperationFieldNames],
|
|
1420
|
+
});
|
|
1421
|
+
registry = finalizedOperationFields.registry;
|
|
1299
1422
|
const payloadFields = new Map<string, LawStructuralRef<"value-field">>();
|
|
1300
1423
|
const indexPayloadValue = (
|
|
1301
1424
|
valueRef: LawValueTypeRef,
|
|
@@ -1477,7 +1600,7 @@ export function discoverLawGraph(
|
|
|
1477
1600
|
// compiler-lowered business-birth directive publishes the generic framework `birth` route.
|
|
1478
1601
|
// Keep this identical to domainInterface/codegen so the typed USDA is sufficient to
|
|
1479
1602
|
// reconstruct the generated-client compatibility surface.
|
|
1480
|
-
publicRoute:
|
|
1603
|
+
publicRoute: publicOfferRoute(intent),
|
|
1481
1604
|
accepts: ref(payloadContractEntity),
|
|
1482
1605
|
...(publicPayloadContractEntity === undefined ? {} : {
|
|
1483
1606
|
publicAccepts: ref(publicPayloadContractEntity),
|
|
@@ -1488,16 +1611,25 @@ export function discoverLawGraph(
|
|
|
1488
1611
|
acceptsWorkspaceEffect: intent.acceptsWorkspaceEffectGate === true,
|
|
1489
1612
|
acceptsVerifiedBirthParentRecovery:
|
|
1490
1613
|
intent.acceptsVerifiedBirthParentRecoveryGate === true,
|
|
1491
|
-
...(
|
|
1492
|
-
? {
|
|
1614
|
+
...(intent.acceptsVerifiedWorkspaceClaimGate === true
|
|
1615
|
+
? { acceptsVerifiedWorkspaceClaim: true }
|
|
1493
1616
|
: {}),
|
|
1494
|
-
|
|
1495
|
-
|
|
1617
|
+
...(intent.authentication !== undefined
|
|
1618
|
+
? { authentication: intent.authentication }
|
|
1619
|
+
: {}),
|
|
1620
|
+
...(intent.selfCertifyingPrincipalGate === true
|
|
1621
|
+
? { selfCertifyingPrincipal: true }
|
|
1622
|
+
: {}),
|
|
1623
|
+
directsWorkspaceEffects: (intent.workspaceEffects ?? []).map((effect) => {
|
|
1624
|
+
const owner = options.workspaceEffectDomain?.(effect.target);
|
|
1625
|
+
const local = owner === undefined || owner === (module.domain ?? module.name)
|
|
1626
|
+
? intentEntities.get(effect.target.id) : undefined;
|
|
1496
1627
|
return local === undefined
|
|
1497
1628
|
? {
|
|
1498
1629
|
kind: "dependency-export" as const,
|
|
1499
1630
|
entityKind: "intent" as const,
|
|
1500
1631
|
label: effect.target.id,
|
|
1632
|
+
...(owner === undefined ? {} : { domain: owner }),
|
|
1501
1633
|
}
|
|
1502
1634
|
: ref(local);
|
|
1503
1635
|
}),
|
|
@@ -1508,6 +1640,10 @@ export function discoverLawGraph(
|
|
|
1508
1640
|
birthRecord: ref(aggregateByLabel.get("NomosBirthRecord")!.node.entity),
|
|
1509
1641
|
birthPrefix: "nomos-birth-record:",
|
|
1510
1642
|
}),
|
|
1643
|
+
...(intent.birthsChild !== true || aggregateByLabel.get("SignerDelegation")?.fields.get("certificates") === undefined ? {} : {
|
|
1644
|
+
birthDelegations: ref(aggregateByLabel.get("SignerDelegation")!.fields.get("certificates")!.entity),
|
|
1645
|
+
birthDelegationPrefix: SIGNER_DELEGATION_PREFIX,
|
|
1646
|
+
}),
|
|
1511
1647
|
...(intent.birthsChild !== true || intentEntities.get("seedBirthPolicy") === undefined ? {} : {
|
|
1512
1648
|
birthPolicySeed: ref(intentEntities.get("seedBirthPolicy")!),
|
|
1513
1649
|
}),
|
|
@@ -1709,10 +1845,15 @@ export function discoverLawGraph(
|
|
|
1709
1845
|
});
|
|
1710
1846
|
for (const [index, intentNode] of intentNodes.entries()) {
|
|
1711
1847
|
const declaration = intents.find((intent) => intent.id === intentNode.entity.label)!;
|
|
1848
|
+
if (declaration.acceptsVerifiedWorkspaceClaimGate === true &&
|
|
1849
|
+
declaration.acceptsVerifiedBirthParentRecoveryGate === true) {
|
|
1850
|
+
throw new Error(`directive '${declaration.id}' declares competing workspace admission policies`);
|
|
1851
|
+
}
|
|
1712
1852
|
const gate = declaration.requiresRelationGate;
|
|
1713
1853
|
if (
|
|
1714
1854
|
declaration.acceptsWorkspaceEffectGate === true &&
|
|
1715
|
-
declaration.acceptsVerifiedBirthParentRecoveryGate !== true
|
|
1855
|
+
declaration.acceptsVerifiedBirthParentRecoveryGate !== true &&
|
|
1856
|
+
declaration.acceptsVerifiedWorkspaceClaimGate !== true
|
|
1716
1857
|
) {
|
|
1717
1858
|
if (gate === undefined || gate.object !== "workspace:self" || gate.objectFrom !== undefined) {
|
|
1718
1859
|
fail(
|
|
@@ -1722,6 +1863,17 @@ export function discoverLawGraph(
|
|
|
1722
1863
|
}
|
|
1723
1864
|
}
|
|
1724
1865
|
if (gate === undefined) continue;
|
|
1866
|
+
if (
|
|
1867
|
+
gate.subjectFromAttestedRead !== undefined &&
|
|
1868
|
+
!(declaration.declaredForeignReads ?? []).some(
|
|
1869
|
+
(edge) => edge.queryId === gate.subjectFromAttestedRead,
|
|
1870
|
+
)
|
|
1871
|
+
) {
|
|
1872
|
+
fail(
|
|
1873
|
+
`intent '${declaration.id}' authorization subject read ` +
|
|
1874
|
+
`'${gate.subjectFromAttestedRead}' is not declared with .readsFrom(...)`,
|
|
1875
|
+
);
|
|
1876
|
+
}
|
|
1725
1877
|
const objectType = gate.objectFrom?.recordType ?? gate.object.split(":", 1)[0]!;
|
|
1726
1878
|
const exactLabel = gate.relation.includes("#") ? gate.relation : `${objectType}#${gate.relation}`;
|
|
1727
1879
|
const candidates = relationNodes.filter((relation) =>
|
|
@@ -1770,6 +1922,9 @@ export function discoverLawGraph(
|
|
|
1770
1922
|
: ref(candidates[0].entity),
|
|
1771
1923
|
object: authorizationObject,
|
|
1772
1924
|
...(objectFrom === undefined ? {} : { objectFrom }),
|
|
1925
|
+
...(gate.subjectFromAttestedRead === undefined
|
|
1926
|
+
? {}
|
|
1927
|
+
: { subjectFromAttestedRead: gate.subjectFromAttestedRead }),
|
|
1773
1928
|
},
|
|
1774
1929
|
};
|
|
1775
1930
|
}
|
|
@@ -1800,10 +1955,10 @@ export function discoverLawGraph(
|
|
|
1800
1955
|
}
|
|
1801
1956
|
|
|
1802
1957
|
const pinnedSources = [...(module.trustSources ?? [])].sort((a, b) => compareText(a.workspace, b.workspace));
|
|
1803
|
-
const
|
|
1958
|
+
const trustPolicies = [...(module.trustPolicies ?? [])].sort((a, b) => compareText(a.policyId, b.policyId));
|
|
1804
1959
|
const policyLabels = [
|
|
1805
1960
|
...pinnedSources.map((source) => `source:${source.workspace}`),
|
|
1806
|
-
...
|
|
1961
|
+
...trustPolicies.map((policy) => policy.policyId),
|
|
1807
1962
|
];
|
|
1808
1963
|
reconciled = identities.reconcile({
|
|
1809
1964
|
kind: "policy",
|
|
@@ -1829,7 +1984,24 @@ export function discoverLawGraph(
|
|
|
1829
1984
|
onDishonor: source.onDishonor ?? "refuse",
|
|
1830
1985
|
};
|
|
1831
1986
|
}),
|
|
1832
|
-
...
|
|
1987
|
+
...trustPolicies.map((policy): LawTrustSourceSetNode | LawAuthorizedCustodySourceNode => {
|
|
1988
|
+
if (policy.authorizationOnly === true) {
|
|
1989
|
+
return {
|
|
1990
|
+
kind: "policy",
|
|
1991
|
+
entity: entity(registry, reconciled.resolved[policy.policyId]!, "policy", options.source?.("policy", policy.policyId, module.name)),
|
|
1992
|
+
domain: domainRef,
|
|
1993
|
+
policyKind: "authorized-custody-source",
|
|
1994
|
+
monotone: false,
|
|
1995
|
+
onDishonor: "refuse",
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
if (
|
|
1999
|
+
policy.allowListType === undefined ||
|
|
2000
|
+
policy.genesisField === undefined ||
|
|
2001
|
+
policy.keysField === undefined
|
|
2002
|
+
) {
|
|
2003
|
+
fail(`policy '${policy.policyId}' has no source-set fields`);
|
|
2004
|
+
}
|
|
1833
2005
|
const allowList = aggregateByLabel.get(policy.allowListType);
|
|
1834
2006
|
if (allowList === undefined) fail(`policy '${policy.policyId}' targets unknown aggregate '${policy.allowListType}'`);
|
|
1835
2007
|
const genesisField = allowList.fields.get(policy.genesisField);
|
|
@@ -1856,8 +2028,9 @@ export function discoverLawGraph(
|
|
|
1856
2028
|
policyNodes.filter((node): node is LawPinnedTrustSourceNode => node.policyKind === "pinned-source")
|
|
1857
2029
|
.map((node) => [node.workspace, node] as const),
|
|
1858
2030
|
);
|
|
1859
|
-
const
|
|
1860
|
-
policyNodes.filter((node): node is LawTrustSourceSetNode
|
|
2031
|
+
const dynamicPolicyByLabel = new Map(
|
|
2032
|
+
policyNodes.filter((node): node is LawTrustSourceSetNode | LawAuthorizedCustodySourceNode =>
|
|
2033
|
+
node.policyKind === "source-set" || node.policyKind === "authorized-custody-source")
|
|
1861
2034
|
.map((node) => [node.entity.label, node] as const),
|
|
1862
2035
|
);
|
|
1863
2036
|
const foreignReadNodes: LawForeignReadNode[] = [];
|
|
@@ -1867,13 +2040,34 @@ export function discoverLawGraph(
|
|
|
1867
2040
|
for (const edge of declaration.declaredForeignReads ?? []) {
|
|
1868
2041
|
const source = "from" in edge
|
|
1869
2042
|
? pinnedPolicyByWorkspace.get(edge.from)
|
|
1870
|
-
:
|
|
2043
|
+
: dynamicPolicyByLabel.get(edge.policy);
|
|
1871
2044
|
if (source === undefined) {
|
|
1872
2045
|
fail(
|
|
1873
2046
|
`intent '${declaration.id}' foreign read '${edge.queryId}' targets undeclared ` +
|
|
1874
2047
|
`${"from" in edge ? `source '${edge.from}'` : `policy '${edge.policy}'`}`,
|
|
1875
2048
|
);
|
|
1876
2049
|
}
|
|
2050
|
+
if (
|
|
2051
|
+
source.policyKind === "authorized-custody-source" &&
|
|
2052
|
+
declaration.requiresRelationGate?.subjectFromAttestedRead !== edge.queryId
|
|
2053
|
+
) {
|
|
2054
|
+
const subjectQuery = declaration.requiresRelationGate?.subjectFromAttestedRead;
|
|
2055
|
+
const subjectEdge = declaration.declaredForeignReads?.find((candidate) =>
|
|
2056
|
+
candidate.queryId === subjectQuery
|
|
2057
|
+
&& "policy" in candidate
|
|
2058
|
+
&& "policy" in edge
|
|
2059
|
+
&& candidate.policy === edge.policy
|
|
2060
|
+
&& "fromPayload" in candidate
|
|
2061
|
+
&& "fromPayload" in edge
|
|
2062
|
+
&& candidate.fromPayload === edge.fromPayload
|
|
2063
|
+
);
|
|
2064
|
+
if (subjectEdge === undefined) {
|
|
2065
|
+
fail(
|
|
2066
|
+
`intent '${declaration.id}' authorized custody read '${edge.queryId}' must derive its ` +
|
|
2067
|
+
`Zanzibar subject from an attested read bound to the same source`,
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
1877
2071
|
const fromField = "fromPayload" in edge
|
|
1878
2072
|
? payloadFieldsByIntent.get(declaration.id)?.get(edge.fromPayload)
|
|
1879
2073
|
: undefined;
|
|
@@ -1912,6 +2106,10 @@ export function discoverLawGraph(
|
|
|
1912
2106
|
});
|
|
1913
2107
|
registry = reconciled.registry;
|
|
1914
2108
|
const invariantNodes: LawInvariantNode[] = invariants.map((invariant) => {
|
|
2109
|
+
const refusalType = invariant.refusal === undefined ? undefined : typeEntitiesByLabel.get(invariant.refusal.name);
|
|
2110
|
+
if (invariant.refusal !== undefined && refusalType === undefined) {
|
|
2111
|
+
fail(`invariant '${invariant.id}' refusal targets unknown nominal type '${invariant.refusal.name}'`);
|
|
2112
|
+
}
|
|
1915
2113
|
const point = invariant.__nomosPointGuard;
|
|
1916
2114
|
const pointAggregate = point === undefined ? undefined : aggregateByLabel.get(point.aggregateId)?.node;
|
|
1917
2115
|
if (point !== undefined && pointAggregate === undefined) {
|
|
@@ -1940,6 +2138,7 @@ export function discoverLawGraph(
|
|
|
1940
2138
|
),
|
|
1941
2139
|
domain: domainRef,
|
|
1942
2140
|
invariantKind: "workspace",
|
|
2141
|
+
...(refusalType === undefined ? {} : { refusalType: ref(refusalType) }),
|
|
1943
2142
|
on: intentRef(intentByLabel, invariant.on, `invariant '${invariant.id}'`),
|
|
1944
2143
|
...(nativeReads === undefined ? {} : { reads: nativeReads }),
|
|
1945
2144
|
...(invariant.__nomosEvaluator === undefined
|
|
@@ -1978,6 +2177,22 @@ export function discoverLawGraph(
|
|
|
1978
2177
|
});
|
|
1979
2178
|
}
|
|
1980
2179
|
|
|
2180
|
+
// Derive the output family closure from rules and composed steps. A tenant
|
|
2181
|
+
// cannot omit a reachable refusal by supplying a handwritten command list.
|
|
2182
|
+
const refusalTypesFor = (id: string, active = new Set<string>()): LawRef<"type">[] => {
|
|
2183
|
+
if (active.has(id)) fail(`cyclic refusal contract composition at '${id}'`);
|
|
2184
|
+
const next = new Set(active).add(id);
|
|
2185
|
+
const direct = invariantNodes.flatMap((rule) => rule.invariantKind === "workspace"
|
|
2186
|
+
&& rule.on.id === id && rule.refusalType !== undefined ? [rule.refusalType] : []);
|
|
2187
|
+
const steps = intentNodes.find(node => node.entity.id === id)?.steps ?? [];
|
|
2188
|
+
return [...new Map([...direct, ...steps.flatMap(step => refusalTypesFor(step.id, next))]
|
|
2189
|
+
.map(type => [type.id, type])).values()].sort((a, b) => compareText(a.id, b.id));
|
|
2190
|
+
};
|
|
2191
|
+
for (const [index, node] of intentNodes.entries()) {
|
|
2192
|
+
const domainRefusals = refusalTypesFor(node.entity.id);
|
|
2193
|
+
if (domainRefusals.length > 0) intentNodes[index] = { ...node, domainRefusals };
|
|
2194
|
+
}
|
|
2195
|
+
|
|
1981
2196
|
const capabilities = [...(module.impureCapabilities ?? [])].sort((a, b) =>
|
|
1982
2197
|
compareText(a.aggregate.id, b.aggregate.id),
|
|
1983
2198
|
);
|
|
@@ -1992,7 +2207,12 @@ export function discoverLawGraph(
|
|
|
1992
2207
|
readonly name?: unknown;
|
|
1993
2208
|
readonly capability?: unknown;
|
|
1994
2209
|
readonly endpoint?: unknown;
|
|
2210
|
+
readonly execution?: unknown;
|
|
1995
2211
|
};
|
|
2212
|
+
const execution = metadata.execution as {
|
|
2213
|
+
readonly placement?: unknown;
|
|
2214
|
+
readonly cardinality?: unknown;
|
|
2215
|
+
} | undefined;
|
|
1996
2216
|
return {
|
|
1997
2217
|
kind: "capability",
|
|
1998
2218
|
entity: entity(
|
|
@@ -2014,6 +2234,12 @@ export function discoverLawGraph(
|
|
|
2014
2234
|
? metadata.capability
|
|
2015
2235
|
: capability.aggregate.id,
|
|
2016
2236
|
...(typeof metadata.endpoint === "string" ? { endpoint: metadata.endpoint } : {}),
|
|
2237
|
+
...(execution?.placement === "custodian"
|
|
2238
|
+
? { executionPlacement: execution.placement }
|
|
2239
|
+
: {}),
|
|
2240
|
+
...(execution?.cardinality === "singleton"
|
|
2241
|
+
? { executionCardinality: execution.cardinality }
|
|
2242
|
+
: {}),
|
|
2017
2243
|
};
|
|
2018
2244
|
});
|
|
2019
2245
|
|
|
@@ -2207,6 +2433,9 @@ export function discoverLawGraph(
|
|
|
2207
2433
|
of: readAggregate,
|
|
2208
2434
|
contract: ref(readContractEntity),
|
|
2209
2435
|
public: read.public,
|
|
2436
|
+
...(read.authentication === undefined
|
|
2437
|
+
? {}
|
|
2438
|
+
: { authentication: read.authentication }),
|
|
2210
2439
|
...(predicate === undefined ? {} : { predicate }),
|
|
2211
2440
|
};
|
|
2212
2441
|
switch (read.readKind) {
|
|
@@ -2238,6 +2467,8 @@ export function discoverLawGraph(
|
|
|
2238
2467
|
filtered: read.filtered,
|
|
2239
2468
|
};
|
|
2240
2469
|
case "ordered":
|
|
2470
|
+
if (!Number.isInteger(read.limit) || read.limit < 1 || read.limit > 0xffff_ffff)
|
|
2471
|
+
throw new Error(`ordered read '${read.id}' needs an integer limit from 1 through 4294967295`);
|
|
2241
2472
|
return {
|
|
2242
2473
|
...base,
|
|
2243
2474
|
readKind: "ordered",
|
|
@@ -2353,13 +2584,23 @@ export function discoverLawGraph(
|
|
|
2353
2584
|
parent: string,
|
|
2354
2585
|
label: string,
|
|
2355
2586
|
status?: "active" | "retired",
|
|
2356
|
-
|
|
2587
|
+
allowAbsent = false,
|
|
2588
|
+
): [string, LawIdentityEntity] | undefined => {
|
|
2357
2589
|
const matches = Object.entries(registry.entities).filter(([, candidate]) =>
|
|
2358
2590
|
candidate.kind === kind &&
|
|
2359
2591
|
candidate.parent === parent &&
|
|
2360
2592
|
(status === undefined || candidate.status === status) &&
|
|
2361
2593
|
(candidate.label === label || candidate.priorLabels?.includes(label) === true)
|
|
2362
2594
|
);
|
|
2595
|
+
if (allowAbsent && matches.length === 0) return undefined;
|
|
2596
|
+
// Resolve the latest unambiguous declaration when a label has been reused.
|
|
2597
|
+
// Field tombstones below additionally retain its older retired generations
|
|
2598
|
+
// so one candidate can migrate frontiers from before that reuse.
|
|
2599
|
+
if (matches.length > 1) {
|
|
2600
|
+
const latest = Math.max(...matches.map(([, candidate]) => candidate.generation));
|
|
2601
|
+
const latestMatches = matches.filter(([, candidate]) => candidate.generation === latest);
|
|
2602
|
+
if (latestMatches.length === 1) return latestMatches[0]!;
|
|
2603
|
+
}
|
|
2363
2604
|
if (matches.length !== 1) {
|
|
2364
2605
|
fail(
|
|
2365
2606
|
`${kind} retirement '${label}' resolves to ${matches.length} prior identities under '${parent}'; ` +
|
|
@@ -2368,42 +2609,61 @@ export function discoverLawGraph(
|
|
|
2368
2609
|
}
|
|
2369
2610
|
return matches[0]!;
|
|
2370
2611
|
};
|
|
2371
|
-
const retirements = (module.retirements ?? []).
|
|
2372
|
-
const
|
|
2612
|
+
const retirements = (module.retirements ?? []).flatMap((declaration): LawRetirement[] => {
|
|
2613
|
+
const frameworkRetirement = (module.aggregates ?? []).some(
|
|
2373
2614
|
(aggregate) => aggregate.id === declaration.aggregate && aggregate.framework === true,
|
|
2374
|
-
)
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
const [aggregateKey, aggregate] = identityEntity(
|
|
2615
|
+
);
|
|
2616
|
+
const retirementParent = frameworkRetirement ? LAW_FRAMEWORK_PARENT : domainKey;
|
|
2617
|
+
const aggregateIdentity = identityEntity(
|
|
2378
2618
|
"aggregate",
|
|
2379
2619
|
retirementParent,
|
|
2380
2620
|
declaration.aggregate,
|
|
2381
2621
|
declaration.kind === "aggregate" ? "retired" : undefined,
|
|
2622
|
+
frameworkRetirement,
|
|
2382
2623
|
);
|
|
2624
|
+
// Framework evolution is composed into both established and greenfield
|
|
2625
|
+
// domains. A tombstone exists only when this identity layer actually has
|
|
2626
|
+
// the historical declaration; greenfield law never invents a past. Tenant
|
|
2627
|
+
// retirements remain strict so a typo cannot silently erase intent.
|
|
2628
|
+
if (aggregateIdentity === undefined) return [];
|
|
2629
|
+
const [aggregateKey, aggregate] = aggregateIdentity;
|
|
2383
2630
|
if (declaration.kind === "aggregate") {
|
|
2384
|
-
return {
|
|
2631
|
+
return [{
|
|
2385
2632
|
kind: "aggregate",
|
|
2386
2633
|
sid: aggregate.sid,
|
|
2387
2634
|
label: aggregate.label,
|
|
2388
|
-
};
|
|
2635
|
+
}];
|
|
2389
2636
|
}
|
|
2390
|
-
const
|
|
2637
|
+
const fieldIdentity = identityEntity(
|
|
2391
2638
|
"field",
|
|
2392
2639
|
aggregateKey,
|
|
2393
2640
|
declaration.field ?? "",
|
|
2394
2641
|
"retired",
|
|
2642
|
+
frameworkRetirement,
|
|
2395
2643
|
);
|
|
2396
|
-
return
|
|
2644
|
+
if (fieldIdentity === undefined) return [];
|
|
2645
|
+
// A candidate may replace any older frontier, not just the last compiler
|
|
2646
|
+
// generation. Keep every known tombstone for this explicitly retired
|
|
2647
|
+
// field; otherwise an older installed SID has no retirement authority.
|
|
2648
|
+
const retiredFields = Object.values(registry.entities).filter((field) =>
|
|
2649
|
+
field.kind === "field" && field.parent === aggregateKey && field.status === "retired" &&
|
|
2650
|
+
(field.label === declaration.field || field.priorLabels?.includes(declaration.field ?? "") === true)
|
|
2651
|
+
);
|
|
2652
|
+
return retiredFields.map((field) => ({
|
|
2397
2653
|
kind: "field",
|
|
2398
2654
|
sid: field.sid,
|
|
2399
2655
|
label: field.label,
|
|
2400
2656
|
parentSid: aggregate.sid,
|
|
2401
|
-
};
|
|
2657
|
+
}));
|
|
2402
2658
|
}).sort((left, right) => compareText(`${left.kind}:${left.sid}`, `${right.kind}:${right.sid}`));
|
|
2403
2659
|
return { registry, graph: { v: 1, domain: domainNode, retirements, nodes } };
|
|
2404
2660
|
}
|
|
2405
2661
|
|
|
2406
|
-
type ReadInputBase = {
|
|
2662
|
+
type ReadInputBase = {
|
|
2663
|
+
id: string;
|
|
2664
|
+
public: boolean;
|
|
2665
|
+
authentication?: MemberAuthentication;
|
|
2666
|
+
};
|
|
2407
2667
|
type ReadInput =
|
|
2408
2668
|
| (ReadInputBase & { readKind: "query"; of: string; key: readonly string[] })
|
|
2409
2669
|
| (ReadInputBase & { readKind: "count" | "exists"; of: string; by?: string; where?: CanonicalPred; filtered: boolean })
|
|
@@ -2442,34 +2702,41 @@ function readInputs(module: DomainModule): ReadInput[] {
|
|
|
2442
2702
|
const isPublic = (value: unknown): boolean =>
|
|
2443
2703
|
!(value && typeof value === "object" &&
|
|
2444
2704
|
(value as { businessBirthInternal?: unknown }).businessBirthInternal === true);
|
|
2705
|
+
const authenticationOf = (value: unknown): MemberAuthentication | undefined =>
|
|
2706
|
+
(value as { authentication?: MemberAuthentication }).authentication;
|
|
2707
|
+
const member = (value: unknown) => {
|
|
2708
|
+
const authentication = authenticationOf(value);
|
|
2709
|
+
return authentication === undefined ? {} : { authentication };
|
|
2710
|
+
};
|
|
2445
2711
|
const reads: ReadInput[] = [
|
|
2446
|
-
...(module.queries ?? []).map((read) => ({ id: read.id, public: isPublic(read), readKind: "query" as const, of: read.returns, key: read.key })),
|
|
2712
|
+
...(module.queries ?? []).map((read) => ({ id: read.id, public: isPublic(read), ...member(read), readKind: "query" as const, of: read.returns, key: read.key })),
|
|
2447
2713
|
...(module.counts ?? []).map((value) => {
|
|
2448
2714
|
const read = finishCount(value);
|
|
2449
|
-
return { id: read.id, public: isPublic(value), readKind: "count" as const, of: read.of, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2715
|
+
return { id: read.id, public: isPublic(value), ...member(value), readKind: "count" as const, of: read.of, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2450
2716
|
}),
|
|
2451
2717
|
...(module.exists_ ?? []).map((value) => {
|
|
2452
2718
|
const read = finishExists(value);
|
|
2453
|
-
return { id: read.id, public: isPublic(value), readKind: "exists" as const, of: read.of, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2719
|
+
return { id: read.id, public: isPublic(value), ...member(value), readKind: "exists" as const, of: read.of, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2454
2720
|
}),
|
|
2455
2721
|
...(module.sums ?? []).map((value) => {
|
|
2456
2722
|
const read = finishSum(value);
|
|
2457
|
-
return { id: read.id, public: isPublic(value), readKind: "sum" as const, of: read.of, value: read.sumField, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2723
|
+
return { id: read.id, public: isPublic(value), ...member(value), readKind: "sum" as const, of: read.of, value: read.sumField, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2458
2724
|
}),
|
|
2459
2725
|
...(module.mins ?? []).map((value) => {
|
|
2460
2726
|
const read = finishExtremum(value);
|
|
2461
|
-
return { id: read.id, public: isPublic(value), readKind: "min" as const, of: read.of, value: read.valueField, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2727
|
+
return { id: read.id, public: isPublic(value), ...member(value), readKind: "min" as const, of: read.of, value: read.valueField, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2462
2728
|
}),
|
|
2463
2729
|
...(module.maxes ?? []).map((value) => {
|
|
2464
2730
|
const read = finishExtremum(value);
|
|
2465
|
-
return { id: read.id, public: isPublic(value), readKind: "max" as const, of: read.of, value: read.valueField, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2731
|
+
return { id: read.id, public: isPublic(value), ...member(value), readKind: "max" as const, of: read.of, value: read.valueField, ...(read.by === undefined ? {} : { by: read.by }), ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined };
|
|
2466
2732
|
}),
|
|
2467
|
-
...(module.orderedReads ?? []).map((read) => ({ id: read.id, public: isPublic(read), readKind: "ordered" as const, of: read.of, orderBy: read.orderKey, descending: read.orderDesc, limit: read.limit, ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined })),
|
|
2468
|
-
...(module.spatials ?? []).map((read) => ({ id: read.id, public: isPublic(read), readKind: "spatial" as const, of: read.of, geometry: read.on })),
|
|
2733
|
+
...(module.orderedReads ?? []).map((read) => ({ id: read.id, public: isPublic(read), ...member(read), readKind: "ordered" as const, of: read.of, orderBy: read.orderKey, descending: read.orderDesc, limit: read.limit, ...(read.where === undefined ? {} : { where: read.where }), filtered: read.where !== undefined })),
|
|
2734
|
+
...(module.spatials ?? []).map((read) => ({ id: read.id, public: isPublic(read), ...member(read), readKind: "spatial" as const, of: read.of, geometry: read.on })),
|
|
2469
2735
|
...(module.deriveds ?? []).map((read) => "kind" in read && read.kind === "temporalEnum"
|
|
2470
2736
|
? {
|
|
2471
2737
|
id: read.id,
|
|
2472
2738
|
public: isPublic(read),
|
|
2739
|
+
...member(read),
|
|
2473
2740
|
readKind: "temporalEnum" as const,
|
|
2474
2741
|
of: read.of,
|
|
2475
2742
|
sourceField: read.sourceField,
|
|
@@ -2478,8 +2745,8 @@ function readInputs(module: DomainModule): ReadInput[] {
|
|
|
2478
2745
|
transitions: read.transitions,
|
|
2479
2746
|
returns: read.returns,
|
|
2480
2747
|
}
|
|
2481
|
-
: { id: read.id, public: isPublic(read), readKind: "derived" as const, of: read.of, returns: read.returns }),
|
|
2482
|
-
...(module.combineds ?? []).map((read) => ({ id: read.id, public: isPublic(read), readKind: "combined" as const, of: read.of, via: read.refField, reads: read.reads, returns: read.returns })),
|
|
2748
|
+
: { id: read.id, public: isPublic(read), ...member(read), readKind: "derived" as const, of: read.of, returns: read.returns }),
|
|
2749
|
+
...(module.combineds ?? []).map((read) => ({ id: read.id, public: isPublic(read), ...member(read), readKind: "combined" as const, of: read.of, via: read.refField, reads: read.reads, returns: read.returns })),
|
|
2483
2750
|
];
|
|
2484
2751
|
return reads.sort((a, b) => compareText(a.id, b.id));
|
|
2485
2752
|
}
|
|
@@ -2556,7 +2823,20 @@ function readResult(read: ReadInput, aggregate: LawRef<"aggregate">): RawLawRead
|
|
|
2556
2823
|
|
|
2557
2824
|
function storedFieldValue(field: Field): LawValueType {
|
|
2558
2825
|
if (field.kind === "json") return { kind: "unknown" };
|
|
2559
|
-
if (field.kind === "ref"
|
|
2826
|
+
if (field.kind === "ref") {
|
|
2827
|
+
// A same-workspace or sibling-workspace reference is stored as its stable
|
|
2828
|
+
// id string. Atomic and versioned Nomos references are different lawful
|
|
2829
|
+
// values: their workspace/type/id address (or pinned/series pair) is one
|
|
2830
|
+
// indivisible value and must remain structured in the law graph. Lowering
|
|
2831
|
+
// every ref to string made the generated transport disagree with the
|
|
2832
|
+
// generated public type and deferred that contradiction until tenant
|
|
2833
|
+
// application compilation.
|
|
2834
|
+
if (field.nomosRef !== undefined || field.versionedForeignRef !== undefined) {
|
|
2835
|
+
return lowerLawValueType(field.zod);
|
|
2836
|
+
}
|
|
2837
|
+
return { kind: "string", constraints: [] };
|
|
2838
|
+
}
|
|
2839
|
+
if (field.kind === "position") {
|
|
2560
2840
|
return { kind: "string", constraints: [] };
|
|
2561
2841
|
}
|
|
2562
2842
|
if (field.kind === "counter") return { kind: "integer", constraints: [] };
|
|
@@ -2638,30 +2918,167 @@ function linkStoredField(
|
|
|
2638
2918
|
};
|
|
2639
2919
|
}
|
|
2640
2920
|
|
|
2641
|
-
function
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2921
|
+
function descriptorTypeValue(
|
|
2922
|
+
descriptor: ValueObjectDescriptor,
|
|
2923
|
+
byName: ReadonlyMap<string, ValueObjectDescriptor>,
|
|
2924
|
+
active: ReadonlySet<string>,
|
|
2925
|
+
): LawValueType {
|
|
2926
|
+
if (active.has(descriptor.name)) {
|
|
2927
|
+
fail(`value object '${descriptor.name}' recursively contains itself without a declared recursive type`);
|
|
2928
|
+
}
|
|
2929
|
+
const next = new Set(active).add(descriptor.name);
|
|
2930
|
+
const semantic: LawValueSemantic = {
|
|
2931
|
+
kind: "value-object", name: descriptor.name,
|
|
2932
|
+
...(descriptor.geometry === undefined ? {} : { geometry: descriptor.geometry }),
|
|
2933
|
+
};
|
|
2934
|
+
if (descriptor.geometry !== undefined) {
|
|
2935
|
+
const scalar: LawValueType = { kind: "number", constraints: [] };
|
|
2936
|
+
const position: LawValueType = { kind: "list", element: scalar };
|
|
2937
|
+
const coordinates: LawValueType = descriptor.geometry === "Point"
|
|
2938
|
+
? position
|
|
2939
|
+
: descriptor.geometry === "Polygon"
|
|
2940
|
+
? { kind: "list", element: { kind: "list", element: position } }
|
|
2941
|
+
: { kind: "list", element: position };
|
|
2942
|
+
return {
|
|
2943
|
+
kind: "record",
|
|
2944
|
+
semantic,
|
|
2945
|
+
fields: [
|
|
2946
|
+
{
|
|
2947
|
+
name: "type",
|
|
2948
|
+
required: true,
|
|
2949
|
+
value: { kind: "literal", value: descriptor.geometry },
|
|
2950
|
+
},
|
|
2951
|
+
{ name: "coordinates", required: true, value: coordinates },
|
|
2952
|
+
],
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
if (descriptor.union !== undefined) {
|
|
2956
|
+
return {
|
|
2957
|
+
kind: "sum",
|
|
2958
|
+
semantic,
|
|
2959
|
+
options: Object.entries(descriptor.union)
|
|
2960
|
+
.sort(([a], [b]) => compareText(a, b))
|
|
2961
|
+
.map(([discriminator, arm]) => {
|
|
2962
|
+
const fields: LawValueMember[] = [{
|
|
2963
|
+
name: "type",
|
|
2964
|
+
required: true,
|
|
2965
|
+
value: { kind: "literal", value: discriminator },
|
|
2966
|
+
}];
|
|
2967
|
+
if ("ref" in arm) {
|
|
2968
|
+
const target = byName.get(arm.ref);
|
|
2969
|
+
if (target === undefined) {
|
|
2970
|
+
fail(`value object '${descriptor.name}' references unknown type '${arm.ref}'`);
|
|
2971
|
+
}
|
|
2972
|
+
// Named union arms are deliberately nested under `value`; this is
|
|
2973
|
+
// the authored value-object wire shape, not a flattened record.
|
|
2974
|
+
fields.push({
|
|
2975
|
+
name: "value",
|
|
2976
|
+
required: true,
|
|
2977
|
+
value: descriptorTypeValue(target, byName, next),
|
|
2978
|
+
});
|
|
2979
|
+
} else {
|
|
2980
|
+
fields.push(...Object.entries(arm.fields)
|
|
2981
|
+
.sort(([a], [b]) => compareText(a, b))
|
|
2982
|
+
.map(([name, field]) => ({
|
|
2983
|
+
name,
|
|
2984
|
+
required: field.optional !== true,
|
|
2985
|
+
value: descriptorValue(
|
|
2986
|
+
field,
|
|
2987
|
+
byName,
|
|
2988
|
+
next,
|
|
2989
|
+
`${descriptor.name}${discriminator[0]!.toUpperCase()}${discriminator.slice(1)}`,
|
|
2990
|
+
name,
|
|
2991
|
+
),
|
|
2992
|
+
})));
|
|
2993
|
+
}
|
|
2994
|
+
return {
|
|
2995
|
+
kind: "record" as const,
|
|
2996
|
+
fields,
|
|
2997
|
+
};
|
|
2998
|
+
}),
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
return {
|
|
3002
|
+
kind: "record",
|
|
3003
|
+
semantic,
|
|
3004
|
+
fields: Object.entries(descriptor.fields ?? {})
|
|
3005
|
+
.sort(([a], [b]) => compareText(a, b))
|
|
3006
|
+
.map(([name, field]) => ({
|
|
3007
|
+
name,
|
|
3008
|
+
required: field.optional !== true,
|
|
3009
|
+
value: descriptorValue(field, byName, next, descriptor.name, name),
|
|
3010
|
+
})),
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
function descriptorValue(
|
|
3015
|
+
field: ValueObjectFieldDescriptor,
|
|
3016
|
+
byName: ReadonlyMap<string, ValueObjectDescriptor>,
|
|
3017
|
+
active: ReadonlySet<string> = new Set(),
|
|
3018
|
+
ownerName?: string,
|
|
3019
|
+
fieldName?: string,
|
|
3020
|
+
): LawValueType {
|
|
3021
|
+
const value: LawValueType = (() => {
|
|
3022
|
+
switch (field.type) {
|
|
3023
|
+
case "string": {
|
|
3024
|
+
const semantic: LawValueSemantic | undefined = field.digest === "sha256"
|
|
3025
|
+
? { kind: "sha256-digest" }
|
|
3026
|
+
: field.idOf !== undefined
|
|
3027
|
+
? {
|
|
3028
|
+
kind: "id-reference",
|
|
3029
|
+
target: field.idOf,
|
|
3030
|
+
targetKind: field.idOfContract === true ? "contract" : "aggregate",
|
|
3031
|
+
}
|
|
3032
|
+
: field.brand !== undefined
|
|
3033
|
+
? { kind: "branded-id", name: field.brand }
|
|
3034
|
+
: undefined;
|
|
3035
|
+
return {
|
|
3036
|
+
kind: "string",
|
|
3037
|
+
constraints: [],
|
|
3038
|
+
...(semantic === undefined ? {} : { semantic }),
|
|
3039
|
+
};
|
|
3040
|
+
}
|
|
2645
3041
|
case "number":
|
|
2646
|
-
return {
|
|
3042
|
+
return {
|
|
3043
|
+
kind: field.int === true ? "integer" : "number",
|
|
3044
|
+
constraints: [],
|
|
3045
|
+
...(field.unit === undefined
|
|
3046
|
+
? {}
|
|
3047
|
+
: { semantic: { kind: "unit", name: field.unit } as const }),
|
|
3048
|
+
};
|
|
2647
3049
|
case "boolean":
|
|
2648
3050
|
return { kind: "boolean" };
|
|
2649
3051
|
case "enum":
|
|
2650
3052
|
return {
|
|
2651
3053
|
kind: "enum",
|
|
2652
3054
|
values: [...field.values].sort(compareText),
|
|
2653
|
-
...(field.name
|
|
3055
|
+
...(field.name !== undefined
|
|
3056
|
+
? { name: field.name }
|
|
3057
|
+
: ownerName !== undefined && fieldName !== undefined
|
|
3058
|
+
? { name: `${ownerName}${fieldName[0]!.toUpperCase()}${fieldName.slice(1)}` }
|
|
3059
|
+
: {}),
|
|
2654
3060
|
};
|
|
2655
3061
|
case "literal":
|
|
2656
3062
|
return { kind: "literal", value: field.value };
|
|
2657
3063
|
case "array":
|
|
2658
|
-
return {
|
|
3064
|
+
return {
|
|
3065
|
+
kind: "list",
|
|
3066
|
+
element: descriptorValue(field.items, byName, active, ownerName, fieldName),
|
|
3067
|
+
};
|
|
2659
3068
|
case "map":
|
|
2660
|
-
return {
|
|
3069
|
+
return {
|
|
3070
|
+
kind: "map",
|
|
3071
|
+
value: descriptorValue(field.values, byName, active, ownerName, fieldName),
|
|
3072
|
+
};
|
|
2661
3073
|
case "object":
|
|
2662
|
-
case "geometry":
|
|
2663
|
-
|
|
2664
|
-
|
|
3074
|
+
case "geometry": {
|
|
3075
|
+
const target = byName.get(field.ref);
|
|
3076
|
+
if (target === undefined) fail(`value object field references unknown type '${field.ref}'`);
|
|
3077
|
+
return descriptorTypeValue(target, byName, active);
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
})();
|
|
3081
|
+
return field.nullable === true ? { kind: "nullable", value } : value;
|
|
2665
3082
|
}
|
|
2666
3083
|
|
|
2667
3084
|
function mergeDrivers(driver: Driver): LawMergeDriver[] {
|
|
@@ -2823,12 +3240,22 @@ export function lowerAnonymousValueGraph<K extends LawEntityKind>(
|
|
|
2823
3240
|
}
|
|
2824
3241
|
case "sum": {
|
|
2825
3242
|
const variants = value.options.map((option) => {
|
|
3243
|
+
const discriminator = option.kind === "record"
|
|
3244
|
+
? option.fields.find((field) =>
|
|
3245
|
+
field.name === "type" &&
|
|
3246
|
+
field.required &&
|
|
3247
|
+
field.value.kind === "literal" &&
|
|
3248
|
+
typeof field.value.value === "string")?.value
|
|
3249
|
+
: undefined;
|
|
3250
|
+
const label = discriminator?.kind === "literal" && typeof discriminator.value === "string"
|
|
3251
|
+
? discriminator.value
|
|
3252
|
+
: undefined;
|
|
2826
3253
|
const child = lower(option);
|
|
2827
3254
|
const variantEntity = structuralEntity(
|
|
2828
3255
|
owner,
|
|
2829
3256
|
"value-variant",
|
|
2830
|
-
{ parent: entity.id, value: child.id },
|
|
2831
|
-
`${owner.label}#${child.id}`,
|
|
3257
|
+
{ parent: entity.id, ...(label === undefined ? {} : { label }), value: child.id },
|
|
3258
|
+
`${owner.label}#${label ?? child.id}`,
|
|
2832
3259
|
);
|
|
2833
3260
|
if (!nodes.has(variantEntity.id)) {
|
|
2834
3261
|
nodes.set(variantEntity.id, {
|
|
@@ -2836,6 +3263,7 @@ export function lowerAnonymousValueGraph<K extends LawEntityKind>(
|
|
|
2836
3263
|
structuralKind: "value-variant",
|
|
2837
3264
|
entity: variantEntity,
|
|
2838
3265
|
owner: structuralRef(entity),
|
|
3266
|
+
...(label === undefined ? {} : { label }),
|
|
2839
3267
|
value: child,
|
|
2840
3268
|
});
|
|
2841
3269
|
}
|
|
@@ -2866,6 +3294,10 @@ export function lowerAnonymousValueGraph<K extends LawEntityKind>(
|
|
|
2866
3294
|
export function lowerAnonymousContractFields(
|
|
2867
3295
|
source: LawValueType,
|
|
2868
3296
|
owner: LawEntity<"contract">,
|
|
3297
|
+
wireForField: (
|
|
3298
|
+
name: string,
|
|
3299
|
+
structuralSid: string,
|
|
3300
|
+
) => LawOperationFieldWire["protobuf"] = (_name, structuralSid) => ({ canonical: structuralSid }),
|
|
2869
3301
|
): { readonly fields: readonly LawStructuralRef<"value-field">[]; readonly nodes: readonly LawAnonymousValueNode[] } {
|
|
2870
3302
|
const value = canonicalValueType(source);
|
|
2871
3303
|
if (value.kind !== "record") {
|
|
@@ -2881,10 +3313,15 @@ export function lowerAnonymousContractFields(
|
|
|
2881
3313
|
{ name: member.name, required: member.required, value: lowered.root.id },
|
|
2882
3314
|
`${owner.label}#${member.name}`,
|
|
2883
3315
|
);
|
|
3316
|
+
const wire = wireForField(member.name, entity.sid);
|
|
2884
3317
|
nodes.set(entity.id, {
|
|
2885
3318
|
kind: "structural",
|
|
2886
3319
|
structuralKind: "value-field",
|
|
2887
|
-
entity
|
|
3320
|
+
entity: {
|
|
3321
|
+
...entity,
|
|
3322
|
+
wireKey: wire.canonical,
|
|
3323
|
+
...(wire.aliases === undefined ? {} : { wireAliases: wire.aliases }),
|
|
3324
|
+
},
|
|
2888
3325
|
owner: ref(owner),
|
|
2889
3326
|
name: member.name,
|
|
2890
3327
|
required: member.required,
|