@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
|
@@ -7,58 +7,103 @@ import 'package:nomos_types/nomos_kernel_protocol.dart' as protocol;
|
|
|
7
7
|
import 'package:test/test.dart';
|
|
8
8
|
|
|
9
9
|
final class _ProofTransport
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
with NmsPlatformCredentialProviderHost
|
|
11
|
+
implements
|
|
12
|
+
PeerOfficeConnection,
|
|
13
|
+
NomosKernelCallTransport,
|
|
14
|
+
NomosRuntimeV2EventTransport {
|
|
15
|
+
final _runtimeEvents = StreamController<protocol.RuntimeEvent>.broadcast();
|
|
12
16
|
protocol.CallRequest? lastCall;
|
|
17
|
+
protocol.CredentialUse? lastCredentialUse;
|
|
13
18
|
var providerToken = protocol.ProviderTokenVerificationStatus
|
|
14
19
|
.PROVIDER_TOKEN_VERIFICATION_STATUS_NO_MATCHING_KEY;
|
|
15
20
|
var enrolledDevice = true;
|
|
16
21
|
var resolvedPrincipal = 'user:jack';
|
|
17
22
|
var syncCalls = 0;
|
|
23
|
+
final syncSessions = <String>[];
|
|
24
|
+
var offerCalls = 0;
|
|
25
|
+
var expireNextSessionOffer = false;
|
|
26
|
+
final refreshedTokens = <String>[];
|
|
27
|
+
final authenticationRequests = <protocol.AwaitAuthenticationRequest>[];
|
|
28
|
+
protocol.AuthenticationReadiness? authenticationResult;
|
|
18
29
|
|
|
19
30
|
_ProofTransport() {
|
|
20
31
|
scheduleMicrotask(
|
|
21
|
-
() =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
() => _runtimeEvents.add(
|
|
33
|
+
protocol.RuntimeEvent(
|
|
34
|
+
ready: protocol.RuntimeReady(runtimeVersion: 'unbundled-dev'),
|
|
35
|
+
),
|
|
36
|
+
),
|
|
26
37
|
);
|
|
27
38
|
}
|
|
28
39
|
|
|
29
40
|
@override
|
|
30
|
-
Stream<
|
|
41
|
+
Stream<protocol.RuntimeEvent> get runtimeEvents => _runtimeEvents.stream;
|
|
31
42
|
|
|
43
|
+
void pushRuntime(protocol.RuntimeEvent event) => _runtimeEvents.add(event);
|
|
44
|
+
|
|
45
|
+
int _requests = 0;
|
|
32
46
|
@override
|
|
33
|
-
|
|
34
|
-
if (message['op'] != 'connect') {
|
|
35
|
-
throw UnsupportedError('unexpected legacy operation ${message['op']}');
|
|
36
|
-
}
|
|
37
|
-
final id = message['id']! as int;
|
|
38
|
-
final args = (message['args']! as Map).cast<String, Object?>();
|
|
39
|
-
scheduleMicrotask(
|
|
40
|
-
() => _messages.add({
|
|
41
|
-
'v': kWebviewBridgeVersion,
|
|
42
|
-
'id': id,
|
|
43
|
-
'ok': true,
|
|
44
|
-
'result': {'workspace': args['workspace']},
|
|
45
|
-
}),
|
|
46
|
-
);
|
|
47
|
-
}
|
|
47
|
+
int nextRuntimeRequestId() => ++_requests;
|
|
48
48
|
|
|
49
49
|
@override
|
|
50
50
|
Future<protocol.RuntimeResponse> invokeRuntime(
|
|
51
51
|
protocol.RuntimeRequest request,
|
|
52
52
|
) async {
|
|
53
|
+
if (request.hasAwaitAuthentication()) {
|
|
54
|
+
authenticationRequests.add(request.awaitAuthentication.deepCopy());
|
|
55
|
+
return protocol.RuntimeResponse(
|
|
56
|
+
protocolVersion: 2,
|
|
57
|
+
requestId: request.requestId,
|
|
58
|
+
authenticationReadiness: authenticationResult ??
|
|
59
|
+
protocol.AuthenticationReadiness(
|
|
60
|
+
outcome: protocol.AuthenticationReadinessOutcome
|
|
61
|
+
.AUTHENTICATION_READINESS_OUTCOME_READY,
|
|
62
|
+
posture: protocol.AuthenticationPostureResponse(
|
|
63
|
+
providerToken: protocol.ProviderTokenVerificationStatus
|
|
64
|
+
.PROVIDER_TOKEN_VERIFICATION_STATUS_VALID,
|
|
65
|
+
enrolledDevice: true,
|
|
66
|
+
resolvedPrincipal: 'user:jack',
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (request.hasBindSession()) {
|
|
72
|
+
return protocol.RuntimeResponse(
|
|
73
|
+
protocolVersion: 2,
|
|
74
|
+
requestId: request.requestId,
|
|
75
|
+
sessionBound: protocol.SessionBound(
|
|
76
|
+
workspace: request.bindSession.workspace,
|
|
77
|
+
session: request.bindSession.hasSession()
|
|
78
|
+
? request.bindSession.session
|
|
79
|
+
: request.bindSession.workspace,
|
|
80
|
+
credentialCapability: request.bindSession.hasSession()
|
|
81
|
+
? request.bindSession.session
|
|
82
|
+
: request.bindSession.workspace,
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
53
86
|
if (request.hasSyncWorkspace()) {
|
|
54
87
|
syncCalls += 1;
|
|
88
|
+
syncSessions.add(request.syncWorkspace.workspace);
|
|
55
89
|
providerToken = protocol.ProviderTokenVerificationStatus
|
|
56
90
|
.PROVIDER_TOKEN_VERIFICATION_STATUS_VALID;
|
|
57
91
|
return protocol.RuntimeResponse(
|
|
58
92
|
protocolVersion: 2,
|
|
59
93
|
requestId: request.requestId,
|
|
60
94
|
syncWorkspace: protocol.SyncWorkspaceResponse(
|
|
61
|
-
workspace: request.syncWorkspace.
|
|
95
|
+
workspace: request.syncWorkspace.workspace,
|
|
96
|
+
),
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (request.hasRefreshCredentials()) {
|
|
100
|
+
refreshedTokens.add(utf8.decode(request.refreshCredentials.authToken));
|
|
101
|
+
return protocol.RuntimeResponse(
|
|
102
|
+
protocolVersion: 2,
|
|
103
|
+
requestId: request.requestId,
|
|
104
|
+
credentialsRefreshed: protocol.CredentialsRefreshed(
|
|
105
|
+
session: request.refreshCredentials.session,
|
|
106
|
+
hasAuthToken: request.refreshCredentials.authToken.isNotEmpty,
|
|
62
107
|
),
|
|
63
108
|
);
|
|
64
109
|
}
|
|
@@ -73,8 +118,11 @@ final class _ProofTransport
|
|
|
73
118
|
Future<protocol.CallResponse> callKernel({
|
|
74
119
|
required String session,
|
|
75
120
|
required protocol.CallRequest request,
|
|
121
|
+
protocol.CredentialUse credentialUse =
|
|
122
|
+
protocol.CredentialUse.CREDENTIAL_USE_UNSPECIFIED,
|
|
76
123
|
}) async {
|
|
77
124
|
lastCall = request.deepCopy();
|
|
125
|
+
lastCredentialUse = credentialUse;
|
|
78
126
|
if (request.hasQuery() && request.query.hasAuthenticationPosture()) {
|
|
79
127
|
return protocol.CallResponse(
|
|
80
128
|
protocolVersion: 1,
|
|
@@ -88,6 +136,21 @@ final class _ProofTransport
|
|
|
88
136
|
),
|
|
89
137
|
);
|
|
90
138
|
}
|
|
139
|
+
if (request.hasOffer()) {
|
|
140
|
+
offerCalls += 1;
|
|
141
|
+
if (expireNextSessionOffer &&
|
|
142
|
+
credentialUse == protocol.CredentialUse.CREDENTIAL_USE_SESSION) {
|
|
143
|
+
expireNextSessionOffer = false;
|
|
144
|
+
return protocol.CallResponse(
|
|
145
|
+
protocolVersion: 1,
|
|
146
|
+
requestId: request.requestId,
|
|
147
|
+
failure: protocol.Failure(
|
|
148
|
+
code: 'nomos.auth.token_expired',
|
|
149
|
+
message: 'auth: token verification failed (Expired)',
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
91
154
|
return protocol.CallResponse(
|
|
92
155
|
protocolVersion: 1,
|
|
93
156
|
requestId: request.requestId,
|
|
@@ -102,80 +165,231 @@ final class _ProofTransport
|
|
|
102
165
|
}
|
|
103
166
|
|
|
104
167
|
void main() {
|
|
168
|
+
test('Reception surfaces a terminal expiry without owning refresh or replay',
|
|
169
|
+
() async {
|
|
170
|
+
final transport = _ProofTransport()..expireNextSessionOffer = true;
|
|
171
|
+
final bridge = DartReception(transport);
|
|
172
|
+
addTearDown(bridge.dispose);
|
|
173
|
+
await bridge.ready;
|
|
174
|
+
final interaction = await bridge.bindSession(
|
|
175
|
+
workspace: 'home',
|
|
176
|
+
session: 'home',
|
|
177
|
+
);
|
|
178
|
+
await bridge.session('home').refreshCredentials(
|
|
179
|
+
authToken: 'expired-token',
|
|
180
|
+
);
|
|
181
|
+
var refreshes = 0;
|
|
182
|
+
bridge.nomosInternalRegisterCredentialProvider(
|
|
183
|
+
interaction: interaction,
|
|
184
|
+
cloud: 'https://nomos.example',
|
|
185
|
+
signIn: ({deviceChallenge}) async {
|
|
186
|
+
refreshes += 1;
|
|
187
|
+
return 'fresh-token';
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
await expectLater(
|
|
192
|
+
bridge.session('home').offerGeneratedCallOutcome(
|
|
193
|
+
call: NmsInternalGeneratedCalls.create(
|
|
194
|
+
domain: 'estate',
|
|
195
|
+
directive: 'seedComplianceDisciplines',
|
|
196
|
+
protobufType:
|
|
197
|
+
'type.nomos.dev/nomos.operation.v1.Payload_seed_compliance_test',
|
|
198
|
+
protobufPayload: Uint8List.fromList([1]),
|
|
199
|
+
),
|
|
200
|
+
),
|
|
201
|
+
throwsA(
|
|
202
|
+
isA<AuthError>()
|
|
203
|
+
.having((error) => error.code, 'code', 'nomos.auth.token_expired')
|
|
204
|
+
.having((error) => error.workspace, 'workspace', 'home')
|
|
205
|
+
.having(
|
|
206
|
+
(error) => error.operation,
|
|
207
|
+
'operation',
|
|
208
|
+
'seedComplianceDisciplines',
|
|
209
|
+
),
|
|
210
|
+
));
|
|
211
|
+
|
|
212
|
+
// The real shared-runtime retry is exercised through its binary frame
|
|
213
|
+
// driver in credential_recovery_runtime.test.ts. A terminal refusal here
|
|
214
|
+
// must never start a second, language-specific retry procedure.
|
|
215
|
+
expect(transport.offerCalls, 1);
|
|
216
|
+
expect(refreshes, 0);
|
|
217
|
+
// The one token installation above belongs to test arrangement. The
|
|
218
|
+
// terminal refusal must not cause Reception to refresh or replay it.
|
|
219
|
+
expect(transport.refreshedTokens, ['expired-token']);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('diagnostics are an observation-only view of bound sessions', () async {
|
|
223
|
+
final transport = _ProofTransport();
|
|
224
|
+
final reception = DartReception(transport);
|
|
225
|
+
addTearDown(reception.dispose);
|
|
226
|
+
await reception.ready;
|
|
227
|
+
await reception.bindSession(
|
|
228
|
+
workspace: 'workspace-home', session: 'session-home');
|
|
229
|
+
await reception.bindSession(
|
|
230
|
+
workspace: 'workspace-estate', session: 'session-estate');
|
|
231
|
+
final diagnostics = reception.syncDiagnostics;
|
|
232
|
+
expect(diagnostics.read().map((row) => row.workspace),
|
|
233
|
+
['workspace-home', 'workspace-estate']);
|
|
234
|
+
expect(transport.syncCalls, 0);
|
|
235
|
+
final changed = diagnostics.changes.first;
|
|
236
|
+
transport.pushRuntime(protocol.RuntimeEvent(
|
|
237
|
+
session: 'session-estate',
|
|
238
|
+
syncCompleted: protocol.SyncCompleted(
|
|
239
|
+
result: protocol.SyncWorkspaceResponse(
|
|
240
|
+
remoteRefusal: protocol.SyncRefusal(reason: 'Exact refusal'),
|
|
241
|
+
)),
|
|
242
|
+
));
|
|
243
|
+
await changed;
|
|
244
|
+
expect(diagnostics.read().last.status.lastError, 'Exact refusal');
|
|
245
|
+
expect(
|
|
246
|
+
identical(diagnostics.read().last.status,
|
|
247
|
+
reception.session('session-estate').currentStatus),
|
|
248
|
+
isTrue);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test('a successful typed sync clears locally tracked write debt', () async {
|
|
252
|
+
final transport = _ProofTransport();
|
|
253
|
+
final bridge = DartReception(transport);
|
|
254
|
+
addTearDown(bridge.dispose);
|
|
255
|
+
await bridge.ready;
|
|
256
|
+
await bridge.bindSession(workspace: 'home', session: 'home');
|
|
257
|
+
|
|
258
|
+
final outcome = await bridge.session('home').offerGeneratedCallOutcome(
|
|
259
|
+
call: NmsInternalGeneratedCalls.create(
|
|
260
|
+
domain: 'notes',
|
|
261
|
+
directive: 'writeNote',
|
|
262
|
+
protobufType:
|
|
263
|
+
'type.nomos.dev/nomos.operation.v1.Payload_write_note_test',
|
|
264
|
+
protobufPayload: Uint8List.fromList([0x0a, 0x01, 0x01]),
|
|
265
|
+
),
|
|
266
|
+
);
|
|
267
|
+
expect(bridge.session('home').currentStatus.phase, SyncPhase.syncing);
|
|
268
|
+
expect(bridge.session('home').currentStatus.ahead, isNull);
|
|
269
|
+
|
|
270
|
+
transport.pushRuntime(
|
|
271
|
+
protocol.RuntimeEvent(
|
|
272
|
+
session: 'home',
|
|
273
|
+
syncCompleted: protocol.SyncCompleted(
|
|
274
|
+
reason: 'write',
|
|
275
|
+
result: protocol.SyncWorkspaceResponse(
|
|
276
|
+
admittedIntentIds: [outcome.intentId],
|
|
277
|
+
convergedIntentIds: [outcome.intentId],
|
|
278
|
+
currentHead: 'confirmed-head',
|
|
279
|
+
stillAhead: false,
|
|
280
|
+
),
|
|
281
|
+
),
|
|
282
|
+
),
|
|
283
|
+
);
|
|
284
|
+
await outcome.receipt.converged.timeout(const Duration(seconds: 1));
|
|
285
|
+
await Future<void>.delayed(Duration.zero);
|
|
286
|
+
|
|
287
|
+
expect(bridge.session('home').currentStatus.phase, SyncPhase.idle);
|
|
288
|
+
expect(bridge.session('home').currentStatus.ahead, 0);
|
|
289
|
+
});
|
|
290
|
+
|
|
105
291
|
test('law-selected enrolled-device proof withholds the provider token',
|
|
106
292
|
() async {
|
|
107
293
|
final transport = _ProofTransport();
|
|
108
|
-
final bridge =
|
|
294
|
+
final bridge = DartReception(transport);
|
|
109
295
|
addTearDown(bridge.dispose);
|
|
110
296
|
final secret = base64Encode(List<int>.filled(32, 7));
|
|
111
297
|
await bridge.ready;
|
|
112
|
-
await bridge.
|
|
298
|
+
await bridge.bindSession(
|
|
113
299
|
workspace: 'home',
|
|
114
300
|
session: 'home',
|
|
115
|
-
authorSecret: secret,
|
|
116
|
-
authToken: 'stale.provider.token',
|
|
117
301
|
);
|
|
302
|
+
await bridge.session('home').refreshCredentials(
|
|
303
|
+
authorSecret: secret,
|
|
304
|
+
authToken: 'stale.provider.token',
|
|
305
|
+
);
|
|
118
306
|
final call = NmsInternalGeneratedCalls.create(
|
|
119
307
|
domain: 'identity',
|
|
120
308
|
directive: 'recoverProvider',
|
|
121
|
-
|
|
309
|
+
protobufType:
|
|
310
|
+
'type.nomos.dev/nomos.operation.v1.Payload_recover_provider_test',
|
|
311
|
+
protobufPayload: Uint8List.fromList([1]),
|
|
122
312
|
);
|
|
123
313
|
|
|
124
|
-
await bridge.session('home').
|
|
125
|
-
expect(
|
|
126
|
-
|
|
314
|
+
await bridge.session('home').offerGeneratedCallOutcome(call: call);
|
|
315
|
+
expect(
|
|
316
|
+
transport.lastCredentialUse,
|
|
317
|
+
protocol.CredentialUse.CREDENTIAL_USE_SESSION,
|
|
318
|
+
);
|
|
319
|
+
expect(transport.lastCall!.offer.authoring.authToken, isEmpty);
|
|
320
|
+
expect(transport.lastCall!.offer.authoring.authorSecret, isEmpty);
|
|
127
321
|
|
|
128
|
-
await bridge.session('home').
|
|
322
|
+
await bridge.session('home').offerGeneratedCallOutcome(
|
|
129
323
|
call: call,
|
|
130
324
|
authenticationProof: NomosOfferAuthenticationProof.enrolledDevice,
|
|
131
325
|
);
|
|
326
|
+
expect(
|
|
327
|
+
transport.lastCredentialUse,
|
|
328
|
+
protocol.CredentialUse.CREDENTIAL_USE_ENROLLED_DEVICE,
|
|
329
|
+
);
|
|
132
330
|
expect(transport.lastCall!.offer.authoring.authToken, isEmpty);
|
|
133
|
-
expect(transport.lastCall!.offer.authoring.authorSecret,
|
|
331
|
+
expect(transport.lastCall!.offer.authoring.authorSecret, isEmpty);
|
|
134
332
|
});
|
|
135
333
|
|
|
136
|
-
test('enrolled-device proof
|
|
334
|
+
test('enrolled-device proof is selected without copying its key through Dart',
|
|
137
335
|
() async {
|
|
138
336
|
final transport = _ProofTransport();
|
|
139
|
-
final bridge =
|
|
337
|
+
final bridge = DartReception(transport);
|
|
140
338
|
addTearDown(bridge.dispose);
|
|
141
339
|
await bridge.ready;
|
|
142
|
-
await bridge.
|
|
340
|
+
await bridge.bindSession(
|
|
143
341
|
workspace: 'home',
|
|
144
342
|
session: 'home',
|
|
145
|
-
authToken: 'stale.provider.token',
|
|
146
343
|
);
|
|
344
|
+
await bridge.session('home').refreshCredentials(
|
|
345
|
+
authToken: 'stale.provider.token',
|
|
346
|
+
);
|
|
147
347
|
final call = NmsInternalGeneratedCalls.create(
|
|
148
348
|
domain: 'identity',
|
|
149
349
|
directive: 'recoverProvider',
|
|
150
|
-
|
|
350
|
+
protobufType:
|
|
351
|
+
'type.nomos.dev/nomos.operation.v1.Payload_recover_provider_test',
|
|
352
|
+
protobufPayload: Uint8List.fromList([1]),
|
|
151
353
|
);
|
|
152
354
|
|
|
153
|
-
await
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
355
|
+
await bridge.session('home').offerGeneratedCallOutcome(
|
|
356
|
+
call: call,
|
|
357
|
+
authenticationProof: NomosOfferAuthenticationProof.enrolledDevice,
|
|
358
|
+
);
|
|
359
|
+
expect(
|
|
360
|
+
transport.lastCredentialUse,
|
|
361
|
+
protocol.CredentialUse.CREDENTIAL_USE_ENROLLED_DEVICE,
|
|
159
362
|
);
|
|
160
|
-
expect(transport.lastCall,
|
|
363
|
+
expect(transport.lastCall!.offer.authoring.authorSecret, isEmpty);
|
|
161
364
|
});
|
|
162
365
|
|
|
163
366
|
test('authentication recovery waits for the exact typed kernel postcondition',
|
|
164
367
|
() async {
|
|
165
368
|
final transport = _ProofTransport();
|
|
166
|
-
final bridge =
|
|
369
|
+
final bridge = DartReception(transport);
|
|
167
370
|
addTearDown(bridge.dispose);
|
|
168
371
|
final secret = base64Encode(List<int>.filled(32, 7));
|
|
169
372
|
await bridge.ready;
|
|
170
|
-
await bridge.
|
|
373
|
+
await bridge.bindSession(
|
|
171
374
|
workspace: 'home',
|
|
172
375
|
session: 'home',
|
|
173
|
-
authorSecret: secret,
|
|
174
|
-
authToken: 'stale.provider.token',
|
|
175
376
|
);
|
|
377
|
+
await bridge.session('home').refreshCredentials(
|
|
378
|
+
authorSecret: secret,
|
|
379
|
+
authToken: 'stale.provider.token',
|
|
380
|
+
);
|
|
176
381
|
final home = bridge.session('home');
|
|
177
382
|
|
|
178
|
-
final before = await home.nmsAuthenticationPosture(
|
|
383
|
+
final before = await home.nmsAuthenticationPosture(
|
|
384
|
+
principal: 'user:jack',
|
|
385
|
+
authorSecret: secret,
|
|
386
|
+
);
|
|
387
|
+
expect(
|
|
388
|
+
transport.lastCredentialUse,
|
|
389
|
+
protocol.CredentialUse.CREDENTIAL_USE_SESSION,
|
|
390
|
+
reason:
|
|
391
|
+
'an explicit device proof must not suppress the live provider credential',
|
|
392
|
+
);
|
|
179
393
|
expect(
|
|
180
394
|
before.providerToken,
|
|
181
395
|
NomosProviderTokenVerification.noMatchingKey,
|
|
@@ -184,10 +398,96 @@ void main() {
|
|
|
184
398
|
|
|
185
399
|
final after = await home.nmsAwaitAuthenticationReady(
|
|
186
400
|
principal: 'user:jack',
|
|
401
|
+
initialBackoff: const Duration(milliseconds: 10),
|
|
187
402
|
);
|
|
188
403
|
expect(after.providerToken, NomosProviderTokenVerification.valid);
|
|
189
404
|
expect(after.enrolledDevice, isTrue);
|
|
190
405
|
expect(after.resolvedPrincipal, 'user:jack');
|
|
191
|
-
expect(transport.
|
|
406
|
+
expect(transport.authenticationRequests, hasLength(1));
|
|
407
|
+
final requirement = transport.authenticationRequests.single;
|
|
408
|
+
expect(requirement.session, 'home');
|
|
409
|
+
expect(requirement.principal, 'user:jack');
|
|
410
|
+
expect(requirement.initialBackoffMillis, 10);
|
|
411
|
+
expect(requirement.patienceMillis, 60000);
|
|
412
|
+
expect(requirement.maximumBackoffMillis, 8000);
|
|
413
|
+
expect(transport.syncCalls, 0,
|
|
414
|
+
reason: 'the client drives no sync rounds of its own');
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
test('Reception preserves the runtime last posture when patience expires',
|
|
418
|
+
() async {
|
|
419
|
+
final transport = _ProofTransport();
|
|
420
|
+
final bridge = DartReception(transport, allowStaleRunnerBundle: true);
|
|
421
|
+
addTearDown(bridge.dispose);
|
|
422
|
+
await bridge.ready;
|
|
423
|
+
await bridge.bindSession(workspace: 'home', session: 'home');
|
|
424
|
+
transport.authenticationResult = protocol.AuthenticationReadiness(
|
|
425
|
+
outcome: protocol.AuthenticationReadinessOutcome
|
|
426
|
+
.AUTHENTICATION_READINESS_OUTCOME_PATIENCE_EXHAUSTED,
|
|
427
|
+
posture: protocol.AuthenticationPostureResponse(
|
|
428
|
+
providerToken: protocol.ProviderTokenVerificationStatus
|
|
429
|
+
.PROVIDER_TOKEN_VERIFICATION_STATUS_NO_MATCHING_KEY,
|
|
430
|
+
enrolledDevice: false,
|
|
431
|
+
resolvedPrincipal: '',
|
|
432
|
+
),
|
|
433
|
+
);
|
|
434
|
+
final posture = await bridge
|
|
435
|
+
.session('home')
|
|
436
|
+
.nmsAwaitAuthenticationReady(principal: 'user:jack');
|
|
437
|
+
expect(posture.providerToken, NomosProviderTokenVerification.noMatchingKey);
|
|
438
|
+
expect(posture.enrolledDevice, isFalse);
|
|
439
|
+
expect(transport.authenticationRequests, hasLength(1));
|
|
440
|
+
expect(transport.syncCalls, 0);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
test(
|
|
444
|
+
'birth readiness crosses the runtime boundary without a client sync loop',
|
|
445
|
+
() async {
|
|
446
|
+
final transport = _ProofTransport();
|
|
447
|
+
final bridge = DartReception(transport);
|
|
448
|
+
addTearDown(bridge.dispose);
|
|
449
|
+
await bridge.ready;
|
|
450
|
+
await bridge.bindSession(workspace: 'home', session: 'home');
|
|
451
|
+
final home = bridge.session('home');
|
|
452
|
+
|
|
453
|
+
final unspecified = await home.nmsAuthenticationPosture(
|
|
454
|
+
principal: 'user:jack',
|
|
455
|
+
includeBirthEvidence: true,
|
|
456
|
+
);
|
|
457
|
+
expect(transport.lastCall!.query.authenticationPosture.includeBirthEvidence,
|
|
458
|
+
isTrue);
|
|
459
|
+
expect(unspecified.isReadyToBirthFor('user:jack'), isFalse,
|
|
460
|
+
reason:
|
|
461
|
+
'an older kernel omitting the field cannot prove birth readiness');
|
|
462
|
+
|
|
463
|
+
transport.authenticationResult = protocol.AuthenticationReadiness(
|
|
464
|
+
outcome: protocol.AuthenticationReadinessOutcome
|
|
465
|
+
.AUTHENTICATION_READINESS_OUTCOME_PATIENCE_EXHAUSTED,
|
|
466
|
+
posture: protocol.AuthenticationPostureResponse(
|
|
467
|
+
providerToken: protocol.ProviderTokenVerificationStatus
|
|
468
|
+
.PROVIDER_TOKEN_VERIFICATION_STATUS_VALID,
|
|
469
|
+
enrolledDevice: true,
|
|
470
|
+
resolvedPrincipal: 'user:jack',
|
|
471
|
+
birthEvidence: protocol.BirthEvidenceReadiness(
|
|
472
|
+
status: protocol
|
|
473
|
+
.BirthEvidenceStatus.BIRTH_EVIDENCE_STATUS_DELEGATION_REQUIRED,
|
|
474
|
+
detail: 'the current device has no retained delegation',
|
|
475
|
+
),
|
|
476
|
+
),
|
|
477
|
+
);
|
|
478
|
+
final posture = await home.nmsAwaitAuthenticationReady(
|
|
479
|
+
principal: 'user:jack',
|
|
480
|
+
requireBirthEvidence: true,
|
|
481
|
+
);
|
|
482
|
+
expect(posture.isReadyFor('user:jack'), isTrue);
|
|
483
|
+
expect(posture.isReadyToBirthFor('user:jack'), isFalse);
|
|
484
|
+
expect(posture.needsBirthDelegation, isTrue);
|
|
485
|
+
expect(posture.birthEvidenceDetail,
|
|
486
|
+
'the current device has no retained delegation');
|
|
487
|
+
expect(
|
|
488
|
+
transport.authenticationRequests.single.criterion,
|
|
489
|
+
protocol.AuthenticationReadinessCriterion
|
|
490
|
+
.AUTHENTICATION_READINESS_CRITERION_BIRTH_EVIDENCE);
|
|
491
|
+
expect(transport.syncCalls, 0);
|
|
192
492
|
});
|
|
193
493
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import 'dart:async';
|
|
2
|
+
import 'dart:typed_data';
|
|
3
|
+
|
|
4
|
+
import 'package:nomos_client/src/nms_generated_runtime.dart';
|
|
5
|
+
import 'package:nomos_types/nomos_kernel_protocol.dart' as p;
|
|
6
|
+
import 'package:test/test.dart';
|
|
7
|
+
|
|
8
|
+
final class _Office implements PeerOfficeConnection {
|
|
9
|
+
final events = StreamController<p.RuntimeEvent>.broadcast(sync: true);
|
|
10
|
+
final calls = <p.RuntimeRequest>[];
|
|
11
|
+
int sequence = 0;
|
|
12
|
+
|
|
13
|
+
@override
|
|
14
|
+
Stream<p.RuntimeEvent> get runtimeEvents => events.stream;
|
|
15
|
+
|
|
16
|
+
@override
|
|
17
|
+
int nextRuntimeRequestId() => ++sequence;
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
Future<p.RuntimeResponse> invokeRuntime(p.RuntimeRequest request) async {
|
|
21
|
+
calls.add(request.deepCopy());
|
|
22
|
+
if (!request.hasFramework() ||
|
|
23
|
+
!request.framework.hasCheckInterfaceCompatibility()) {
|
|
24
|
+
throw StateError(
|
|
25
|
+
'unexpected runtime call ${request.whichCommand().name}');
|
|
26
|
+
}
|
|
27
|
+
return p.RuntimeResponse(
|
|
28
|
+
protocolVersion: 2,
|
|
29
|
+
requestId: request.requestId,
|
|
30
|
+
framework: p.FrameworkResponse(
|
|
31
|
+
interfaceCompatibilityVerdict: p.InterfaceCompatibilityVerdict(
|
|
32
|
+
localLawCurrency: p.LocalLawCurrency.LOCAL_LAW_CURRENCY_CURRENT,
|
|
33
|
+
examined: p.InterfaceCompatibilityResponse(
|
|
34
|
+
compatible: false,
|
|
35
|
+
workspaceFrontier: 'head-${calls.length}',
|
|
36
|
+
members: [
|
|
37
|
+
p.InterfaceMemberVerdict(
|
|
38
|
+
domain: 'estate',
|
|
39
|
+
kind: p.InterfaceMemberKind.INTERFACE_MEMBER_KIND_AGGREGATE,
|
|
40
|
+
member: 'Asset',
|
|
41
|
+
status: p.InterfaceCompatibilityStatus
|
|
42
|
+
.INTERFACE_COMPATIBILITY_STATUS_EXACT,
|
|
43
|
+
),
|
|
44
|
+
p.InterfaceMemberVerdict(
|
|
45
|
+
domain: 'estate',
|
|
46
|
+
kind: p.InterfaceMemberKind.INTERFACE_MEMBER_KIND_FIELD,
|
|
47
|
+
member: 'createCatalogueAssetGrid',
|
|
48
|
+
field_4: 'fieldRequirements',
|
|
49
|
+
status: p.InterfaceCompatibilityStatus
|
|
50
|
+
.INTERFACE_COMPATIBILITY_STATUS_INCOMPATIBLE,
|
|
51
|
+
reason: p.InterfaceCompatibilityReason
|
|
52
|
+
.INTERFACE_COMPATIBILITY_REASON_WIRE_CONTRACT_CHANGED,
|
|
53
|
+
diagnostic:
|
|
54
|
+
'application wire 146915208 is not accepted by this law',
|
|
55
|
+
),
|
|
56
|
+
p.InterfaceMemberVerdict(
|
|
57
|
+
domain: 'estate',
|
|
58
|
+
kind: p.InterfaceMemberKind.INTERFACE_MEMBER_KIND_DIRECTIVE,
|
|
59
|
+
member: 'createCatalogueAssetGrid',
|
|
60
|
+
status: p.InterfaceCompatibilityStatus
|
|
61
|
+
.INTERFACE_COMPATIBILITY_STATUS_INCOMPATIBLE,
|
|
62
|
+
),
|
|
63
|
+
],
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void main() {
|
|
72
|
+
late _Office office;
|
|
73
|
+
late DartReception reception;
|
|
74
|
+
late NomosSession session;
|
|
75
|
+
final matrix = Uint8List.fromList([1, 2, 3]);
|
|
76
|
+
|
|
77
|
+
setUp(() {
|
|
78
|
+
office = _Office();
|
|
79
|
+
reception = DartReception(office);
|
|
80
|
+
session = reception.session('estate');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
tearDown(() async {
|
|
84
|
+
await reception.dispose();
|
|
85
|
+
await office.events.close();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('the exact unsafe write is typed while unrelated members stay usable',
|
|
89
|
+
() async {
|
|
90
|
+
final unsafe = await session.operationCompatibility(
|
|
91
|
+
matrix,
|
|
92
|
+
domain: 'estate',
|
|
93
|
+
directive: 'createCatalogueAssetGrid',
|
|
94
|
+
);
|
|
95
|
+
expect(
|
|
96
|
+
unsafe,
|
|
97
|
+
isA<NomosOperationUnavailable>()
|
|
98
|
+
.having(
|
|
99
|
+
(value) => value.guidance,
|
|
100
|
+
'guidance',
|
|
101
|
+
NomosCompatibilityGuidance.controlPlaneDecisionRequired,
|
|
102
|
+
)
|
|
103
|
+
.having(
|
|
104
|
+
(value) =>
|
|
105
|
+
value.differences.map((difference) => difference.field_4),
|
|
106
|
+
'differences',
|
|
107
|
+
contains('fieldRequirements'),
|
|
108
|
+
),
|
|
109
|
+
);
|
|
110
|
+
await expectLater(
|
|
111
|
+
session.assertOperationCompatible(
|
|
112
|
+
matrix,
|
|
113
|
+
domain: 'estate',
|
|
114
|
+
directive: 'createCatalogueAssetGrid',
|
|
115
|
+
),
|
|
116
|
+
throwsA(isA<NomosOperationUnavailable>()),
|
|
117
|
+
);
|
|
118
|
+
expect(
|
|
119
|
+
await session.operationCompatibility(
|
|
120
|
+
matrix,
|
|
121
|
+
domain: 'estate',
|
|
122
|
+
directive: 'renameAsset',
|
|
123
|
+
),
|
|
124
|
+
isA<NomosOperationAvailable>(),
|
|
125
|
+
reason: 'a partial application is not a global failure',
|
|
126
|
+
);
|
|
127
|
+
expect(office.calls, hasLength(1),
|
|
128
|
+
reason: 'all three checks share one immutable matrix examination');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('a law-change observation invalidates the session cache', () async {
|
|
132
|
+
await session.operationCompatibility(
|
|
133
|
+
matrix,
|
|
134
|
+
domain: 'estate',
|
|
135
|
+
directive: 'createCatalogueAssetGrid',
|
|
136
|
+
);
|
|
137
|
+
office.events.add(p.RuntimeEvent(
|
|
138
|
+
session: 'estate',
|
|
139
|
+
lawChanged: p.LawChanged(
|
|
140
|
+
domain: 'estate',
|
|
141
|
+
packageSha256: 'next-law',
|
|
142
|
+
),
|
|
143
|
+
));
|
|
144
|
+
await session.operationCompatibility(
|
|
145
|
+
matrix,
|
|
146
|
+
domain: 'estate',
|
|
147
|
+
directive: 'createCatalogueAssetGrid',
|
|
148
|
+
);
|
|
149
|
+
expect(office.calls, hasLength(2));
|
|
150
|
+
});
|
|
151
|
+
}
|