@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
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// THE CONNECTED LANE, END TO END, against the node local-development platform
|
|
2
|
+
// shell — the local ADMITTING PEER.
|
|
3
|
+
//
|
|
4
|
+
// `NomosTestCloud` spawns `platform-shells/node/local-development/server.ts`,
|
|
5
|
+
// which mints this universe's trust root, stands `root` up against it, births
|
|
6
|
+
// `proof-platform` under root with a trust-root-signed birth certificate, and
|
|
7
|
+
// installs the compiled co2 application law onto it. `NomosTestHarness
|
|
8
|
+
// .cloudBound` then runs the REAL warranted onboarding: mint a device key in
|
|
9
|
+
// the local kernel, take a device-bound proof from the shell's identity
|
|
10
|
+
// provider, enrol the first device on the platform, birth the owner's receiving
|
|
11
|
+
// group there, and mount it as an ordinary cloud-bound session.
|
|
12
|
+
//
|
|
13
|
+
// Nothing here creates a workspace host-side, and nothing reaches past
|
|
14
|
+
// dispatch: every step is an ordinary typed offer through the platform's own law.
|
|
15
|
+
@TestOn('vm')
|
|
16
|
+
library;
|
|
17
|
+
|
|
18
|
+
import 'dart:io';
|
|
19
|
+
|
|
20
|
+
import 'package:nomos_client/src/nms_conformance_runtime.dart';
|
|
21
|
+
import 'package:test/test.dart';
|
|
22
|
+
|
|
23
|
+
// The compiled application's own pre-bound framework calls. The harness accepts
|
|
24
|
+
// no other transport for a framework directive.
|
|
25
|
+
import '../../../examples/co2-birth/build/application/co2_application/lib/src/generated/application.framework_calls.dart'
|
|
26
|
+
show nomosInternalApplicationFrameworkCalls;
|
|
27
|
+
|
|
28
|
+
String get _repoRoot => Directory.current.parent.parent.path;
|
|
29
|
+
String get _serverEntry =>
|
|
30
|
+
'$_repoRoot/platform-shells/node/local-development/server.ts';
|
|
31
|
+
String get _co2LawUsdz => '$_repoRoot/examples/co2-birth/build/co2.law.usdz';
|
|
32
|
+
String get _governanceCalls =>
|
|
33
|
+
'$_repoRoot/cloud/governance/build/governance.framework.mjs';
|
|
34
|
+
String get _runtimeDir =>
|
|
35
|
+
Platform.environment['NOMOS_CANDIDATE_RUNTIME'] ??
|
|
36
|
+
Platform.environment['NOMOS_DART_RUNTIME'] ??
|
|
37
|
+
Platform.environment['NOMOS_OFFLINE_RUNTIME'] ??
|
|
38
|
+
'${Platform.environment['HOME'] ?? ''}/.holon/runtime';
|
|
39
|
+
|
|
40
|
+
/// The prerequisites this test cannot build for itself.
|
|
41
|
+
String? _missingPrereq() {
|
|
42
|
+
if (!File(_serverEntry).existsSync()) {
|
|
43
|
+
return 'the local development shell is not in this checkout ($_serverEntry)';
|
|
44
|
+
}
|
|
45
|
+
if (!File(_co2LawUsdz).existsSync()) {
|
|
46
|
+
return 'compile the fixture first: cd examples/co2-birth && npx nomos-compile';
|
|
47
|
+
}
|
|
48
|
+
if (!File(_governanceCalls).existsSync()) {
|
|
49
|
+
return 'compile the governance package first: cd cloud/governance && npm run compile';
|
|
50
|
+
}
|
|
51
|
+
for (final artifact in const [
|
|
52
|
+
'holon.wasm',
|
|
53
|
+
'kernel.repository.xml',
|
|
54
|
+
'bootstrap.law.usdz',
|
|
55
|
+
'nomos.law.usdz',
|
|
56
|
+
]) {
|
|
57
|
+
if (!File('$_runtimeDir/$artifact').existsSync()) {
|
|
58
|
+
return 'point NOMOS_CANDIDATE_RUNTIME at a complete runtime bundle (missing $artifact)';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
void main() {
|
|
65
|
+
test(
|
|
66
|
+
'CONNECTED: root births the platform, and a home is born and mounted on it',
|
|
67
|
+
() async {
|
|
68
|
+
final skip = _missingPrereq();
|
|
69
|
+
if (skip != null) {
|
|
70
|
+
markTestSkipped(skip);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
final diagnostics = <String>[];
|
|
74
|
+
void log(String line) {
|
|
75
|
+
diagnostics.add(line);
|
|
76
|
+
printOnFailure(line);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
final cloud = await NomosTestCloud.start(
|
|
80
|
+
serverEntry: _serverEntry,
|
|
81
|
+
platform: 'proof-platform',
|
|
82
|
+
lawUsdzPaths: [_co2LawUsdz],
|
|
83
|
+
applicationMaxChildWorkspacesPerUser: 5,
|
|
84
|
+
runtimeDirectory: _runtimeDir,
|
|
85
|
+
mintTrustRoot: true,
|
|
86
|
+
testIdentityProvider: true,
|
|
87
|
+
readyTimeout: const Duration(minutes: 4),
|
|
88
|
+
onDiagnostic: log,
|
|
89
|
+
);
|
|
90
|
+
addTearDown(cloud.stop);
|
|
91
|
+
|
|
92
|
+
// The universe is pinned to a trust root every peer in it must agree on.
|
|
93
|
+
expect(cloud.trustRootPublicKey, isNotNull);
|
|
94
|
+
expect(cloud.testKRootPublic, equals(cloud.trustRootPublicKey));
|
|
95
|
+
|
|
96
|
+
final harness = await NomosTestHarness.cloudBound(
|
|
97
|
+
cloud: cloud,
|
|
98
|
+
lawUsdzPaths: [_co2LawUsdz],
|
|
99
|
+
platformWorkspace: 'proof-platform',
|
|
100
|
+
subject: 'user:proof-owner',
|
|
101
|
+
applicationFrameworkCalls: nomosInternalApplicationFrameworkCalls,
|
|
102
|
+
registerTearDown: addTearDown,
|
|
103
|
+
phaseTimeout: const Duration(minutes: 4),
|
|
104
|
+
onDiagnostic: log,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Phase 6 mounted the born home: it is a real, verified, cloud-bound session.
|
|
108
|
+
final home = harness.homeWorkspace;
|
|
109
|
+
expect(home, isNotNull);
|
|
110
|
+
expect(home, isNot(equals('proof-platform')));
|
|
111
|
+
expect(harness.workspace, equals(home));
|
|
112
|
+
|
|
113
|
+
final remote = await cloud.remoteHead(home!);
|
|
114
|
+
expect(remote.initialized, isTrue);
|
|
115
|
+
expect(remote.head, hasLength(40));
|
|
116
|
+
},
|
|
117
|
+
timeout: const Timeout(Duration(minutes: 10)),
|
|
118
|
+
);
|
|
119
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import 'dart:convert';
|
|
2
|
+
|
|
3
|
+
import 'package:nomos_client/src/console_enrolment.dart';
|
|
4
|
+
import 'package:test/test.dart';
|
|
5
|
+
|
|
6
|
+
void main() {
|
|
7
|
+
final device = NomosConsoleEnrolmentDevice.fromSeed(List.filled(32, 7));
|
|
8
|
+
|
|
9
|
+
Future<Object?> refusal(int status, Map<String, Object?> body) async {
|
|
10
|
+
try {
|
|
11
|
+
await enrolWithConsole(
|
|
12
|
+
console: 'http://console.test',
|
|
13
|
+
tenant: 'co2-platform',
|
|
14
|
+
scope: 'user',
|
|
15
|
+
providerToken: 'token',
|
|
16
|
+
device: device,
|
|
17
|
+
workspaces: const ['co2-platform'],
|
|
18
|
+
post: (_, __) async =>
|
|
19
|
+
NomosConsoleResponse(status: status, body: jsonEncode(body)),
|
|
20
|
+
);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return error;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
test('a console refusal carries its stable code and retry verdict', () async {
|
|
28
|
+
final error = await refusal(403, {
|
|
29
|
+
'error': 'home is not a workspace of tenant co2-platform',
|
|
30
|
+
'code': 'workspace_not_in_tenant',
|
|
31
|
+
'retryable': false,
|
|
32
|
+
});
|
|
33
|
+
expect(
|
|
34
|
+
error,
|
|
35
|
+
isA<NomosConsoleEnrolmentRefused>()
|
|
36
|
+
.having((e) => e.status, 'status', 403)
|
|
37
|
+
.having((e) => e.code, 'code', 'workspace_not_in_tenant')
|
|
38
|
+
.having((e) => e.retryable, 'retryable', isFalse)
|
|
39
|
+
.having((e) => e.message, 'message', contains('not a workspace')),
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('an older console without a verdict leaves it to the status', () async {
|
|
44
|
+
final error = await refusal(503, {'error': 'busy'});
|
|
45
|
+
expect(
|
|
46
|
+
error,
|
|
47
|
+
isA<NomosConsoleEnrolmentRefused>()
|
|
48
|
+
.having((e) => e.code, 'code', isEmpty)
|
|
49
|
+
.having((e) => e.retryable, 'retryable', isNull),
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import 'dart:convert';
|
|
2
|
+
import 'dart:io';
|
|
3
|
+
import 'dart:typed_data';
|
|
4
|
+
|
|
5
|
+
import 'package:fixnum/fixnum.dart';
|
|
6
|
+
import 'package:nomos_client/src/console_enrolment.dart';
|
|
7
|
+
import 'package:nomos_client/src/runtime_v2_transport.dart';
|
|
8
|
+
import 'package:nomos_peer_host/nomos_peer_host.dart'
|
|
9
|
+
show NomosDeviceIdentityStore, NomosProviderCredentialStore;
|
|
10
|
+
import 'package:nomos_types/nomos_kernel_protocol.dart' as p;
|
|
11
|
+
import 'package:test/test.dart';
|
|
12
|
+
|
|
13
|
+
/// The golden vector every device-side client reproduces byte for byte
|
|
14
|
+
/// (`peer-office/test/fixtures/console_enrol_request_vector.json`).
|
|
15
|
+
final Map<String,
|
|
16
|
+
Object?> vector = jsonDecode(File.fromUri(Directory.current.uri.resolve(
|
|
17
|
+
'../../peer-office/test/fixtures/console_enrol_request_vector.json'))
|
|
18
|
+
.readAsStringSync()) as Map<String, Object?>;
|
|
19
|
+
|
|
20
|
+
Uint8List _hex(String hex) => Uint8List.fromList([
|
|
21
|
+
for (var i = 0; i < hex.length; i += 2)
|
|
22
|
+
int.parse(hex.substring(i, i + 2), radix: 16),
|
|
23
|
+
]);
|
|
24
|
+
String _toHex(List<int> bytes) =>
|
|
25
|
+
bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
|
|
26
|
+
|
|
27
|
+
class _Platform
|
|
28
|
+
with NmsPlatformCredentialProviderHost
|
|
29
|
+
implements NomosRuntimeV2Transport {
|
|
30
|
+
final frames = <p.RuntimeRequest>[];
|
|
31
|
+
final List<p.RuntimeResponse> answers;
|
|
32
|
+
_Platform(this.answers);
|
|
33
|
+
int sequence = 0;
|
|
34
|
+
@override
|
|
35
|
+
int nextRuntimeRequestId() => ++sequence;
|
|
36
|
+
@override
|
|
37
|
+
Future<p.RuntimeResponse> invokeRuntime(p.RuntimeRequest request) async {
|
|
38
|
+
frames.add(request);
|
|
39
|
+
return answers.removeAt(0);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class _Store implements NomosDeviceIdentityStore {
|
|
44
|
+
_Store(this.saved);
|
|
45
|
+
final Map<String, Uint8List> saved;
|
|
46
|
+
@override
|
|
47
|
+
Future<Uint8List?> load(String identity) async => saved[identity];
|
|
48
|
+
@override
|
|
49
|
+
Future<void> save(String identity, Uint8List secret) async =>
|
|
50
|
+
saved[identity] = secret;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class _Cache implements NomosProviderCredentialStore {
|
|
54
|
+
@override
|
|
55
|
+
Future<List<String>> loadCandidates(String entry) async => ['cached-token'];
|
|
56
|
+
@override
|
|
57
|
+
Future<void> retainCandidate(String entry, String authToken) async {}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
void main() {
|
|
61
|
+
final seed = _hex(vector['seedHex'] as String);
|
|
62
|
+
final workspaces = (vector['workspaces'] as List).cast<String>();
|
|
63
|
+
final body = vector['body'] as Map<String, Object?>;
|
|
64
|
+
|
|
65
|
+
test(
|
|
66
|
+
'reproduces the golden enrolment vector byte for byte, signature included',
|
|
67
|
+
() {
|
|
68
|
+
final device = NomosConsoleEnrolmentDevice.fromSeed(seed);
|
|
69
|
+
expect(consoleBase64Url(device.publicKey), vector['devicePublicKey']);
|
|
70
|
+
expect(consoleDeviceKeyHash(device.publicKey), vector['keyHash']);
|
|
71
|
+
final bytes = consoleEnrolRequestBytes(
|
|
72
|
+
tenant: vector['tenant'] as String,
|
|
73
|
+
scope: vector['scope'] as String,
|
|
74
|
+
keyHash: vector['keyHash'] as String,
|
|
75
|
+
workspaces: workspaces,
|
|
76
|
+
providerToken: vector['providerToken'] as String,
|
|
77
|
+
);
|
|
78
|
+
expect(_toHex(bytes), vector['enrolRequestBytesHex']);
|
|
79
|
+
final request = consoleEnrolmentRequest(
|
|
80
|
+
tenant: vector['tenant'] as String,
|
|
81
|
+
scope: vector['scope'] as String,
|
|
82
|
+
providerToken: vector['providerToken'] as String,
|
|
83
|
+
device: device,
|
|
84
|
+
workspaces: workspaces,
|
|
85
|
+
);
|
|
86
|
+
expect(request.path, vector['path']);
|
|
87
|
+
expect(request.body, body);
|
|
88
|
+
// The wire JSON is the TS client's JSON.stringify, key order included.
|
|
89
|
+
expect(jsonEncode(request.body), jsonEncode(body));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test(
|
|
93
|
+
'the shell performs the enrolment effect: fresh token, device signature, typed receipt',
|
|
94
|
+
() async {
|
|
95
|
+
const identity = 'co2-platform|co2:pYn3MMqQ';
|
|
96
|
+
final signIns = <String?>[];
|
|
97
|
+
final posts = <(Uri, Map<String, Object?>)>[];
|
|
98
|
+
var status = 201;
|
|
99
|
+
final platform = _Platform([
|
|
100
|
+
p.RuntimeResponse(
|
|
101
|
+
protocolVersion: 2,
|
|
102
|
+
requestId: Int64(7),
|
|
103
|
+
receivingGroupOpened:
|
|
104
|
+
p.ReceivingGroupOpened(workspace: 'nomos-rg-a')),
|
|
105
|
+
])
|
|
106
|
+
..registerDeviceIdentityStore(_Store({identity: seed}))
|
|
107
|
+
..registerProviderCredentialStore(_Cache())
|
|
108
|
+
..registerCredentialProvider(
|
|
109
|
+
capability: 'home',
|
|
110
|
+
cloud: 'http://127.0.0.1:8788',
|
|
111
|
+
signIn: ({String? deviceChallenge}) async {
|
|
112
|
+
signIns.add(deviceChallenge);
|
|
113
|
+
return vector['providerToken'] as String;
|
|
114
|
+
},
|
|
115
|
+
)
|
|
116
|
+
..registerConsolePost((url, text) async {
|
|
117
|
+
final sent = jsonDecode(text) as Map<String, Object?>;
|
|
118
|
+
posts.add((url, sent));
|
|
119
|
+
return NomosConsoleResponse(
|
|
120
|
+
status: status,
|
|
121
|
+
body: status == 201
|
|
122
|
+
? jsonEncode({
|
|
123
|
+
'keyHash': vector['keyHash'],
|
|
124
|
+
'principal': 'co2:pYn3MMqQ',
|
|
125
|
+
'workspaces': {for (final w in workspaces) w: '$w-head'},
|
|
126
|
+
'revoked': false,
|
|
127
|
+
})
|
|
128
|
+
: jsonEncode({
|
|
129
|
+
'error':
|
|
130
|
+
'this provider token has already been used; sign in again'
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
final effect = p.PeerConsoleEnrolmentEffect(
|
|
135
|
+
effectId: 'open-1:console:enrol-1',
|
|
136
|
+
deviceIdentity: identity,
|
|
137
|
+
capability: 'home',
|
|
138
|
+
console: 'http://127.0.0.1:8797/',
|
|
139
|
+
tenant: vector['tenant'] as String,
|
|
140
|
+
scope: vector['scope'] as String,
|
|
141
|
+
workspaces: workspaces,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
final receipt = await platform.performConsoleEnrolment(effect);
|
|
145
|
+
expect(receipt.effectId, effect.effectId);
|
|
146
|
+
expect(receipt.hasConsoleEnrolled(), isTrue, reason: '$receipt');
|
|
147
|
+
expect(receipt.consoleEnrolled.principal, 'co2:pYn3MMqQ');
|
|
148
|
+
expect(receipt.consoleEnrolled.keyHash, vector['keyHash']);
|
|
149
|
+
expect(receipt.consoleEnrolled.heads['nomos-rg-a'], 'nomos-rg-a-head');
|
|
150
|
+
expect(signIns, [null],
|
|
151
|
+
reason: 'a plain ID token: never signIn(deviceChallenge: <hash>)');
|
|
152
|
+
expect(posts.single.$1.toString(),
|
|
153
|
+
'http://127.0.0.1:8797/v1/tenants/co2-platform/providers/co2/enrolments');
|
|
154
|
+
expect(posts.single.$2, body,
|
|
155
|
+
reason: 'the golden request, signature included');
|
|
156
|
+
expect(receipt.writeToBuffer().length, greaterThan(0));
|
|
157
|
+
expect(utf8.decode(receipt.writeToBuffer(), allowMalformed: true),
|
|
158
|
+
isNot(contains(vector['providerToken'])),
|
|
159
|
+
reason: 'the token never returns to the runtime');
|
|
160
|
+
|
|
161
|
+
status = 409;
|
|
162
|
+
final spent = await platform.performConsoleEnrolment(effect);
|
|
163
|
+
expect(spent.hasConsoleEnrolmentRefused(), isTrue);
|
|
164
|
+
expect(spent.consoleEnrolmentRefused.status, 409);
|
|
165
|
+
expect(
|
|
166
|
+
spent.consoleEnrolmentRefused.message, contains('already been used'));
|
|
167
|
+
expect(signIns, [null, null],
|
|
168
|
+
reason: 'every attempt asks the provider afresh, bypassing the cache');
|
|
169
|
+
|
|
170
|
+
// The effect rides the ordinary credential-effect driver.
|
|
171
|
+
final driven = _Platform([
|
|
172
|
+
p.RuntimeResponse(
|
|
173
|
+
protocolVersion: 2,
|
|
174
|
+
requestId: Int64(9),
|
|
175
|
+
receivingGroupOpened:
|
|
176
|
+
p.ReceivingGroupOpened(workspace: 'nomos-rg-a')),
|
|
177
|
+
])
|
|
178
|
+
..registerDeviceIdentityStore(_Store({identity: seed}))
|
|
179
|
+
..registerCredentialProvider(
|
|
180
|
+
capability: 'home',
|
|
181
|
+
cloud: 'x',
|
|
182
|
+
signIn: ({String? deviceChallenge}) async => 'token')
|
|
183
|
+
..registerConsolePost((url, text) async =>
|
|
184
|
+
const NomosConsoleResponse(status: 403, body: '{"error":"no"}'));
|
|
185
|
+
var calls = 0;
|
|
186
|
+
final result = await driven.driveCredentialEffects(
|
|
187
|
+
p.RuntimeRequest(protocolVersion: 2, requestId: Int64(9)),
|
|
188
|
+
(frame) async {
|
|
189
|
+
calls += 1;
|
|
190
|
+
if (calls == 1) {
|
|
191
|
+
return p.RuntimeResponse(
|
|
192
|
+
protocolVersion: 2,
|
|
193
|
+
requestId: Int64(9),
|
|
194
|
+
correspondencePending: p.CorrespondencePending(
|
|
195
|
+
workId: 'open-1', consoleEnrolment: effect),
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
expect(
|
|
199
|
+
frame.continueCorrespondence.receipt.consoleEnrolmentRefused.status,
|
|
200
|
+
403);
|
|
201
|
+
return p.RuntimeResponse(
|
|
202
|
+
protocolVersion: 2,
|
|
203
|
+
requestId: Int64(9),
|
|
204
|
+
receivingGroupOpened:
|
|
205
|
+
p.ReceivingGroupOpened(workspace: 'nomos-rg-a'));
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
expect(result.hasReceivingGroupOpened(), isTrue);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test(
|
|
212
|
+
'a shell without the identity or a provider answers typed, never guesses',
|
|
213
|
+
() async {
|
|
214
|
+
final effect = p.PeerConsoleEnrolmentEffect(
|
|
215
|
+
effectId: 'e', deviceIdentity: 'missing', capability: 'home');
|
|
216
|
+
final bare = _Platform([]);
|
|
217
|
+
expect((await bare.performConsoleEnrolment(effect)).hasFailure(), isTrue);
|
|
218
|
+
final noKey = _Platform([])
|
|
219
|
+
..registerDeviceIdentityStore(_Store({}))
|
|
220
|
+
..registerCredentialProvider(
|
|
221
|
+
capability: 'home',
|
|
222
|
+
cloud: 'x',
|
|
223
|
+
signIn: ({String? deviceChallenge}) async => 't');
|
|
224
|
+
final receipt = await noKey.performConsoleEnrolment(effect);
|
|
225
|
+
expect(receipt.failure.message, contains('no usable identity'));
|
|
226
|
+
});
|
|
227
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// NOMOS — TYPED ERROR MINTING (§7 structured runtime error DX). `nomosErrorFromInfo` routes a structured
|
|
2
2
|
// `NomosErrorInfo` to the MOST SPECIFIC typed class by stable code prefix, so an app's `errorBuilder` branches
|
|
3
|
-
// on `is` and reads structured fields (not scraped prose). Every typed error still extends `
|
|
3
|
+
// on `is` and reads structured fields (not scraped prose). Every typed error still extends `NomosRuntimeError`.
|
|
4
4
|
import 'package:nomos_client/src/nms_generated_runtime.dart';
|
|
5
5
|
import 'package:test/test.dart';
|
|
6
6
|
|
|
@@ -52,7 +52,7 @@ void main() {
|
|
|
52
52
|
'nomos.law.incompatibleMember': 'mood',
|
|
53
53
|
},
|
|
54
54
|
));
|
|
55
|
-
expect(e, isA<
|
|
55
|
+
expect(e, isA<NomosRuntimeError>()); // still catchable generically
|
|
56
56
|
expect(e, isA<LawMismatchError>());
|
|
57
57
|
final m = e as LawMismatchError;
|
|
58
58
|
expect(m.code, 'nomos.law.mismatch');
|
|
@@ -127,7 +127,7 @@ void main() {
|
|
|
127
127
|
'nomos.authz.directiveId': 'birthEstateWorkspace',
|
|
128
128
|
},
|
|
129
129
|
));
|
|
130
|
-
expect(e, isA<
|
|
130
|
+
expect(e, isA<NomosRuntimeError>());
|
|
131
131
|
expect(e, isA<AuthzRefusedError>());
|
|
132
132
|
expect(e, isA<ParentSignerEnrollmentMissing>());
|
|
133
133
|
final p = e as ParentSignerEnrollmentMissing;
|
|
@@ -181,8 +181,8 @@ void main() {
|
|
|
181
181
|
() {
|
|
182
182
|
expect(nomosErrorFromInfo(info('nomos.custody.missing_object')),
|
|
183
183
|
isA<CustodyError>());
|
|
184
|
-
final g = nomosErrorFromInfo(info('nomos.
|
|
185
|
-
expect(g, isA<
|
|
184
|
+
final g = nomosErrorFromInfo(info('nomos.reception.error'));
|
|
185
|
+
expect(g, isA<NomosRuntimeError>());
|
|
186
186
|
expect(g, isNot(isA<LawMismatchError>()));
|
|
187
187
|
});
|
|
188
188
|
}
|