@githolon/dsl 0.106.0 → 0.107.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.
@@ -104,56 +104,62 @@ final class NomosBirthCertificate {
104
104
  Map<String, Object?> wire,
105
105
  String camel,
106
106
  String snake,
107
- ) => (wire[camel] ?? wire[snake] ?? '').toString();
107
+ ) =>
108
+ (wire[camel] ?? wire[snake] ?? '').toString();
108
109
 
109
110
  static List<int> _bytes(
110
111
  Map<String, Object?> wire,
111
112
  String camel,
112
113
  String snake,
113
- ) => ((wire[camel] ?? wire[snake]) as List? ?? const <Object?>[])
114
- .map((value) => (value as num).toInt())
115
- .toList(growable: false);
114
+ ) =>
115
+ ((wire[camel] ?? wire[snake]) as List? ?? const <Object?>[])
116
+ .map((value) => (value as num).toInt())
117
+ .toList(growable: false);
116
118
 
117
119
  factory NomosBirthCertificate.fromWire(
118
120
  Map<String, Object?> wire,
119
- ) => NomosBirthCertificate(
120
- child: _string(wire, 'child', 'child'),
121
- founder: _string(wire, 'founder', 'founder'),
122
- verified: wire['verified'] == true,
123
- parentKey: _bytes(wire, 'parentKey', 'parent_key'),
124
- parentId: _string(wire, 'parentId', 'parent_id'),
125
- epoch: (wire['epoch'] as num?)?.toInt() ?? 0,
126
- signature: _bytes(wire, 'signature', 'signature'),
127
- verifiedVia: (wire['verifiedVia'] ?? wire['verified_via'])?.toString(),
128
- idpToken: (wire['idpToken'] ?? wire['idp_token'])?.toString(),
129
- capturedClock: ((wire['capturedClock'] ?? wire['captured_clock']) as num?)
130
- ?.toInt(),
131
- authProviderIssuer:
132
- (wire['authProviderIssuer'] ?? wire['auth_provider_issuer'])
133
- ?.toString(),
134
- authProviderJwks: (wire['authProviderJwks'] ?? wire['auth_provider_jwks'])
135
- ?.toString(),
136
- authProviderAudience:
137
- (wire['authProviderAudience'] ?? wire['auth_provider_audience'])
138
- ?.toString(),
139
- );
121
+ ) =>
122
+ NomosBirthCertificate(
123
+ child: _string(wire, 'child', 'child'),
124
+ founder: _string(wire, 'founder', 'founder'),
125
+ verified: wire['verified'] == true,
126
+ parentKey: _bytes(wire, 'parentKey', 'parent_key'),
127
+ parentId: _string(wire, 'parentId', 'parent_id'),
128
+ epoch: (wire['epoch'] as num?)?.toInt() ?? 0,
129
+ signature: _bytes(wire, 'signature', 'signature'),
130
+ verifiedVia: (wire['verifiedVia'] ?? wire['verified_via'])?.toString(),
131
+ idpToken: (wire['idpToken'] ?? wire['idp_token'])?.toString(),
132
+ capturedClock:
133
+ ((wire['capturedClock'] ?? wire['captured_clock']) as num?)
134
+ ?.toInt(),
135
+ authProviderIssuer:
136
+ (wire['authProviderIssuer'] ?? wire['auth_provider_issuer'])
137
+ ?.toString(),
138
+ authProviderJwks:
139
+ (wire['authProviderJwks'] ?? wire['auth_provider_jwks'])
140
+ ?.toString(),
141
+ authProviderAudience:
142
+ (wire['authProviderAudience'] ?? wire['auth_provider_audience'])
143
+ ?.toString(),
144
+ );
140
145
 
141
146
  Map<String, Object?> toWire() => <String, Object?>{
142
- 'child': child,
143
- 'founder': founder,
144
- 'verified': verified,
145
- 'parentKey': parentKey,
146
- 'parentId': parentId,
147
- 'epoch': epoch,
148
- 'signature': signature,
149
- if (verifiedVia != null) 'verifiedVia': verifiedVia,
150
- if (idpToken != null) 'idpToken': idpToken,
151
- if (capturedClock != null) 'capturedClock': capturedClock,
152
- if (authProviderIssuer != null) 'authProviderIssuer': authProviderIssuer,
153
- if (authProviderJwks != null) 'authProviderJwks': authProviderJwks,
154
- if (authProviderAudience != null)
155
- 'authProviderAudience': authProviderAudience,
156
- };
147
+ 'child': child,
148
+ 'founder': founder,
149
+ 'verified': verified,
150
+ 'parentKey': parentKey,
151
+ 'parentId': parentId,
152
+ 'epoch': epoch,
153
+ 'signature': signature,
154
+ if (verifiedVia != null) 'verifiedVia': verifiedVia,
155
+ if (idpToken != null) 'idpToken': idpToken,
156
+ if (capturedClock != null) 'capturedClock': capturedClock,
157
+ if (authProviderIssuer != null)
158
+ 'authProviderIssuer': authProviderIssuer,
159
+ if (authProviderJwks != null) 'authProviderJwks': authProviderJwks,
160
+ if (authProviderAudience != null)
161
+ 'authProviderAudience': authProviderAudience,
162
+ };
157
163
  }
158
164
 
159
165
  /// Facts signed by [NomosBridge.signBirthCert]. The secret remains a separate argument and never
@@ -188,20 +194,21 @@ final class NomosBirthCertificateSpec {
188
194
  final String? authProviderAudience;
189
195
 
190
196
  Map<String, Object?> toWire() => <String, Object?>{
191
- 'child': child,
192
- 'founder': founder,
193
- 'verified': verified,
194
- 'parentKey': parentKey,
195
- 'parentId': parentId,
196
- 'epoch': epoch,
197
- if (verifiedVia != null) 'verifiedVia': verifiedVia,
198
- if (idpToken != null) 'idpToken': idpToken,
199
- if (capturedClock != null) 'capturedClock': capturedClock,
200
- if (authProviderIssuer != null) 'authProviderIssuer': authProviderIssuer,
201
- if (authProviderJwks != null) 'authProviderJwks': authProviderJwks,
202
- if (authProviderAudience != null)
203
- 'authProviderAudience': authProviderAudience,
204
- };
197
+ 'child': child,
198
+ 'founder': founder,
199
+ 'verified': verified,
200
+ 'parentKey': parentKey,
201
+ 'parentId': parentId,
202
+ 'epoch': epoch,
203
+ if (verifiedVia != null) 'verifiedVia': verifiedVia,
204
+ if (idpToken != null) 'idpToken': idpToken,
205
+ if (capturedClock != null) 'capturedClock': capturedClock,
206
+ if (authProviderIssuer != null)
207
+ 'authProviderIssuer': authProviderIssuer,
208
+ if (authProviderJwks != null) 'authProviderJwks': authProviderJwks,
209
+ if (authProviderAudience != null)
210
+ 'authProviderAudience': authProviderAudience,
211
+ };
205
212
  }
206
213
 
207
214
  /// The protocol version the runner and the bridge agree on (`webview-runner.mjs` `WEBVIEW_BRIDGE_VERSION`).
@@ -268,6 +275,119 @@ class TransferProgress {
268
275
  );
269
276
  }
270
277
 
278
+ enum KernelProgressOperation { unspecified, restoreMain }
279
+
280
+ enum KernelProgressPhase {
281
+ unspecified,
282
+ checkCustody,
283
+ readChain,
284
+ initializeEngine,
285
+ readTimeline,
286
+ hydrateLaw,
287
+ recoveryPrescan,
288
+ verifyIntents,
289
+ promoteCustody,
290
+ rebuildFrontier,
291
+ complete,
292
+ }
293
+
294
+ enum KernelProgressUnit { unspecified, intent, lawPackage }
295
+
296
+ enum KernelLawHydrationStep {
297
+ unspecified,
298
+ readClosure,
299
+ composeStage,
300
+ deriveSchemas,
301
+ loadPolicyShell,
302
+ packageComplete,
303
+ }
304
+
305
+ /// Typed, authority-free progress from a long-running kernel operation.
306
+ ///
307
+ /// Unlike a spinner, [fraction] is derived from work the canonical kernel has
308
+ /// actually completed. This is ephemeral execution telemetry: it cannot enter
309
+ /// custody or authorize an effect.
310
+ final class KernelProgress {
311
+ const KernelProgress({
312
+ required this.sequence,
313
+ required this.operation,
314
+ required this.phase,
315
+ required this.completed,
316
+ required this.total,
317
+ required this.unit,
318
+ required this.terminal,
319
+ required this.lawHydrationStep,
320
+ required this.lawPackageSha256,
321
+ required this.hostObservedElapsedMicros,
322
+ required this.hostObservedPhaseElapsedMicros,
323
+ required this.kernelAllocatorLiveBytes,
324
+ required this.kernelAllocatorPeakBytes,
325
+ required this.processResidentBytes,
326
+ required this.processPeakResidentBytes,
327
+ });
328
+
329
+ final int sequence;
330
+ final KernelProgressOperation operation;
331
+ final KernelProgressPhase phase;
332
+ final int completed;
333
+ final int total;
334
+ final KernelProgressUnit unit;
335
+ final bool terminal;
336
+ final KernelLawHydrationStep lawHydrationStep;
337
+ final String lawPackageSha256;
338
+ final int hostObservedElapsedMicros;
339
+ final int hostObservedPhaseElapsedMicros;
340
+ final int kernelAllocatorLiveBytes;
341
+ final int kernelAllocatorPeakBytes;
342
+ final int processResidentBytes;
343
+ final int processPeakResidentBytes;
344
+
345
+ int get unaccountedResidentBytes {
346
+ final remainder = processResidentBytes - kernelAllocatorLiveBytes;
347
+ return remainder > 0 ? remainder : 0;
348
+ }
349
+
350
+ double? get fraction =>
351
+ (total <= 0) ? null : (completed / total).clamp(0.0, 1.0);
352
+
353
+ factory KernelProgress.fromMessage(Map<String, Object?> message) =>
354
+ KernelProgress(
355
+ sequence: _wireInteger(message['sequence']) ?? 0,
356
+ operation: KernelProgressOperation.values.firstWhere(
357
+ (value) => value.name == message['operation'],
358
+ orElse: () => KernelProgressOperation.unspecified,
359
+ ),
360
+ phase: KernelProgressPhase.values.firstWhere(
361
+ (value) => value.name == message['phase'],
362
+ orElse: () => KernelProgressPhase.unspecified,
363
+ ),
364
+ completed: _wireInteger(message['completed']) ?? 0,
365
+ total: _wireInteger(message['total']) ?? 0,
366
+ unit: KernelProgressUnit.values.firstWhere(
367
+ (value) => value.name == message['unit'],
368
+ orElse: () => KernelProgressUnit.unspecified,
369
+ ),
370
+ terminal: message['terminal'] == true,
371
+ lawHydrationStep: KernelLawHydrationStep.values.firstWhere(
372
+ (value) => value.name == message['lawHydrationStep'],
373
+ orElse: () => KernelLawHydrationStep.unspecified,
374
+ ),
375
+ lawPackageSha256: message['lawPackageSha256']?.toString() ?? '',
376
+ hostObservedElapsedMicros:
377
+ _wireInteger(message['hostObservedElapsedMicros']) ?? 0,
378
+ hostObservedPhaseElapsedMicros:
379
+ _wireInteger(message['hostObservedPhaseElapsedMicros']) ?? 0,
380
+ kernelAllocatorLiveBytes:
381
+ _wireInteger(message['kernelAllocatorLiveBytes']) ?? 0,
382
+ kernelAllocatorPeakBytes:
383
+ _wireInteger(message['kernelAllocatorPeakBytes']) ?? 0,
384
+ processResidentBytes:
385
+ _wireInteger(message['processResidentBytes']) ?? 0,
386
+ processPeakResidentBytes:
387
+ _wireInteger(message['processPeakResidentBytes']) ?? 0,
388
+ );
389
+ }
390
+
271
391
  int? _wireInteger(Object? value) => value is num ? value.toInt() : null;
272
392
 
273
393
  /// One opaque point in this workspace's verified history. Applications use it as the handle passed to a
@@ -339,17 +459,18 @@ class SyncStatus {
339
459
  DateTime? lastSyncedAt,
340
460
  String? lastError,
341
461
  bool clearError = false,
342
- }) => SyncStatus(
343
- phase: phase ?? this.phase,
344
- ahead: ahead ?? this.ahead,
345
- behind: behind ?? this.behind,
346
- saved: saved ?? this.saved,
347
- onMain: onMain ?? this.onMain,
348
- deadLetters: deadLetters ?? this.deadLetters,
349
- transfer: clearTransfer ? null : (transfer ?? this.transfer),
350
- lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt,
351
- lastError: clearError ? null : (lastError ?? this.lastError),
352
- );
462
+ }) =>
463
+ SyncStatus(
464
+ phase: phase ?? this.phase,
465
+ ahead: ahead ?? this.ahead,
466
+ behind: behind ?? this.behind,
467
+ saved: saved ?? this.saved,
468
+ onMain: onMain ?? this.onMain,
469
+ deadLetters: deadLetters ?? this.deadLetters,
470
+ transfer: clearTransfer ? null : (transfer ?? this.transfer),
471
+ lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt,
472
+ lastError: clearError ? null : (lastError ?? this.lastError),
473
+ );
353
474
  }
354
475
 
355
476
  bool _sameTransferProgress(TransferProgress? left, TransferProgress? right) =>
@@ -389,10 +510,10 @@ class NomosCreated {
389
510
  /// The canonical [NomosRef] view — the `{workspace,type,id}` triple, followable/serializable
390
511
  /// (`nomos://<workspace>/<type>/<id>`). One reference, everywhere.
391
512
  NomosRef<Object?> get ref => NmsInternalNomosRefs.create<Object?>(
392
- workspace: workspace,
393
- type: type,
394
- id: id,
395
- );
513
+ workspace: workspace,
514
+ type: type,
515
+ id: id,
516
+ );
396
517
  @override
397
518
  String toString() => id;
398
519
  }
@@ -419,10 +540,10 @@ class NomosBbox {
419
540
  double? minLat,
420
541
  double? maxLng,
421
542
  double? maxLat,
422
- }) : minX = (minX ?? minLng)!,
423
- minY = (minY ?? minLat)!,
424
- maxX = (maxX ?? maxLng)!,
425
- maxY = (maxY ?? maxLat)!;
543
+ }) : minX = (minX ?? minLng)!,
544
+ minY = (minY ?? minLat)!,
545
+ maxX = (maxX ?? maxLng)!,
546
+ maxY = (maxY ?? maxLat)!;
426
547
 
427
548
  /// Deprecated geographic accessors — spatial axes are generic. Prefer [minX]/[minY]/[maxX]/[maxY].
428
549
  @Deprecated(
@@ -443,16 +564,16 @@ class NomosBbox {
443
564
  double get maxLat => maxY;
444
565
 
445
566
  Map<String, Object?> toJson() => {
446
- 'minX': minX,
447
- 'minY': minY,
448
- 'maxX': maxX,
449
- 'maxY': maxY,
450
- // Geographic aliases so a pre-genericisation runner (which reads minLng/…) still works.
451
- 'minLng': minX,
452
- 'minLat': minY,
453
- 'maxLng': maxX,
454
- 'maxLat': maxY,
455
- };
567
+ 'minX': minX,
568
+ 'minY': minY,
569
+ 'maxX': maxX,
570
+ 'maxY': maxY,
571
+ // Geographic aliases so a pre-genericisation runner (which reads minLng/…) still works.
572
+ 'minLng': minX,
573
+ 'minLat': minY,
574
+ 'maxLng': maxX,
575
+ 'maxLat': maxY,
576
+ };
456
577
  }
457
578
 
458
579
  /// One member's structural compat verdict — `ok`, plus the exact break [reason] when not.
@@ -513,9 +634,8 @@ class NomosCompat {
513
634
  final install = (m['install'] as Map?)?.cast<String, Object?>() ?? const {};
514
635
  return NomosCompat(
515
636
  generatedFor: (m['generatedFor'] as String?) ?? '',
516
- workspaceRuns: ((m['workspaceRuns'] as List?) ?? const [])
517
- .map((e) => '$e')
518
- .toList(),
637
+ workspaceRuns:
638
+ ((m['workspaceRuns'] as List?) ?? const []).map((e) => '$e').toList(),
519
639
  matches: m['matches'] == true,
520
640
  offerKnown: m['offerKnown'] == true,
521
641
  structurallyCompatible: m['structurallyCompatible'] as bool?,
@@ -554,13 +674,13 @@ class NomosScopeKey {
554
674
  this.workspace,
555
675
  });
556
676
  Map<String, Object?> toJson() => {
557
- 'scope': scope,
558
- 'epoch': epoch,
559
- 'key': key,
560
- if (ownedKeySubject != null) 'ownedKeySubject': ownedKeySubject,
561
- if (ownedCustody != null) 'ownedCustody': ownedCustody,
562
- if (workspace != null) 'workspace': workspace,
563
- };
677
+ 'scope': scope,
678
+ 'epoch': epoch,
679
+ 'key': key,
680
+ if (ownedKeySubject != null) 'ownedKeySubject': ownedKeySubject,
681
+ if (ownedCustody != null) 'ownedCustody': ownedCustody,
682
+ if (workspace != null) 'workspace': workspace,
683
+ };
564
684
  }
565
685
 
566
686
  /// The entire app-facing multi-device surface for owned business state. The request is deliberately an
@@ -790,7 +910,7 @@ class BirthIncomplete implements Exception {
790
910
  return 'BirthIncomplete: ${failedBirths.length} child workspace(s) did NOT come up — $list. '
791
911
  'The parent offer admitted, but the child was not fully born, so opening it would poll head:null '
792
912
  'until timeout. ${lawUnavailable ? "The child's law package is not resolvable from the parent's "
793
- "custody — deploy it to the parent (POST /v2/workspaces/<parent>/domains) BEFORE birthing." : "See the outcome's reason/code."}';
913
+ "custody — deploy it to the parent (POST /v2/workspaces/<parent>/domains) BEFORE birthing." : "See the outcome's reason/code."}';
794
914
  }
795
915
  }
796
916
 
@@ -852,14 +972,13 @@ class NomosEncryption {
852
972
  final subjects = rows.isEmpty
853
973
  ? const <String, dynamic>{}
854
974
  : ((rows.first['data'] as Map?)?['subjects'] as Map?) ??
855
- const <String, dynamic>{};
975
+ const <String, dynamic>{};
856
976
  final out = <String>[];
857
977
  subjects.forEach((subj, leafRaw) {
858
978
  Map? leaf;
859
979
  try {
860
- leaf = leafRaw is String
861
- ? jsonDecode(leafRaw) as Map
862
- : (leafRaw as Map);
980
+ leaf =
981
+ leafRaw is String ? jsonDecode(leafRaw) as Map : (leafRaw as Map);
863
982
  } catch (_) {
864
983
  leaf = null;
865
984
  }
@@ -986,7 +1105,8 @@ class NomosEncryption {
986
1105
  },
987
1106
  actor: actor,
988
1107
  domainHash: domainHash,
989
- )).head;
1108
+ ))
1109
+ .head;
990
1110
  return NomosEpochResult(head: head, epoch: epoch, roster: members);
991
1111
  }
992
1112
 
@@ -1060,13 +1180,14 @@ class NomosEncryption {
1060
1180
  Map<String, String>? memberKeys,
1061
1181
  List<String>? expectRoster,
1062
1182
  String? openedAt,
1063
- }) => _advance(
1064
- _defScope(scope),
1065
- scopeKey: scopeKey,
1066
- memberKeys: memberKeys,
1067
- expectRoster: expectRoster,
1068
- openedAt: openedAt,
1069
- );
1183
+ }) =>
1184
+ _advance(
1185
+ _defScope(scope),
1186
+ scopeKey: scopeKey,
1187
+ memberKeys: memberKeys,
1188
+ expectRoster: expectRoster,
1189
+ openedAt: openedAt,
1190
+ );
1070
1191
  }
1071
1192
 
1072
1193
  /// The result of [NomosBridge.offerCreates]: the new local [head], every aggregate the plan minted, and —
@@ -1091,8 +1212,9 @@ final class NomosOperationStatus {
1091
1212
  /// adopted that shared position. Callers never inspect workspaces, URLs, credentials, headers or Git heads.
1092
1213
  final class NomosOperationReceipt {
1093
1214
  NomosOperationReceipt._()
1094
- : _status = const NomosOperationStatus(NomosOperationPhase.locallyAccepted),
1095
- _changes = StreamController<NomosOperationStatus>.broadcast();
1215
+ : _status =
1216
+ const NomosOperationStatus(NomosOperationPhase.locallyAccepted),
1217
+ _changes = StreamController<NomosOperationStatus>.broadcast();
1096
1218
 
1097
1219
  NomosOperationStatus _status;
1098
1220
  final StreamController<NomosOperationStatus> _changes;
@@ -1307,12 +1429,14 @@ class NomosBridge {
1307
1429
  []; // recent span events — so BOOT spans (emitted during connect, before the UI subscribes) survive
1308
1430
  final StreamController<TransferProgress> _transferEvents =
1309
1431
  StreamController<TransferProgress>.broadcast();
1432
+ final StreamController<KernelProgress> _kernelProgressEvents =
1433
+ StreamController<KernelProgress>.broadcast();
1310
1434
  // The DERIVED app-ready sync state. seeded-on-listen with a metrics poll; updated on sync/signal/transfer.
1311
1435
  late final StreamController<SyncStatus> _syncStatusCtrl =
1312
1436
  StreamController<SyncStatus>.broadcast(
1313
- onListen: _startStatusPoll,
1314
- onCancel: _stopStatusPollIfUnused,
1315
- );
1437
+ onListen: _startStatusPoll,
1438
+ onCancel: _stopStatusPollIfUnused,
1439
+ );
1316
1440
  SyncStatus _status = const SyncStatus();
1317
1441
  final Map<String, SyncStatus> _statusBySession = {};
1318
1442
  final Map<String, StreamController<SyncStatus>> _syncStatusBySession = {};
@@ -1349,7 +1473,7 @@ class NomosBridge {
1349
1473
  // child sessions. The callback receives only the typed review object; child
1350
1474
  // addresses, archives, credentials and lifecycle directives remain private.
1351
1475
  final Map<String, Future<void> Function(DomainClientModelAdoptionRequired)>
1352
- _sessionModelChangeHandlers = {};
1476
+ _sessionModelChangeHandlers = {};
1353
1477
  // [acquireSession]'s per-workspace single-flight: workspace → the in-flight open every concurrent
1354
1478
  // acquirer joins (removed when it completes; a live session then hits the fast path instead).
1355
1479
  final Map<String, Future<NomosSession>> _acquiring = {};
@@ -1621,6 +1745,12 @@ class NomosBridge {
1621
1745
  );
1622
1746
  return;
1623
1747
  }
1748
+ if (event == 'kernelProgress') {
1749
+ if (!_kernelProgressEvents.isClosed) {
1750
+ _kernelProgressEvents.add(KernelProgress.fromMessage(m));
1751
+ }
1752
+ return;
1753
+ }
1624
1754
  if (event == 'trace') {
1625
1755
  // the realtime cloud flamepath: { event:'trace', trace:{at, oid, edge, clients} } — one per admission.
1626
1756
  if (!_flameEvents.isClosed) _flameEvents.add(m);
@@ -1801,8 +1931,8 @@ class NomosBridge {
1801
1931
  final push = (result['pushError'] as Map?)?.cast<String, Object?>();
1802
1932
  final status = push?['status'];
1803
1933
  if (status == 401 || status == 403) return true;
1804
- final text = '${message['error'] ?? ''} ${push?['error'] ?? ''}'
1805
- .toLowerCase();
1934
+ final text =
1935
+ '${message['error'] ?? ''} ${push?['error'] ?? ''}'.toLowerCase();
1806
1936
  return text.contains('unauthenticated') ||
1807
1937
  text.contains('token expired') ||
1808
1938
  text.contains('invalid token');
@@ -1899,21 +2029,20 @@ class NomosBridge {
1899
2029
  const [])
1900
2030
  .map((e) => (e as Map).cast<String, Object?>())
1901
2031
  .map((w) {
1902
- final ws = w['workspace']?.toString() ?? '';
1903
- // `connected` is the app's own connect() truth; `parked`/resident come from the runner realm.
1904
- w['state'] = (w['parked'] == true)
1905
- ? 'parked'
1906
- : (connected.contains(ws) ? 'connected' : 'resident');
1907
- return w;
1908
- })
1909
- .toList();
2032
+ final ws = w['workspace']?.toString() ?? '';
2033
+ // `connected` is the app's own connect() truth; `parked`/resident come from the runner realm.
2034
+ w['state'] = (w['parked'] == true)
2035
+ ? 'parked'
2036
+ : (connected.contains(ws) ? 'connected' : 'resident');
2037
+ return w;
2038
+ }).toList();
1910
2039
  }
1911
2040
 
1912
2041
  /// Framework-private plane persistence primitive. It snapshots exact local custody even when [workspace]
1913
2042
  /// was born in the kernel but no Dart runner session has ever acquired it. This does not connect, mount a
1914
2043
  /// tenant session, fetch from cloud, or grant authority; the serving realm exports its resident plane view.
1915
2044
  Future<({String workspace, String head, String? snapshot, bool unchanged})>
1916
- nomosInternalSnapshotWorkspace(String workspace, {String? ifHead}) async {
2045
+ nomosInternalSnapshotWorkspace(String workspace, {String? ifHead}) async {
1917
2046
  final r = _asMap(
1918
2047
  await _call('snapshotWorkspace', {
1919
2048
  'workspace': workspace,
@@ -1995,8 +2124,8 @@ class NomosBridge {
1995
2124
  if (authorSecret != null && authorSecret.isNotEmpty) {
1996
2125
  _eventPlane._sessionAuthorSecrets[ws] = authorSecret;
1997
2126
  }
1998
- _eventPlane._lastRecovery = (r['recovery'] as Map?)
1999
- ?.cast<String, Object?>();
2127
+ _eventPlane._lastRecovery =
2128
+ (r['recovery'] as Map?)?.cast<String, Object?>();
2000
2129
  if (_eventPlane._syncStatusCtrl.hasListener) {
2001
2130
  unawaited(_eventPlane._pollMetricsOnce());
2002
2131
  }
@@ -2032,12 +2161,13 @@ class NomosBridge {
2032
2161
  Future<Map<String, Object?>> resolveCustodyBreak(
2033
2162
  String decision, {
2034
2163
  String? session,
2035
- }) async => _asMap(
2036
- await _call('resolveCustodyBreak', {
2037
- 'decision': decision,
2038
- if (session != null) 'session': session,
2039
- }),
2040
- );
2164
+ }) async =>
2165
+ _asMap(
2166
+ await _call('resolveCustodyBreak', {
2167
+ 'decision': decision,
2168
+ if (session != null) 'session': session,
2169
+ }),
2170
+ );
2041
2171
 
2042
2172
  /// The parked salvaged intents (re-offerable local work an `adopt` rescued) — metadata only.
2043
2173
  Future<List<Map<String, Object?>>> salvagedIntents({String? session}) async {
@@ -2054,23 +2184,25 @@ class NomosBridge {
2054
2184
  Future<Map<String, Object?>> reofferSalvaged({
2055
2185
  String? id,
2056
2186
  String? session,
2057
- }) async => _asMap(
2058
- await _call('reofferSalvaged', {
2059
- if (id != null) 'id': id,
2060
- if (session != null) 'session': session,
2061
- }),
2062
- );
2187
+ }) async =>
2188
+ _asMap(
2189
+ await _call('reofferSalvaged', {
2190
+ if (id != null) 'id': id,
2191
+ if (session != null) 'session': session,
2192
+ }),
2193
+ );
2063
2194
 
2064
2195
  /// Discard one parked salvaged intent — the app's explicit choice.
2065
2196
  Future<Map<String, Object?>> discardSalvaged(
2066
2197
  String id, {
2067
2198
  String? session,
2068
- }) async => _asMap(
2069
- await _call('discardSalvaged', {
2070
- 'id': id,
2071
- if (session != null) 'session': session,
2072
- }),
2073
- );
2199
+ }) async =>
2200
+ _asMap(
2201
+ await _call('discardSalvaged', {
2202
+ 'id': id,
2203
+ if (session != null) 'session': session,
2204
+ }),
2205
+ );
2074
2206
 
2075
2207
  // ── THE DEAD-LETTER QUEUE (refused-but-legitimate work is NEVER lost) — the Dart mirror of the
2076
2208
  // JS holon's DLQ surface (`deadLetters()` / `retryDeadLetter()` / `discardDeadLetter()`). A
@@ -2095,23 +2227,25 @@ class NomosBridge {
2095
2227
  Future<Map<String, Object?>> retryDeadLetter(
2096
2228
  String id, {
2097
2229
  String? session,
2098
- }) async => _asMap(
2099
- await _call('retryDeadLetter', {
2100
- 'id': id,
2101
- if (session != null) 'session': session,
2102
- }),
2103
- );
2230
+ }) async =>
2231
+ _asMap(
2232
+ await _call('retryDeadLetter', {
2233
+ 'id': id,
2234
+ if (session != null) 'session': session,
2235
+ }),
2236
+ );
2104
2237
 
2105
2238
  /// Discard one dead letter — the app's EXPLICIT choice to drop the work. `{ok}`.
2106
2239
  Future<Map<String, Object?>> discardDeadLetter(
2107
2240
  String id, {
2108
2241
  String? session,
2109
- }) async => _asMap(
2110
- await _call('discardDeadLetter', {
2111
- 'id': id,
2112
- if (session != null) 'session': session,
2113
- }),
2114
- );
2242
+ }) async =>
2243
+ _asMap(
2244
+ await _call('discardDeadLetter', {
2245
+ 'id': id,
2246
+ if (session != null) 'session': session,
2247
+ }),
2248
+ );
2115
2249
 
2116
2250
  /// SALVAGE — best-effort extraction of this holon's local-only authored work (un-synced pending
2117
2251
  /// writes + the DLQ), each with its full `changeB64` bytes: `{pendingWrites, deadLetters}`. The
@@ -2126,13 +2260,14 @@ class NomosBridge {
2126
2260
  List<Map<String, Object?>> pendingWrites = const [],
2127
2261
  List<Map<String, Object?>> deadLetters = const [],
2128
2262
  String? session,
2129
- }) async => _asMap(
2130
- await _call('absorbSalvage', {
2131
- 'pendingWrites': pendingWrites,
2132
- 'deadLetters': deadLetters,
2133
- if (session != null) 'session': session,
2134
- }),
2135
- );
2263
+ }) async =>
2264
+ _asMap(
2265
+ await _call('absorbSalvage', {
2266
+ 'pendingWrites': pendingWrites,
2267
+ 'deadLetters': deadLetters,
2268
+ if (session != null) 'session': session,
2269
+ }),
2270
+ );
2136
2271
 
2137
2272
  /// The salvage report from the most recent `connect(recover: true)` — `{ salvagedWrites, requeuedDeadLetters,
2138
2273
  /// unsalvageable }`, or null if the connection didn't recover. Show "recovered N writes" / surface
@@ -2218,18 +2353,19 @@ class NomosBridge {
2218
2353
  String? session,
2219
2354
  String? authorSecret,
2220
2355
  NomosBirthCertificate? birthCertificate,
2221
- }) => offerOutcome(
2222
- domain: domain,
2223
- directiveId: directiveId,
2224
- payload: payload,
2225
- actor: actor,
2226
- domainHash: domainHash,
2227
- nomosConflictSnapshots: nomosConflictSnapshots,
2228
- force: force,
2229
- session: session,
2230
- authorSecret: authorSecret,
2231
- birthCertificate: birthCertificate,
2232
- );
2356
+ }) =>
2357
+ offerOutcome(
2358
+ domain: domain,
2359
+ directiveId: directiveId,
2360
+ payload: payload,
2361
+ actor: actor,
2362
+ domainHash: domainHash,
2363
+ nomosConflictSnapshots: nomosConflictSnapshots,
2364
+ force: force,
2365
+ session: session,
2366
+ authorSecret: authorSecret,
2367
+ birthCertificate: birthCertificate,
2368
+ );
2233
2369
 
2234
2370
  /// THE ONE OUTCOME-RETURNING OFFER LANE — [offerDirective] answering the full typed [NomosOfferOutcome]
2235
2371
  /// (head + law-minted `created` NomosRefs + births), for EVERY generated method (create or mutate). A pure
@@ -2343,8 +2479,7 @@ class NomosBridge {
2343
2479
  }
2344
2480
  }
2345
2481
  final sourceSession = session ?? _sessionName;
2346
- final birthAuthorSecret =
2347
- authorSecret ??
2482
+ final birthAuthorSecret = authorSecret ??
2348
2483
  (sourceSession == null
2349
2484
  ? null
2350
2485
  : _eventPlane._sessionAuthorSecrets[sourceSession]);
@@ -2403,8 +2538,7 @@ class NomosBridge {
2403
2538
  }) async {
2404
2539
  if (!RegExp(
2405
2540
  r"no active installed law declares domain '",
2406
- ).hasMatch(e.toString()))
2407
- return e;
2541
+ ).hasMatch(e.toString())) return e;
2408
2542
  final self = this;
2409
2543
  final sessionWs = self is NomosSession ? self.workspace : null;
2410
2544
  var activeKeys = const <String>[];
@@ -2557,43 +2691,41 @@ class NomosBridge {
2557
2691
  return ready(session(workspace));
2558
2692
  }
2559
2693
  // SINGLE-FLIGHT: one in-flight open per workspace per plane; concurrent callers join it.
2560
- return plane._acquiring
2561
- .putIfAbsent(workspace, () async {
2562
- // RESIDENCY IS THE KERNEL'S TO DEMAND AND OURS TO SATISFY. Replaying a chain can reach a
2563
- // colocated read whose source workspace is not mounted; the kernel refuses TYPED, naming it.
2564
- // Mount the named sibling — which consults local custody first and only then clones — and
2565
- // retry. Bounded, and each name is satisfied at most once, so a genuinely missing workspace
2566
- // fails with the kernel's own refusal instead of spinning.
2567
- final satisfied = <String>{};
2568
- for (var round = 0; ; round++) {
2569
- try {
2570
- return await _acquireSessionOnce(
2571
- workspace,
2572
- ready: ready,
2573
- inheritPrincipal: inheritPrincipal,
2574
- ifAbsentCredentials: ifAbsentCredentials,
2575
- authorSecret: authorSecret,
2576
- );
2577
- } catch (error) {
2578
- final required = nomosInternalResidencyRequiredWorkspace(error);
2579
- if (required == null ||
2580
- required == workspace ||
2581
- !satisfied.add(required) ||
2582
- round >= 8) {
2583
- rethrow;
2584
- }
2585
- await acquireSession(
2586
- required,
2587
- ifAbsentCredentials: ifAbsentCredentials,
2588
- authorSecret: authorSecret,
2589
- inheritedPrincipal: sourcePrincipal,
2590
- );
2591
- }
2694
+ return plane._acquiring.putIfAbsent(workspace, () async {
2695
+ // RESIDENCY IS THE KERNEL'S TO DEMAND AND OURS TO SATISFY. Replaying a chain can reach a
2696
+ // colocated read whose source workspace is not mounted; the kernel refuses TYPED, naming it.
2697
+ // Mount the named sibling — which consults local custody first and only then clones — and
2698
+ // retry. Bounded, and each name is satisfied at most once, so a genuinely missing workspace
2699
+ // fails with the kernel's own refusal instead of spinning.
2700
+ final satisfied = <String>{};
2701
+ for (var round = 0;; round++) {
2702
+ try {
2703
+ return await _acquireSessionOnce(
2704
+ workspace,
2705
+ ready: ready,
2706
+ inheritPrincipal: inheritPrincipal,
2707
+ ifAbsentCredentials: ifAbsentCredentials,
2708
+ authorSecret: authorSecret,
2709
+ );
2710
+ } catch (error) {
2711
+ final required = nomosInternalResidencyRequiredWorkspace(error);
2712
+ if (required == null ||
2713
+ required == workspace ||
2714
+ !satisfied.add(required) ||
2715
+ round >= 8) {
2716
+ rethrow;
2592
2717
  }
2593
- })
2594
- .whenComplete(() {
2595
- plane._acquiring.remove(workspace);
2596
- });
2718
+ await acquireSession(
2719
+ required,
2720
+ ifAbsentCredentials: ifAbsentCredentials,
2721
+ authorSecret: authorSecret,
2722
+ inheritedPrincipal: sourcePrincipal,
2723
+ );
2724
+ }
2725
+ }
2726
+ }).whenComplete(() {
2727
+ plane._acquiring.remove(workspace);
2728
+ });
2597
2729
  }
2598
2730
 
2599
2731
  Future<NomosSession> _acquireSessionOnce(
@@ -2765,16 +2897,17 @@ class NomosBridge {
2765
2897
  List<Map<String, Object?>>? nomosConflictSnapshots,
2766
2898
  bool? force,
2767
2899
  String? session,
2768
- }) => offerDirective(
2769
- domain: domain,
2770
- directiveId: directiveId,
2771
- payload: payload,
2772
- actor: actor,
2773
- domainHash: domainHash,
2774
- nomosConflictSnapshots: nomosConflictSnapshots,
2775
- force: force,
2776
- session: session,
2777
- );
2900
+ }) =>
2901
+ offerDirective(
2902
+ domain: domain,
2903
+ directiveId: directiveId,
2904
+ payload: payload,
2905
+ actor: actor,
2906
+ domainHash: domainHash,
2907
+ nomosConflictSnapshots: nomosConflictSnapshots,
2908
+ force: force,
2909
+ session: session,
2910
+ );
2778
2911
 
2779
2912
  /// Resolve the generated law's standard OSGi Contract Namespace requirements before bind.
2780
2913
  Future<void> assertKernelCoherence(
@@ -2900,14 +3033,15 @@ class NomosBridge {
2900
3033
  List<String>? actions,
2901
3034
  String domain = '',
2902
3035
  String directiveId = 'undo',
2903
- }) async => _asMap(
2904
- await _call('undoMostRecent', {
2905
- 'scope': scope,
2906
- if (actions != null) 'actions': actions,
2907
- 'domain': domain,
2908
- 'directiveId': directiveId,
2909
- }),
2910
- );
3036
+ }) async =>
3037
+ _asMap(
3038
+ await _call('undoMostRecent', {
3039
+ 'scope': scope,
3040
+ if (actions != null) 'actions': actions,
3041
+ 'domain': domain,
3042
+ 'directiveId': directiveId,
3043
+ }),
3044
+ );
2911
3045
 
2912
3046
  /// REDO the most-recent undo (strike the strike → its target re-applies). Same [scope]/[domain]/[directiveId]
2913
3047
  /// as [undoMostRecent]. Returns `{ok, redone, head}`.
@@ -2915,13 +3049,14 @@ class NomosBridge {
2915
3049
  String scope = 'all',
2916
3050
  String domain = '',
2917
3051
  String directiveId = 'undo',
2918
- }) async => _asMap(
2919
- await _call('redoMostRecent', {
2920
- 'scope': scope,
2921
- 'domain': domain,
2922
- 'directiveId': directiveId,
2923
- }),
2924
- );
3052
+ }) async =>
3053
+ _asMap(
3054
+ await _call('redoMostRecent', {
3055
+ 'scope': scope,
3056
+ 'domain': domain,
3057
+ 'directiveId': directiveId,
3058
+ }),
3059
+ );
2925
3060
 
2926
3061
  /// Framework-private business correction seam. Generated clients bind the domain, its actions and actor;
2927
3062
  /// application code supplies only the correction kind and its mandatory reason.
@@ -2932,16 +3067,17 @@ class NomosBridge {
2932
3067
  required String reason,
2933
3068
  String? domainHash,
2934
3069
  String? actor,
2935
- }) async => _asMap(
2936
- await _call('correctMostRecent', {
2937
- 'kind': kind,
2938
- 'domain': domain,
2939
- 'actions': actions,
2940
- 'reason': reason,
2941
- if (domainHash != null) 'domainHash': domainHash,
2942
- if (actor != null) 'actor': actor,
2943
- }),
2944
- );
3070
+ }) async =>
3071
+ _asMap(
3072
+ await _call('correctMostRecent', {
3073
+ 'kind': kind,
3074
+ 'domain': domain,
3075
+ 'actions': actions,
3076
+ 'reason': reason,
3077
+ if (domainHash != null) 'domainHash': domainHash,
3078
+ if (actor != null) 'actor': actor,
3079
+ }),
3080
+ );
2945
3081
 
2946
3082
  /// Framework-private exact-history adoption seam. Generated clients expose this as
2947
3083
  /// `model.adopt()` and, only when prior business outcomes differ, a chained
@@ -3043,12 +3179,13 @@ class NomosBridge {
3043
3179
  String? base,
3044
3180
  int? limit,
3045
3181
  String? session,
3046
- }) => _watchStream(
3047
- kind: 'activity',
3048
- base: base,
3049
- limit: limit,
3050
- session: session,
3051
- );
3182
+ }) =>
3183
+ _watchStream(
3184
+ kind: 'activity',
3185
+ base: base,
3186
+ limit: limit,
3187
+ session: session,
3188
+ );
3052
3189
 
3053
3190
  /// Mint an ed25519 DEVICE KEY in-kernel → `{secret, public}` (base64). The SECRET stays on this device
3054
3191
  /// (persist it in secure storage); pass it to [connect] as `authorSecret` (or per-offer `signWith`) so the
@@ -3071,16 +3208,17 @@ class NomosBridge {
3071
3208
  Future<NomosBirthCertificate> signBirthCert(
3072
3209
  NomosBirthCertificateSpec spec,
3073
3210
  String deviceSecret,
3074
- ) async => NomosBirthCertificate.fromWire(
3075
- _asMap(
3076
- _asMap(
3077
- await _call('signBirthCert', {
3078
- 'fields': spec.toWire(),
3079
- 'deviceSecret': deviceSecret,
3080
- }),
3081
- )['cert'],
3082
- ),
3083
- );
3211
+ ) async =>
3212
+ NomosBirthCertificate.fromWire(
3213
+ _asMap(
3214
+ _asMap(
3215
+ await _call('signBirthCert', {
3216
+ 'fields': spec.toWire(),
3217
+ 'deviceSecret': deviceSecret,
3218
+ }),
3219
+ )['cert'],
3220
+ ),
3221
+ );
3084
3222
 
3085
3223
  /// MINT THE KEYLESS ENROLL-ONCE DELEGATION (`enrollFirstDevice.delegationCert`, the verified-first-device
3086
3224
  /// lane). The device SELF-signs it; its authority is the carried `idpToken` (the kernel re-verifies that to
@@ -3093,12 +3231,11 @@ class NomosBridge {
3093
3231
  String deviceSecret,
3094
3232
  ) async =>
3095
3233
  _asMap(
3096
- await _call('mintKeylessDelegation', {
3097
- 'spec': spec,
3098
- 'deviceSecret': deviceSecret,
3099
- }),
3100
- )['cert']
3101
- as Map<String, Object?>? ??
3234
+ await _call('mintKeylessDelegation', {
3235
+ 'spec': spec,
3236
+ 'deviceSecret': deviceSecret,
3237
+ }),
3238
+ )['cert'] as Map<String, Object?>? ??
3102
3239
  const {};
3103
3240
 
3104
3241
  /// ENROLL THIS DEVICE — the LIVE gate: bind a device key's PUBLIC half to `principal` on-chain as a
@@ -3109,13 +3246,14 @@ class NomosBridge {
3109
3246
  required String principal,
3110
3247
  required String publicKey,
3111
3248
  String? authToken,
3112
- }) async => _asMap(
3113
- await _call('enrollDevice', {
3114
- 'principal': principal,
3115
- 'publicKey': publicKey,
3116
- if (authToken != null) 'authToken': authToken,
3117
- }),
3118
- );
3249
+ }) async =>
3250
+ _asMap(
3251
+ await _call('enrollDevice', {
3252
+ 'principal': principal,
3253
+ 'publicKey': publicKey,
3254
+ if (authToken != null) 'authToken': authToken,
3255
+ }),
3256
+ );
3119
3257
 
3120
3258
  /// Derive the device key's base64 PUBLIC half from its base64 SECRET seed, inside the LOCAL kernel
3121
3259
  /// (the secret never leaves the device). The recovery lanes use this when only the secret was
@@ -3139,16 +3277,17 @@ class NomosBridge {
3139
3277
  String? publicKey,
3140
3278
  String? authToken,
3141
3279
  bool remote = false,
3142
- }) async => _asMap(
3143
- await _call('parentSignerEnrollment', {
3144
- 'parent': parent,
3145
- 'principal': principal,
3146
- if (keyHash != null) 'keyHash': keyHash,
3147
- if (publicKey != null) 'publicKey': publicKey,
3148
- if (authToken != null) 'authToken': authToken,
3149
- if (remote) 'remote': true,
3150
- }),
3151
- );
3280
+ }) async =>
3281
+ _asMap(
3282
+ await _call('parentSignerEnrollment', {
3283
+ 'parent': parent,
3284
+ 'principal': principal,
3285
+ if (keyHash != null) 'keyHash': keyHash,
3286
+ if (publicKey != null) 'publicKey': publicKey,
3287
+ if (authToken != null) 'authToken': authToken,
3288
+ if (remote) 'remote': true,
3289
+ }),
3290
+ );
3152
3291
 
3153
3292
  /// IDEMPOTENT PARENT-SIGNER RECOVERY — ensure this device key is a live `signer` on `parent`,
3154
3293
  /// lawfully restoring the tuple a parent custody REBIRTH lost (the device key + the born home stay
@@ -3171,19 +3310,20 @@ class NomosBridge {
3171
3310
  String? authToken,
3172
3311
  String? idToken,
3173
3312
  String? verifiedVia,
3174
- }) async => _asMap(
3175
- await _call('ensureParentSignerEnrollment', {
3176
- 'parent': parent,
3177
- 'principal': principal,
3178
- if (publicKey != null) 'publicKey': publicKey,
3179
- if (authorSecret != null) 'authorSecret': authorSecret,
3180
- if (domain != null) 'domain': domain,
3181
- if (directiveId != null) 'directiveId': directiveId,
3182
- if (authToken != null) 'authToken': authToken,
3183
- if (idToken != null) 'idToken': idToken,
3184
- if (verifiedVia != null) 'verifiedVia': verifiedVia,
3185
- }),
3186
- );
3313
+ }) async =>
3314
+ _asMap(
3315
+ await _call('ensureParentSignerEnrollment', {
3316
+ 'parent': parent,
3317
+ 'principal': principal,
3318
+ if (publicKey != null) 'publicKey': publicKey,
3319
+ if (authorSecret != null) 'authorSecret': authorSecret,
3320
+ if (domain != null) 'domain': domain,
3321
+ if (directiveId != null) 'directiveId': directiveId,
3322
+ if (authToken != null) 'authToken': authToken,
3323
+ if (idToken != null) 'idToken': idToken,
3324
+ if (verifiedVia != null) 'verifiedVia': verifiedVia,
3325
+ }),
3326
+ );
3187
3327
 
3188
3328
  /// AUTHORING PREFLIGHT — evaluate the SAME premises the kernel's authorization gate judges,
3189
3329
  /// READ-ONLY, and return a typed verdict WITHOUT authoring — so the app catches a doomed write
@@ -3199,16 +3339,17 @@ class NomosBridge {
3199
3339
  String? publicKey,
3200
3340
  String? keyHash,
3201
3341
  String? authToken,
3202
- }) async => _asMap(
3203
- await _call('canAuthor', {
3204
- 'directiveId': directiveId,
3205
- if (ws != null) 'ws': ws,
3206
- if (principal != null) 'principal': principal,
3207
- if (publicKey != null) 'publicKey': publicKey,
3208
- if (keyHash != null) 'keyHash': keyHash,
3209
- if (authToken != null) 'authToken': authToken,
3210
- }),
3211
- );
3342
+ }) async =>
3343
+ _asMap(
3344
+ await _call('canAuthor', {
3345
+ 'directiveId': directiveId,
3346
+ if (ws != null) 'ws': ws,
3347
+ if (principal != null) 'principal': principal,
3348
+ if (publicKey != null) 'publicKey': publicKey,
3349
+ if (keyHash != null) 'keyHash': keyHash,
3350
+ if (authToken != null) 'authToken': authToken,
3351
+ }),
3352
+ );
3212
3353
 
3213
3354
  /// VERIFY_CHAIN — the kernel's from-genesis self-verification of THIS holon's folded ledger (read-only:
3214
3355
  /// contiguity → every intent re-admitted through the ONE gate against the state folded from the prefix). For
@@ -3222,7 +3363,8 @@ class NomosBridge {
3222
3363
  /// receives only the resulting business application.
3223
3364
  Future<Map<String, Object?>> nomosInternalBirthReceivingGroup(
3224
3365
  Map<String, Object?> spec,
3225
- ) async => _asMap(await _call('nomosInternalBirthReceivingGroup', spec));
3366
+ ) async =>
3367
+ _asMap(await _call('nomosInternalBirthReceivingGroup', spec));
3226
3368
 
3227
3369
  /// Sign a cross-custody SHARE attestation `{secret, asserterWorkspace, object, relation, subject,
3228
3370
  /// attestedAt}` → `{publicKey, signature}`. This is what drives `recordShare` into an invitee's home
@@ -3230,7 +3372,8 @@ class NomosBridge {
3230
3372
  /// with `subject`, and the invitee's home gate verifies the signature before recording it.
3231
3373
  Future<Map<String, Object?>> attestationSign(
3232
3374
  Map<String, Object?> args,
3233
- ) async => _asMap(await _call('attestationSign', {'args': args}));
3375
+ ) async =>
3376
+ _asMap(await _call('attestationSign', {'args': args}));
3234
3377
 
3235
3378
  /// Issue a ROLE-DELEGATION cert (the `.delegatedRole()` lane, kernel `delegationCertSign` op). A platform
3236
3379
  /// signs — with its grantor secret `signerSecret` (base64) — a cert granting `relation` to `subject`,
@@ -3247,18 +3390,19 @@ class NomosBridge {
3247
3390
  required String subject,
3248
3391
  int epoch = 1,
3249
3392
  List<Object?>? certChain,
3250
- }) async => _asMap(
3251
- await _call('issueDelegationCert', {
3252
- 'args': {
3253
- 'signerSecret': signerSecret,
3254
- 'grantorId': grantorId,
3255
- 'relation': relation,
3256
- 'subject': subject,
3257
- 'epoch': epoch,
3258
- if (certChain != null) 'certChain': certChain,
3259
- },
3260
- }),
3261
- );
3393
+ }) async =>
3394
+ _asMap(
3395
+ await _call('issueDelegationCert', {
3396
+ 'args': {
3397
+ 'signerSecret': signerSecret,
3398
+ 'grantorId': grantorId,
3399
+ 'relation': relation,
3400
+ 'subject': subject,
3401
+ 'epoch': epoch,
3402
+ if (certChain != null) 'certChain': certChain,
3403
+ },
3404
+ }),
3405
+ );
3262
3406
 
3263
3407
  /// A declared query's rows from the local projection. `keys` (E2E sealing) injects the reader's held
3264
3408
  /// scope keys so encrypted fields AEAD-open in-wasm; absent ⇒ they stay opaque envelopes (today's
@@ -3318,21 +3462,21 @@ class NomosBridge {
3318
3462
  List<NomosScopeKey>? keys,
3319
3463
  String? principal,
3320
3464
  String? session,
3321
- ]) async => _asRows(
3322
- await _call('queryById', {
3323
- 'id': id,
3324
- ...?_readAuthArgs(keys, principal),
3325
- if (session != null) 'session': session,
3326
- }),
3327
- );
3465
+ ]) async =>
3466
+ _asRows(
3467
+ await _call('queryById', {
3468
+ 'id': id,
3469
+ ...?_readAuthArgs(keys, principal),
3470
+ if (session != null) 'session': session,
3471
+ }),
3472
+ );
3328
3473
 
3329
3474
  /// Compare an immutable publication pin with the stable series' one compiled
3330
3475
  /// current pointer. This is an O(current-state) check: it neither resolves the
3331
3476
  /// pinned publication nor reconstructs aggregate history.
3332
- Future<ReferenceVersionStatus<TVersion>> checkReferenceVersion<
3333
- TVersion,
3334
- TSeries
3335
- >(VersionedNomosRef<TVersion, TSeries> reference) async {
3477
+ Future<ReferenceVersionStatus<TVersion>>
3478
+ checkReferenceVersion<TVersion, TSeries>(
3479
+ VersionedNomosRef<TVersion, TSeries> reference) async {
3336
3480
  final result = _asMap(
3337
3481
  await _call('checkReferenceVersions', {
3338
3482
  'refs': [
@@ -3390,15 +3534,16 @@ class NomosBridge {
3390
3534
  List<NomosScopeKey>? keys,
3391
3535
  String? principal,
3392
3536
  String? session,
3393
- ]) async => _asRows(
3394
- await _call('queryAt', {
3395
- 'commit': moment.id,
3396
- 'queryId': queryId,
3397
- 'params': params,
3398
- ...?_readAuthArgs(keys, principal),
3399
- if (session != null) 'session': session,
3400
- }),
3401
- );
3537
+ ]) async =>
3538
+ _asRows(
3539
+ await _call('queryAt', {
3540
+ 'commit': moment.id,
3541
+ 'queryId': queryId,
3542
+ 'params': params,
3543
+ ...?_readAuthArgs(keys, principal),
3544
+ if (session != null) 'session': session,
3545
+ }),
3546
+ );
3402
3547
 
3403
3548
  /// Read one aggregate from the verified world at [moment]. `keys`/`principal`: see [queryAt].
3404
3549
  Future<List<Map<String, dynamic>>> queryByIdAt(
@@ -3407,14 +3552,15 @@ class NomosBridge {
3407
3552
  List<NomosScopeKey>? keys,
3408
3553
  String? principal,
3409
3554
  String? session,
3410
- ]) async => _asRows(
3411
- await _call('queryByIdAt', {
3412
- 'commit': moment.id,
3413
- 'id': id,
3414
- ...?_readAuthArgs(keys, principal),
3415
- if (session != null) 'session': session,
3416
- }),
3417
- );
3555
+ ]) async =>
3556
+ _asRows(
3557
+ await _call('queryByIdAt', {
3558
+ 'commit': moment.id,
3559
+ 'id': id,
3560
+ ...?_readAuthArgs(keys, principal),
3561
+ if (session != null) 'session': session,
3562
+ }),
3563
+ );
3418
3564
 
3419
3565
  /// Maintained historic count/sum values at [moment]. These are the temporal counterparts of [count]/[sum].
3420
3566
  Future<int> countAt(
@@ -3424,14 +3570,13 @@ class NomosBridge {
3424
3570
  String? session,
3425
3571
  ]) async =>
3426
3572
  ((_asMap(
3427
- await _call('countAt', {
3428
- 'commit': moment.id,
3429
- 'countId': countId,
3430
- 'group': group,
3431
- if (session != null) 'session': session,
3432
- }),
3433
- )['count'])
3434
- as num)
3573
+ await _call('countAt', {
3574
+ 'commit': moment.id,
3575
+ 'countId': countId,
3576
+ 'group': group,
3577
+ if (session != null) 'session': session,
3578
+ }),
3579
+ )['count']) as num)
3435
3580
  .toInt();
3436
3581
 
3437
3582
  Future<int> sumAt(
@@ -3441,14 +3586,13 @@ class NomosBridge {
3441
3586
  String? session,
3442
3587
  ]) async =>
3443
3588
  ((_asMap(
3444
- await _call('sumAt', {
3445
- 'commit': moment.id,
3446
- 'sumId': sumId,
3447
- 'group': group,
3448
- if (session != null) 'session': session,
3449
- }),
3450
- )['sum'])
3451
- as num)
3589
+ await _call('sumAt', {
3590
+ 'commit': moment.id,
3591
+ 'sumId': sumId,
3592
+ 'group': group,
3593
+ if (session != null) 'session': session,
3594
+ }),
3595
+ )['sum']) as num)
3452
3596
  .toInt();
3453
3597
 
3454
3598
  /// The read auth sidecar (private reads + E2E): `keys`/`principal` as top-level call args, or null when
@@ -3564,14 +3708,15 @@ class NomosBridge {
3564
3708
  required String domain,
3565
3709
  required String domainHash,
3566
3710
  required String recoveryPrincipal,
3567
- }) async => _asMap(
3568
- await _call('cryptoOwnedProtectIdentity', {
3569
- 'scope': scope,
3570
- 'domain': domain,
3571
- 'domainHash': domainHash,
3572
- 'recoveryPrincipal': recoveryPrincipal,
3573
- }),
3574
- );
3711
+ }) async =>
3712
+ _asMap(
3713
+ await _call('cryptoOwnedProtectIdentity', {
3714
+ 'scope': scope,
3715
+ 'domain': domain,
3716
+ 'domainHash': domainHash,
3717
+ 'recoveryPrincipal': recoveryPrincipal,
3718
+ }),
3719
+ );
3575
3720
 
3576
3721
  /// Prepare the private framework payload behind generated share/unshare/transfer methods.
3577
3722
  Future<Map<String, Object?>> nomosPrepareOwnedRecordAction<TAggregate>({
@@ -3579,17 +3724,18 @@ class NomosBridge {
3579
3724
  required String scope,
3580
3725
  required NomosRef<TAggregate> record,
3581
3726
  required String peer,
3582
- }) async => _asMap(
3583
- await _call('cryptoOwnedPrepareRecordAction', {
3584
- 'action': action,
3585
- 'scope': scope,
3586
- 'record': {
3587
- 'type': NmsInternalNomosRefs.type(record),
3588
- 'id': NmsInternalNomosRefs.id(record),
3589
- },
3590
- 'peer': peer,
3591
- }),
3592
- );
3727
+ }) async =>
3728
+ _asMap(
3729
+ await _call('cryptoOwnedPrepareRecordAction', {
3730
+ 'action': action,
3731
+ 'scope': scope,
3732
+ 'record': {
3733
+ 'type': NmsInternalNomosRefs.type(record),
3734
+ 'id': NmsInternalNomosRefs.id(record),
3735
+ },
3736
+ 'peer': peer,
3737
+ }),
3738
+ );
3593
3739
 
3594
3740
  /// FRAMEWORK-INTERNAL business birth: derive the unborn child's owned key from its deterministic address.
3595
3741
  Future<NomosScopeKey> nomosOwnedBirthScopeKey(
@@ -3618,34 +3764,35 @@ class NomosBridge {
3618
3764
  }
3619
3765
 
3620
3766
  /// FRAMEWORK-INTERNAL: issue an opaque request for this session's current device.
3621
- Future<String> nomosOwnedDeviceRequest(String scope) async =>
3622
- (_asMap(
3623
- await _call('cryptoOwnedDeviceRequest', {'scope': scope}),
3624
- )['request'] ??
3625
- '')
3626
- .toString();
3767
+ Future<String> nomosOwnedDeviceRequest(String scope) async => (_asMap(
3768
+ await _call('cryptoOwnedDeviceRequest', {'scope': scope}),
3769
+ )['request'] ??
3770
+ '')
3771
+ .toString();
3627
3772
 
3628
3773
  /// FRAMEWORK-INTERNAL: validate an opaque request and prepare the atomic signer + custody offer.
3629
3774
  Future<Map<String, Object?>> nomosPrepareOwnedDeviceApproval(
3630
3775
  String request,
3631
3776
  String scope,
3632
- ) async => _asMap(
3633
- await _call('cryptoOwnedPrepareApproval', {
3634
- 'request': request,
3635
- 'scope': scope,
3636
- }),
3637
- );
3777
+ ) async =>
3778
+ _asMap(
3779
+ await _call('cryptoOwnedPrepareApproval', {
3780
+ 'request': request,
3781
+ 'scope': scope,
3782
+ }),
3783
+ );
3638
3784
 
3639
3785
  /// Wrap a scope key TO a recipient's public key (committer side): `{hpkeEpk, ct}` base64 ciphertext.
3640
3786
  Future<Map<String, Object?>> cryptoWrapKey({
3641
3787
  required String recipientPub,
3642
3788
  required String scopeKey,
3643
- }) async => _asMap(
3644
- await _call('cryptoWrapKey', {
3645
- 'recipientPub': recipientPub,
3646
- 'scopeKey': scopeKey,
3647
- }),
3648
- );
3789
+ }) async =>
3790
+ _asMap(
3791
+ await _call('cryptoWrapKey', {
3792
+ 'recipientPub': recipientPub,
3793
+ 'scopeKey': scopeKey,
3794
+ }),
3795
+ );
3649
3796
 
3650
3797
  /// Unwrap an on-chain WrappedKey with this device's secret → the base64 scope key (reader side).
3651
3798
  Future<String> cryptoUnwrapKey({
@@ -3669,13 +3816,14 @@ class NomosBridge {
3669
3816
  String spatialId,
3670
3817
  NomosBbox bbox, [
3671
3818
  String? session,
3672
- ]) async => _asRows(
3673
- await _call('spatialWithin', {
3674
- 'spatialId': spatialId,
3675
- 'bbox': bbox.toJson(),
3676
- if (session != null) 'session': session,
3677
- }),
3678
- );
3819
+ ]) async =>
3820
+ _asRows(
3821
+ await _call('spatialWithin', {
3822
+ 'spatialId': spatialId,
3823
+ 'bbox': bbox.toJson(),
3824
+ if (session != null) 'session': session,
3825
+ }),
3826
+ );
3679
3827
 
3680
3828
  /// A maintained O(1) count / sum.
3681
3829
  Future<int> count(
@@ -3684,23 +3832,21 @@ class NomosBridge {
3684
3832
  String? session,
3685
3833
  ]) async =>
3686
3834
  ((_asMap(
3687
- await _call('count', {
3688
- 'countId': countId,
3689
- 'group': group,
3690
- if (session != null) 'session': session,
3691
- }),
3692
- )['count'])
3693
- as num)
3835
+ await _call('count', {
3836
+ 'countId': countId,
3837
+ 'group': group,
3838
+ if (session != null) 'session': session,
3839
+ }),
3840
+ )['count']) as num)
3694
3841
  .toInt();
3695
3842
  Future<int> sum(String sumId, [String group = '', String? session]) async =>
3696
3843
  ((_asMap(
3697
- await _call('sum', {
3698
- 'sumId': sumId,
3699
- 'group': group,
3700
- if (session != null) 'session': session,
3701
- }),
3702
- )['sum'])
3703
- as num)
3844
+ await _call('sum', {
3845
+ 'sumId': sumId,
3846
+ 'group': group,
3847
+ if (session != null) 'session': session,
3848
+ }),
3849
+ )['sum']) as num)
3704
3850
  .toInt();
3705
3851
 
3706
3852
  /// THE PENDING-CONFLICTS READ (Surfaced merge conflicts — the DX layer): the MAINTAINED,
@@ -3712,41 +3858,46 @@ class NomosBridge {
3712
3858
  /// `PendingConflictRow` and pairs them with the designated `resolve…` helpers.)
3713
3859
  Future<List<Map<String, dynamic>>> pendingConflicts([
3714
3860
  String? session,
3715
- ]) async => _asRows(
3716
- await _call('pendingConflicts', {if (session != null) 'session': session}),
3717
- );
3861
+ ]) async =>
3862
+ _asRows(
3863
+ await _call(
3864
+ 'pendingConflicts', {if (session != null) 'session': session}),
3865
+ );
3718
3866
 
3719
3867
  /// Framework-filtered pending conflicts for one generated aggregate type. This is the
3720
3868
  /// primitive generated clients use; application code never filters the heterogeneous queue.
3721
3869
  Future<List<Map<String, dynamic>>> pendingConflictsFor(
3722
3870
  String aggregateType, [
3723
3871
  String? session,
3724
- ]) async => _asRows(
3725
- await _call('pendingConflicts', {
3726
- 'aggregateType': aggregateType,
3727
- if (session != null) 'session': session,
3728
- }),
3729
- );
3872
+ ]) async =>
3873
+ _asRows(
3874
+ await _call('pendingConflicts', {
3875
+ 'aggregateType': aggregateType,
3876
+ if (session != null) 'session': session,
3877
+ }),
3878
+ );
3730
3879
 
3731
3880
  /// Counts-only workspace summary over the maintained conflict index.
3732
3881
  Future<Map<String, Object?>> pendingConflictSummary([
3733
3882
  String? session,
3734
- ]) async => _asMap(
3735
- await _call('pendingConflictSummary', {
3736
- if (session != null) 'session': session,
3737
- }),
3738
- );
3883
+ ]) async =>
3884
+ _asMap(
3885
+ await _call('pendingConflictSummary', {
3886
+ if (session != null) 'session': session,
3887
+ }),
3888
+ );
3739
3889
 
3740
3890
  /// Push local writes → the session branch → cloud admission, and pull canonical main back.
3741
3891
  Future<Map<String, Object?>> sync({
3742
3892
  bool admit = true,
3743
3893
  String? session,
3744
- }) async => _asMap(
3745
- await _call('sync', {
3746
- 'admit': admit,
3747
- if (session != null) 'session': session,
3748
- }),
3749
- );
3894
+ }) async =>
3895
+ _asMap(
3896
+ await _call('sync', {
3897
+ 'admit': admit,
3898
+ if (session != null) 'session': session,
3899
+ }),
3900
+ );
3750
3901
 
3751
3902
  /// PERSIST: a base64 snapshot of the whole local holon (the bare nomos.git incl. un-synced writes + the
3752
3903
  /// DLQ). Store it on disk and pass it back as `connect(restoreFrom:)` next launch — the app then boots from
@@ -3792,6 +3943,11 @@ class NomosBridge {
3792
3943
  Stream<TransferProgress> get transferProgress =>
3793
3944
  _eventPlane._transferEvents.stream;
3794
3945
 
3946
+ /// Live typed progress from the canonical kernel while a long synchronous
3947
+ /// operation is in flight (currently cold custody verification/replay).
3948
+ Stream<KernelProgress> get kernelProgress =>
3949
+ _eventPlane._kernelProgressEvents.stream;
3950
+
3795
3951
  /// THE APP-READY SYNC STATE — a truthful aggregation of sync rounds, the doorbell, transfer progress, and a
3796
3952
  /// periodic metrics poll. Map straight to a sync-state page. Starts a lightweight 4s metrics poll while
3797
3953
  /// listened to (stops on cancel). [currentStatus] is the latest snapshot for a non-stream read.
@@ -3809,16 +3965,16 @@ class NomosBridge {
3809
3965
  : _eventPlane._currentSessionStatus(session);
3810
3966
  }
3811
3967
 
3812
- Stream<SyncStatus> _sessionSyncStatus(String session) => _eventPlane
3813
- ._syncStatusBySession
3814
- .putIfAbsent(
3815
- session,
3816
- () => StreamController<SyncStatus>.broadcast(
3817
- onListen: () => _eventPlane._startSessionStatusPoll(session),
3818
- onCancel: _eventPlane._stopStatusPollIfUnused,
3819
- ),
3820
- )
3821
- .stream;
3968
+ Stream<SyncStatus> _sessionSyncStatus(String session) =>
3969
+ _eventPlane._syncStatusBySession
3970
+ .putIfAbsent(
3971
+ session,
3972
+ () => StreamController<SyncStatus>.broadcast(
3973
+ onListen: () => _eventPlane._startSessionStatusPoll(session),
3974
+ onCancel: _eventPlane._stopStatusPollIfUnused,
3975
+ ),
3976
+ )
3977
+ .stream;
3822
3978
 
3823
3979
  SyncStatus _currentSessionStatus(String session) =>
3824
3980
  _eventPlane._statusBySession[session] ?? const SyncStatus();
@@ -4016,14 +4172,13 @@ class NomosBridge {
4016
4172
  // Counters prove custody debt, but they do not prove that a failed or
4017
4173
  // offline transport recovered. Only a subsequent successful sync/link
4018
4174
  // event may clear those lifecycle states.
4019
- final phase =
4020
- current.transfer != null ||
4175
+ final phase = current.transfer != null ||
4021
4176
  current.phase == SyncPhase.error ||
4022
4177
  current.phase == SyncPhase.offline
4023
4178
  ? current.phase
4024
4179
  : (behind > 0
4025
- ? SyncPhase.behind
4026
- : (ahead > 0 ? SyncPhase.syncing : SyncPhase.idle));
4180
+ ? SyncPhase.behind
4181
+ : (ahead > 0 ? SyncPhase.syncing : SyncPhase.idle));
4027
4182
  _pushSessionStatus(
4028
4183
  session,
4029
4184
  current.copyWith(
@@ -4139,36 +4294,39 @@ class NomosBridge {
4139
4294
  String? session,
4140
4295
  String? principal,
4141
4296
  int? intervalMs,
4142
- ]) => _watchStream(
4143
- kind: 'query',
4144
- queryId: queryId,
4145
- params: params,
4146
- session: session,
4147
- principal: principal,
4148
- intervalMs: intervalMs,
4149
- );
4297
+ ]) =>
4298
+ _watchStream(
4299
+ kind: 'query',
4300
+ queryId: queryId,
4301
+ params: params,
4302
+ session: session,
4303
+ principal: principal,
4304
+ intervalMs: intervalMs,
4305
+ );
4150
4306
  Stream<List<dynamic>> watchById(
4151
4307
  String id, [
4152
4308
  String? session,
4153
4309
  String? principal,
4154
- ]) => _watchStream(
4155
- kind: 'byId',
4156
- id: id,
4157
- session: session,
4158
- principal: principal,
4159
- );
4310
+ ]) =>
4311
+ _watchStream(
4312
+ kind: 'byId',
4313
+ id: id,
4314
+ session: session,
4315
+ principal: principal,
4316
+ );
4160
4317
 
4161
4318
  /// Reactive SPATIAL read: re-emits the R*Tree probe's rows whenever they change locally.
4162
4319
  Stream<List<dynamic>> watchSpatial(
4163
4320
  String spatialId,
4164
4321
  NomosBbox bbox, [
4165
4322
  String? session,
4166
- ]) => _watchStream(
4167
- kind: 'spatial',
4168
- spatialId: spatialId,
4169
- bbox: bbox,
4170
- session: session,
4171
- );
4323
+ ]) =>
4324
+ _watchStream(
4325
+ kind: 'spatial',
4326
+ spatialId: spatialId,
4327
+ bbox: bbox,
4328
+ session: session,
4329
+ );
4172
4330
 
4173
4331
  /// Reactive PENDING-CONFLICTS read: re-emits the maintained Surfaced "decisions needed"
4174
4332
  /// rows whenever the index changes (derived, not drained — a resolution write clears its row).
@@ -4181,12 +4339,13 @@ class NomosBridge {
4181
4339
  Future<Map<String, Object?>> checkCompatibility(
4182
4340
  Map<String, Object?> requirement, [
4183
4341
  Map<String, Object?>? offer,
4184
- ]) async => _asMap(
4185
- await _call('checkCompatibility', {
4186
- 'requirement': requirement,
4187
- if (offer != null) 'offer': offer,
4188
- }),
4189
- );
4342
+ ]) async =>
4343
+ _asMap(
4344
+ await _call('checkCompatibility', {
4345
+ 'requirement': requirement,
4346
+ if (offer != null) 'offer': offer,
4347
+ }),
4348
+ );
4190
4349
 
4191
4350
  /// THE COMPAT SUPERPOWER (#72b): compute the LIVE per-member verdict for this client's baked
4192
4351
  /// [compat] manifest + structural [requirement] against the workspace's on-ledger offer. The
@@ -4432,6 +4591,7 @@ class NomosBridge {
4432
4591
  if (!_flameEvents.isClosed) await _flameEvents.close();
4433
4592
  if (!_spanEvents.isClosed) await _spanEvents.close();
4434
4593
  if (!_transferEvents.isClosed) await _transferEvents.close();
4594
+ if (!_kernelProgressEvents.isClosed) await _kernelProgressEvents.close();
4435
4595
  final sessionStatuses = _syncStatusBySession.values.toList(growable: false);
4436
4596
  _syncStatusBySession.clear();
4437
4597
  for (final status in sessionStatuses) {
@@ -4514,8 +4674,7 @@ class NomosSession extends NomosBridge {
4514
4674
  final modelChange = parent._sessionModelChangeHandlers[this.workspace];
4515
4675
  final opened = parent.acquireSession(
4516
4676
  workspace,
4517
- ifAbsentCredentials:
4518
- ifAbsentCredentials ??
4677
+ ifAbsentCredentials: ifAbsentCredentials ??
4519
4678
  (retained == null ? null : retained.credentials),
4520
4679
  authorSecret:
4521
4680
  authorSecret ?? parent._sessionAuthorSecrets[this.workspace],
@@ -4617,14 +4776,15 @@ class NomosSession extends NomosBridge {
4617
4776
  String? authToken,
4618
4777
  bool allowUnborn = false,
4619
4778
  String? authorSecret,
4620
- }) => parent.follow(
4621
- ref,
4622
- cloud: cloud,
4623
- clientId: clientId,
4624
- authToken: authToken,
4625
- allowUnborn: allowUnborn,
4626
- authorSecret: authorSecret ?? parent._sessionAuthorSecrets[workspace],
4627
- );
4779
+ }) =>
4780
+ parent.follow(
4781
+ ref,
4782
+ cloud: cloud,
4783
+ clientId: clientId,
4784
+ authToken: authToken,
4785
+ allowUnborn: allowUnborn,
4786
+ authorSecret: authorSecret ?? parent._sessionAuthorSecrets[workspace],
4787
+ );
4628
4788
 
4629
4789
  @override
4630
4790
  Future<Object?> _call(String op, [Map<String, Object?> args = const {}]) =>
@@ -4717,11 +4877,11 @@ class _BridgeForeignWorkspaceReader implements NomosForeignWorkspaceReader {
4717
4877
  // workspace reads empty (→ ForeignNotFound) rather than throwing. A genuinely unreachable cloud throws,
4718
4878
  // which resolveResult classifies as ForeignUnreachable.
4719
4879
  Future<void> _ensureMounted() => _mounting ??= _bridge.connect(
4720
- cloud: _cloud,
4721
- workspace: _workspace,
4722
- session: _workspace,
4723
- allowUnborn: true,
4724
- );
4880
+ cloud: _cloud,
4881
+ workspace: _workspace,
4882
+ session: _workspace,
4883
+ allowUnborn: true,
4884
+ );
4725
4885
 
4726
4886
  @override
4727
4887
  Future<List<Map<String, dynamic>>> queryById(String id) async {