@githolon/dsl 0.108.7 → 0.110.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +80 -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 +214 -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 +268 -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 +23950 -15776
- 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 +550 -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_event_desk_close_test.dart +16 -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 +1276 -0
- package/src/codegen_call_usda.ts +49 -6
- package/src/codegen_dart.ts +83 -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 +2017 -1195
- 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_usda.ts
CHANGED
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
LawWorkspaceTypeNode,
|
|
28
28
|
LawWorkspaceRelationNode,
|
|
29
29
|
} from "./law_graph.js";
|
|
30
|
+
import { MemberAuthenticationKind, type AuthenticationProviderRef } from "./member_authentication.js";
|
|
30
31
|
|
|
31
32
|
const FRAMEWORK_SCALAR: Readonly<Record<string, string>> = {
|
|
32
33
|
string: "/Nomos/Framework/Types/t_0000000000000001",
|
|
@@ -35,10 +36,16 @@ const FRAMEWORK_SCALAR: Readonly<Record<string, string>> = {
|
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
const FRAMEWORK_RELATIONS = [
|
|
38
|
-
|
|
39
|
+
// admin and installDomain also admit the framework's console and custodian principals: token-free
|
|
40
|
+
// genesis (D22) seats a `console:`/`custodian:` founder as admin and as model authority. These two
|
|
41
|
+
// scopes are framework vocabulary (`member_authentication.ts`); no tenant scope is ever named here.
|
|
42
|
+
// This layer is the framework unit every law composes with: changing it moves the unit, so it lands
|
|
43
|
+
// only together with a stage-zero law refreshed through `npm run prepare:kernel` (the candidate's
|
|
44
|
+
// companion and nomos_flutter/assets/nomos_kernel/bootstrap.law.usdz), never alone.
|
|
45
|
+
{ key: "workspace#admin", id: "r_0000000000000001", object: "o_0000000000000001", subjects: ["user", "key", "console", "custodian"] },
|
|
39
46
|
{ key: "workspace#creator", id: "r_0000000000000002", object: "o_0000000000000001", subjects: ["user", "key"] },
|
|
40
47
|
{ key: "workspace#platformCreator", id: "r_0000000000000003", object: "o_0000000000000001", subjects: ["user", "key"] },
|
|
41
|
-
{ key: "workspace#installDomain", id: "r_0000000000000004", object: "o_0000000000000001", subjects: ["user", "key"] },
|
|
48
|
+
{ key: "workspace#installDomain", id: "r_0000000000000004", object: "o_0000000000000001", subjects: ["user", "key", "console", "custodian"] },
|
|
42
49
|
{ key: "identity#signer", id: "r_0000000000000005", object: "o_0000000000000002", subjects: ["key"] },
|
|
43
50
|
] as const;
|
|
44
51
|
|
|
@@ -146,6 +153,22 @@ export function emitFrameworkLawUsda(): string {
|
|
|
146
153
|
}
|
|
147
154
|
type ResolveDependency = (dependency: LawDependencyRef<any>) => string;
|
|
148
155
|
|
|
156
|
+
/**
|
|
157
|
+
* A member's declared provider (identity target model D7, D22). An enrolled or sovereign provider is
|
|
158
|
+
* its kind and scope and nothing else: no issuer, key or token is law. The legacy digest form keeps
|
|
159
|
+
* today's scope/identity pair, which the kernel still requires paired.
|
|
160
|
+
*/
|
|
161
|
+
function authenticationProviderOpinions(provider: AuthenticationProviderRef, pad: string): string[] {
|
|
162
|
+
const scope = `${pad}custom uniform string nomos:authenticationProviderScope = ${quote(provider.scope)}`;
|
|
163
|
+
switch (provider.kind) {
|
|
164
|
+
case "legacySelected":
|
|
165
|
+
return [scope, `${pad}custom uniform string nomos:authenticationProviderIdentity = ${quote(provider.identitySha256)}`];
|
|
166
|
+
case "enrolled":
|
|
167
|
+
case "sovereign":
|
|
168
|
+
return [`${pad}custom uniform token nomos:authenticationProviderKind = ${quote(provider.kind)}`, scope];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
149
172
|
function entityLabelOpinions(
|
|
150
173
|
entity: { readonly label: string; readonly priorLabels: readonly string[] },
|
|
151
174
|
indent: number,
|
|
@@ -165,6 +188,8 @@ function entityLabelOpinions(
|
|
|
165
188
|
export interface CompiledSparseLawGraphUsda {
|
|
166
189
|
readonly text: string;
|
|
167
190
|
readonly paths: ReadonlyMap<string, string>;
|
|
191
|
+
/** The exact same nominal export resolution used while emitting relationship targets. */
|
|
192
|
+
readonly resolveDependency: ResolveDependency;
|
|
168
193
|
}
|
|
169
194
|
|
|
170
195
|
/** Render one sparse law layer and retain its exact identity-path projection for client codegen. */
|
|
@@ -304,10 +329,10 @@ export function compileSparseLawGraphUsda(
|
|
|
304
329
|
candidates = dependencyPaths.get(`*:${dependency.entityKind}:${dependency.label}`) ?? [];
|
|
305
330
|
}
|
|
306
331
|
if (candidates.length === 0) {
|
|
307
|
-
fail(`no closure path
|
|
332
|
+
fail(`domain '${graph.domain.entity.label}' has no closure path resolving dependency '${dependency.domain ?? "?"}:${dependency.entityKind}:${dependency.label}'`);
|
|
308
333
|
}
|
|
309
334
|
if (candidates.length > 1) {
|
|
310
|
-
fail(`dependency '${dependency.domain ?? "?"}:${dependency.entityKind}:${dependency.label}' is ambiguous in the closure`);
|
|
335
|
+
fail(`domain '${graph.domain.entity.label}' dependency '${dependency.domain ?? "?"}:${dependency.entityKind}:${dependency.label}' is ambiguous in the closure`);
|
|
311
336
|
}
|
|
312
337
|
return candidates[0]!;
|
|
313
338
|
};
|
|
@@ -437,8 +462,12 @@ export function compileSparseLawGraphUsda(
|
|
|
437
462
|
}
|
|
438
463
|
case "nullable":
|
|
439
464
|
case "default": {
|
|
440
|
-
//
|
|
441
|
-
|
|
465
|
+
// Wrappers do not own prims, but their meaning must survive structural
|
|
466
|
+
// interning. A nullable field is not the same contract as a non-null field.
|
|
467
|
+
const child = childKey(node.expression.value.id);
|
|
468
|
+
if (child !== undefined) key = JSON.stringify(node.expression.kind === "nullable"
|
|
469
|
+
? ["nullable", child]
|
|
470
|
+
: ["default", child, node.expression.defaultValue]);
|
|
442
471
|
break;
|
|
443
472
|
}
|
|
444
473
|
case "record": {
|
|
@@ -450,19 +479,25 @@ export function compileSparseLawGraphUsda(
|
|
|
450
479
|
}
|
|
451
480
|
if (members.length === (anonymousFieldsByOwner.get(id)?.length ?? 0)) {
|
|
452
481
|
members.sort(([left], [right]) => left.localeCompare(right));
|
|
453
|
-
key = JSON.stringify(["record", members
|
|
482
|
+
key = JSON.stringify(["record", members,
|
|
483
|
+
node.expression.semantic?.kind === "value-object" ? node.expression.semantic.geometry : undefined]);
|
|
454
484
|
}
|
|
455
485
|
break;
|
|
456
486
|
}
|
|
457
487
|
case "sum": {
|
|
458
|
-
const members: string
|
|
488
|
+
const members: Array<readonly [string, string]> = [];
|
|
459
489
|
for (const variant of anonymousVariantsByOwner.get(id) ?? []) {
|
|
460
490
|
const child = childKey(variant.value.id);
|
|
461
491
|
if (child === undefined) break;
|
|
462
|
-
|
|
492
|
+
// A union arm's discriminator is part of its wire contract. Two sums
|
|
493
|
+
// with the same carried value shapes but different arm labels cannot
|
|
494
|
+
// share one USDA prim: authoring reconstructs the nominal oneof from
|
|
495
|
+
// these labels before it decodes the generated Protobuf call.
|
|
496
|
+
members.push([variant.label ?? variant.entity.label, child]);
|
|
463
497
|
}
|
|
464
498
|
if (members.length === (anonymousVariantsByOwner.get(id)?.length ?? 0)) {
|
|
465
|
-
members.sort()
|
|
499
|
+
members.sort(([leftLabel, leftChild], [rightLabel, rightChild]) =>
|
|
500
|
+
leftLabel.localeCompare(rightLabel) || leftChild.localeCompare(rightChild));
|
|
466
501
|
key = JSON.stringify(["sum", members]);
|
|
467
502
|
}
|
|
468
503
|
break;
|
|
@@ -547,14 +582,16 @@ export function compileSparseLawGraphUsda(
|
|
|
547
582
|
for (const variant of anonymousVariantsByOwner.get(canonicalId) ?? []) {
|
|
548
583
|
const child = semanticTypeKey(variant.value.id);
|
|
549
584
|
if (child === undefined) continue;
|
|
550
|
-
const
|
|
585
|
+
const key = JSON.stringify([variant.label ?? variant.entity.label, child]);
|
|
586
|
+
const matches = canonicalVariants.get(key) ?? [];
|
|
551
587
|
matches.push(variant);
|
|
552
|
-
canonicalVariants.set(
|
|
588
|
+
canonicalVariants.set(key, matches);
|
|
553
589
|
}
|
|
554
590
|
for (const variant of anonymousVariantsByOwner.get(duplicateId) ?? []) {
|
|
555
591
|
const child = semanticTypeKey(variant.value.id);
|
|
556
592
|
if (child === undefined) continue;
|
|
557
|
-
const
|
|
593
|
+
const key = JSON.stringify([variant.label ?? variant.entity.label, child]);
|
|
594
|
+
const canonical = canonicalVariants.get(key)?.shift();
|
|
558
595
|
if (canonical !== undefined) {
|
|
559
596
|
pathById.set(variant.entity.id, requiredPath(canonical.entity.id, pathById));
|
|
560
597
|
}
|
|
@@ -631,14 +668,17 @@ export function compileSparseLawGraphUsda(
|
|
|
631
668
|
`${" ".repeat(indent)}custom uniform token nomos:objectNamespace = ${quote(objectType.namespace)}`,
|
|
632
669
|
], undefined, () => "NomosObjectType");
|
|
633
670
|
}
|
|
634
|
-
if (contracts.length > 0 || payloadContracts.length > 0) {
|
|
671
|
+
if (contracts.length > 0 || payloadContracts.length > 0 || readContracts.length > 0) {
|
|
635
672
|
lines.push("");
|
|
636
|
-
const emittedContracts: Array<LawContractNode | LawPayloadContractNode> =
|
|
637
|
-
|
|
673
|
+
const emittedContracts: Array<LawContractNode | LawPayloadContractNode | LawReadContractNode> =
|
|
674
|
+
[...contracts, ...payloadContracts, ...readContracts]
|
|
675
|
+
.sort((a, b) => a.entity.id.localeCompare(b.entity.id));
|
|
638
676
|
emitContainer(lines, "Contracts", emittedContracts, 12, (contract, indent) =>
|
|
639
677
|
contract.kind === "contract"
|
|
640
678
|
? emitContract(contract, fields, pathById, resolveDependency, indent)
|
|
641
|
-
:
|
|
679
|
+
: contract.kind === "payload-contract"
|
|
680
|
+
? emitPayloadContract(contract, anonymousFields, anonymousTypeById, pathById, indent)
|
|
681
|
+
: emitReadContract(contract, pathById, indent));
|
|
642
682
|
}
|
|
643
683
|
if (relations.length > 0) {
|
|
644
684
|
lines.push("");
|
|
@@ -654,7 +694,7 @@ export function compileSparseLawGraphUsda(
|
|
|
654
694
|
if (reads.length > 0) {
|
|
655
695
|
lines.push("");
|
|
656
696
|
emitContainer(lines, "Reads", reads, 12, (read, indent) =>
|
|
657
|
-
emitRead(read, readContracts, readPredicates, pathById, indent));
|
|
697
|
+
emitRead(read, readContracts, readPredicates, anonymousTypeById, pathById, indent));
|
|
658
698
|
}
|
|
659
699
|
if (policies.length > 0) {
|
|
660
700
|
lines.push("");
|
|
@@ -683,7 +723,7 @@ export function compileSparseLawGraphUsda(
|
|
|
683
723
|
(flow) => `w_${flow.entity.sid}`);
|
|
684
724
|
}
|
|
685
725
|
lines.push(" }", " }", "}", "");
|
|
686
|
-
return { text: lines.join("\n"), paths: new Map(pathById) };
|
|
726
|
+
return { text: lines.join("\n"), paths: new Map(pathById), resolveDependency };
|
|
687
727
|
}
|
|
688
728
|
|
|
689
729
|
/** First W4.4 vertical slice: render domain, aggregate, stored-field and reusable-contract opinions. */
|
|
@@ -769,7 +809,7 @@ function emitPolicy(
|
|
|
769
809
|
if (policy.keyHashes.length > 0) {
|
|
770
810
|
body.push(`${pad}custom uniform string[] nomos:keyHashes = ${stringList(policy.keyHashes)}`);
|
|
771
811
|
}
|
|
772
|
-
} else {
|
|
812
|
+
} else if (policy.policyKind === "source-set") {
|
|
773
813
|
body.push(
|
|
774
814
|
`${pad}custom rel nomos:allowList = <${requiredPath(policy.allowList.id, paths)}>`,
|
|
775
815
|
`${pad}custom rel nomos:genesisField = <${requiredPath(policy.genesisField.id, paths)}>`,
|
|
@@ -793,6 +833,9 @@ function emitInvariant(
|
|
|
793
833
|
? [`${pad}custom uniform token nomos:evaluator = ${quote(invariant.evaluator)}`]
|
|
794
834
|
: []),
|
|
795
835
|
];
|
|
836
|
+
if (invariant.invariantKind === "workspace" && invariant.refusalType !== undefined) {
|
|
837
|
+
body.push(`${pad}custom rel nomos:refusalType = <${requiredPath(invariant.refusalType.id, paths)}>`);
|
|
838
|
+
}
|
|
796
839
|
if (invariant.invariantKind === "workspace" && invariant.reads !== undefined) {
|
|
797
840
|
body.push(`${pad}custom uniform token nomos:readEvaluator = "point-v1"`);
|
|
798
841
|
for (const [index, read] of invariant.reads.entries()) {
|
|
@@ -916,6 +959,12 @@ function emitCapability(
|
|
|
916
959
|
...(capability.endpoint === undefined
|
|
917
960
|
? []
|
|
918
961
|
: [`${pad}custom uniform asset nomos:endpoint = @${capability.endpoint.replaceAll("@", "@@")}@`]),
|
|
962
|
+
...(capability.executionPlacement === undefined
|
|
963
|
+
? []
|
|
964
|
+
: [`${pad}custom uniform token nomos:executionPlacement = ${quote(capability.executionPlacement)}`]),
|
|
965
|
+
...(capability.executionCardinality === undefined
|
|
966
|
+
? []
|
|
967
|
+
: [`${pad}custom uniform token nomos:executionCardinality = ${quote(capability.executionCardinality)}`]),
|
|
919
968
|
`${pad}custom rel nomos:aggregate = <${requiredPath(capability.task.id, paths)}>`,
|
|
920
969
|
`${pad}custom rel nomos:obligation = <${requiredPath(capability.obligation.id, paths)}>`,
|
|
921
970
|
`${pad}custom rel nomos:complete = <${requiredPath(capability.complete.id, paths)}>`,
|
|
@@ -989,18 +1038,38 @@ function emitIntent(
|
|
|
989
1038
|
...(intent.acceptsVerifiedBirthParentRecovery
|
|
990
1039
|
? [`${pad}custom uniform token nomos:workspaceEffectAdmission = "VerifiedBirthParentRecovery"`]
|
|
991
1040
|
: []),
|
|
992
|
-
...(intent.
|
|
1041
|
+
...(intent.acceptsVerifiedWorkspaceClaim
|
|
1042
|
+
? [`${pad}custom uniform token nomos:workspaceEffectAdmission = "VerifiedWorkspaceClaim"`]
|
|
1043
|
+
: []),
|
|
1044
|
+
...(intent.authentication?.kind === MemberAuthenticationKind.EnrolledDevice
|
|
993
1045
|
? [`${pad}custom uniform token nomos:offerAuthenticationProof = "EnrolledDevice"`]
|
|
994
1046
|
: []),
|
|
1047
|
+
...(intent.authentication?.kind === MemberAuthenticationKind.SelectedProvider
|
|
1048
|
+
? authenticationProviderOpinions(intent.authentication.provider, pad)
|
|
1049
|
+
: []),
|
|
1050
|
+
// D22 sovereign self-certification: the kernel admits this intent's founding signer tuple iff the
|
|
1051
|
+
// signing key's sha256 is the captured principal's subject (and the payload's keyHash).
|
|
1052
|
+
...(intent.selfCertifyingPrincipal === true
|
|
1053
|
+
? [`${pad}custom uniform token nomos:selfCertifyingPrincipal = "true"`]
|
|
1054
|
+
: []),
|
|
995
1055
|
`${pad}custom rel nomos:target = ${targets([intent.target], paths, resolveDependency)}`,
|
|
996
1056
|
`${pad}custom rel nomos:accepts = <${requiredPath(intent.accepts.id, paths)}>`,
|
|
997
1057
|
...(intent.publicAccepts === undefined
|
|
998
1058
|
? []
|
|
999
1059
|
: [`${pad}custom rel nomos:publicAccepts = <${requiredPath(intent.publicAccepts.id, paths)}>`]),
|
|
1000
1060
|
];
|
|
1061
|
+
if ((intent.domainRefusals?.length ?? 0) > 0) {
|
|
1062
|
+
body.push(`${pad}custom rel nomos:refusalTypes = [${intent.domainRefusals!.map(type => `<${requiredPath(type.id, paths)}>`).join(", ")}]`);
|
|
1063
|
+
}
|
|
1001
1064
|
if (intent.reads.length > 0) {
|
|
1002
1065
|
body.push(`${pad}custom rel nomos:reads = ${targets(intent.reads, paths, resolveDependency)}`);
|
|
1003
1066
|
}
|
|
1067
|
+
// A composed business intent executes its steps, so it depends on their whole law. The edge
|
|
1068
|
+
// is declared here rather than rediscovered by any consumer of the emitted law.
|
|
1069
|
+
if (intent.steps.length > 0) {
|
|
1070
|
+
body.push(`${pad}custom rel nomos:steps = ${relList(intent.steps
|
|
1071
|
+
.map((step) => `<${requiredPath(step.id, paths)}>`))}`);
|
|
1072
|
+
}
|
|
1004
1073
|
if ((intent.directsWorkspaceEffects ?? []).length > 0) {
|
|
1005
1074
|
body.push(
|
|
1006
1075
|
`${pad}custom rel nomos:directsWorkspaceEffect = ${targets(intent.directsWorkspaceEffects, paths, resolveDependency)}`,
|
|
@@ -1017,6 +1086,11 @@ function emitIntent(
|
|
|
1017
1086
|
`${pad}custom rel nomos:requiresObjectIdField = <${requiredPath(intent.authorization.objectFrom.idField.id, paths)}>`,
|
|
1018
1087
|
);
|
|
1019
1088
|
}
|
|
1089
|
+
if (intent.authorization.subjectFromAttestedRead !== undefined) {
|
|
1090
|
+
body.push(
|
|
1091
|
+
`${pad}custom uniform token nomos:requiresSubjectFromAttestedRead = ${quote(intent.authorization.subjectFromAttestedRead)}`,
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1020
1094
|
}
|
|
1021
1095
|
if (intent.requiresHostCapabilities.length > 0) {
|
|
1022
1096
|
body.push(
|
|
@@ -1033,6 +1107,12 @@ function emitIntent(
|
|
|
1033
1107
|
`${pad}custom uniform string nomos:birthPrefix = ${quote(intent.birthPrefix ?? "")}`,
|
|
1034
1108
|
);
|
|
1035
1109
|
}
|
|
1110
|
+
if (intent.birthDelegations !== undefined) {
|
|
1111
|
+
body.push(
|
|
1112
|
+
`${pad}custom rel nomos:birthDelegations = <${requiredPath(intent.birthDelegations.id, paths)}>`,
|
|
1113
|
+
`${pad}custom uniform string nomos:birthDelegationPrefix = ${quote(intent.birthDelegationPrefix ?? "")}`,
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1036
1116
|
if (intent.birthPolicySeed !== undefined) {
|
|
1037
1117
|
body.push(
|
|
1038
1118
|
`${pad}custom rel nomos:birthPolicySeed = <${requiredPath(intent.birthPolicySeed.id, paths)}>`,
|
|
@@ -1166,6 +1246,7 @@ function emitRead(
|
|
|
1166
1246
|
read: LawReadNode,
|
|
1167
1247
|
contracts: readonly LawReadContractNode[],
|
|
1168
1248
|
predicates: readonly LawPredicateNode[],
|
|
1249
|
+
types: ReadonlyMap<string, LawAnonymousValueTypeNode>,
|
|
1169
1250
|
paths: ReadonlyMap<string, string>,
|
|
1170
1251
|
indent: number,
|
|
1171
1252
|
): string[] {
|
|
@@ -1181,13 +1262,25 @@ function emitRead(
|
|
|
1181
1262
|
`${pad}custom uniform bool nomos:public = ${read.public ?? false}`,
|
|
1182
1263
|
`${pad}custom rel nomos:of = <${requiredPath(read.of.id, paths)}>`,
|
|
1183
1264
|
`${pad}custom rel nomos:returns = <${requiredPath(returns, paths)}>`,
|
|
1265
|
+
`${pad}custom rel nomos:contract = <${requiredPath(contract.entity.id, paths)}>`,
|
|
1266
|
+
...(read.authentication?.kind === MemberAuthenticationKind.SelectedProvider
|
|
1267
|
+
? authenticationProviderOpinions(read.authentication.provider, pad)
|
|
1268
|
+
: []),
|
|
1184
1269
|
];
|
|
1270
|
+
if (contract.returns.kind === "scalar") {
|
|
1271
|
+
let type = types.get(returns);
|
|
1272
|
+
while (type?.expression.kind === "default") type = types.get(type.expression.value.id);
|
|
1273
|
+
if (type?.expression.kind === "nullable") body.push(`${pad}custom uniform bool nomos:nullable = true`);
|
|
1274
|
+
}
|
|
1185
1275
|
const fieldTarget = (field: { readonly field: { readonly id: string }; readonly path: readonly { readonly id: string }[] }): string => {
|
|
1186
1276
|
const terminal = field.path[field.path.length - 1] ?? field.field;
|
|
1187
1277
|
return `<${requiredPath(terminal.id, paths)}>`;
|
|
1188
1278
|
};
|
|
1189
1279
|
switch (read.readKind) {
|
|
1190
1280
|
case "query":
|
|
1281
|
+
// Interpretation is part of law identity. Never silently change historical captured
|
|
1282
|
+
// witnesses when the kernel gains rename-aware domain reads.
|
|
1283
|
+
body.push(`${pad}custom uniform token nomos:capturedReadSemantics = "current-labels-v1"`);
|
|
1191
1284
|
body.push(`${pad}custom rel nomos:key = ${relList(read.key.map(fieldTarget))}`);
|
|
1192
1285
|
body.push(`${pad}custom uniform string[] nomos:keyPath = ${stringList(read.key.map((field) => field.authoredPath))}`);
|
|
1193
1286
|
break;
|
|
@@ -1435,6 +1528,48 @@ function emitPayloadContract(
|
|
|
1435
1528
|
return body;
|
|
1436
1529
|
}
|
|
1437
1530
|
|
|
1531
|
+
/** A read's signature: its parameters and its result. The read names it with `nomos:contract`.
|
|
1532
|
+
* Parameter value types (a spatial read's bounds union, for example) are declared nowhere else,
|
|
1533
|
+
* so without this prim nothing in the emitted law would say the read depends on them. */
|
|
1534
|
+
function emitReadContract(
|
|
1535
|
+
contract: LawReadContractNode,
|
|
1536
|
+
paths: ReadonlyMap<string, string>,
|
|
1537
|
+
indent: number,
|
|
1538
|
+
): string[] {
|
|
1539
|
+
const pad = " ".repeat(indent);
|
|
1540
|
+
const returns = contract.returns.kind === "rows"
|
|
1541
|
+
? contract.returns.aggregate.id
|
|
1542
|
+
: contract.returns.value.id;
|
|
1543
|
+
const body = [
|
|
1544
|
+
...entityLabelOpinions(contract.entity, indent),
|
|
1545
|
+
`${pad}custom rel nomos:returns = <${requiredPath(returns, paths)}>`,
|
|
1546
|
+
];
|
|
1547
|
+
if (contract.parameters.length > 0) {
|
|
1548
|
+
body.push("", `${pad}def Scope "Parameters"`, `${pad}{`);
|
|
1549
|
+
for (const [index, parameter] of contract.parameters.entries()) {
|
|
1550
|
+
if (index > 0) body.push("");
|
|
1551
|
+
body.push(
|
|
1552
|
+
`${pad} def Scope "Parameter_${String(index).padStart(4, "0")}"`,
|
|
1553
|
+
`${pad} {`,
|
|
1554
|
+
`${pad} custom uniform string nomos:name = ${quote(parameter.name)}`,
|
|
1555
|
+
);
|
|
1556
|
+
if (parameter.field !== undefined) {
|
|
1557
|
+
const terminal = parameter.field.path[parameter.field.path.length - 1] ?? parameter.field.field;
|
|
1558
|
+
body.push(
|
|
1559
|
+
`${pad} custom rel nomos:field = <${requiredPath(terminal.id, paths)}>`,
|
|
1560
|
+
`${pad} custom uniform string nomos:fieldPath = ${quote(parameter.field.authoredPath)}`,
|
|
1561
|
+
);
|
|
1562
|
+
}
|
|
1563
|
+
if (parameter.value !== undefined) {
|
|
1564
|
+
body.push(`${pad} custom rel nomos:type = <${requiredPath(parameter.value.id, paths)}>`);
|
|
1565
|
+
}
|
|
1566
|
+
body.push(`${pad} }`);
|
|
1567
|
+
}
|
|
1568
|
+
body.push(`${pad}}`);
|
|
1569
|
+
}
|
|
1570
|
+
return body;
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1438
1573
|
function emitType(
|
|
1439
1574
|
type: LawTypeNode,
|
|
1440
1575
|
fields: readonly LawFieldNode[],
|
|
@@ -1619,6 +1754,7 @@ function emitAnonymousType(
|
|
|
1619
1754
|
body.push(
|
|
1620
1755
|
`${pad} def Scope "v_${variant.entity.sid}"`,
|
|
1621
1756
|
`${pad} {`,
|
|
1757
|
+
`${pad} custom uniform string nomos:label = ${quote(variant.label ?? variant.entity.label)}`,
|
|
1622
1758
|
`${pad} custom rel nomos:type = <${requiredPath(variant.value.id, paths)}>`,
|
|
1623
1759
|
`${pad} }`,
|
|
1624
1760
|
);
|
|
@@ -1652,6 +1788,11 @@ function emitAnonymousValueSemantic(
|
|
|
1652
1788
|
case "unit":
|
|
1653
1789
|
case "value-object":
|
|
1654
1790
|
body.push(`${pad}custom uniform string nomos:semanticName = ${quote(semantic.name)}`);
|
|
1791
|
+
if (semantic.kind === "value-object" && semantic.geometry !== undefined) {
|
|
1792
|
+
// Geometry remains an ordinary typed record in custody. Its explicit
|
|
1793
|
+
// RFC 7946 meaning permits the operation boundary to pack coordinates.
|
|
1794
|
+
body.push(`${pad}custom uniform token nomos:geometry = ${quote(semantic.geometry)}`);
|
|
1795
|
+
}
|
|
1655
1796
|
break;
|
|
1656
1797
|
case "recipient":
|
|
1657
1798
|
body.push(`${pad}custom uniform token nomos:subject = ${quote(semantic.subject)}`);
|
|
@@ -1687,6 +1828,11 @@ function emitAnonymousField(
|
|
|
1687
1828
|
`${pad}def Scope "f_${field.entity.sid}"`,
|
|
1688
1829
|
`${pad}{`,
|
|
1689
1830
|
`${pad} custom uniform string nomos:label = ${quote(field.name)}`,
|
|
1831
|
+
`${pad} custom uniform string nomos:wireKey = ${quote(field.entity.wireKey ?? field.entity.sid)}`,
|
|
1832
|
+
...(field.entity.wireAliases === undefined || field.entity.wireAliases.length === 0
|
|
1833
|
+
? []
|
|
1834
|
+
: [`${pad} custom uniform string[] nomos:wireAliases = ${stringList(field.entity.wireAliases)}`]),
|
|
1835
|
+
`${pad} custom uniform string nomos:schemaIdentity = ${quote(field.entity.sid)}`,
|
|
1690
1836
|
`${pad} custom uniform bool nomos:required = ${field.required}`,
|
|
1691
1837
|
`${pad} custom rel nomos:type = <${requiredPath(field.value.id, paths)}>`,
|
|
1692
1838
|
];
|
|
@@ -1847,9 +1993,9 @@ function emitField(
|
|
|
1847
1993
|
if (field.nullable) body.push(`${pad} custom uniform bool nomos:nullable = true`);
|
|
1848
1994
|
if (field.encrypted) body.push(`${pad} custom uniform bool nomos:encrypted = true`);
|
|
1849
1995
|
if (field.blindIndexed) body.push(`${pad} custom uniform bool nomos:blindIndexed = true`);
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
}
|
|
1996
|
+
// Shape and reference target are independent. Atomic workspace/type/id addresses and
|
|
1997
|
+
// versioned references retain their structural type just like every other value object.
|
|
1998
|
+
body.push(`${pad} custom rel nomos:type = <${requiredPath(field.value.id, paths)}>`);
|
|
1853
1999
|
if (field.refTarget !== undefined) {
|
|
1854
2000
|
body.push(`${pad} custom rel nomos:refTarget = ${targets([field.refTarget], paths, resolveDependency)}`);
|
|
1855
2001
|
body.push(`${pad} custom uniform token nomos:referenceMode = ${quote(field.referenceMode ?? "current")}`);
|
package/src/law_identity.ts
CHANGED
|
@@ -18,6 +18,7 @@ export const LAW_ENTITY_KINDS = [
|
|
|
18
18
|
"flow",
|
|
19
19
|
"workspace-type",
|
|
20
20
|
"contract",
|
|
21
|
+
"operation-field",
|
|
21
22
|
"type",
|
|
22
23
|
"object-type",
|
|
23
24
|
] as const;
|
|
@@ -25,6 +26,19 @@ export const LAW_ENTITY_KINDS = [
|
|
|
25
26
|
export type LawEntityKind = (typeof LAW_ENTITY_KINDS)[number];
|
|
26
27
|
export type LawIdentityStatus = "active" | "retired";
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Durable transport allocation for one named operation field.
|
|
31
|
+
*
|
|
32
|
+
* These are wire keys, not identities. `canonical` is used by newly generated
|
|
33
|
+
* clients; aliases remain decodable during an explicitly managed overlap window.
|
|
34
|
+
*/
|
|
35
|
+
export interface LawOperationFieldWire {
|
|
36
|
+
readonly protobuf: {
|
|
37
|
+
readonly canonical: string;
|
|
38
|
+
readonly aliases?: readonly string[];
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
export interface LawIdentityEntity {
|
|
29
43
|
readonly kind: LawEntityKind;
|
|
30
44
|
readonly sid: string;
|
|
@@ -34,6 +48,8 @@ export interface LawIdentityEntity {
|
|
|
34
48
|
readonly priorLabels?: readonly string[];
|
|
35
49
|
readonly generation: number;
|
|
36
50
|
readonly status: LawIdentityStatus;
|
|
51
|
+
/** Present only on an operation-field ledger row. The row's label + lineage carry meaning. */
|
|
52
|
+
readonly operationFieldWire?: LawOperationFieldWire;
|
|
37
53
|
}
|
|
38
54
|
|
|
39
55
|
export interface LawIdentityRegistry {
|
|
@@ -54,6 +70,8 @@ export interface ReconcileLawIdentityScopeInput {
|
|
|
54
70
|
readonly carries?: readonly LawIdentityCarry[];
|
|
55
71
|
/** Used only while importing an existing compiler-minted identity byte-for-byte. */
|
|
56
72
|
readonly preferredSids?: Readonly<Record<string, string>>;
|
|
73
|
+
/** First-appearance transport allocations for named operation fields. */
|
|
74
|
+
readonly preferredOperationFieldWire?: Readonly<Record<string, LawOperationFieldWire>>;
|
|
57
75
|
/**
|
|
58
76
|
* Defaults to true. Set false only when this compile sees a non-exhaustive slice of
|
|
59
77
|
* a shared scope (currently project-root domains and framework declarations).
|
|
@@ -95,6 +113,7 @@ const KIND_PREFIX: Readonly<Record<LawEntityKind, string>> = {
|
|
|
95
113
|
flow: "w",
|
|
96
114
|
"workspace-type": "x",
|
|
97
115
|
contract: "c",
|
|
116
|
+
"operation-field": "u",
|
|
98
117
|
type: "t",
|
|
99
118
|
"object-type": "o",
|
|
100
119
|
};
|
|
@@ -191,97 +210,105 @@ export function createLawIdentityReconciler(
|
|
|
191
210
|
const carriedTo = new Set<string>();
|
|
192
211
|
|
|
193
212
|
for (const carry of [...(input.carries ?? [])].sort((a, b) => compareText(a.to, b.to))) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
213
|
+
if (carry.from === carry.to) {
|
|
214
|
+
throw new Error(`NMS-ID-004 identity carry '${carry.from}' -> '${carry.to}' is not a rename`);
|
|
215
|
+
}
|
|
216
|
+
if (carriedFrom.has(carry.from) || carriedTo.has(carry.to)) {
|
|
217
|
+
throw new Error(`NMS-ID-004 duplicate identity carry involving '${carry.from}' or '${carry.to}'`);
|
|
218
|
+
}
|
|
219
|
+
const key = activeByLabel.get(carry.from);
|
|
220
|
+
if (key === undefined) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
`NMS-ID-004 cannot carry missing active ${input.kind} '${carry.from}' in ${scopeName(input.parent)}`,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
if (!requested.has(carry.to)) {
|
|
226
|
+
throw new Error(`NMS-ID-004 carry target '${carry.to}' is not a current ${input.kind} declaration`);
|
|
227
|
+
}
|
|
228
|
+
const occupied = activeByLabel.get(carry.to);
|
|
229
|
+
if (occupied !== undefined && occupied !== key) {
|
|
230
|
+
throw new Error(`NMS-ID-003 active ${input.kind} label '${carry.to}' already owns another SID`);
|
|
231
|
+
}
|
|
232
|
+
const entity = entities[key]!;
|
|
233
|
+
entities[key] = {
|
|
234
|
+
...entity,
|
|
235
|
+
label: carry.to,
|
|
236
|
+
priorLabels: appendUnique(entity.priorLabels, carry.from),
|
|
237
|
+
};
|
|
238
|
+
activeByLabel.delete(carry.from);
|
|
239
|
+
activeByLabel.set(carry.to, key);
|
|
240
|
+
carriedFrom.add(carry.from);
|
|
241
|
+
carriedTo.add(carry.to);
|
|
242
|
+
carried.push({ ...carry, key });
|
|
224
243
|
}
|
|
225
244
|
|
|
226
245
|
const resolved: Record<string, string> = {};
|
|
227
246
|
const allocated: { label: string; key: string; generation: number }[] = [];
|
|
228
247
|
for (const label of labels) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
248
|
+
const existing = activeByLabel.get(label);
|
|
249
|
+
if (existing !== undefined) {
|
|
250
|
+
const preferredWire = input.preferredOperationFieldWire?.[label];
|
|
251
|
+
if (preferredWire !== undefined && entities[existing]!.operationFieldWire === undefined) {
|
|
252
|
+
entities[existing] = { ...entities[existing]!, operationFieldWire: preferredWire };
|
|
253
|
+
}
|
|
254
|
+
resolved[label] = existing;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const historic = Object.values(entities).filter(
|
|
259
|
+
(entity) =>
|
|
260
|
+
entity.kind === input.kind &&
|
|
261
|
+
entity.parent === input.parent &&
|
|
262
|
+
(entity.label === label || entity.priorLabels?.includes(label) === true),
|
|
263
|
+
);
|
|
264
|
+
const generation = historic.reduce((max, entity) => Math.max(max, entity.generation), -1) + 1;
|
|
265
|
+
const preferredSid = generation === 0 ? input.preferredSids?.[label] : undefined;
|
|
266
|
+
// A compatibility proposal may repeat a deterministic legacy SID whose former
|
|
267
|
+
// owner is now a tombstone (most visibly a field beneath a recreated aggregate).
|
|
268
|
+
// That is evidence to allocate afresh, never authority to reuse the old identity.
|
|
269
|
+
const preferredKey = preferredSid === undefined
|
|
270
|
+
? undefined
|
|
271
|
+
: lawEntityKey(input.kind, preferredSid);
|
|
272
|
+
const preferredAvailable =
|
|
273
|
+
preferredSid !== undefined && preferredKey !== undefined && entities[preferredKey] === undefined;
|
|
274
|
+
const sid = preferredAvailable
|
|
275
|
+
? preferredSid
|
|
276
|
+
: mintStableId(
|
|
277
|
+
`law-entity:${input.kind}:${input.parent ?? "@root"}:${label}:generation:${generation}`,
|
|
278
|
+
);
|
|
279
|
+
const key = lawEntityKey(input.kind, sid);
|
|
280
|
+
if (entities[key] !== undefined) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`NMS-ID-002 SID collision: ${key} is already ${describeEntity(entities[key]!)}`,
|
|
254
283
|
);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
resolved[label] = key;
|
|
271
|
-
allocated.push({ label, key, generation });
|
|
284
|
+
}
|
|
285
|
+
entities[key] = {
|
|
286
|
+
kind: input.kind,
|
|
287
|
+
sid,
|
|
288
|
+
...(input.parent === undefined ? {} : { parent: input.parent }),
|
|
289
|
+
label,
|
|
290
|
+
generation,
|
|
291
|
+
status: "active",
|
|
292
|
+
...(input.preferredOperationFieldWire?.[label] === undefined
|
|
293
|
+
? {}
|
|
294
|
+
: { operationFieldWire: input.preferredOperationFieldWire[label] }),
|
|
295
|
+
};
|
|
296
|
+
activeByLabel.set(label, key);
|
|
297
|
+
resolved[label] = key;
|
|
298
|
+
allocated.push({ label, key, generation });
|
|
272
299
|
}
|
|
273
300
|
|
|
274
301
|
const retired: string[] = [];
|
|
275
302
|
if (input.retireAbsent !== false) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
303
|
+
for (const [key, entity] of scopeEntries) {
|
|
304
|
+
if (carriedFrom.has(entity.label)) continue;
|
|
305
|
+
if (requested.has(entity.label)) continue;
|
|
306
|
+
if (entities[key]?.status === "active") {
|
|
307
|
+
entities[key] = { ...entities[key]!, status: "retired" };
|
|
308
|
+
retired.push(key);
|
|
309
|
+
retireDescendants(entities, key, retired);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
285
312
|
}
|
|
286
313
|
|
|
287
314
|
return {
|
|
@@ -320,6 +347,17 @@ export function validateLawIdentityRegistry(registry: LawIdentityRegistry): void
|
|
|
320
347
|
if (entity.status !== "active" && entity.status !== "retired") {
|
|
321
348
|
throw new Error(`NMS-ID-001 ${key} has invalid status`);
|
|
322
349
|
}
|
|
350
|
+
if (entity.operationFieldWire !== undefined) {
|
|
351
|
+
if (entity.kind !== "operation-field") {
|
|
352
|
+
throw new Error(`NMS-ID-001 ${key} carries operation-field wire custody but is not an operation field`);
|
|
353
|
+
}
|
|
354
|
+
const keys = [
|
|
355
|
+
entity.operationFieldWire.protobuf.canonical,
|
|
356
|
+
...(entity.operationFieldWire.protobuf.aliases ?? []),
|
|
357
|
+
];
|
|
358
|
+
assertUniqueNonEmpty(keys, `${key} protobuf wire keys`);
|
|
359
|
+
for (const wireKey of keys) assertSid(wireKey, `${key} protobuf wire key`);
|
|
360
|
+
}
|
|
323
361
|
if (entity.priorLabels !== undefined) {
|
|
324
362
|
assertUniqueNonEmpty([...entity.priorLabels], `${key} prior labels`);
|
|
325
363
|
if (entity.priorLabels.includes(entity.label)) {
|