@githolon/dsl 0.107.4 → 0.108.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.
Files changed (93) hide show
  1. package/dart/CHANGELOG.md +24 -0
  2. package/dart/lib/src/application_framework_calls.dart +299 -0
  3. package/dart/lib/src/generated_call.dart +96 -0
  4. package/dart/lib/src/nms_generated_runtime.dart +29 -0
  5. package/dart/lib/src/node_runner_transport.dart +77 -1
  6. package/dart/lib/src/result_usda.dart +487 -0
  7. package/dart/lib/src/runner/node-entry.mjs +10634 -6122
  8. package/dart/lib/src/runner/offline-install.mjs +4187 -2716
  9. package/dart/lib/src/runtime_v2_gateway.dart +54 -0
  10. package/dart/lib/src/runtime_v2_transport.dart +117 -0
  11. package/dart/lib/src/session_bound.dart +7 -2
  12. package/dart/lib/src/test_harness.dart +373 -282
  13. package/dart/lib/src/webview_bridge.dart +2146 -725
  14. package/dart/pubspec.lock +17 -1
  15. package/dart/pubspec.yaml +3 -2
  16. package/dart/test/acquire_session_credentials_test.dart +1 -1
  17. package/dart/test/acquire_session_test.dart +68 -14
  18. package/dart/test/adv_realm_interference_test.dart +6 -4
  19. package/dart/test/cluster_births_test.dart +11 -8
  20. package/dart/test/cluster_local_autosync_test.dart +1 -1
  21. package/dart/test/cluster_scale_test.dart +3 -2
  22. package/dart/test/dlq_session_surface_test.dart +52 -35
  23. package/dart/test/first_app_gauntlet_test.dart +1 -1
  24. package/dart/test/local_sync_inert_test.dart +23 -26
  25. package/dart/test/offer_authentication_proof_test.dart +193 -0
  26. package/dart/test/result_usda_test.dart +49 -0
  27. package/dart/test/session_bound_test.dart +8 -11
  28. package/dart/test/stale_bundle_test.dart +18 -3
  29. package/dart/test/test_harness_test.dart +14 -27
  30. package/dart/test/webview_bridge_test.dart +504 -83
  31. package/dart_types/CHANGELOG.md +17 -0
  32. package/dart_types/lib/nomos_kernel_protocol.dart +11 -0
  33. package/dart_types/lib/src/custody.dart +64 -19
  34. package/dart_types/lib/src/local_work_rejected.dart +30 -45
  35. package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pb.dart +169 -0
  36. package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pbenum.dart +11 -0
  37. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +17945 -0
  38. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +933 -0
  39. package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pb.dart +245 -0
  40. package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pbenum.dart +160 -0
  41. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +8664 -0
  42. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +369 -0
  43. package/dart_types/lib/src/surfaced.dart +30 -25
  44. package/dart_types/pubspec.lock +16 -0
  45. package/dart_types/pubspec.yaml +3 -1
  46. package/dart_types/test/surfaced_test.dart +2 -1
  47. package/package.json +1 -1
  48. package/runtime/generated-application-host.js +5760 -1879
  49. package/src/authoring.ts +3 -2
  50. package/src/birth_meter_ensure.ts +2 -0
  51. package/src/births.ts +21 -0
  52. package/src/build_package.ts +30 -0
  53. package/src/business_birth.ts +41 -35
  54. package/src/codegen_call_usda.ts +1111 -0
  55. package/src/codegen_dart.ts +207 -282
  56. package/src/codegen_dart_application.ts +195 -252
  57. package/src/codegen_dart_client.ts +1978 -593
  58. package/src/codegen_dart_framework_calls.ts +291 -0
  59. package/src/codegen_dart_scenario.ts +7 -0
  60. package/src/codegen_proof.ts +3 -4
  61. package/src/codegen_provider_dart.ts +21 -7
  62. package/src/codegen_query_usda.ts +214 -0
  63. package/src/codegen_result_usda.ts +685 -0
  64. package/src/codegen_ts.ts +3945 -1111
  65. package/src/compile_package_main.ts +392 -46
  66. package/src/directive.ts +19 -4
  67. package/src/engine_entry.ts +45 -4
  68. package/src/framework/application_home.ts +4 -0
  69. package/src/framework/auth_provider_law.ts +296 -20
  70. package/src/framework/birth_certificate_law.ts +24 -0
  71. package/src/framework/home.ts +83 -40
  72. package/src/framework/owned_custody.ts +25 -12
  73. package/src/framework/owned_custody_value.ts +51 -0
  74. package/src/framework/relations.ts +47 -21
  75. package/src/framework/signing_identity.ts +100 -17
  76. package/src/framework/workspaces.ts +39 -10
  77. package/src/framework_call_definitions.ts +53 -0
  78. package/src/framework_read_definitions.ts +45 -0
  79. package/src/identity_frontier.ts +58 -0
  80. package/src/index.ts +22 -1
  81. package/src/intent.ts +216 -16
  82. package/src/law_check.ts +19 -1
  83. package/src/law_graph.ts +57 -8
  84. package/src/law_graph_usda.ts +73 -5
  85. package/src/law_value_type.ts +106 -19
  86. package/src/read.ts +47 -0
  87. package/src/read_projection_namespace.ts +7 -0
  88. package/src/shape_compat.ts +44 -42
  89. package/src/stable_ids.ts +37 -2
  90. package/src/test_call_usda.ts +83 -0
  91. package/src/wire.ts +36 -2
  92. package/src/wire_encode.ts +45 -1
  93. package/src/workspace_sharing.ts +27 -10
@@ -0,0 +1,193 @@
1
+ import 'dart:async';
2
+ import 'dart:convert';
3
+ import 'dart:typed_data';
4
+
5
+ import 'package:nomos_client/src/nms_generated_runtime.dart';
6
+ import 'package:nomos_types/nomos_kernel_protocol.dart' as protocol;
7
+ import 'package:test/test.dart';
8
+
9
+ final class _ProofTransport
10
+ implements BridgeTransport, NomosKernelCallTransport {
11
+ final _messages = StreamController<Map<String, Object?>>.broadcast();
12
+ protocol.CallRequest? lastCall;
13
+ var providerToken = protocol.ProviderTokenVerificationStatus
14
+ .PROVIDER_TOKEN_VERIFICATION_STATUS_NO_MATCHING_KEY;
15
+ var enrolledDevice = true;
16
+ var resolvedPrincipal = 'user:jack';
17
+ var syncCalls = 0;
18
+
19
+ _ProofTransport() {
20
+ scheduleMicrotask(
21
+ () => _messages.add({
22
+ 'v': kWebviewBridgeVersion,
23
+ 'event': 'ready',
24
+ 'bundleVersion': 'unbundled-dev',
25
+ }),
26
+ );
27
+ }
28
+
29
+ @override
30
+ Stream<Map<String, Object?>> get messages => _messages.stream;
31
+
32
+ @override
33
+ void send(Map<String, Object?> message) {
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
+ }
48
+
49
+ @override
50
+ Future<protocol.RuntimeResponse> invokeRuntime(
51
+ protocol.RuntimeRequest request,
52
+ ) async {
53
+ if (request.hasSyncWorkspace()) {
54
+ syncCalls += 1;
55
+ providerToken = protocol.ProviderTokenVerificationStatus
56
+ .PROVIDER_TOKEN_VERIFICATION_STATUS_VALID;
57
+ return protocol.RuntimeResponse(
58
+ protocolVersion: 2,
59
+ requestId: request.requestId,
60
+ syncWorkspace: protocol.SyncWorkspaceResponse(
61
+ workspace: request.syncWorkspace.session,
62
+ ),
63
+ );
64
+ }
65
+ return protocol.RuntimeResponse(
66
+ protocolVersion: 2,
67
+ requestId: request.requestId,
68
+ realmClosed: protocol.RealmClosed(),
69
+ );
70
+ }
71
+
72
+ @override
73
+ Future<protocol.CallResponse> callKernel({
74
+ required String session,
75
+ required protocol.CallRequest request,
76
+ }) async {
77
+ lastCall = request.deepCopy();
78
+ if (request.hasQuery() && request.query.hasAuthenticationPosture()) {
79
+ return protocol.CallResponse(
80
+ protocolVersion: 1,
81
+ requestId: request.requestId,
82
+ query: protocol.QueryResponse(
83
+ authenticationPosture: protocol.AuthenticationPostureResponse(
84
+ providerToken: providerToken,
85
+ enrolledDevice: enrolledDevice,
86
+ resolvedPrincipal: resolvedPrincipal,
87
+ ),
88
+ ),
89
+ );
90
+ }
91
+ return protocol.CallResponse(
92
+ protocolVersion: 1,
93
+ requestId: request.requestId,
94
+ offer: protocol.OfferResponse(
95
+ admitted: protocol.OfferAdmitted(
96
+ head: 'HEAD-offer',
97
+ intentId: 'intent-offer',
98
+ ),
99
+ ),
100
+ );
101
+ }
102
+ }
103
+
104
+ void main() {
105
+ test('law-selected enrolled-device proof withholds the provider token',
106
+ () async {
107
+ final transport = _ProofTransport();
108
+ final bridge = NomosBridge(transport);
109
+ addTearDown(bridge.dispose);
110
+ final secret = base64Encode(List<int>.filled(32, 7));
111
+ await bridge.ready;
112
+ await bridge.connect(
113
+ workspace: 'home',
114
+ session: 'home',
115
+ authorSecret: secret,
116
+ authToken: 'stale.provider.token',
117
+ );
118
+ final call = NmsInternalGeneratedCalls.create(
119
+ domain: 'identity',
120
+ directive: 'recoverProvider',
121
+ canonicalUsda: Uint8List.fromList([1]),
122
+ );
123
+
124
+ await bridge.session('home').offerCallUsdaOutcome(call: call);
125
+ expect(transport.lastCall!.offer.authoring.authToken, isNotEmpty);
126
+ expect(transport.lastCall!.offer.authoring.authorSecret, isNotEmpty);
127
+
128
+ await bridge.session('home').offerCallUsdaOutcome(
129
+ call: call,
130
+ authenticationProof: NomosOfferAuthenticationProof.enrolledDevice,
131
+ );
132
+ expect(transport.lastCall!.offer.authoring.authToken, isEmpty);
133
+ expect(transport.lastCall!.offer.authoring.authorSecret, isNotEmpty);
134
+ });
135
+
136
+ test('enrolled-device proof fails before transport without a device key',
137
+ () async {
138
+ final transport = _ProofTransport();
139
+ final bridge = NomosBridge(transport);
140
+ addTearDown(bridge.dispose);
141
+ await bridge.ready;
142
+ await bridge.connect(
143
+ workspace: 'home',
144
+ session: 'home',
145
+ authToken: 'stale.provider.token',
146
+ );
147
+ final call = NmsInternalGeneratedCalls.create(
148
+ domain: 'identity',
149
+ directive: 'recoverProvider',
150
+ canonicalUsda: Uint8List.fromList([1]),
151
+ );
152
+
153
+ await expectLater(
154
+ bridge.session('home').offerCallUsdaOutcome(
155
+ call: call,
156
+ authenticationProof: NomosOfferAuthenticationProof.enrolledDevice,
157
+ ),
158
+ throwsA(isA<StateError>()),
159
+ );
160
+ expect(transport.lastCall, isNull);
161
+ });
162
+
163
+ test('authentication recovery waits for the exact typed kernel postcondition',
164
+ () async {
165
+ final transport = _ProofTransport();
166
+ final bridge = NomosBridge(transport);
167
+ addTearDown(bridge.dispose);
168
+ final secret = base64Encode(List<int>.filled(32, 7));
169
+ await bridge.ready;
170
+ await bridge.connect(
171
+ workspace: 'home',
172
+ session: 'home',
173
+ authorSecret: secret,
174
+ authToken: 'stale.provider.token',
175
+ );
176
+ final home = bridge.session('home');
177
+
178
+ final before = await home.nmsAuthenticationPosture(principal: 'user:jack');
179
+ expect(
180
+ before.providerToken,
181
+ NomosProviderTokenVerification.noMatchingKey,
182
+ );
183
+ expect(before.enrolledDevice, isTrue);
184
+
185
+ final after = await home.nmsAwaitAuthenticationReady(
186
+ principal: 'user:jack',
187
+ );
188
+ expect(after.providerToken, NomosProviderTokenVerification.valid);
189
+ expect(after.enrolledDevice, isTrue);
190
+ expect(after.resolvedPrincipal, 'user:jack');
191
+ expect(transport.syncCalls, 1);
192
+ });
193
+ }
@@ -0,0 +1,49 @@
1
+ import 'dart:convert';
2
+ import 'dart:typed_data';
3
+
4
+ import 'package:nomos_client/src/nms_generated_runtime.dart';
5
+ import 'package:test/test.dart';
6
+
7
+ void main() {
8
+ test('parses canonical nominal rows without a generic result map', () {
9
+ final result = NmsUsdaResult.parse(
10
+ Uint8List.fromList(
11
+ utf8.encode('''#usda 1.0
12
+ (
13
+ defaultPrim = "Result"
14
+ )
15
+
16
+ def NomosReadResult "Result"
17
+ {
18
+ custom uniform bool nomos:done = true
19
+
20
+ def NomosListValue "Rows"
21
+ {
22
+ def NomosRecordValue "i_00000000"
23
+ {
24
+ custom uniform string nomos:id = "note:1"
25
+ custom rel nomos:type = </Nomos/Domains/d_1/Aggregates/a_note>
26
+
27
+ def NomosStringValue "f_title"
28
+ {
29
+ custom rel nomos:field = </Nomos/Domains/d_1/Aggregates/a_note/Fields/f_title>
30
+ custom uniform string nomos:value = "Ship"
31
+ }
32
+ }
33
+ }
34
+ }
35
+ '''),
36
+ ),
37
+ );
38
+
39
+ expect(result.done, isTrue);
40
+ expect(result.rows.single.relationship('nomos:type'),
41
+ '/Nomos/Domains/d_1/Aggregates/a_note');
42
+ expect(
43
+ result.rows.single
44
+ .requiredField('/Nomos/Domains/d_1/Aggregates/a_note/Fields/f_title')
45
+ .stringValue(),
46
+ 'Ship',
47
+ );
48
+ });
49
+ }
@@ -59,7 +59,7 @@ Future<NomosTestHarness> _harness() => NomosTestHarness.ephemeral(
59
59
  );
60
60
 
61
61
  Future<NomosOfferOutcome> _birthEstate(
62
- NomosSession session,
62
+ HomeApplication application,
63
63
  NomosTestHarness harness, {
64
64
  String owner = _owner,
65
65
  }) {
@@ -69,12 +69,7 @@ Future<NomosOfferOutcome> _birthEstate(
69
69
  lawHash: harness.lawHashes(harness.workspace).first,
70
70
  bornAt: DateTime.now().toUtc().toIso8601String(),
71
71
  );
72
- return session.offerOutcome(
73
- domain: 'home',
74
- directiveId: 'birthEstateWorkspace',
75
- payload: facts.nmsInternalToPayloadJson(),
76
- actor: owner,
77
- );
72
+ return nomosInternalHomeBirthEstateWorkspace(application, facts);
78
73
  }
79
74
 
80
75
  void main() {
@@ -124,14 +119,15 @@ void main() {
124
119
  // This fixture predates businessBirth and intentionally keeps its kernel birth
125
120
  // primitive out of the generated tenant application. The raw offer is framework
126
121
  // setup; the generated application remains the only public business surface.
127
- final birth = await _birthEstate(home, harness);
122
+ final birth = await _birthEstate(homeApplication, harness);
128
123
  expect(birth.workspace, harness.workspace,
129
124
  reason:
130
125
  'the birth offer landed in the SESSION workspace, no loose parent');
131
126
  expect(birth.gatewayVerdict, isNull,
132
127
  reason: 'the local offer lane, not the legacy relay');
133
128
  expect(birth.born, hasLength(1));
134
- expect(birth.birthOutcomes.first['status'], 'born');
129
+ expect(birth.birthOutcomes.first.status,
130
+ NomosBirthOutcomeStatus.BIRTH_OUTCOME_STATUS_BORN);
135
131
 
136
132
  // FOLLOW THE REF (ask 8): NomosRef in, mounted session out — never a string pair.
137
133
  final estate = await harness.bridge.follow(birth.bornRefs.single,
@@ -184,8 +180,9 @@ void main() {
184
180
  // emitted, regardless of ticks. The fix delegates to the parent plane like every other
185
181
  // reactive read; the first tick must deliver a snapshot (empty — no Surfaced law here).
186
182
  final first = session.watchPendingConflicts().first;
187
- await nomosInternalBindHomeApplication(session, _owner);
188
- await _birthEstate(session, harness);
183
+ final application =
184
+ await nomosInternalBindHomeApplication(session, _owner);
185
+ await _birthEstate(application, harness);
189
186
  final rows = await first.timeout(const Duration(seconds: 30));
190
187
  expect(rows, isEmpty,
191
188
  reason:
@@ -4,6 +4,7 @@
4
4
  import 'dart:async';
5
5
 
6
6
  import 'package:nomos_client/src/nms_conformance_runtime.dart';
7
+ import 'package:nomos_types/nomos_kernel_protocol.dart' as protocol;
7
8
  import 'package:test/test.dart';
8
9
 
9
10
  class _StampedRunner implements BridgeTransport {
@@ -19,16 +20,29 @@ class _StampedRunner implements BridgeTransport {
19
20
  @override
20
21
  Stream<Map<String, Object?>> get messages => _incoming.stream;
21
22
  @override
23
+ Future<protocol.RuntimeResponse> invokeRuntime(
24
+ protocol.RuntimeRequest request,
25
+ ) async =>
26
+ protocol.RuntimeResponse(
27
+ protocolVersion: 2,
28
+ requestId: request.requestId,
29
+ realmClosed: protocol.RealmClosed(),
30
+ );
31
+ @override
22
32
  void send(Map<String, Object?> message) {}
23
33
  }
24
34
 
25
35
  void main() {
26
- test('a PRE-STAMP bundle (no bundleVersion) fails ready with StaleRunnerBundle', () async {
36
+ test(
37
+ 'a PRE-STAMP bundle (no bundleVersion) fails ready with StaleRunnerBundle',
38
+ () async {
27
39
  final b = NomosBridge(_StampedRunner(null));
28
40
  await expectLater(b.ready, throwsA(isA<StaleRunnerBundle>()));
29
41
  });
30
42
 
31
- test('an OLDER stamp fails ready, and the error names found/expected + the remedy', () async {
43
+ test(
44
+ 'an OLDER stamp fails ready, and the error names found/expected + the remedy',
45
+ () async {
32
46
  final b = NomosBridge(_StampedRunner('0.53.1'));
33
47
  Object? err;
34
48
  try {
@@ -59,7 +73,8 @@ void main() {
59
73
  });
60
74
 
61
75
  test('allowStaleRunnerBundle is the deliberate escape hatch', () async {
62
- final b = NomosBridge(_StampedRunner('0.1.0'), allowStaleRunnerBundle: true);
76
+ final b =
77
+ NomosBridge(_StampedRunner('0.1.0'), allowStaleRunnerBundle: true);
63
78
  await b.ready;
64
79
  });
65
80
  }
@@ -11,7 +11,10 @@ library;
11
11
 
12
12
  import 'dart:io';
13
13
 
14
+ import 'package:fixnum/fixnum.dart' show Int64;
14
15
  import 'package:nomos_client/src/nms_conformance_runtime.dart';
16
+ import 'package:nomos_types/nomos_kernel_protocol.dart'
17
+ show RuntimeTransportFailure, SyncWorkspaceResponse;
15
18
  import 'package:test/test.dart';
16
19
 
17
20
  String get _repoEntry =>
@@ -46,35 +49,19 @@ void main() {
46
49
  'convergence never reports rejected or dead-lettered business work as success',
47
50
  () {
48
51
  expect(
49
- nmsPermanentConvergenceFailure({
50
- 'stillAhead': false,
51
- 'admission': {
52
- 'ok': true,
53
- 'sessions': [
54
- {
55
- 'rejected': [
56
- {'directiveId': 'commissionAsset', 'error': 'event-mismatch'}
57
- ]
58
- }
59
- ],
60
- 'deadLetters': [
61
- {'directiveId': 'commissionAsset', 'error': 'event-mismatch'}
62
- ],
63
- },
64
- }),
65
- contains('commissionAsset'));
52
+ nmsPermanentConvergenceFailure(
53
+ SyncWorkspaceResponse(refused: Int64.ONE),
54
+ ),
55
+ contains('refused=1'));
66
56
  expect(
67
- nmsPermanentConvergenceFailure({
68
- 'stillAhead': false,
69
- 'pushError': {'refused': true, 'error': 'policy-refused'},
70
- }),
57
+ nmsPermanentConvergenceFailure(SyncWorkspaceResponse(
58
+ pushError: RuntimeTransportFailure(
59
+ refused: true,
60
+ message: 'policy-refused',
61
+ ),
62
+ )),
71
63
  contains('policy-refused'));
72
- expect(
73
- nmsPermanentConvergenceFailure({
74
- 'stillAhead': false,
75
- 'admission': {'ok': true, 'sessions': const []},
76
- }),
77
- isNull);
64
+ expect(nmsPermanentConvergenceFailure(SyncWorkspaceResponse()), isNull);
78
65
  });
79
66
 
80
67
  test('ephemeral rejects an empty deploy list with a named remedy', () async {