@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
|
@@ -5,21 +5,48 @@ import type { DomainModule } from "./codegen_dart.js";
|
|
|
5
5
|
import { dartMemberName, introspectPayload } from "./codegen_dart.js";
|
|
6
6
|
import type { PayloadFieldSpec } from "./codegen_dart.js";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type
|
|
11
|
-
} from "./
|
|
8
|
+
DART_CALL_PROTO_PRELUDE,
|
|
9
|
+
emitDartCallProtoEncoder,
|
|
10
|
+
type DartCallProtoFieldAccess,
|
|
11
|
+
} from "./codegen_call_proto.js";
|
|
12
12
|
import type { LawGraph } from "./law_graph.js";
|
|
13
13
|
import { isBusinessIntent } from "./intent.js";
|
|
14
|
+
import { MemberAuthenticationKind } from "./member_authentication.js";
|
|
14
15
|
import { fixedFrameworkCallDefinitions } from "./framework_call_definitions.js";
|
|
15
16
|
import { collectFixedFrameworkDartEnums } from "./framework_call_dart_enums.js";
|
|
16
17
|
import { APPLICATION_HOME_DOMAIN } from "./framework/application_home_domain.js";
|
|
18
|
+
import { RECOVER_RECEIVING_GROUP_DEVICE_ID as FRAMEWORK_RECOVERY_DOOR_ID } from "./framework/receiving_group_recovery.js";
|
|
19
|
+
import { REPAIR_CHILD_AUTHENTICATION_ID as FRAMEWORK_CHILD_REPAIR_ID } from "./framework/child_authentication.js";
|
|
20
|
+
import {
|
|
21
|
+
PARENT_MODEL_AUTHORITY_SEAT_AGGREGATE,
|
|
22
|
+
PARENT_MODEL_AUTHORITY_SEAT_ID,
|
|
23
|
+
SEAT_MODEL_AUTHORITY_ID as FRAMEWORK_MODEL_AUTHORITY_SEAT_ID,
|
|
24
|
+
} from "./framework/model_authority_repair.js";
|
|
17
25
|
import { workspaceSharingInvitationRedeemPayload } from "./workspace_sharing.js";
|
|
18
26
|
import { zodArrayElement, zodDef, zodObjectShape } from "./zod_introspection.js";
|
|
19
27
|
|
|
20
28
|
type AnyDirective = Directive<unknown>;
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
/** Resolve the authored effect behind a public business intent. Application
|
|
31
|
+
* languages intentionally expose only nominal intents in `module.directives`,
|
|
32
|
+
* while fixed framework-call encoders must derive their payload from the exact
|
|
33
|
+
* private effect composed by that intent. */
|
|
34
|
+
const authoredDirective = (
|
|
35
|
+
module: DomainModule,
|
|
36
|
+
directiveId: string,
|
|
37
|
+
): AnyDirective | undefined =>
|
|
38
|
+
(module.directives as AnyDirective[]).find(
|
|
39
|
+
(candidate) => candidate.id === directiveId,
|
|
40
|
+
) ??
|
|
41
|
+
(module.applicationIntents ?? [])
|
|
42
|
+
.flatMap((candidate) =>
|
|
43
|
+
isBusinessIntent(candidate)
|
|
44
|
+
? candidate.steps.map((step) => step.directive as AnyDirective)
|
|
45
|
+
: [],
|
|
46
|
+
)
|
|
47
|
+
.find((candidate) => candidate.id === directiveId);
|
|
48
|
+
|
|
49
|
+
const frameworkFieldAccess = (field: PayloadFieldSpec): DartCallProtoFieldAccess => {
|
|
23
50
|
const member = `payload.${dartMemberName(field.name)}`;
|
|
24
51
|
if (field.nullAdmits === true) return { value: member, slot: true };
|
|
25
52
|
const value = field.optional ? `${member}!` : member;
|
|
@@ -45,6 +72,12 @@ const frameworkFieldAccess = (field: PayloadFieldSpec): DartCallUsdaFieldAccess
|
|
|
45
72
|
}
|
|
46
73
|
};
|
|
47
74
|
|
|
75
|
+
/** The exact Dart type `introspectPayload` derives for `inheritedModelAuthorityEvidence.holders`. The
|
|
76
|
+
* hand-written `NmsModelAuthorityHolder` typedef in `application_framework_calls.dart` is structurally
|
|
77
|
+
* this type; asserting it here means a schema change breaks the COMPILER, never the app. */
|
|
78
|
+
const MODEL_AUTHORITY_HOLDERS_DART_TYPE =
|
|
79
|
+
"List<({String principal, List<({String deviceKeySubject, String grantedAt, String? verifiedVia, int? validFromEpoch})> signers})>";
|
|
80
|
+
|
|
48
81
|
const FIXED_CALLS = fixedFrameworkCallDefinitions
|
|
49
82
|
.filter((definition) => definition.dartBirth === true)
|
|
50
83
|
.map((definition) => ({ kind: definition.kind, directive: definition.directive.id }));
|
|
@@ -100,20 +133,62 @@ export interface DartFrameworkCallLaw {
|
|
|
100
133
|
readonly paths: ReadonlyMap<string, string>;
|
|
101
134
|
}
|
|
102
135
|
|
|
136
|
+
/** Exact fixed framework effects for which this composed law emits Dart calls.
|
|
137
|
+
* The operation-schema compiler consumes this selector instead of maintaining
|
|
138
|
+
* a second list of framework payloads. */
|
|
139
|
+
export function dartFrameworkOperationDirectiveIds(
|
|
140
|
+
law: DartFrameworkCallLaw,
|
|
141
|
+
): readonly string[] {
|
|
142
|
+
const fixed = FIXED_CALLS.filter((definition) =>
|
|
143
|
+
law.graph.nodes.some((node) =>
|
|
144
|
+
node.kind === "intent" &&
|
|
145
|
+
(node.entity.label === definition.directive ||
|
|
146
|
+
node.publicRoute === definition.directive),
|
|
147
|
+
),
|
|
148
|
+
).map((definition) => definition.directive);
|
|
149
|
+
// The declared receiving-group recovery door is bound exactly like a fixed framework call (below),
|
|
150
|
+
// so its payload needs the same host transport contract: without this entry the generated encoder
|
|
151
|
+
// names a `Payload_…` message the operation proto never carries.
|
|
152
|
+
const declaresFrameworkDoor = law.graph.nodes.some((node) =>
|
|
153
|
+
node.kind === "intent" && node.entity.label === FRAMEWORK_RECOVERY_DOOR_ID);
|
|
154
|
+
// The framework child-authentication repair (composed whenever the package births children) is bound
|
|
155
|
+
// the same way, so its `{workspace, user, deviceKeySubject?}` payload rides the operation transport.
|
|
156
|
+
const declaresChildRepair = law.graph.nodes.some((node) =>
|
|
157
|
+
node.kind === "intent" && node.entity.label === FRAMEWORK_CHILD_REPAIR_ID);
|
|
158
|
+
// The model-authority self-seat (composed on the same era rule) is bound the same way, so its
|
|
159
|
+
// holder-set payload rides the operation transport.
|
|
160
|
+
const declaresModelAuthorityPull = law.graph.nodes.some((node) =>
|
|
161
|
+
node.kind === "intent" && node.entity.label === FRAMEWORK_MODEL_AUTHORITY_SEAT_ID);
|
|
162
|
+
return [
|
|
163
|
+
...fixed,
|
|
164
|
+
...(declaresFrameworkDoor ? [FRAMEWORK_RECOVERY_DOOR_ID] : []),
|
|
165
|
+
...(declaresChildRepair ? [FRAMEWORK_CHILD_REPAIR_ID] : []),
|
|
166
|
+
...(declaresModelAuthorityPull ? [FRAMEWORK_MODEL_AUTHORITY_SEAT_ID] : []),
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
|
|
103
170
|
/** Emit the pre-bind framework call factory from the exact composed law graph.
|
|
104
171
|
* The output contains no schemas or dynamic values: every field access and USDA
|
|
105
172
|
* relationship is expanded by the compiler. */
|
|
106
173
|
export function generateDartApplicationFrameworkCalls(
|
|
107
174
|
laws: readonly DartFrameworkCallLaw[],
|
|
175
|
+
descriptor: {
|
|
176
|
+
/** The compiled law package identity — the descriptor's own closure, `currentLaw[<application-home domain>]`. */
|
|
177
|
+
readonly lawSha256: string;
|
|
178
|
+
},
|
|
108
179
|
): string | undefined {
|
|
180
|
+
if (!/^[0-9a-f]{64}$/.test(descriptor.lawSha256)) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Dart framework call codegen: the application birth contract needs the compiled law package sha256 identity, not '${descriptor.lawSha256}'`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
109
185
|
const frameworkEnumDartTypes = collectFixedFrameworkDartEnums().dartTypes;
|
|
110
186
|
const fixedEmitted = FIXED_CALLS.flatMap((definition) => laws.flatMap((law) => {
|
|
111
187
|
const declares = law.graph.nodes.some((node) =>
|
|
112
188
|
node.kind === "intent" &&
|
|
113
189
|
(node.entity.label === definition.directive || node.publicRoute === definition.directive));
|
|
114
190
|
if (!declares) return [];
|
|
115
|
-
const directive = (law.module
|
|
116
|
-
candidate.id === definition.directive);
|
|
191
|
+
const directive = authoredDirective(law.module, definition.directive);
|
|
117
192
|
if (directive === undefined) {
|
|
118
193
|
throw new Error(
|
|
119
194
|
`Dart framework call codegen: '${law.graph.domain.entity.label}/${definition.directive}' has no authored directive`,
|
|
@@ -128,11 +203,11 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
128
203
|
: `${field.dartType}${field.optional ? "?" : ""}`;
|
|
129
204
|
const payloadType = `({${fields.map((field) =>
|
|
130
205
|
`${parameterType(field)} ${dartMemberName(field.name)}`).join(", ")}})`;
|
|
131
|
-
const access = new Map<string,
|
|
206
|
+
const access = new Map<string, DartCallProtoFieldAccess>(fields.map((field) => [
|
|
132
207
|
field.name,
|
|
133
208
|
frameworkFieldAccess(field),
|
|
134
209
|
]));
|
|
135
|
-
const encoder =
|
|
210
|
+
const encoder = emitDartCallProtoEncoder(
|
|
136
211
|
law.graph,
|
|
137
212
|
law.paths,
|
|
138
213
|
law.graph.domain.entity.label,
|
|
@@ -151,11 +226,11 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
151
226
|
: `${field.dartType}${field.optional ? "?" : ""}`;
|
|
152
227
|
const payloadType = `({${fields.map((field) =>
|
|
153
228
|
`${parameterType(field)} ${dartMemberName(field.name)}`).join(", ")}})`;
|
|
154
|
-
|
|
229
|
+
const access = new Map<string, DartCallProtoFieldAccess>(fields.map((field) => [
|
|
155
230
|
field.name,
|
|
156
231
|
frameworkFieldAccess(field),
|
|
157
232
|
]));
|
|
158
|
-
const encoder =
|
|
233
|
+
const encoder = emitDartCallProtoEncoder(
|
|
159
234
|
law.graph,
|
|
160
235
|
law.paths,
|
|
161
236
|
law.graph.domain.entity.label,
|
|
@@ -181,11 +256,146 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
181
256
|
// verifier epoch); every target must independently declare the narrow recovery door.
|
|
182
257
|
// The host never chooses an operation name and the compiler refuses an ambiguous or
|
|
183
258
|
// differently-shaped candidate.
|
|
259
|
+
// THE DECLARED DOOR BINDS FIRST. When the application declared its receiving-group recovery posture,
|
|
260
|
+
// the framework composed `nomosInternalRecoverReceivingGroupDevice7c1f5e` into the application-home
|
|
261
|
+
// domain; it is presentation-internal, so it is never a public application intent and the structural
|
|
262
|
+
// search below cannot see it. Bind it exactly like a fixed framework call (by id, from the composed
|
|
263
|
+
// graph). A tenant-authored door beside it is refused: one application has one recovery route.
|
|
264
|
+
const frameworkDoor = laws.flatMap((law) => {
|
|
265
|
+
const declares = law.graph.nodes.some((node) =>
|
|
266
|
+
node.kind === "intent" && node.entity.label === FRAMEWORK_RECOVERY_DOOR_ID);
|
|
267
|
+
if (!declares) return [];
|
|
268
|
+
const directive = authoredDirective(law.module, FRAMEWORK_RECOVERY_DOOR_ID);
|
|
269
|
+
if (directive === undefined) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`Dart framework call codegen: '${law.graph.domain.entity.label}/${FRAMEWORK_RECOVERY_DOOR_ID}' has no authored directive`,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
const fields = introspectPayload(directive.payloadSchema as z.ZodTypeAny, new Map());
|
|
275
|
+
const payloadType = fields.length === 1 ? `({String user})` : `({String user, String? deviceKeySubject})`;
|
|
276
|
+
const access = new Map<string, DartCallProtoFieldAccess>(fields.map((field) => [
|
|
277
|
+
field.name, frameworkFieldAccess(field),
|
|
278
|
+
]));
|
|
279
|
+
const encoder = emitDartCallProtoEncoder(
|
|
280
|
+
law.graph, law.paths, law.graph.domain.entity.label, FRAMEWORK_RECOVERY_DOOR_ID, payloadType, access,
|
|
281
|
+
);
|
|
282
|
+
return [{
|
|
283
|
+
kind: "recoverExistingReceivingGroupDevice",
|
|
284
|
+
directive: FRAMEWORK_RECOVERY_DOOR_ID,
|
|
285
|
+
domain: law.graph.domain.entity.label,
|
|
286
|
+
fields,
|
|
287
|
+
payloadType,
|
|
288
|
+
encoder,
|
|
289
|
+
routeByDirective: false as const,
|
|
290
|
+
}];
|
|
291
|
+
});
|
|
292
|
+
// THE CHILD-AUTHENTICATION REPAIR IS FRAMEWORK LAW (receiving_group_lifecycle.md cut 1 item 3): when the
|
|
293
|
+
// package births children the application-home domain composes `nomosInternalRepairChildAuthentication7c1f5e`,
|
|
294
|
+
// the ONE parent action that repairs a child refusing this device's key, addressed by workspace. It is
|
|
295
|
+
// presentation-internal, so it is bound here by id exactly like the recovery door; the Reception's repair
|
|
296
|
+
// lane calls it and no tenant ever routes a child kind by name.
|
|
297
|
+
const frameworkChildRepair = laws.flatMap((law) => {
|
|
298
|
+
const declares = law.graph.nodes.some((node) =>
|
|
299
|
+
node.kind === "intent" && node.entity.label === FRAMEWORK_CHILD_REPAIR_ID);
|
|
300
|
+
if (!declares) return [];
|
|
301
|
+
const directive = authoredDirective(law.module, FRAMEWORK_CHILD_REPAIR_ID);
|
|
302
|
+
if (directive === undefined) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`Dart framework call codegen: '${law.graph.domain.entity.label}/${FRAMEWORK_CHILD_REPAIR_ID}' has no authored directive`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
const fields = introspectPayload(directive.payloadSchema as z.ZodTypeAny, new Map());
|
|
308
|
+
const expected: readonly [string, boolean][] = [["workspace", false], ["user", false], ["deviceKeySubject", true]];
|
|
309
|
+
if (
|
|
310
|
+
fields.length !== expected.length ||
|
|
311
|
+
fields.some((field, index) =>
|
|
312
|
+
field.name !== expected[index]![0] || field.optional !== expected[index]![1] ||
|
|
313
|
+
field.dartType !== "String" || field.shape !== "scalar" || field.nullAdmits === true)
|
|
314
|
+
) {
|
|
315
|
+
throw new Error(
|
|
316
|
+
`Dart framework call codegen: the framework child-authentication repair '${FRAMEWORK_CHILD_REPAIR_ID}' must accept { workspace: string, user: string, deviceKeySubject?: string }`,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
const payloadType = `({String workspace, String user, String? deviceKeySubject})`;
|
|
320
|
+
const access = new Map<string, DartCallProtoFieldAccess>(fields.map((field) => [
|
|
321
|
+
field.name, frameworkFieldAccess(field),
|
|
322
|
+
]));
|
|
323
|
+
const encoder = emitDartCallProtoEncoder(
|
|
324
|
+
law.graph, law.paths, law.graph.domain.entity.label, FRAMEWORK_CHILD_REPAIR_ID, payloadType, access,
|
|
325
|
+
);
|
|
326
|
+
return [{
|
|
327
|
+
kind: "repairChildAuthentication",
|
|
328
|
+
directive: FRAMEWORK_CHILD_REPAIR_ID,
|
|
329
|
+
domain: law.graph.domain.entity.label,
|
|
330
|
+
fields,
|
|
331
|
+
payloadType,
|
|
332
|
+
encoder,
|
|
333
|
+
routeByDirective: false as const,
|
|
334
|
+
}];
|
|
335
|
+
});
|
|
336
|
+
if (frameworkChildRepair.length > 1) {
|
|
337
|
+
throw new Error(
|
|
338
|
+
`Dart framework call codegen: the framework child-authentication repair is composed into ${frameworkChildRepair.length} domains; exactly one is allowed`,
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
// THE MODEL-AUTHORITY SELF-HEAL IS FRAMEWORK LAW (parent_directed_model_transition.md, the third door):
|
|
342
|
+
// when the package births children the application-home domain composes
|
|
343
|
+
// `nomosInternalPullParentModelAuthority7c1f5e`, the ONE child-side action that asks this workspace's own
|
|
344
|
+
// verified parent for the model-lifecycle authority it should have been born holding. Bound here by id
|
|
345
|
+
// exactly like the child repair; the Reception offers it and no tenant passes a parameter for it.
|
|
346
|
+
const frameworkModelAuthorityPull = laws.flatMap((law) => {
|
|
347
|
+
const declares = law.graph.nodes.some((node) =>
|
|
348
|
+
node.kind === "intent" && node.entity.label === FRAMEWORK_MODEL_AUTHORITY_SEAT_ID);
|
|
349
|
+
if (!declares) return [];
|
|
350
|
+
const directive = authoredDirective(law.module, FRAMEWORK_MODEL_AUTHORITY_SEAT_ID);
|
|
351
|
+
if (directive === undefined) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
`Dart framework call codegen: '${law.graph.domain.entity.label}/${FRAMEWORK_MODEL_AUTHORITY_SEAT_ID}' has no authored directive`,
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
const fields = introspectPayload(directive.payloadSchema as z.ZodTypeAny, new Map());
|
|
357
|
+
const expected: readonly [string, string, string][] = [
|
|
358
|
+
["holders", "recordList", MODEL_AUTHORITY_HOLDERS_DART_TYPE],
|
|
359
|
+
["seatedAt", "scalar", "String"],
|
|
360
|
+
];
|
|
361
|
+
if (
|
|
362
|
+
fields.length !== expected.length ||
|
|
363
|
+
fields.some((field, index) =>
|
|
364
|
+
field.name !== expected[index]![0] || field.shape !== expected[index]![1] ||
|
|
365
|
+
field.dartType !== expected[index]![2] || field.optional !== false || field.nullAdmits === true)
|
|
366
|
+
) {
|
|
367
|
+
throw new Error(
|
|
368
|
+
`Dart framework call codegen: the framework model-authority self-seat '${FRAMEWORK_MODEL_AUTHORITY_SEAT_ID}' must accept { holders: [{ principal, signers: [...] }], seatedAt: string }`,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
const payloadType =
|
|
372
|
+
`({${MODEL_AUTHORITY_HOLDERS_DART_TYPE} holders, String seatedAt})`;
|
|
373
|
+
const access = new Map<string, DartCallProtoFieldAccess>(fields.map((field) => [
|
|
374
|
+
field.name, frameworkFieldAccess(field),
|
|
375
|
+
]));
|
|
376
|
+
const encoder = emitDartCallProtoEncoder(
|
|
377
|
+
law.graph, law.paths, law.graph.domain.entity.label, FRAMEWORK_MODEL_AUTHORITY_SEAT_ID, payloadType, access,
|
|
378
|
+
);
|
|
379
|
+
return [{
|
|
380
|
+
kind: "seatParentModelAuthority",
|
|
381
|
+
directive: FRAMEWORK_MODEL_AUTHORITY_SEAT_ID,
|
|
382
|
+
domain: law.graph.domain.entity.label,
|
|
383
|
+
fields,
|
|
384
|
+
payloadType,
|
|
385
|
+
encoder,
|
|
386
|
+
routeByDirective: false as const,
|
|
387
|
+
}];
|
|
388
|
+
});
|
|
389
|
+
if (frameworkModelAuthorityPull.length > 1) {
|
|
390
|
+
throw new Error(
|
|
391
|
+
`Dart framework call codegen: the framework model-authority self-heal is composed into ${frameworkModelAuthorityPull.length} domains; exactly one is allowed`,
|
|
392
|
+
);
|
|
393
|
+
}
|
|
184
394
|
const recoveryCandidates = laws.flatMap((law) =>
|
|
185
395
|
(law.module.applicationIntents ?? []).flatMap((candidate) => {
|
|
186
396
|
if (
|
|
187
397
|
!isBusinessIntent(candidate) ||
|
|
188
|
-
candidate.
|
|
398
|
+
candidate.authentication?.kind !== MemberAuthenticationKind.EnrolledDevice ||
|
|
189
399
|
candidate.steps.length !== 0 ||
|
|
190
400
|
candidate.workspaceEffects.length === 0 ||
|
|
191
401
|
!candidate.workspaceEffects.every(
|
|
@@ -194,23 +404,25 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
194
404
|
) return [];
|
|
195
405
|
const fields = introspectPayload(candidate.contract.accepts, new Map());
|
|
196
406
|
if (
|
|
197
|
-
fields.length !== 1 ||
|
|
407
|
+
(fields.length !== 1 && fields.length !== 2) ||
|
|
198
408
|
fields[0]!.name !== "user" ||
|
|
199
409
|
fields[0]!.dartType !== "String" ||
|
|
200
410
|
fields[0]!.shape !== "scalar" ||
|
|
201
411
|
fields[0]!.optional ||
|
|
202
|
-
fields[0]!.nullAdmits === true
|
|
412
|
+
fields[0]!.nullAdmits === true ||
|
|
413
|
+
(fields.length === 2 && (fields[1]!.name !== "deviceKeySubject" ||
|
|
414
|
+
fields[1]!.dartType !== "String" || fields[1]!.shape !== "scalar" ||
|
|
415
|
+
!fields[1]!.optional))
|
|
203
416
|
) {
|
|
204
417
|
throw new Error(
|
|
205
|
-
`Dart framework call codegen: existing receiving-group recovery intent '${candidate.id}' must accept
|
|
418
|
+
`Dart framework call codegen: existing receiving-group recovery intent '${candidate.id}' must accept { user: string, deviceKeySubject?: string }`,
|
|
206
419
|
);
|
|
207
420
|
}
|
|
208
|
-
const payloadType = `({String user})`;
|
|
209
|
-
const access = new Map<string,
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const encoder = emitDartCallUsdaEncoder(
|
|
421
|
+
const payloadType = fields.length === 1 ? `({String user})` : `({String user, String? deviceKeySubject})`;
|
|
422
|
+
const access = new Map<string, DartCallProtoFieldAccess>(fields.map((field) => [
|
|
423
|
+
field.name, frameworkFieldAccess(field),
|
|
424
|
+
]));
|
|
425
|
+
const encoder = emitDartCallProtoEncoder(
|
|
214
426
|
law.graph,
|
|
215
427
|
law.paths,
|
|
216
428
|
law.graph.domain.entity.label,
|
|
@@ -228,12 +440,26 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
228
440
|
routeByDirective: false as const,
|
|
229
441
|
}];
|
|
230
442
|
}));
|
|
443
|
+
if (frameworkDoor.length > 0 && recoveryCandidates.length > 0) {
|
|
444
|
+
throw new Error(
|
|
445
|
+
`Dart framework call codegen: the application declared its receiving-group recovery posture (the framework composed ` +
|
|
446
|
+
`'${FRAMEWORK_RECOVERY_DOOR_ID}') and still authors its own recovery intent '${recoveryCandidates[0]!.directive}'; ` +
|
|
447
|
+
`delete the tenant door — one application has one recovery route`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
231
450
|
if (recoveryCandidates.length > 1) {
|
|
232
451
|
throw new Error(
|
|
233
452
|
`Dart framework call codegen: application composes ${recoveryCandidates.length} existing receiving-group recovery intents; exactly one is allowed`,
|
|
234
453
|
);
|
|
235
454
|
}
|
|
236
|
-
const
|
|
455
|
+
const recoveryDoors = frameworkDoor.length > 0 ? frameworkDoor : recoveryCandidates;
|
|
456
|
+
const emitted = [
|
|
457
|
+
...fixedEmitted,
|
|
458
|
+
...invitationEmitted,
|
|
459
|
+
...recoveryDoors,
|
|
460
|
+
...frameworkChildRepair,
|
|
461
|
+
...frameworkModelAuthorityPull,
|
|
462
|
+
];
|
|
237
463
|
if (emitted.length === 0) return undefined;
|
|
238
464
|
|
|
239
465
|
const certificateEntry = emitted.find((entry) =>
|
|
@@ -251,8 +477,12 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
251
477
|
if (certificateEntry === undefined || certificateField === undefined) {
|
|
252
478
|
throw new Error("Dart framework call codegen: cannot locate the BirthCertificate law record");
|
|
253
479
|
}
|
|
254
|
-
const
|
|
255
|
-
|
|
480
|
+
const certificateLaw = laws.find(
|
|
481
|
+
(law) => law.graph.domain.entity.label === certificateEntry.domain,
|
|
482
|
+
);
|
|
483
|
+
const directive = certificateLaw === undefined
|
|
484
|
+
? undefined
|
|
485
|
+
: authoredDirective(certificateLaw.module, certificateEntry.directive);
|
|
256
486
|
if (directive === undefined) {
|
|
257
487
|
throw new Error("Dart framework call codegen: cannot locate the BirthCertificate directive");
|
|
258
488
|
}
|
|
@@ -288,6 +518,8 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
288
518
|
.filter((definition) => definition.dartBirth === true)
|
|
289
519
|
.map((definition) => definition.kind),
|
|
290
520
|
"recoverExistingReceivingGroupDevice",
|
|
521
|
+
"repairChildAuthentication",
|
|
522
|
+
"seatParentModelAuthority",
|
|
291
523
|
"redeemInvitation",
|
|
292
524
|
])].flatMap((kind) => {
|
|
293
525
|
const alternatives = emitted.filter((entry) => entry.kind === kind);
|
|
@@ -295,15 +527,46 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
295
527
|
(kind === "recoverExistingReceivingGroupDevice"
|
|
296
528
|
? [{ name: "user", dartType: "String", shape: "scalar", optional: false } satisfies PayloadFieldSpec]
|
|
297
529
|
: invitationContractFields);
|
|
530
|
+
if (kind === "seatParentModelAuthority") {
|
|
531
|
+
const seat = alternatives[0];
|
|
532
|
+
return [
|
|
533
|
+
` @override`,
|
|
534
|
+
` NmsGeneratedCall seatParentModelAuthority({required List<NmsModelAuthorityHolder> holders, required String seatedAt}) {`,
|
|
535
|
+
...(seat === undefined
|
|
536
|
+
? [` throw StateError("The compiled application has no framework model-authority self-seat law (it births no children).");`]
|
|
537
|
+
: [
|
|
538
|
+
` final payload = (holders: holders, seatedAt: seatedAt);`,
|
|
539
|
+
` return ${seat.encoder.functionName}(payload);`,
|
|
540
|
+
]),
|
|
541
|
+
` }`,
|
|
542
|
+
``,
|
|
543
|
+
];
|
|
544
|
+
}
|
|
545
|
+
if (kind === "repairChildAuthentication") {
|
|
546
|
+
const repair = alternatives[0];
|
|
547
|
+
return [
|
|
548
|
+
` @override`,
|
|
549
|
+
` NmsGeneratedCall repairChildAuthentication({required String workspace, required String user, String? deviceKeySubject}) {`,
|
|
550
|
+
...(repair === undefined
|
|
551
|
+
? [` throw StateError("The compiled application has no framework child-authentication repair law (it births no children).");`]
|
|
552
|
+
: [
|
|
553
|
+
` final payload = (workspace: workspace, user: user, deviceKeySubject: deviceKeySubject);`,
|
|
554
|
+
` return ${repair.encoder.functionName}(payload);`,
|
|
555
|
+
]),
|
|
556
|
+
` }`,
|
|
557
|
+
``,
|
|
558
|
+
];
|
|
559
|
+
}
|
|
298
560
|
if (kind === "recoverExistingReceivingGroupDevice") {
|
|
299
561
|
const recovery = alternatives[0];
|
|
300
562
|
return [
|
|
301
563
|
` @override`,
|
|
302
|
-
` NmsGeneratedCall recoverExistingReceivingGroupDevice({required String user}) {`,
|
|
564
|
+
` NmsGeneratedCall recoverExistingReceivingGroupDevice({required String user, String? deviceKeySubject}) {`,
|
|
303
565
|
...(recovery === undefined
|
|
304
566
|
? [` throw StateError("The compiled application has no existing receiving-group device recovery law.");`]
|
|
305
567
|
: [
|
|
306
|
-
` final payload = (user: user,)
|
|
568
|
+
recovery.fields.length === 1 ? ` final payload = (user: user,);` :
|
|
569
|
+
` final payload = (user: user, deviceKeySubject: deviceKeySubject);`,
|
|
307
570
|
` return ${recovery.encoder.functionName}(payload);`,
|
|
308
571
|
]),
|
|
309
572
|
` }`,
|
|
@@ -326,14 +589,23 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
326
589
|
...(routeByDirective ? [` required String directive,`] : []),
|
|
327
590
|
...signature,
|
|
328
591
|
` }) {`,
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
592
|
+
// With no alternative the switch is only its unreachable default, so binding the payload
|
|
593
|
+
// would leave a dead local — `dart analyze` reports unused_local_variable and exits
|
|
594
|
+
// non-zero on the generated package. Refuse the same way the three fixed methods above do.
|
|
595
|
+
...(alternatives.length === 0
|
|
596
|
+
? [
|
|
597
|
+
` throw StateError("The compiled application has no '${kind}' call in domain '$domain'.");`,
|
|
598
|
+
]
|
|
599
|
+
: [
|
|
600
|
+
` final payload = (`,
|
|
601
|
+
...payload,
|
|
602
|
+
` );`,
|
|
603
|
+
` return switch (${routeByDirective ? "'$domain/$directive'" : "domain"}) {`,
|
|
604
|
+
...alternatives.map((entry) =>
|
|
605
|
+
` ${JSON.stringify(routeByDirective ? `${entry.domain}/${entry.directive}` : entry.domain)} => ${entry.encoder.functionName}(payload),`),
|
|
606
|
+
` _ => throw StateError("The compiled application has no '${kind}' call in domain '$domain'."),`,
|
|
607
|
+
` };`,
|
|
608
|
+
]),
|
|
337
609
|
` }`,
|
|
338
610
|
``,
|
|
339
611
|
];
|
|
@@ -343,14 +615,16 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
343
615
|
`// AUTO-GENERATED by nomos-compile — pre-bind framework calls for this exact application law.`,
|
|
344
616
|
`// No host authority or payload schema lives here. Do not edit.`,
|
|
345
617
|
`// ignore_for_file: invalid_use_of_internal_member, unused_element, unused_import, unused_shown_name`,
|
|
346
|
-
`import 'dart:convert' show base64Encode
|
|
618
|
+
`import 'dart:convert' show base64Encode;`,
|
|
347
619
|
`import 'dart:typed_data' show Uint8List;`,
|
|
348
|
-
`import 'package:
|
|
620
|
+
`import 'package:fixnum/fixnum.dart' show Int64;`,
|
|
621
|
+
`import 'operation_payloads.pb.dart' as _nmsop;`,
|
|
622
|
+
`import 'package:nomos_types/nomos_kernel_protocol.dart' show ApplicationBirthContract, BirthCertificate;`,
|
|
349
623
|
`import 'package:nomos_types/nomos_types.dart' show NomosSlot, Sha256Digest;`,
|
|
350
624
|
`import 'package:nomos_client/src/application_framework_calls.dart';`,
|
|
351
625
|
`import 'package:nomos_client/src/generated_call.dart';`,
|
|
352
626
|
``,
|
|
353
|
-
...
|
|
627
|
+
...DART_CALL_PROTO_PRELUDE,
|
|
354
628
|
...(certificateRecordType === undefined
|
|
355
629
|
? []
|
|
356
630
|
: [
|
|
@@ -365,6 +639,15 @@ export function generateDartApplicationFrameworkCalls(
|
|
|
365
639
|
` const _NmsCompiledApplicationFrameworkCalls();`,
|
|
366
640
|
` @override`,
|
|
367
641
|
` String get applicationHomeDomain => ${JSON.stringify(APPLICATION_HOME_DOMAIN)};`,
|
|
642
|
+
` @override`,
|
|
643
|
+
` String get applicationAuthorityDomain => ${JSON.stringify(recoveryDoors[0]?.domain ?? APPLICATION_HOME_DOMAIN)};`,
|
|
644
|
+
` @override`,
|
|
645
|
+
` String get parentModelAuthoritySeatAggregate => ${JSON.stringify(PARENT_MODEL_AUTHORITY_SEAT_AGGREGATE)};`,
|
|
646
|
+
` @override`,
|
|
647
|
+
` String get parentModelAuthoritySeatId => ${JSON.stringify(PARENT_MODEL_AUTHORITY_SEAT_ID)};`,
|
|
648
|
+
` @override`,
|
|
649
|
+
` ApplicationBirthContract get applicationBirthContract =>`,
|
|
650
|
+
` ApplicationBirthContract(lawSha256: ${JSON.stringify(descriptor.lawSha256)});`,
|
|
368
651
|
``,
|
|
369
652
|
...methods,
|
|
370
653
|
`}`,
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { IndexedVariant } from "./indexed_variant.js";
|
|
2
|
+
import { dartMemberName, dartTypeOfVoField, unionArmClassName } from "./codegen_dart.js";
|
|
3
|
+
|
|
4
|
+
/** Stateless, generated proof of a runtime field/value relationship. Constructors
|
|
5
|
+
* remain library-private: callers narrow the binding and receive only its edit API.
|
|
6
|
+
*/
|
|
7
|
+
export function emitDartIndexedVariant(d: IndexedVariant): string {
|
|
8
|
+
const n = d.name;
|
|
9
|
+
const v = d.value.name;
|
|
10
|
+
const entries = Object.entries(d.cases).sort(([a], [b]) => a.localeCompare(b));
|
|
11
|
+
const armClass = (arm: string) => unionArmClassName(v, arm);
|
|
12
|
+
const caseClass = (kind: string) => unionArmClassName(n, kind);
|
|
13
|
+
const kindsByArm = new Map<string, string[]>();
|
|
14
|
+
for (const [kind, arm] of entries) kindsByArm.set(arm, [...(kindsByArm.get(arm) ?? []), kind]);
|
|
15
|
+
const classes = entries.map(([kind, arm]) => {
|
|
16
|
+
const shape = d.value.descriptor.union![arm]!;
|
|
17
|
+
const fields = "ref" in shape
|
|
18
|
+
? [{ member: "value", type: shape.ref, optional: false }]
|
|
19
|
+
: Object.entries(shape.fields).filter(([, f]) => f.type !== "literal").map(([key, f]) => ({
|
|
20
|
+
member: dartMemberName(key),
|
|
21
|
+
type: dartTypeOfVoField(f, armClass(arm), key) + (f.optional && !f.nullable ? "?" : ""),
|
|
22
|
+
optional: f.optional === true,
|
|
23
|
+
}));
|
|
24
|
+
const args = fields.length === 1
|
|
25
|
+
? `${fields[0]!.type} value`
|
|
26
|
+
: fields.length === 0 ? "" : `{${fields.map((f) => `${f.optional ? "" : "required "}${f.type} ${f.member}`).join(", ")}}`;
|
|
27
|
+
const construct = "ref" in shape ? `${armClass(arm)}(value)`
|
|
28
|
+
: `${armClass(arm)}(${fields.map((f) => `${f.member}: ${fields.length === 1 ? "value" : f.member}`).join(", ")})`;
|
|
29
|
+
return `final class ${caseClass(kind)} extends ${n}Editable {
|
|
30
|
+
final ${armClass(arm)}? value;
|
|
31
|
+
const ${caseClass(kind)}._(String id, String? definitionVersion, this.value) : super._('${kind}', id, definitionVersion);
|
|
32
|
+
${n}Edit edit(${args}) => ${n}Edit._(id, kind, definitionVersion, ${construct});
|
|
33
|
+
}`;
|
|
34
|
+
});
|
|
35
|
+
const decodeCases = entries.map(([kind, arm]) => {
|
|
36
|
+
const shape = d.value.descriptor.union![arm]!;
|
|
37
|
+
const keys = "ref" in shape ? ["value"] : Object.keys(shape.fields).filter((key) => shape.fields[key]!.type !== "literal");
|
|
38
|
+
return ` '${kind}' => ${armClass(arm)}.fromProjected(${keys.length === 1
|
|
39
|
+
? `{'type': '${arm}', '${keys[0]}': input}`
|
|
40
|
+
: `{'type': '${arm}', ...(input as Map).cast<String, Object?>()}`}),`;
|
|
41
|
+
});
|
|
42
|
+
return `/// Runtime narrowing for the declared ${n} discriminator/value relationship.
|
|
43
|
+
sealed class ${n}Binding {
|
|
44
|
+
final String id;
|
|
45
|
+
final String kind;
|
|
46
|
+
final String? definitionVersion;
|
|
47
|
+
const ${n}Binding._(this.id, this.kind, this.definitionVersion);
|
|
48
|
+
|
|
49
|
+
/// Recover a definition kind only when the declared relationship is unambiguous.
|
|
50
|
+
static String? kindOf(${v}? value) => switch (value) {
|
|
51
|
+
${[...kindsByArm].filter(([, kinds]) => kinds.length === 1).map(([arm, kinds]) => ` ${armClass(arm)}() => '${kinds[0]}',`).join("\n")}
|
|
52
|
+
_ => null,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
static ${n}Binding resolve({required String id, required String kind, ${v}? value, String? definitionVersion}) {
|
|
56
|
+
switch (kind) {
|
|
57
|
+
${entries.map(([kind, arm]) => ` case '${kind}':
|
|
58
|
+
if (value != null && value is! ${armClass(arm)}) {
|
|
59
|
+
return ${n}ShapeMismatch._(id, kind, definitionVersion, value);
|
|
60
|
+
}
|
|
61
|
+
return ${caseClass(kind)}._(id, definitionVersion, value as ${armClass(arm)}?);`).join("\n")}
|
|
62
|
+
default:
|
|
63
|
+
return ${n}Unsupported._(id, kind, definitionVersion);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
sealed class ${n}Editable extends ${n}Binding {
|
|
69
|
+
const ${n}Editable._(String kind, String id, String? definitionVersion) : super._(id, kind, definitionVersion);
|
|
70
|
+
${n}Edit clear() => ${n}Edit._(id, kind, definitionVersion, null);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
${classes.join("\n\n")}
|
|
74
|
+
|
|
75
|
+
sealed class ${n}Rejection extends ${n}Binding implements Exception {
|
|
76
|
+
const ${n}Rejection._(super.id, super.kind, super.definitionVersion) : super._();
|
|
77
|
+
String get message;
|
|
78
|
+
@override
|
|
79
|
+
String toString() => message;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
final class ${n}Unsupported extends ${n}Rejection {
|
|
83
|
+
const ${n}Unsupported._(super.id, super.kind, super.definitionVersion) : super._();
|
|
84
|
+
@override
|
|
85
|
+
String get message => 'Unsupported ${n} kind: $kind';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
final class ${n}ShapeMismatch extends ${n}Rejection {
|
|
89
|
+
final ${v} value;
|
|
90
|
+
const ${n}ShapeMismatch._(super.id, super.kind, super.definitionVersion, this.value) : super._();
|
|
91
|
+
@override
|
|
92
|
+
String get message => '${n} $id has a value incompatible with $kind';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
final class ${n}DefinitionChanged extends ${n}Rejection {
|
|
96
|
+
const ${n}DefinitionChanged._(super.id, super.kind, super.definitionVersion) : super._();
|
|
97
|
+
@override
|
|
98
|
+
String get message => '${n} $id changed; reopen its editor';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
final class ${n}InvalidInput extends ${n}Rejection {
|
|
102
|
+
const ${n}InvalidInput._(super.id, super.kind, super.definitionVersion) : super._();
|
|
103
|
+
@override
|
|
104
|
+
String get message => 'Invalid input for ${n} $id ($kind)';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// An edit can only be constructed by a narrowed field or the checked JSON boundary.
|
|
108
|
+
final class ${n}Edit {
|
|
109
|
+
final String id;
|
|
110
|
+
final String kind;
|
|
111
|
+
final String? definitionVersion;
|
|
112
|
+
final ${v}? _value;
|
|
113
|
+
${n}Edit._(this.id, this.kind, this.definitionVersion, ${v}? value)
|
|
114
|
+
: _value = value == null ? null : ${v}.fromProjected(_${n}Snapshot(value.toJson()) as Map<String, Object?>);
|
|
115
|
+
// Copy at both boundaries: mutable nested collections cannot change an already-created edit.
|
|
116
|
+
${v}? get value => _value == null ? null : ${v}.fromProjected(_${n}Snapshot(_value.toJson()) as Map<String, Object?>);
|
|
117
|
+
|
|
118
|
+
/// Recheck the current definition immediately before submitting. No I/O.
|
|
119
|
+
${n}Rejection? rejectionFor(${n}Binding current) {
|
|
120
|
+
if (current is ${n}Rejection) return current;
|
|
121
|
+
if (current.id != id || current.kind != kind || current.definitionVersion != definitionVersion) {
|
|
122
|
+
return ${n}DefinitionChanged._(id, kind, definitionVersion);
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/// Only for untyped external input (JSON/actions). UI code uses the narrowed edit method.
|
|
128
|
+
static ${n}Edit decode(${n}Binding field, Object? input) {
|
|
129
|
+
if (field is ${n}Rejection) throw field;
|
|
130
|
+
if (input == null) return (field as ${n}Editable).clear();
|
|
131
|
+
try {
|
|
132
|
+
final ${v} value;
|
|
133
|
+
if (input is ${v}) {
|
|
134
|
+
value = input;
|
|
135
|
+
} else if (input is Map && input.containsKey('type')) {
|
|
136
|
+
value = ${v}.fromProjected(input.cast<String, Object?>());
|
|
137
|
+
} else {
|
|
138
|
+
value = switch (field.kind) {
|
|
139
|
+
${decodeCases.join("\n")}
|
|
140
|
+
_ => throw ${n}Unsupported._(field.id, field.kind, field.definitionVersion),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
final checked = ${n}Binding.resolve(id: field.id, kind: field.kind, definitionVersion: field.definitionVersion, value: value);
|
|
144
|
+
if (checked is ${n}Rejection) throw checked;
|
|
145
|
+
return ${n}Edit._(field.id, field.kind, field.definitionVersion, value);
|
|
146
|
+
} on ${n}Rejection {
|
|
147
|
+
rethrow;
|
|
148
|
+
} on Object {
|
|
149
|
+
throw ${n}InvalidInput._(field.id, field.kind, field.definitionVersion);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
Object? _${n}Snapshot(Object? value) => switch (value) {
|
|
155
|
+
Map value => value.map((key, item) => MapEntry(key as String, _${n}Snapshot(item))),
|
|
156
|
+
List value => value.map(_${n}Snapshot).toList(),
|
|
157
|
+
_ => value,
|
|
158
|
+
};`;
|
|
159
|
+
}
|