@githolon/dsl 0.108.7 → 0.110.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/operation-contract.wasm +0 -0
- package/check_package.mjs +12 -15
- package/compile_package.mjs +17 -18
- package/compile_proof.mjs +16 -1
- package/dart/CHANGELOG.md +76 -1
- package/dart/README.md +25 -2
- package/dart/lib/src/admission_decision.dart +41 -0
- package/dart/lib/src/application_framework_calls.dart +52 -2
- package/dart/lib/src/application_model_adoption.dart +187 -0
- package/dart/lib/src/application_status.dart +73 -0
- package/dart/lib/src/console_enrolment.dart +271 -0
- package/dart/lib/src/console_http_io.dart +26 -0
- package/dart/lib/src/console_http_stub.dart +7 -0
- package/dart/lib/src/dev_cloud.dart +69 -22
- package/dart/lib/src/generated_call.dart +83 -23
- package/dart/lib/src/kernel_primitives.dart +119 -0
- package/dart/lib/src/nms_conformance_runtime.dart +1 -1
- package/dart/lib/src/nms_generated_runtime.dart +32 -10
- package/dart/lib/src/nms_test_environment.dart +1 -1
- package/dart/lib/src/node_runner_transport.dart +41 -46
- package/dart/lib/src/observed_session_directory.dart +70 -0
- package/dart/lib/src/operation_receipts.dart +112 -0
- package/dart/lib/src/peer_application_streams.dart +103 -0
- package/dart/lib/src/reception/dart_reception.dart +4280 -0
- package/dart/lib/src/reception/event_desk.dart +211 -0
- package/dart/lib/src/reception/extremum_read.dart +46 -0
- package/dart/lib/src/reception/local_copies.dart +371 -0
- package/dart/lib/src/reception/peer_office_connection.dart +11 -0
- package/dart/lib/src/reception/progress_desk.dart +267 -0
- package/dart/lib/src/reception/reception_contract.dart +11 -0
- package/dart/lib/src/reception/reception_session.dart +284 -0
- package/dart/lib/src/reception/sync_diagnostics.dart +26 -0
- package/dart/lib/src/reception/workspace_preparation_report.dart +126 -0
- package/dart/lib/src/replica_readiness.dart +123 -0
- package/dart/lib/src/runner/node-entry.mjs +23905 -15774
- package/dart/lib/src/runtime_v2_gateway.dart +56 -3
- package/dart/lib/src/runtime_v2_transport.dart +544 -3
- package/dart/lib/src/session_bound.dart +200 -311
- package/dart/lib/src/signing_identity_kernel.dart +84 -0
- package/dart/lib/src/sync_status_projection.dart +548 -0
- package/dart/lib/src/sync_status_reducer.dart +170 -0
- package/dart/lib/src/test_harness.dart +809 -1153
- package/dart/lib/src/testing/test_custody.dart +66 -0
- package/dart/lib/src/testing/test_peer.dart +328 -0
- package/dart/lib/src/typed_watch_registry.dart +169 -0
- package/dart/lib/src/workspace_open_progress.dart +27 -0
- package/dart/pubspec.lock +24 -1
- package/dart/pubspec.yaml +7 -2
- package/dart/pubspec_overrides.yaml +2 -0
- package/dart/test/admission_decision_test.dart +48 -0
- package/dart/test/background_model_adoption_test.dart +228 -0
- package/dart/test/bundle_version_pairing_test.dart +4 -4
- package/dart/test/child_authentication_repair_test.dart +359 -0
- package/dart/test/cloud_bound_local_shell_test.dart +119 -0
- package/dart/test/console_enrolment_refusal_test.dart +52 -0
- package/dart/test/console_enrolment_test.dart +227 -0
- package/dart/test/errors_test.dart +5 -5
- package/dart/test/event_plane_seam_test.dart +50 -164
- package/dart/test/extremum_read_test.dart +58 -0
- package/dart/test/fixtures/wedge/wedge-entry.mjs +3 -21
- package/dart/test/generated_query_test.dart +32 -0
- package/dart/test/harness_phase_timeout_test.dart +18 -23
- package/dart/test/kernel_author_after_read_test.dart +242 -0
- package/dart/test/kernel_fence_test.dart +137 -0
- package/dart/test/local_copies_test.dart +222 -0
- package/dart/test/model_adoption_test.dart +198 -0
- package/dart/test/node_peer_local_custody_test.dart +153 -0
- package/dart/test/offer_authentication_proof_test.dart +352 -52
- package/dart/test/operation_compatibility_test.dart +151 -0
- package/dart/test/platform_credential_effect_test.dart +386 -0
- package/dart/test/receiving_group_open_test.dart +213 -0
- package/dart/test/reception/workspace_preparation_report_test.dart +103 -0
- package/dart/test/reception_span_trace_test.dart +23 -0
- package/dart/test/replica_readiness_test.dart +156 -0
- package/dart/test/runtime_projections_test.dart +92 -0
- package/dart/test/runtime_v2_gateway_test.dart +131 -0
- package/dart/test/signing_identity_kernel_test.dart +75 -0
- package/dart/test/sync_status_preparation_report_test.dart +29 -0
- package/dart/test/sync_status_reducer_test.dart +419 -0
- package/dart/test/test_harness_test.dart +71 -95
- package/dart/test/typed_query_watch_test.dart +170 -0
- package/dart/test/typed_watch_registry_test.dart +249 -0
- package/dart_lints/README.md +18 -0
- package/dart_lints/lib/nomos_lints.dart +70 -0
- package/dart_lints/pubspec.lock +580 -0
- package/dart_lints/pubspec.yaml +12 -0
- package/dart_lints/test/reference_identity_test.dart +75 -0
- package/dart_types/CHANGELOG.md +18 -0
- package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
- package/dart_types/lib/nomos_types.dart +9 -1
- package/dart_types/lib/src/admission_decision.dart +37 -0
- package/dart_types/lib/src/aggregate_meta.dart +1 -1
- package/dart_types/lib/src/approved_model.dart +65 -0
- package/dart_types/lib/src/custody.dart +10 -18
- package/dart_types/lib/src/error_info.dart +4 -4
- package/dart_types/lib/src/errors.dart +29 -29
- package/dart_types/lib/src/foreign_ref.dart +62 -33
- package/dart_types/lib/src/local_work_rejected.dart +3 -3
- package/dart_types/lib/src/nomos_ref.dart +3 -1
- package/dart_types/lib/src/principal.dart +2 -2
- package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
- package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
- package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
- package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
- package/dart_types/lib/src/runtime_outcome.dart +133 -0
- package/dart_types/lib/src/subscriptions.dart +116 -23
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/extremum_subscriptions_test.dart +40 -0
- package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
- package/dart_types/test/nomos_ref_address_test.dart +25 -0
- package/dart_types/test/ordered_subscriptions_test.dart +34 -0
- package/operation_contract_check.mjs +24 -0
- package/package.json +11 -6
- package/src/aggregate.ts +70 -10
- package/src/application_topology.ts +18 -11
- package/src/attested.ts +3 -0
- package/src/attested_core.ts +46 -3
- package/src/birth_meter_ensure.ts +19 -7
- package/src/births.ts +29 -4
- package/src/build_package.ts +140 -13
- package/src/business_birth.ts +181 -4
- package/src/codegen_call_proto.ts +1274 -0
- package/src/codegen_call_usda.ts +49 -6
- package/src/codegen_dart.ts +79 -44
- package/src/codegen_dart_client.ts +458 -800
- package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
- package/src/codegen_dart_framework_calls.ts +320 -37
- package/src/codegen_dart_indexed_variant.ts +159 -0
- package/src/codegen_dart_scenario.ts +42 -13
- package/src/codegen_proof.ts +3 -3
- package/src/codegen_provider_dart.ts +5 -0
- package/src/codegen_query_proto.ts +158 -0
- package/src/codegen_refusal.ts +189 -0
- package/src/codegen_result_proto.ts +931 -0
- package/src/codegen_result_usda.ts +4 -0
- package/src/codegen_ts.ts +464 -616
- package/src/codegen_workspace_access.ts +105 -0
- package/src/compatibility_graph.ts +759 -0
- package/src/compatibility_usda.ts +264 -0
- package/src/compile_package_main.ts +1994 -1189
- package/src/custody_placement.ts +156 -0
- package/src/custody_placement_usda.ts +91 -0
- package/src/decl_shapes.ts +21 -2
- package/src/describe_model.ts +1 -0
- package/src/directive.ts +59 -2
- package/src/drivers.ts +51 -0
- package/src/engine_entry.ts +52 -8
- package/src/evolve_preview.ts +11 -4
- package/src/exists.ts +2 -0
- package/src/fields.ts +75 -11
- package/src/flow_gate.ts +2 -1
- package/src/framework/application_home.ts +170 -18
- package/src/framework/attested_receipts.ts +8 -3
- package/src/framework/auth_provider_law.ts +169 -9
- package/src/framework/birth_certificate_law.ts +4 -0
- package/src/framework/capability.ts +34 -3
- package/src/framework/child_authentication.ts +346 -0
- package/src/framework/console_governance.ts +295 -0
- package/src/framework/delegated_roles.ts +301 -0
- package/src/framework/domain_lifecycle.ts +26 -13
- package/src/framework/founding_genesis.ts +193 -0
- package/src/framework/framework_aggregates.ts +1 -1
- package/src/framework/genesis.ts +6 -1
- package/src/framework/governance_relations.ts +19 -0
- package/src/framework/home.ts +5 -734
- package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
- package/src/framework/model_authority_repair.ts +116 -0
- package/src/framework/model_authority_seed.ts +185 -0
- package/src/framework/model_transition.ts +211 -0
- package/src/framework/owned_custody.ts +1 -1
- package/src/framework/principal_enrollment.ts +302 -0
- package/src/framework/receiving_group.ts +857 -0
- package/src/framework/receiving_group_recovery.ts +314 -0
- package/src/framework/relations.ts +4 -8
- package/src/framework/signing_identity.ts +242 -95
- package/src/framework/source_roster.ts +11 -5
- package/src/framework/workspace_access.ts +149 -0
- package/src/framework/workspace_invariant.ts +73 -52
- package/src/framework/workspaces.ts +407 -40
- package/src/framework_call_definitions.ts +32 -3
- package/src/generated_client_bundle_boundary.ts +97 -0
- package/src/generated_client_names.ts +1 -0
- package/src/identity_usda.ts +27 -0
- package/src/index.ts +183 -12
- package/src/indexed_variant.ts +83 -0
- package/src/intent.ts +173 -45
- package/src/law_check.ts +8 -5
- package/src/law_dependency_index.ts +231 -0
- package/src/law_graph.ts +508 -71
- package/src/law_graph_usda.ts +170 -24
- package/src/law_identity.ts +119 -81
- package/src/law_source_map.ts +4 -1
- package/src/law_units.ts +498 -0
- package/src/law_value_type.ts +7 -3
- package/src/member_authentication.ts +302 -0
- package/src/null_meta.ts +1 -1
- package/src/openusd_compiled_layer.ts +132 -0
- package/src/operation_contract_check.ts +31 -0
- package/src/ordered_read.ts +2 -1
- package/src/package_config.ts +33 -12
- package/src/package_dependencies.ts +1 -0
- package/src/plan_source_slice.ts +30 -1
- package/src/protobuf_field_number.ts +36 -0
- package/src/provenance_wire.ts +6 -0
- package/src/query.ts +2 -1
- package/src/read.ts +50 -0
- package/src/relation.ts +4 -1
- package/src/relation_schema.ts +15 -2
- package/src/report.ts +2 -2
- package/src/sqlite_computation_bundle.ts +78 -0
- package/src/sqlite_computed.ts +102 -0
- package/src/sqlite_counts.ts +154 -0
- package/src/sqlite_layout.ts +823 -0
- package/src/sqlite_reads.ts +275 -0
- package/src/sqlite_samples.ts +185 -0
- package/src/stable_id_identity_bridge.ts +1 -1
- package/src/stable_ids_for_module.ts +16 -4
- package/src/test_call_usda.ts +6 -6
- package/src/usda_relationship_integrity.ts +20 -3
- package/src/usda_text.ts +21 -1
- package/src/value_object.ts +81 -11
- package/src/wire.ts +22 -0
- package/src/wire_encode.ts +227 -20
- package/src/workspace_sharding.ts +15 -6
- package/src/workspace_sharing.ts +51 -49
- package/src/zod_introspection.ts +2 -0
- package/compat_package.mjs +0 -46
- package/dart/lib/src/home.dart +0 -15
- package/dart/lib/src/runner/offline-install.mjs +0 -15367
- package/dart/lib/src/source_trust.dart +0 -51
- package/dart/lib/src/webview_bridge.dart +0 -6540
- package/dart/lib/src/workspace_name.dart +0 -30
- package/dart/test/acquire_session_credentials_test.dart +0 -150
- package/dart/test/acquire_session_test.dart +0 -534
- package/dart/test/adv_realm_interference_test.dart +0 -600
- package/dart/test/cloud_bound_topology_test.dart +0 -168
- package/dart/test/cluster_births_test.dart +0 -202
- package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
- package/dart/test/cluster_local_autosync_test.dart +0 -123
- package/dart/test/cluster_scale_test.dart +0 -122
- package/dart/test/compat_test.dart +0 -61
- package/dart/test/dlq_session_surface_test.dart +0 -222
- package/dart/test/first_app_gauntlet_test.dart +0 -386
- package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
- package/dart/test/four_layer_nested_topology_test.dart +0 -290
- package/dart/test/home_parity_test.dart +0 -13
- package/dart/test/local_sync_inert_test.dart +0 -107
- package/dart/test/node_runner_transport_test.dart +0 -78
- package/dart/test/parent_signer_recovery_test.dart +0 -155
- package/dart/test/residency_refusal_test.dart +0 -49
- package/dart/test/sealing_client_test.dart +0 -181
- package/dart/test/session_bound_test.dart +0 -285
- package/dart/test/stale_bundle_test.dart +0 -80
- package/dart/test/vo_read_typing_test.dart +0 -131
- package/dart/test/watch_after_offer_stall_test.dart +0 -100
- package/dart/test/webview_bridge_test.dart +0 -1930
- package/dart/test/workspace_name_test.dart +0 -24
- package/runtime/generated-application-host.js +0 -22860
- package/src/codegen_query_usda.ts +0 -214
- package/src/compat_manifest.ts +0 -26
- package/src/compat_package_main.ts +0 -224
- package/src/shape_compat.ts +0 -352
- package/src/usd_state.ts +0 -505
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// This is a generated file - do not edit.
|
|
2
|
+
//
|
|
3
|
+
// Generated from nomos/runtime/v2/sealing_desk.proto.
|
|
4
|
+
|
|
5
|
+
// @dart = 3.3
|
|
6
|
+
|
|
7
|
+
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
|
8
|
+
// ignore_for_file: constant_identifier_names
|
|
9
|
+
// ignore_for_file: curly_braces_in_flow_control_structures
|
|
10
|
+
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
|
|
11
|
+
// ignore_for_file: non_constant_identifier_names
|
|
12
|
+
|
|
13
|
+
import 'dart:core' as $core;
|
|
14
|
+
|
|
15
|
+
import 'package:protobuf/protobuf.dart' as $pb;
|
|
16
|
+
|
|
17
|
+
class OwnedRecordAction extends $pb.ProtobufEnum {
|
|
18
|
+
static const OwnedRecordAction OWNED_RECORD_ACTION_UNSPECIFIED =
|
|
19
|
+
OwnedRecordAction._(
|
|
20
|
+
0, _omitEnumNames ? '' : 'OWNED_RECORD_ACTION_UNSPECIFIED');
|
|
21
|
+
static const OwnedRecordAction OWNED_RECORD_ACTION_SHARE =
|
|
22
|
+
OwnedRecordAction._(1, _omitEnumNames ? '' : 'OWNED_RECORD_ACTION_SHARE');
|
|
23
|
+
static const OwnedRecordAction OWNED_RECORD_ACTION_UNSHARE =
|
|
24
|
+
OwnedRecordAction._(
|
|
25
|
+
2, _omitEnumNames ? '' : 'OWNED_RECORD_ACTION_UNSHARE');
|
|
26
|
+
static const OwnedRecordAction OWNED_RECORD_ACTION_TRANSFER =
|
|
27
|
+
OwnedRecordAction._(
|
|
28
|
+
3, _omitEnumNames ? '' : 'OWNED_RECORD_ACTION_TRANSFER');
|
|
29
|
+
|
|
30
|
+
static const $core.List<OwnedRecordAction> values = <OwnedRecordAction>[
|
|
31
|
+
OWNED_RECORD_ACTION_UNSPECIFIED,
|
|
32
|
+
OWNED_RECORD_ACTION_SHARE,
|
|
33
|
+
OWNED_RECORD_ACTION_UNSHARE,
|
|
34
|
+
OWNED_RECORD_ACTION_TRANSFER,
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
static final $core.List<OwnedRecordAction?> _byValue =
|
|
38
|
+
$pb.ProtobufEnum.$_initByValueList(values, 3);
|
|
39
|
+
static OwnedRecordAction? valueOf($core.int value) =>
|
|
40
|
+
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
|
41
|
+
|
|
42
|
+
const OwnedRecordAction._(super.value, super.name);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const $core.bool _omitEnumNames =
|
|
46
|
+
$core.bool.fromEnvironment('protobuf.omit_enum_names');
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/// Closed, presentation-safe terminal outcomes from the Peer Runtime.
|
|
2
|
+
///
|
|
3
|
+
/// These are facts, not repair procedures. A frontend can exhaustively project
|
|
4
|
+
/// them into its own state vocabulary without parsing diagnostics or taking
|
|
5
|
+
/// ownership of workspace, custody, replica-follow or retry lifecycles.
|
|
6
|
+
library;
|
|
7
|
+
|
|
8
|
+
import 'proto/nomos/runtime/v2/observability_desk.pb.dart'
|
|
9
|
+
show RuntimeUnavailable;
|
|
10
|
+
import 'proto/nomos/runtime/v2/observability_desk.pbenum.dart'
|
|
11
|
+
show RuntimeUnavailableReason;
|
|
12
|
+
|
|
13
|
+
enum NomosUnavailableReason {
|
|
14
|
+
remoteOnlyOffline,
|
|
15
|
+
remoteUnreachable,
|
|
16
|
+
remoteTimeout,
|
|
17
|
+
localReplicaNotReady,
|
|
18
|
+
credentialUnavailable,
|
|
19
|
+
workspaceOpening,
|
|
20
|
+
unknown,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
final class NomosUnavailable implements Exception {
|
|
24
|
+
const NomosUnavailable({
|
|
25
|
+
required this.reason,
|
|
26
|
+
required this.workspace,
|
|
27
|
+
required this.retryable,
|
|
28
|
+
this.retryAfter,
|
|
29
|
+
this.detail = '',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
final NomosUnavailableReason reason;
|
|
33
|
+
final String workspace;
|
|
34
|
+
final bool retryable;
|
|
35
|
+
final Duration? retryAfter;
|
|
36
|
+
|
|
37
|
+
/// Diagnostic prose for logs/support. Application control flow uses
|
|
38
|
+
/// [reason], [retryable] and [retryAfter], never this value.
|
|
39
|
+
final String detail;
|
|
40
|
+
|
|
41
|
+
/// The one translation of the generated `unavailable` arm, for every transport.
|
|
42
|
+
factory NomosUnavailable.fromRuntime(RuntimeUnavailable unavailable) =>
|
|
43
|
+
NomosUnavailable(
|
|
44
|
+
reason: switch (unavailable.reason) {
|
|
45
|
+
RuntimeUnavailableReason
|
|
46
|
+
.RUNTIME_UNAVAILABLE_REASON_REMOTE_ONLY_OFFLINE =>
|
|
47
|
+
NomosUnavailableReason.remoteOnlyOffline,
|
|
48
|
+
RuntimeUnavailableReason
|
|
49
|
+
.RUNTIME_UNAVAILABLE_REASON_REMOTE_UNREACHABLE =>
|
|
50
|
+
NomosUnavailableReason.remoteUnreachable,
|
|
51
|
+
RuntimeUnavailableReason.RUNTIME_UNAVAILABLE_REASON_REMOTE_TIMEOUT =>
|
|
52
|
+
NomosUnavailableReason.remoteTimeout,
|
|
53
|
+
RuntimeUnavailableReason
|
|
54
|
+
.RUNTIME_UNAVAILABLE_REASON_LOCAL_REPLICA_NOT_READY =>
|
|
55
|
+
NomosUnavailableReason.localReplicaNotReady,
|
|
56
|
+
RuntimeUnavailableReason
|
|
57
|
+
.RUNTIME_UNAVAILABLE_REASON_CREDENTIAL_UNAVAILABLE =>
|
|
58
|
+
NomosUnavailableReason.credentialUnavailable,
|
|
59
|
+
RuntimeUnavailableReason
|
|
60
|
+
.RUNTIME_UNAVAILABLE_REASON_WORKSPACE_OPENING =>
|
|
61
|
+
NomosUnavailableReason.workspaceOpening,
|
|
62
|
+
_ => NomosUnavailableReason.unknown,
|
|
63
|
+
},
|
|
64
|
+
workspace: unavailable.workspace,
|
|
65
|
+
retryable: unavailable.retryable,
|
|
66
|
+
retryAfter: unavailable.hasRetryAfterMillis()
|
|
67
|
+
? Duration(milliseconds: unavailable.retryAfterMillis)
|
|
68
|
+
: null,
|
|
69
|
+
detail: unavailable.detail,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
@override
|
|
73
|
+
String toString() =>
|
|
74
|
+
'NomosUnavailable(${reason.name}, workspace: $workspace, retryable: $retryable'
|
|
75
|
+
'${detail.isEmpty ? '' : ', detail: $detail'})';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
enum NomosRefusalReason {
|
|
79
|
+
invalidCredential,
|
|
80
|
+
accessDenied,
|
|
81
|
+
placementPolicy,
|
|
82
|
+
sessionUnbound,
|
|
83
|
+
unknown,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
final class NomosRefused implements Exception {
|
|
87
|
+
const NomosRefused({
|
|
88
|
+
required this.reason,
|
|
89
|
+
required this.workspace,
|
|
90
|
+
required this.retryable,
|
|
91
|
+
this.detail = '',
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
final NomosRefusalReason reason;
|
|
95
|
+
final String workspace;
|
|
96
|
+
final bool retryable;
|
|
97
|
+
|
|
98
|
+
/// Diagnostic prose only; [reason] is the exhaustive control value.
|
|
99
|
+
final String detail;
|
|
100
|
+
|
|
101
|
+
@override
|
|
102
|
+
String toString() =>
|
|
103
|
+
'NomosRefused(${reason.name}, workspace: $workspace, retryable: $retryable)';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
enum NomosRuntimeFailureKind {
|
|
107
|
+
internal,
|
|
108
|
+
protocol,
|
|
109
|
+
integrity,
|
|
110
|
+
unsupported,
|
|
111
|
+
unknown,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
final class NomosRuntimeFailure implements Exception {
|
|
115
|
+
const NomosRuntimeFailure({
|
|
116
|
+
required this.kind,
|
|
117
|
+
required this.code,
|
|
118
|
+
required this.message,
|
|
119
|
+
required this.component,
|
|
120
|
+
this.workspace,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
final NomosRuntimeFailureKind kind;
|
|
124
|
+
final String code;
|
|
125
|
+
final String message;
|
|
126
|
+
final String component;
|
|
127
|
+
final String? workspace;
|
|
128
|
+
|
|
129
|
+
@override
|
|
130
|
+
String toString() =>
|
|
131
|
+
'NomosRuntimeFailure(${kind.name}, $code, component: $component'
|
|
132
|
+
'${message.isEmpty ? '' : ', message: $message'})';
|
|
133
|
+
}
|
|
@@ -95,15 +95,23 @@ class NomosReads {
|
|
|
95
95
|
|
|
96
96
|
/// The maintained-count seam (`client.count`). Reads ONE maintained counter
|
|
97
97
|
/// by `(countId, groupKey)` — O(1) PK lookup, never a scan. Threads in from the
|
|
98
|
-
/// app's host client
|
|
99
|
-
/// (no count seam provided — useful in tests that don't exercise counts).
|
|
98
|
+
/// app's host client. A missing callback is unsupported, not an empty group.
|
|
100
99
|
final Counter? counter;
|
|
101
100
|
|
|
102
101
|
/// The maintained-sum seam (`client.sum`). Reads ONE maintained sum by
|
|
103
102
|
/// `(sumId, groupKey)` — O(1) PK lookup, never a scan. Threads in from the
|
|
104
|
-
/// app's host client
|
|
103
|
+
/// app's host client. A missing callback is unsupported, not a zero sum.
|
|
105
104
|
final Summer? summer;
|
|
106
105
|
|
|
106
|
+
/// Snapshot read callbacks for declared extrema. Missing support refuses; it
|
|
107
|
+
/// must not masquerade as an empty group. Live clients use async Reception.
|
|
108
|
+
final int? Function(String id, String groupKey)? minimum;
|
|
109
|
+
final int? Function(String id, String groupKey)? maximum;
|
|
110
|
+
|
|
111
|
+
/// Ordered snapshot rows, already selected under installed law and authority.
|
|
112
|
+
/// No caller-supplied limit/order goes to this callback. Live clients use Reception.
|
|
113
|
+
final String Function(String id)? ordered;
|
|
114
|
+
|
|
107
115
|
/// The "projection changed" tick. When null, every accessor is a ONE-SHOT read
|
|
108
116
|
/// (a single current value, no further updates) — used in tests / pure snapshots.
|
|
109
117
|
final ReadTick? tick;
|
|
@@ -113,6 +121,9 @@ class NomosReads {
|
|
|
113
121
|
required this.queryById,
|
|
114
122
|
this.counter,
|
|
115
123
|
this.summer,
|
|
124
|
+
this.minimum,
|
|
125
|
+
this.maximum,
|
|
126
|
+
this.ordered,
|
|
116
127
|
this.tick,
|
|
117
128
|
});
|
|
118
129
|
|
|
@@ -131,7 +142,8 @@ class NomosReads {
|
|
|
131
142
|
) {
|
|
132
143
|
final decoded = jsonDecode(rowsJson);
|
|
133
144
|
if (decoded is! List) {
|
|
134
|
-
throw FormatException(
|
|
145
|
+
throw FormatException(
|
|
146
|
+
'read rows must be a JSON array, got ${decoded.runtimeType}');
|
|
135
147
|
}
|
|
136
148
|
final out = <T>[];
|
|
137
149
|
for (final row in decoded) {
|
|
@@ -192,27 +204,97 @@ class NomosReads {
|
|
|
192
204
|
|
|
193
205
|
// ---- maintained count/sum seams (Slice 1) ----
|
|
194
206
|
|
|
207
|
+
T? readFirst<T>(
|
|
208
|
+
String id, T Function(Map<String, dynamic>, String) fromJson) {
|
|
209
|
+
final rows = readTake(id, 1, fromJson);
|
|
210
|
+
return rows.isEmpty ? null : rows.single;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/// [limit] validates the generated result contract; it never selects rows locally.
|
|
214
|
+
List<T> readTake<T>(
|
|
215
|
+
String id, int limit, T Function(Map<String, dynamic>, String) fromJson) {
|
|
216
|
+
final read = ordered;
|
|
217
|
+
if (read == null)
|
|
218
|
+
throw UnsupportedError('Declared ordered reads are not bound');
|
|
219
|
+
if (limit < 1) throw ArgumentError.value(limit, 'limit');
|
|
220
|
+
final rows = jsonDecode(read(id));
|
|
221
|
+
if (rows is! List || rows.length > limit)
|
|
222
|
+
throw const FormatException(
|
|
223
|
+
'Ordered result violates its declared cardinality');
|
|
224
|
+
return rows.map((row) {
|
|
225
|
+
if (row is! Map<String, dynamic> ||
|
|
226
|
+
row['data'] is! Map<String, dynamic> ||
|
|
227
|
+
row['id'] is! String)
|
|
228
|
+
throw const FormatException('Ordered result contains a malformed row');
|
|
229
|
+
return fromJson(row['data'] as Map<String, dynamic>, row['id'] as String);
|
|
230
|
+
}).toList(growable: false);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
Stream<T?> watchFirst<T>(
|
|
234
|
+
String id, T Function(Map<String, dynamic>, String) fromJson) =>
|
|
235
|
+
_reactive(() => readFirst(id, fromJson));
|
|
236
|
+
|
|
237
|
+
Stream<List<T>> watchTake<T>(String id, int limit,
|
|
238
|
+
T Function(Map<String, dynamic>, String) fromJson) =>
|
|
239
|
+
_reactive(() => readTake(id, limit, fromJson));
|
|
240
|
+
|
|
195
241
|
/// Read the current maintained counter for [countId] + [groupKey] NOW. Returns 0
|
|
196
242
|
/// when no entry exists (either truly zero, or no group for this key). O(1) PK
|
|
197
|
-
/// lookup in the `counts` table — never a scan.
|
|
198
|
-
|
|
199
|
-
|
|
243
|
+
/// lookup in the `counts` table — never a scan. Missing support refuses.
|
|
244
|
+
int readCount(String countId, String groupKey) {
|
|
245
|
+
final read = counter;
|
|
246
|
+
if (read == null)
|
|
247
|
+
throw UnsupportedError('Declared count reads are not bound');
|
|
248
|
+
final count = read(countId, groupKey);
|
|
249
|
+
if (count < 0) throw StateError('Negative membership count');
|
|
250
|
+
return count;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// Existence uses the same maintained count; a zero-valued member still exists.
|
|
254
|
+
bool readExists(String id, String groupKey) => readCount(id, groupKey) > 0;
|
|
255
|
+
|
|
256
|
+
Stream<bool> watchExists(String id, String groupKey) =>
|
|
257
|
+
_reactive(() => readExists(id, groupKey));
|
|
200
258
|
|
|
201
259
|
/// Subscribe to the maintained counter for [countId] + [groupKey] as a
|
|
202
260
|
/// `Stream<int>`. Emits the current count immediately, then re-emits on every
|
|
203
|
-
/// [tick].
|
|
261
|
+
/// [tick]. Missing support refuses.
|
|
204
262
|
Stream<int> watchCount(String countId, String groupKey) =>
|
|
205
263
|
_reactive(() => readCount(countId, groupKey));
|
|
206
264
|
|
|
207
265
|
/// Read the current maintained sum for [sumId] + [groupKey] NOW. Returns 0 when
|
|
208
266
|
/// no entry exists (a group pruned at 0 is indistinguishable from absent —
|
|
209
267
|
/// documented Slice-1 caveat). O(1) PK lookup in the `sums` table — never a scan.
|
|
210
|
-
///
|
|
211
|
-
int readSum(String sumId, String groupKey)
|
|
268
|
+
/// Missing support refuses.
|
|
269
|
+
int readSum(String sumId, String groupKey) {
|
|
270
|
+
final read = summer;
|
|
271
|
+
if (read == null)
|
|
272
|
+
throw UnsupportedError('Declared sum reads are not bound');
|
|
273
|
+
return read(sumId, groupKey);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
int? readMin(String id, String groupKey) {
|
|
277
|
+
final read = minimum;
|
|
278
|
+
if (read == null)
|
|
279
|
+
throw UnsupportedError('Declared min reads are not bound');
|
|
280
|
+
return read(id, groupKey);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
int? readMax(String id, String groupKey) {
|
|
284
|
+
final read = maximum;
|
|
285
|
+
if (read == null)
|
|
286
|
+
throw UnsupportedError('Declared max reads are not bound');
|
|
287
|
+
return read(id, groupKey);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
Stream<int?> watchMin(String id, String groupKey) =>
|
|
291
|
+
_reactive(() => readMin(id, groupKey));
|
|
292
|
+
|
|
293
|
+
Stream<int?> watchMax(String id, String groupKey) =>
|
|
294
|
+
_reactive(() => readMax(id, groupKey));
|
|
212
295
|
|
|
213
296
|
/// Subscribe to the maintained sum for [sumId] + [groupKey] as a `Stream<int>`.
|
|
214
|
-
/// Emits the current total immediately, then re-emits on every [tick].
|
|
215
|
-
/// when [summer] is null.
|
|
297
|
+
/// Emits the current total immediately, then re-emits on every [tick].
|
|
216
298
|
Stream<int> watchSum(String sumId, String groupKey) =>
|
|
217
299
|
_reactive(() => readSum(sumId, groupKey));
|
|
218
300
|
|
|
@@ -281,21 +363,24 @@ int readInt(Map<String, dynamic> data, String aggregate, String field) {
|
|
|
281
363
|
final n = int.tryParse(v);
|
|
282
364
|
if (n != null) return n;
|
|
283
365
|
}
|
|
284
|
-
throw FormatException(
|
|
366
|
+
throw FormatException(
|
|
367
|
+
'$aggregate.$field: expected int, got ${v.runtimeType}');
|
|
285
368
|
}
|
|
286
369
|
|
|
287
370
|
/// Read a `set`-kind field as a `Set<String>` (the projection emits a JSON array).
|
|
288
371
|
Set<String> readSet(Map<String, dynamic> data, String aggregate, String field) {
|
|
289
372
|
final v = _required(data, aggregate, field);
|
|
290
373
|
if (v is List) return v.map((e) => e.toString()).toSet();
|
|
291
|
-
throw FormatException(
|
|
374
|
+
throw FormatException(
|
|
375
|
+
'$aggregate.$field: expected a set/array, got ${v.runtimeType}');
|
|
292
376
|
}
|
|
293
377
|
|
|
294
378
|
/// Read a `map`-kind field as a `Map<String, String>`. The projection may emit it
|
|
295
379
|
/// as a flat `{k:v}` object (the loss-less author path) OR — if it folded through a
|
|
296
380
|
/// kernel `Value::Map` — as the structural `{"Map":{k:{value:{Str:v},…}}}` serde
|
|
297
381
|
/// form; both are reduced to `{k:v}` so the aggregate's typed map is stable.
|
|
298
|
-
Map<String, String> readStrMap(
|
|
382
|
+
Map<String, String> readStrMap(
|
|
383
|
+
Map<String, dynamic> data, String aggregate, String field) {
|
|
299
384
|
final v = _required(data, aggregate, field);
|
|
300
385
|
if (v is Map) {
|
|
301
386
|
// Structural kernel `Value::Map` form: `{"Map": {k: {value:{Str:..},stamp:..}}}`.
|
|
@@ -308,7 +393,8 @@ Map<String, String> readStrMap(Map<String, dynamic> data, String aggregate, Stri
|
|
|
308
393
|
return out;
|
|
309
394
|
}
|
|
310
395
|
}
|
|
311
|
-
throw FormatException(
|
|
396
|
+
throw FormatException(
|
|
397
|
+
'$aggregate.$field: expected a map/object, got ${v.runtimeType}');
|
|
312
398
|
}
|
|
313
399
|
|
|
314
400
|
/// Reduce one map entry value to a String, peeling the kernel `{value:{Str:..}}`
|
|
@@ -317,8 +403,10 @@ String _flattenMapValue(Object? val) {
|
|
|
317
403
|
if (val is String) return val;
|
|
318
404
|
if (val is Map) {
|
|
319
405
|
final value = val['value'];
|
|
320
|
-
if (value is Map && value.containsKey('Str'))
|
|
321
|
-
|
|
406
|
+
if (value is Map && value.containsKey('Str'))
|
|
407
|
+
return value['Str'].toString();
|
|
408
|
+
if (value is Map && value.containsKey('Int'))
|
|
409
|
+
return value['Int'].toString();
|
|
322
410
|
}
|
|
323
411
|
return val.toString();
|
|
324
412
|
}
|
|
@@ -446,7 +534,8 @@ int? readIntOrNull(Map<String, dynamic> data, String aggregate, String field) {
|
|
|
446
534
|
final n = int.tryParse(v);
|
|
447
535
|
if (n != null) return n;
|
|
448
536
|
}
|
|
449
|
-
throw FormatException(
|
|
537
|
+
throw FormatException(
|
|
538
|
+
'$aggregate.$field: expected int, got ${v.runtimeType}');
|
|
450
539
|
}
|
|
451
540
|
|
|
452
541
|
/// Read an OPTIONAL enum-kind field's wire string, or `null` when absent (a present
|
|
@@ -473,17 +562,20 @@ String? readJsonStrOrNull(Map<String, dynamic> data, String field) {
|
|
|
473
562
|
/// Read a `set`-kind field as a `Set<String>`, defaulting to EMPTY when the flat
|
|
474
563
|
/// `data` lacks it (a freshly-created aggregate need not have folded the set). A
|
|
475
564
|
/// PRESENT-but-non-array value still throws (parity with [readSet]).
|
|
476
|
-
Set<String> readSetOrEmpty(
|
|
565
|
+
Set<String> readSetOrEmpty(
|
|
566
|
+
Map<String, dynamic> data, String aggregate, String field) {
|
|
477
567
|
final v = data[field];
|
|
478
568
|
if (v == null) return <String>{};
|
|
479
569
|
if (v is List) return v.map((e) => e.toString()).toSet();
|
|
480
|
-
throw FormatException(
|
|
570
|
+
throw FormatException(
|
|
571
|
+
'$aggregate.$field: expected a set/array, got ${v.runtimeType}');
|
|
481
572
|
}
|
|
482
573
|
|
|
483
574
|
/// Read a `map`-kind field as a `Map<String, String>`, defaulting to EMPTY when
|
|
484
575
|
/// absent. A PRESENT value is reduced exactly as [readStrMap] (handling both the flat
|
|
485
576
|
/// `{k:v}` form and the structural kernel `Value::Map` form).
|
|
486
|
-
Map<String, String> readStrMapOrEmpty(
|
|
577
|
+
Map<String, String> readStrMapOrEmpty(
|
|
578
|
+
Map<String, dynamic> data, String aggregate, String field) {
|
|
487
579
|
final v = data[field];
|
|
488
580
|
if (v == null) return <String, String>{};
|
|
489
581
|
return readStrMap(data, aggregate, field);
|
|
@@ -515,7 +607,8 @@ Map<String, Object?> readJsonMapOrEmpty(
|
|
|
515
607
|
return out;
|
|
516
608
|
}
|
|
517
609
|
}
|
|
518
|
-
throw FormatException(
|
|
610
|
+
throw FormatException(
|
|
611
|
+
'$aggregate.$field: expected a map/object, got ${v.runtimeType}');
|
|
519
612
|
}
|
|
520
613
|
|
|
521
614
|
/// Decode one JSON-valued map entry to its object: peel the kernel
|
package/dart_types/pubspec.yaml
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
Pure kernel wire/data types for Nomos Dart frontends — no transport, no bridge,
|
|
10
10
|
no runtime. Typed protobuf and USDA boundary values plus the offer codec,
|
|
11
11
|
reactive read engine, schema validation, and data-only error/trace types.
|
|
12
|
-
version: 0.
|
|
12
|
+
version: 0.11.2
|
|
13
13
|
|
|
14
14
|
environment:
|
|
15
15
|
sdk: ^3.5.0
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import 'package:nomos_types/src/subscriptions.dart';
|
|
2
|
+
import 'package:test/test.dart';
|
|
3
|
+
|
|
4
|
+
void main() {
|
|
5
|
+
test('snapshot membership is a count, not a sum or missing callback',
|
|
6
|
+
() async {
|
|
7
|
+
final reads = NomosReads(
|
|
8
|
+
query: (_, __) => '[]',
|
|
9
|
+
queryById: (_) => '[]',
|
|
10
|
+
counter: (_, group) => group == 'empty' ? 0 : 2,
|
|
11
|
+
summer: (_, __) => 0);
|
|
12
|
+
expect(reads.readExists('hasMembers', 'empty'), false);
|
|
13
|
+
expect(await reads.watchExists('hasMembers', 'filled').first, true);
|
|
14
|
+
expect(reads.readSum('total', 'filled'), 0);
|
|
15
|
+
final unbound = NomosReads(query: (_, __) => '[]', queryById: (_) => '[]');
|
|
16
|
+
expect(() => unbound.readExists('hasMembers', ''), throwsUnsupportedError);
|
|
17
|
+
expect(() => unbound.readCount('count', ''), throwsUnsupportedError);
|
|
18
|
+
expect(() => unbound.readSum('total', ''), throwsUnsupportedError);
|
|
19
|
+
final invalid = NomosReads(
|
|
20
|
+
query: (_, __) => '[]', queryById: (_) => '[]', counter: (_, __) => -1);
|
|
21
|
+
expect(() => invalid.readExists('hasMembers', ''), throwsStateError);
|
|
22
|
+
});
|
|
23
|
+
test(
|
|
24
|
+
'snapshot extrema preserve null and zero without inventing missing support',
|
|
25
|
+
() async {
|
|
26
|
+
final reads = NomosReads(
|
|
27
|
+
query: (_, __) => '[]',
|
|
28
|
+
queryById: (_) => '[]',
|
|
29
|
+
minimum: (_, group) => group == 'empty' ? null : 0,
|
|
30
|
+
maximum: (_, group) => group == 'empty' ? null : 7);
|
|
31
|
+
expect(reads.readMin('minimum', 'empty'), isNull);
|
|
32
|
+
expect(reads.readMin('minimum', 'filled'), 0);
|
|
33
|
+
expect(await reads.watchMin('minimum', 'filled').first, 0);
|
|
34
|
+
expect(await reads.watchMax('maximum', 'empty').first, isNull);
|
|
35
|
+
expect(reads.readMax('maximum', 'filled'), 7);
|
|
36
|
+
final unbound = NomosReads(query: (_, __) => '[]', queryById: (_) => '[]');
|
|
37
|
+
expect(() => unbound.readMin('minimum', ''), throwsUnsupportedError);
|
|
38
|
+
expect(() => unbound.readMax('maximum', ''), throwsUnsupportedError);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import 'dart:typed_data';
|
|
2
|
+
import 'package:nomos_types/src/foreign_ref.dart';
|
|
3
|
+
import 'package:test/test.dart';
|
|
4
|
+
|
|
5
|
+
class Reader implements NomosForeignReader {
|
|
6
|
+
Reader(this.read);
|
|
7
|
+
final Future<Uint8List> Function() read;
|
|
8
|
+
@override
|
|
9
|
+
NomosForeignWorkspaceReader foreignWorkspace(String workspace) =>
|
|
10
|
+
WorkspaceReader(read);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class WorkspaceReader extends NomosForeignWorkspaceReader {
|
|
14
|
+
WorkspaceReader(this.read);
|
|
15
|
+
final Future<Uint8List> Function() read;
|
|
16
|
+
@override
|
|
17
|
+
Future<Uint8List> queryById(String aggregateType, String id) => read();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void main() {
|
|
21
|
+
final ref = NmsInternalForeignRefs.create<String>(
|
|
22
|
+
id: 'definition-1',
|
|
23
|
+
workspace: 'field-library',
|
|
24
|
+
type: 'FieldDefinition',
|
|
25
|
+
fromUsda: (bytes, _, __) => bytes.isEmpty ? null : 'found');
|
|
26
|
+
test('only a successful absent result resolves to null', () async {
|
|
27
|
+
expect(
|
|
28
|
+
await NmsInternalForeignRefs.resolve(
|
|
29
|
+
ref, Reader(() async => Uint8List(0))),
|
|
30
|
+
isNull);
|
|
31
|
+
expect(
|
|
32
|
+
await NmsInternalForeignRefs.resolve(
|
|
33
|
+
ref, Reader(() async => Uint8List(1))),
|
|
34
|
+
'found');
|
|
35
|
+
});
|
|
36
|
+
test(
|
|
37
|
+
'denial and offline transport remain failures with payload-free provenance',
|
|
38
|
+
() async {
|
|
39
|
+
for (final example in [
|
|
40
|
+
(
|
|
41
|
+
StateError('UNAUTHORIZED sensitive-value'),
|
|
42
|
+
ForeignReadFailureKind.denied
|
|
43
|
+
),
|
|
44
|
+
(
|
|
45
|
+
StateError('offline sensitive-value'),
|
|
46
|
+
ForeignReadFailureKind.unreachable
|
|
47
|
+
),
|
|
48
|
+
]) {
|
|
49
|
+
try {
|
|
50
|
+
await NmsInternalForeignRefs.resolve(
|
|
51
|
+
ref, Reader(() async => throw example.$1));
|
|
52
|
+
fail('a failed read must not become a missing record');
|
|
53
|
+
} on ForeignReadFailure catch (failure) {
|
|
54
|
+
expect(failure.kind, example.$2);
|
|
55
|
+
expect(failure.workspace, 'field-library');
|
|
56
|
+
expect(failure.id, 'definition-1');
|
|
57
|
+
expect(failure.toString(), isNot(contains('sensitive-value')));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
test('a missing generated nominal codec is a failure, never missing data',
|
|
62
|
+
() async {
|
|
63
|
+
final locator = NmsInternalForeignRefs.create<String>(
|
|
64
|
+
id: 'definition-1',
|
|
65
|
+
workspace: 'field-library',
|
|
66
|
+
type: 'FieldDefinition');
|
|
67
|
+
expect(
|
|
68
|
+
() => NmsInternalForeignRefs.resolve(
|
|
69
|
+
locator, Reader(() async => Uint8List(1))),
|
|
70
|
+
throwsA(isA<ForeignReadFailure>().having(
|
|
71
|
+
(failure) => failure.sourceErrorType,
|
|
72
|
+
'source type',
|
|
73
|
+
'StateError')));
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import 'package:nomos_types/src/nomos_ref.dart';
|
|
2
|
+
import 'package:test/test.dart';
|
|
3
|
+
|
|
4
|
+
class Drawing {}
|
|
5
|
+
|
|
6
|
+
void main() {
|
|
7
|
+
test(
|
|
8
|
+
'address round trip preserves identity, including literal percent escapes',
|
|
9
|
+
() {
|
|
10
|
+
for (final id in [
|
|
11
|
+
'plain',
|
|
12
|
+
'floor/one',
|
|
13
|
+
'50% complete',
|
|
14
|
+
'%2F',
|
|
15
|
+
'a?#b',
|
|
16
|
+
'Étage 1'
|
|
17
|
+
]) {
|
|
18
|
+
final ref = NmsInternalNomosRefs.create<Drawing>(
|
|
19
|
+
workspace: 'estate-test', type: 'estate.SiteDrawing', id: id);
|
|
20
|
+
final restored = NmsInternalNomosRefs.fromUri<Drawing>(ref.address);
|
|
21
|
+
expect(restored, ref, reason: id);
|
|
22
|
+
expect(restored.id, id);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import 'dart:convert';
|
|
2
|
+
import 'package:nomos_types/src/subscriptions.dart';
|
|
3
|
+
import 'package:test/test.dart';
|
|
4
|
+
|
|
5
|
+
void main() {
|
|
6
|
+
String decode(Map<String, dynamic> data, String id) => id;
|
|
7
|
+
test(
|
|
8
|
+
'ordered snapshots preserve selection order and reject invalid cardinality',
|
|
9
|
+
() async {
|
|
10
|
+
final rows = <Object>[];
|
|
11
|
+
final calls = <String>[];
|
|
12
|
+
final reads = NomosReads(
|
|
13
|
+
query: (_, __) => throw StateError('not a keyed query'),
|
|
14
|
+
queryById: (_) => throw StateError('not a primary-key query'),
|
|
15
|
+
ordered: (id) {
|
|
16
|
+
calls.add(id);
|
|
17
|
+
return jsonEncode(rows);
|
|
18
|
+
});
|
|
19
|
+
expect(reads.readFirst('first', decode), isNull);
|
|
20
|
+
expect(await reads.watchTake('top', 2, decode).first, isEmpty);
|
|
21
|
+
rows.add({'id': 'z', 'data': {}});
|
|
22
|
+
expect(await reads.watchFirst('first', decode).first, 'z');
|
|
23
|
+
rows.add({'id': 'a', 'data': {}});
|
|
24
|
+
expect(reads.readTake('top', 2, decode), ['z', 'a']);
|
|
25
|
+
expect(() => reads.readFirst('first', decode), throwsFormatException);
|
|
26
|
+
rows
|
|
27
|
+
..clear()
|
|
28
|
+
..add({'id': 123, 'data': {}});
|
|
29
|
+
expect(() => reads.readTake('top', 2, decode), throwsFormatException);
|
|
30
|
+
expect(calls, everyElement(anyOf('first', 'top')));
|
|
31
|
+
final missing = NomosReads(query: (_, __) => '[]', queryById: (_) => '[]');
|
|
32
|
+
expect(() => missing.readFirst('first', decode), throwsUnsupportedError);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Compiler-only, read-only invocation of the kernel's contract checker.
|
|
2
|
+
// No peer, workspace, credentials, offers or second execution lifecycle.
|
|
3
|
+
import { WASI } from 'node:wasi';
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const input = process.argv[2];
|
|
9
|
+
const descriptors = process.argv[3];
|
|
10
|
+
if (!input) throw new Error('operation contract checker needs a compiled law package');
|
|
11
|
+
const artifact = new URL('./assets/operation-contract.wasm', import.meta.url);
|
|
12
|
+
const wasi = new WASI({
|
|
13
|
+
version: 'preview1',
|
|
14
|
+
args: ['operation-contract', 'validate-operation-contracts', `/input/${path.basename(input)}`,
|
|
15
|
+
...(descriptors === undefined ? [] : [`/descriptors/${path.basename(descriptors)}`])],
|
|
16
|
+
env: {}, preopens: { '/input': path.dirname(path.resolve(input)),
|
|
17
|
+
...(descriptors === undefined ? {} : { '/descriptors': path.dirname(path.resolve(descriptors)) }) }, returnOnExit: true,
|
|
18
|
+
});
|
|
19
|
+
let bytes;
|
|
20
|
+
try { bytes = readFileSync(artifact); }
|
|
21
|
+
catch { throw new Error(`compiler package is incomplete: missing ${fileURLToPath(artifact)}; reinstall @githolon/dsl`); }
|
|
22
|
+
const module = await WebAssembly.compile(bytes);
|
|
23
|
+
const instance = await WebAssembly.instantiate(module, { wasi_snapshot_preview1: wasi.wasiImport });
|
|
24
|
+
process.exitCode = wasi.start(instance);
|