@githolon/dsl 0.108.6 → 0.110.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +2083 -1248
- 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/shape_compat.ts
DELETED
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
2
|
-
// remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
3
|
-
// wasm32-wasip1 artifact. If a file isn't this / hosting this / authoring for this
|
|
4
|
-
// / proving this — it's gone.
|
|
5
|
-
//
|
|
6
|
-
// SHAPE COMPATIBILITY (#72) — the structural contract a client and a workspace
|
|
7
|
-
// negotiate by, INSTEAD of the package hash. See architecture/shape_compatibility.md.
|
|
8
|
-
//
|
|
9
|
-
// A client fits a workspace iff the workspace's installed interface SUBTYPES what the
|
|
10
|
-
// client depends on:
|
|
11
|
-
// • WRITES are CONTRAVARIANT — for every directive the client calls, the workspace
|
|
12
|
-
// has that directive id and its CURRENT payload schema ACCEPTS the client's
|
|
13
|
-
// payload: every field the workspace REQUIRES the client always sends, and every
|
|
14
|
-
// shared field's kind matches. (Extra client fields are ignored — non-strict zod.)
|
|
15
|
-
// • READS are COVARIANT by STABLE ID (#58) — for every aggregate the client reads,
|
|
16
|
-
// the workspace has that aggregate SID and every field the client CONSUMES (by
|
|
17
|
-
// field sid) is present with a compatible kind. The workspace may serve MORE.
|
|
18
|
-
//
|
|
19
|
-
// Identity is by stable id, not name or hash — that is what makes the relation
|
|
20
|
-
// decidable across renames (a renamed aggregate field keeps its sid, so an old client
|
|
21
|
-
// stays read-compatible). Directive/payload identity is the dispatched id + field
|
|
22
|
-
// names (directives are not sid-tracked yet — a payload rename IS a write break, and
|
|
23
|
-
// is reported precisely).
|
|
24
|
-
|
|
25
|
-
import { z } from "zod";
|
|
26
|
-
import type { DomainModule } from "./codegen_dart.js";
|
|
27
|
-
import { lowerLawValueType, type LawValueType } from "./law_value_type.js";
|
|
28
|
-
import type { StableIds } from "./stable_ids_types.js";
|
|
29
|
-
import type { Field } from "./fields.js";
|
|
30
|
-
import { isBusinessIntent } from "./intent.js";
|
|
31
|
-
|
|
32
|
-
/** One payload field's normalized shape: its kind + whether the schema makes it optional. */
|
|
33
|
-
export interface PayloadFieldShape {
|
|
34
|
-
readonly kind: string;
|
|
35
|
-
readonly optional: boolean;
|
|
36
|
-
}
|
|
37
|
-
/** A directive's payload contract — the field set + types the gate validates against. */
|
|
38
|
-
export interface DirectivePayloadShape {
|
|
39
|
-
readonly fields: Record<string, PayloadFieldShape>;
|
|
40
|
-
}
|
|
41
|
-
/** An aggregate's read contract — fields keyed by STABLE ID (rename-safe), each carrying
|
|
42
|
-
* its current label (for human-readable verdicts) + its read kind. */
|
|
43
|
-
export interface AggregateReadShape {
|
|
44
|
-
readonly sid: string;
|
|
45
|
-
readonly label: string;
|
|
46
|
-
/** keyed by FIELD SID. */
|
|
47
|
-
readonly fields: Record<string, { kind: string; label: string }>;
|
|
48
|
-
}
|
|
49
|
-
/** A domain's full structural interface — the offer (a workspace's installed law) AND
|
|
50
|
-
* the requirement (the law a client was generated from) are the SAME vocabulary. */
|
|
51
|
-
export interface DomainInterface {
|
|
52
|
-
readonly v: 1;
|
|
53
|
-
readonly domain: string;
|
|
54
|
-
readonly domainSid?: string;
|
|
55
|
-
/** keyed by DIRECTIVE ID (the dispatched name). */
|
|
56
|
-
readonly directives: Record<string, DirectivePayloadShape>;
|
|
57
|
-
/** keyed by AGGREGATE SID. */
|
|
58
|
-
readonly aggregates: Record<string, AggregateReadShape>;
|
|
59
|
-
/** ATTESTED READS (slice B + dynamic policies): directive id → its declared foreign-read edges —
|
|
60
|
-
* a STATIC `{queryId, from}` edge or a dynamic `{queryId, policy, fromPayload}` edge — the
|
|
61
|
-
* cross-workspace dependencies this law consumes on its write path. OMITTED when none (era rule). */
|
|
62
|
-
readonly foreignReads?: Record<
|
|
63
|
-
string,
|
|
64
|
-
{ queryId: string; from?: string; policy?: string; fromPayload?: string }[]
|
|
65
|
-
>;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Remove framework-managed aggregate fields from the client-facing structural interface. Stable ids for
|
|
69
|
-
* those fields remain in the law/lockfile; clients negotiate only the business shape they can see. */
|
|
70
|
-
export function publicClientInterface(
|
|
71
|
-
modules: readonly DomainModule[],
|
|
72
|
-
offered: Readonly<Record<string, DomainInterface>>,
|
|
73
|
-
): Record<string, DomainInterface> {
|
|
74
|
-
const hidden = new Map<string, Map<string, Set<string>>>();
|
|
75
|
-
for (const mod of modules) {
|
|
76
|
-
const domain = mod.domain ?? mod.name;
|
|
77
|
-
const byAggregate = hidden.get(domain) ?? new Map<string, Set<string>>();
|
|
78
|
-
hidden.set(domain, byAggregate);
|
|
79
|
-
for (const aggregate of mod.aggregates ?? []) {
|
|
80
|
-
const fields = (aggregate as { internalFields?: readonly string[] }).internalFields ?? [];
|
|
81
|
-
if (fields.length > 0) byAggregate.set(aggregate.id, new Set(fields));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
const result: Record<string, DomainInterface> = {};
|
|
85
|
-
for (const [domain, value] of Object.entries(offered)) {
|
|
86
|
-
const byAggregate = hidden.get(domain);
|
|
87
|
-
if (byAggregate === undefined || byAggregate.size === 0) {
|
|
88
|
-
result[domain] = value;
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
const aggregates: Record<string, AggregateReadShape> = {};
|
|
92
|
-
for (const [sid, aggregate] of Object.entries(value.aggregates)) {
|
|
93
|
-
const fields = byAggregate.get(aggregate.label);
|
|
94
|
-
aggregates[sid] = fields === undefined
|
|
95
|
-
? aggregate
|
|
96
|
-
: {
|
|
97
|
-
...aggregate,
|
|
98
|
-
fields: Object.fromEntries(
|
|
99
|
-
Object.entries(aggregate.fields).filter(([, field]) => !fields.has(field.label)),
|
|
100
|
-
),
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
result[domain] = { ...value, aggregates };
|
|
104
|
-
}
|
|
105
|
-
return result;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** The verdict: compatible iff nothing is missing and nothing is type-incompatible.
|
|
109
|
-
* `missing` = a depended-on directive/aggregate/field the workspace doesn't expose;
|
|
110
|
-
* `incompatible` = present but type-divergent (a payload field kind, a retyped read field). */
|
|
111
|
-
export interface CompatVerdict {
|
|
112
|
-
readonly ok: boolean;
|
|
113
|
-
readonly missing: string[];
|
|
114
|
-
readonly incompatible: string[];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Normalize the canonical language-neutral DSL value graph to the compatibility
|
|
118
|
-
* vocabulary. Language generators are projections of this graph, never authorities
|
|
119
|
-
* for it. */
|
|
120
|
-
function payloadFieldKind(value: LawValueType): string {
|
|
121
|
-
switch (value.kind) {
|
|
122
|
-
case "enum":
|
|
123
|
-
return "enum";
|
|
124
|
-
case "string":
|
|
125
|
-
return "string";
|
|
126
|
-
case "integer":
|
|
127
|
-
return "int";
|
|
128
|
-
case "number":
|
|
129
|
-
return "double";
|
|
130
|
-
case "boolean":
|
|
131
|
-
return "bool";
|
|
132
|
-
case "literal":
|
|
133
|
-
return typeof value.value === "boolean"
|
|
134
|
-
? "bool"
|
|
135
|
-
: typeof value.value === "number"
|
|
136
|
-
? Number.isInteger(value.value) ? "int" : "double"
|
|
137
|
-
: typeof value.value === "string" ? "string" : "json";
|
|
138
|
-
case "list":
|
|
139
|
-
return value.element.kind === "string" ? "set" : "json";
|
|
140
|
-
case "nullable":
|
|
141
|
-
case "default":
|
|
142
|
-
case "recursive":
|
|
143
|
-
return payloadFieldKind(value.value);
|
|
144
|
-
case "map":
|
|
145
|
-
case "record":
|
|
146
|
-
case "sum":
|
|
147
|
-
case "null":
|
|
148
|
-
case "unknown":
|
|
149
|
-
case "recursive-ref":
|
|
150
|
-
return "json";
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/** The aggregate read kind when no stable-id kind is recorded (pre-#58 fallback): the
|
|
155
|
-
* field's own declared kind, with the read-collapsed CRDTs normalized to their scalar. */
|
|
156
|
-
function aggFieldReadKind(f: Field): string {
|
|
157
|
-
switch (f.kind) {
|
|
158
|
-
case "counter":
|
|
159
|
-
return "int";
|
|
160
|
-
case "position":
|
|
161
|
-
return "string";
|
|
162
|
-
default:
|
|
163
|
-
return f.kind;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/** Extract a domain's structural interface from its loaded module + (optionally) its
|
|
168
|
-
* stable-id surface. Without stable ids (pre-#58) aggregate fields key by NAME and the
|
|
169
|
-
* kind comes from the field declaration — a graceful, rename-unaware fallback. */
|
|
170
|
-
export function domainInterface(mod: DomainModule, stableIds?: StableIds): DomainInterface {
|
|
171
|
-
const isInternal = (value: unknown): boolean =>
|
|
172
|
-
!!value &&
|
|
173
|
-
typeof value === "object" &&
|
|
174
|
-
(value as { businessBirthInternal?: unknown }).businessBirthInternal === true;
|
|
175
|
-
const enumTypes = new Map<string, string>();
|
|
176
|
-
// DETERMINISTIC KEY ORDER — directive ids, aggregate sids, and field keys are SORTED, so the
|
|
177
|
-
// emitted interface is byte-stable and the layered-USD fold (which merges + sorts) reproduces it
|
|
178
|
-
// byte-identically (the `nomosStableIds`/`nomosReadGate` convention). architecture/shape_compatibility.md.
|
|
179
|
-
const sortedRec = <T>(entries: Array<[string, T]>): Record<string, T> => {
|
|
180
|
-
const out: Record<string, T> = {};
|
|
181
|
-
for (const [k, v] of entries.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))) out[k] = v;
|
|
182
|
-
return out;
|
|
183
|
-
};
|
|
184
|
-
const directives: Record<string, DirectivePayloadShape> = {};
|
|
185
|
-
const dirEntries: Array<[string, DirectivePayloadShape]> = [];
|
|
186
|
-
for (const d of (mod.directives ?? []) as Array<{
|
|
187
|
-
id?: unknown;
|
|
188
|
-
payloadSchema?: unknown;
|
|
189
|
-
businessBirth?: { publicPayloadSchema?: unknown };
|
|
190
|
-
}>) {
|
|
191
|
-
if (!d || typeof d.id !== "string") continue;
|
|
192
|
-
if (isInternal(d)) continue;
|
|
193
|
-
const fieldEntries: Array<[string, PayloadFieldShape]> = [];
|
|
194
|
-
const schema = d.businessBirth?.publicPayloadSchema ?? d.payloadSchema;
|
|
195
|
-
if (schema && typeof schema === "object") {
|
|
196
|
-
const payload = lowerLawValueType(schema as z.ZodTypeAny);
|
|
197
|
-
if (payload.kind !== "record") {
|
|
198
|
-
throw new Error(`directive '${d.id}' payload must lower to a typed record`);
|
|
199
|
-
}
|
|
200
|
-
for (const field of payload.fields) {
|
|
201
|
-
fieldEntries.push([field.name, { kind: payloadFieldKind(field.value), optional: !field.required }]);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
dirEntries.push([
|
|
205
|
-
d.businessBirth === undefined || isBusinessIntent(d) ? d.id : "birth",
|
|
206
|
-
{ fields: sortedRec(fieldEntries) },
|
|
207
|
-
]);
|
|
208
|
-
}
|
|
209
|
-
Object.assign(directives, sortedRec(dirEntries));
|
|
210
|
-
const aggregates: Record<string, AggregateReadShape> = {};
|
|
211
|
-
const aggEntries: Array<[string, AggregateReadShape]> = [];
|
|
212
|
-
for (const agg of (mod.aggregates ?? []) as Array<{
|
|
213
|
-
id: string;
|
|
214
|
-
fields: Record<string, Field>;
|
|
215
|
-
}>) {
|
|
216
|
-
if (isInternal(agg)) continue;
|
|
217
|
-
const label = agg.id;
|
|
218
|
-
const sa = stableIds?.aggregates?.[label];
|
|
219
|
-
const aggSid = sa?.sid ?? label;
|
|
220
|
-
const fieldEntries: Array<[string, { kind: string; label: string }]> = [];
|
|
221
|
-
for (const [fname, f] of Object.entries(agg.fields ?? {})) {
|
|
222
|
-
// This is the workspace's complete structural offer and the input to law-evolution
|
|
223
|
-
// checking, so framework-managed stored fields belong here too. Only the generated
|
|
224
|
-
// client's view hides them, in publicClientInterface below. Filtering them at both
|
|
225
|
-
// seams makes an unchanged private field look deleted when the current offer is
|
|
226
|
-
// compared with the committed identity ledger.
|
|
227
|
-
if (!f || f.kind === "hasMany") continue;
|
|
228
|
-
const fsid = sa?.fields?.[fname]?.sid ?? fname;
|
|
229
|
-
const kind = sa?.fields?.[fname]?.kind ?? aggFieldReadKind(f);
|
|
230
|
-
fieldEntries.push([fsid, { kind, label: fname }]);
|
|
231
|
-
}
|
|
232
|
-
aggEntries.push([aggSid, { sid: aggSid, label, fields: sortedRec(fieldEntries) }]);
|
|
233
|
-
}
|
|
234
|
-
Object.assign(aggregates, sortedRec(aggEntries));
|
|
235
|
-
// ATTESTED READS (slice B): the declared trust edges — so shape-compat + client codegen can
|
|
236
|
-
// SEE the cross-workspace dependency (typed clients don't call it; it's write-path-internal).
|
|
237
|
-
type ForeignEdge = { queryId: string; from?: string; policy?: string; fromPayload?: string };
|
|
238
|
-
const foreignReadEntries: Array<[string, ForeignEdge[]]> = [];
|
|
239
|
-
for (const d of (mod.directives ?? []) as Array<{ id?: unknown; declaredForeignReads?: ForeignEdge[] }>) {
|
|
240
|
-
if (!d || typeof d.id !== "string") continue;
|
|
241
|
-
if (isInternal(d)) continue;
|
|
242
|
-
if (d.declaredForeignReads !== undefined && d.declaredForeignReads.length > 0) {
|
|
243
|
-
foreignReadEntries.push([d.id, d.declaredForeignReads.map((e) => ({ ...e }))]);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
const foreignReads = sortedRec(foreignReadEntries);
|
|
247
|
-
return {
|
|
248
|
-
v: 1,
|
|
249
|
-
domain: (mod as { domain?: string; name?: string }).domain ?? (mod as { name?: string }).name ?? "",
|
|
250
|
-
...(stableIds?.domain !== undefined ? { domainSid: stableIds.domain } : {}),
|
|
251
|
-
directives,
|
|
252
|
-
aggregates,
|
|
253
|
-
...(foreignReadEntries.length > 0 ? { foreignReads } : {}),
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/** One member's structural verdict — `ok`, plus the exact break `reason` when not. */
|
|
258
|
-
export interface MemberVerdict {
|
|
259
|
-
readonly ok: boolean;
|
|
260
|
-
readonly reason?: string;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/** PER-MEMBER structural verdict (#72b, the compat superpower): the SAME subtype relation as
|
|
264
|
-
* {@link compatible}, decomposed to ONE verdict per callable MEMBER — keyed by directive id
|
|
265
|
-
* (writes) AND by aggregate label (reads). A generated client method (or the CLI gate) consults
|
|
266
|
-
* its own member so a KNOWN-incompatible call refuses CLIENT-SIDE, never as a server 422. */
|
|
267
|
-
export function memberVerdicts(client: DomainInterface, workspace: DomainInterface): Record<string, MemberVerdict> {
|
|
268
|
-
const out: Record<string, MemberVerdict> = {};
|
|
269
|
-
|
|
270
|
-
// WRITES — contravariant, one verdict per directive the client calls.
|
|
271
|
-
for (const [did, cShape] of Object.entries(client.directives)) {
|
|
272
|
-
const wShape = workspace.directives[did];
|
|
273
|
-
if (!wShape) { out[did] = { ok: false, reason: `directive '${did}' is not installed on the workspace` }; continue; }
|
|
274
|
-
const reasons: string[] = [];
|
|
275
|
-
for (const [f, wf] of Object.entries(wShape.fields)) {
|
|
276
|
-
if (wf.optional) continue;
|
|
277
|
-
const cf = cShape.fields[f];
|
|
278
|
-
if (!cf || cf.optional) reasons.push(`workspace requires field '${f}' the client does not always send`);
|
|
279
|
-
}
|
|
280
|
-
for (const [f, cf] of Object.entries(cShape.fields)) {
|
|
281
|
-
const wf = wShape.fields[f];
|
|
282
|
-
if (wf && wf.kind !== cf.kind) reasons.push(`field '${f}' kind ${cf.kind} ≠ workspace ${wf.kind}`);
|
|
283
|
-
}
|
|
284
|
-
out[did] = reasons.length ? { ok: false, reason: reasons.join("; ") } : { ok: true };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// READS — covariant by stable id, one verdict per aggregate the client reads (keyed by LABEL).
|
|
288
|
-
for (const [sid, cAgg] of Object.entries(client.aggregates)) {
|
|
289
|
-
const wAgg = workspace.aggregates[sid];
|
|
290
|
-
if (!wAgg) { out[cAgg.label] = { ok: false, reason: `aggregate '${cAgg.label}' is not served by the workspace` }; continue; }
|
|
291
|
-
const reasons: string[] = [];
|
|
292
|
-
for (const [fsid, cf] of Object.entries(cAgg.fields)) {
|
|
293
|
-
const wf = wAgg.fields[fsid];
|
|
294
|
-
if (!wf) reasons.push(`field '${cAgg.label}.${cf.label}' is not served`);
|
|
295
|
-
else if (wf.kind !== cf.kind) reasons.push(`field '${cAgg.label}.${cf.label}' read kind ${cf.kind} ≠ workspace ${wf.kind}`);
|
|
296
|
-
}
|
|
297
|
-
out[cAgg.label] = reasons.length ? { ok: false, reason: reasons.join("; ") } : { ok: true };
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return out;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/** Decide whether a CLIENT interface is satisfied by a WORKSPACE interface (the offer).
|
|
304
|
-
* Pure + deterministic — the SAME relation runs at connect() and (mirrored) at the
|
|
305
|
-
* editor/CI. Names the exact directive / aggregate / field at fault, never a hash. */
|
|
306
|
-
export function compatible(client: DomainInterface, workspace: DomainInterface): CompatVerdict {
|
|
307
|
-
const missing: string[] = [];
|
|
308
|
-
const incompatible: string[] = [];
|
|
309
|
-
|
|
310
|
-
// WRITES — contravariant. The workspace must accept every payload the client sends.
|
|
311
|
-
for (const [did, cShape] of Object.entries(client.directives)) {
|
|
312
|
-
const wShape = workspace.directives[did];
|
|
313
|
-
if (!wShape) {
|
|
314
|
-
missing.push(`directive '${did}'`);
|
|
315
|
-
continue;
|
|
316
|
-
}
|
|
317
|
-
// Every field the WORKSPACE requires, the client must ALWAYS send (present + required).
|
|
318
|
-
for (const [f, wf] of Object.entries(wShape.fields)) {
|
|
319
|
-
if (wf.optional) continue;
|
|
320
|
-
const cf = cShape.fields[f];
|
|
321
|
-
if (!cf || cf.optional) {
|
|
322
|
-
incompatible.push(`directive '${did}': workspace requires field '${f}' the client does not always send`);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
// Every field both sides know must agree on kind (a payload retype is a write break).
|
|
326
|
-
for (const [f, cf] of Object.entries(cShape.fields)) {
|
|
327
|
-
const wf = wShape.fields[f];
|
|
328
|
-
if (wf && wf.kind !== cf.kind) {
|
|
329
|
-
incompatible.push(`directive '${did}': field '${f}' kind ${cf.kind} ≠ workspace ${wf.kind}`);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// READS — covariant by stable id. Every field the client consumes must be served compatibly.
|
|
335
|
-
for (const [sid, cAgg] of Object.entries(client.aggregates)) {
|
|
336
|
-
const wAgg = workspace.aggregates[sid];
|
|
337
|
-
if (!wAgg) {
|
|
338
|
-
missing.push(`aggregate '${cAgg.label}'`);
|
|
339
|
-
continue;
|
|
340
|
-
}
|
|
341
|
-
for (const [fsid, cf] of Object.entries(cAgg.fields)) {
|
|
342
|
-
const wf = wAgg.fields[fsid];
|
|
343
|
-
if (!wf) {
|
|
344
|
-
missing.push(`field '${cAgg.label}.${cf.label}'`);
|
|
345
|
-
} else if (wf.kind !== cf.kind) {
|
|
346
|
-
incompatible.push(`field '${cAgg.label}.${cf.label}': read kind ${cf.kind} ≠ workspace ${wf.kind}`);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
return { ok: missing.length === 0 && incompatible.length === 0, missing, incompatible };
|
|
352
|
-
}
|