@githolon/dsl 0.101.6 → 0.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dart/CHANGELOG.md +13 -0
  2. package/dart/lib/nomos_client.dart +3 -52
  3. package/dart/lib/src/dev_cloud.dart +5 -0
  4. package/dart/lib/src/home.dart +10 -15
  5. package/dart/lib/src/nms_conformance_runtime.dart +12 -0
  6. package/dart/lib/src/nms_generated_runtime.dart +29 -0
  7. package/dart/lib/src/nms_test_environment.dart +8 -0
  8. package/dart/lib/src/node_runner_transport.dart +56 -18
  9. package/dart/lib/src/provider.dart +5 -1
  10. package/dart/lib/src/record_origin.dart +55 -0
  11. package/dart/lib/src/runner/node-entry.mjs +9105 -0
  12. package/dart/lib/src/runner/offline-install.mjs +4729 -0
  13. package/dart/lib/src/session_bound.dart +23 -10
  14. package/dart/lib/src/source_trust.dart +51 -0
  15. package/dart/lib/src/test_harness.dart +490 -58
  16. package/dart/lib/src/webview_bridge.dart +167 -58
  17. package/dart/lib/src/workspace_name.dart +7 -1
  18. package/dart/pubspec.lock +3 -3
  19. package/dart/pubspec.yaml +4 -2
  20. package/dart/test/acquire_session_credentials_test.dart +34 -17
  21. package/dart/test/acquire_session_test.dart +109 -24
  22. package/dart/test/adv_realm_interference_test.dart +227 -99
  23. package/dart/test/bundle_version_pairing_test.dart +1 -1
  24. package/dart/test/cloud_bound_topology_test.dart +1 -1
  25. package/dart/test/cluster_attested_test.dart +52 -35
  26. package/dart/test/cluster_births_test.dart +5 -2
  27. package/dart/test/cluster_device_keyed_acceptance_test.dart +5 -2
  28. package/dart/test/cluster_local_autosync_test.dart +5 -2
  29. package/dart/test/cluster_scale_test.dart +5 -2
  30. package/dart/test/compat_test.dart +1 -1
  31. package/dart/test/dlq_session_surface_test.dart +2 -1
  32. package/dart/test/errors_test.dart +1 -1
  33. package/dart/test/first_app_gauntlet_test.dart +78 -51
  34. package/dart/test/four_layer_nested_topology_test.dart +1 -1
  35. package/dart/test/harness_phase_timeout_test.dart +1 -1
  36. package/dart/test/home_parity_test.dart +9 -5
  37. package/dart/test/local_sync_inert_test.dart +22 -14
  38. package/dart/test/node_runner_transport_test.dart +9 -5
  39. package/dart/test/null_slot_test.dart +1 -1
  40. package/dart/test/parent_signer_recovery_test.dart +5 -2
  41. package/dart/test/schema_validation_test.dart +1 -1
  42. package/dart/test/sealing_client_test.dart +2 -1
  43. package/dart/test/session_bound_test.dart +92 -119
  44. package/dart/test/stale_bundle_test.dart +1 -1
  45. package/dart/test/test_harness_test.dart +77 -22
  46. package/dart/test/vo_read_typing_test.dart +32 -14
  47. package/dart/test/watch_after_offer_stall_test.dart +2 -1
  48. package/dart/test/webview_bridge_test.dart +17 -4
  49. package/dart/test/wire_test.dart +1 -1
  50. package/dart_types/CHANGELOG.md +8 -0
  51. package/dart_types/lib/nomos_types.dart +7 -6
  52. package/dart_types/lib/src/activity.dart +23 -13
  53. package/dart_types/lib/src/foreign_ref.dart +61 -112
  54. package/dart_types/lib/src/invitation.dart +96 -0
  55. package/dart_types/lib/src/nomos_ref.dart +97 -59
  56. package/dart_types/pubspec.yaml +1 -1
  57. package/dart_types/test/surfaced_test.dart +125 -19
  58. package/package.json +7 -3
  59. package/runtime/generated-application-host.js +8851 -0
  60. package/src/activity.ts +2 -2
  61. package/src/aggregate.ts +24 -1
  62. package/src/application_composition.ts +282 -0
  63. package/src/application_topology.ts +151 -0
  64. package/src/attested_core.ts +2 -2
  65. package/src/authoring_context.ts +9 -0
  66. package/src/birth_meter_ensure.ts +1 -1
  67. package/src/births.ts +53 -5
  68. package/src/build_package.ts +79 -71
  69. package/src/business_birth.ts +93 -10
  70. package/src/clear_directive.ts +3 -1
  71. package/src/codegen_dart.ts +369 -420
  72. package/src/codegen_dart_application.ts +1508 -0
  73. package/src/codegen_dart_client.ts +156 -95
  74. package/src/codegen_dart_scenario.ts +299 -0
  75. package/src/codegen_openapi.ts +8 -3
  76. package/src/codegen_proof.ts +1113 -1137
  77. package/src/codegen_provider_dart.ts +12 -1
  78. package/src/codegen_ts.ts +1176 -496
  79. package/src/compat_package_main.ts +22 -10
  80. package/src/compile_package_main.ts +1536 -337
  81. package/src/contract.ts +10 -4
  82. package/src/dart_barrel_guard.ts +5 -1
  83. package/src/describe_model.ts +13 -5
  84. package/src/directive.ts +244 -5
  85. package/src/engine_entry.ts +56 -13
  86. package/src/engine_javascript.ts +31 -0
  87. package/src/evolve_preview.ts +3 -12
  88. package/src/framework/application_home.ts +24 -10
  89. package/src/framework/capability.ts +15 -1
  90. package/src/framework/domain_lifecycle.ts +8 -0
  91. package/src/framework/framework_aggregates.ts +2 -2
  92. package/src/framework/genesis.ts +11 -1
  93. package/src/framework/home.ts +178 -75
  94. package/src/framework/impure_capability.ts +24 -7
  95. package/src/framework/relations.ts +13 -5
  96. package/src/framework/workspaces.ts +13 -12
  97. package/src/generated_client_names.ts +42 -3
  98. package/src/idof_lint.ts +65 -13
  99. package/src/index.ts +46 -12
  100. package/src/intent.ts +587 -0
  101. package/src/law_check.ts +64 -16
  102. package/src/precondition.ts +16 -4
  103. package/src/read_projection_namespace.ts +2 -7
  104. package/src/recipient.ts +33 -0
  105. package/src/relation_schema.ts +93 -0
  106. package/src/secondary_ensure.ts +11 -2
  107. package/src/shape_compat.ts +11 -1
  108. package/src/usd.ts +30 -8
  109. package/src/usd_layers.ts +447 -246
  110. package/src/usd_state.ts +1 -1
  111. package/src/value_object.ts +49 -13
  112. package/src/wire_encode.ts +124 -26
  113. package/src/workspace_sharing.ts +269 -0
  114. package/src/zod_introspection.ts +84 -0
  115. package/dart/example/nomos_secure_key_store.dart +0 -82
  116. package/dart/example/nomos_webview_transport.dart +0 -63
  117. package/dart/lib/nomos_headless.dart +0 -50
  118. package/dart/lib/testing.dart +0 -14
  119. package/dart/test/co2_product_gauntlet_test.dart +0 -244
  120. package/src/framework/identity.ts +0 -537
@@ -7,21 +7,21 @@
7
7
  * ASYNC DART BRIDGE-CLIENT CODEGEN (#61) — the Flutter sibling of `codegen_ts.ts`.
8
8
  *
9
9
  * `codegen_dart.ts` emits the per-domain TYPES: read-model classes (`…ReadModel.fromProjected`),
10
- * typed intent DTOs (`…Payload.toPayloadJson()`), typed ids, enums. Until this file a Flutter app
10
+ * typed action inputs (`…Input` publicly; private directives retain `…Payload`), typed ids and enums. Until this file a Flutter app
11
11
  * still hand-typed directive ids + query ids against the raw `NomosBridge` (string + Map). This closes
12
12
  * that: ONE generated `<name>.client.dart` per domain, emitted by `nomos-compile` AFTER the package is
13
13
  * hashed (the deployed law's content hash baked in), carrying a `<Domain>Client` over a connected
14
14
  * [NomosBridge] (the WebView runner) with:
15
15
  *
16
- * * a typed OFFER method per directive — takes the generated `…Payload`, serialises via its
17
- * `toPayloadJson()`, auto-stamps omitted `…At` timestamps (the same caller-clock sugar the TS
16
+ * * a typed OFFER method per directive — takes the generated input/implementation DTO, serialises via its
17
+ * `nmsInternalToPayloadJson()`, auto-stamps omitted `…At` timestamps (the same caller-clock sugar the TS
18
18
  * client applies), returns the new local head;
19
19
  * * a typed declared-QUERY accessor per `query(...)` — one-shot `Future<List<…ReadModel>>` + a
20
20
  * reactive `watch…` `Stream<List<…ReadModel>>`, parsed off the bridge's `{type,id,data}` rows;
21
21
  * * by-id read/watch + a type-index `list…` per aggregate;
22
22
  * * typed O(1) count/sum accessors.
23
23
  *
24
- * It IMPORTS the sibling `<name>.dart` (for the read-model + payload classes) and either the vendored
24
+ * It IMPORTS the sibling `<name>.dart` (for the read-model + input classes) and either the vendored
25
25
  * `nomos_client.dart` barrel or the package `nomos_client` barrel (for `NomosBridge`). NO manifest/hash impact —
26
26
  * pure frontend codegen, exactly like `codegen_dart.ts`. NO FALLBACK: an unsupported shape throws at compile
27
27
  * time.
@@ -46,18 +46,22 @@ import {
46
46
  dartRoleHelpers,
47
47
  registerDartNames,
48
48
  concreteClassName,
49
+ dartBusinessRecordInputs,
50
+ dartActionInputClassName,
49
51
  dartMemberName,
50
52
  } from "./codegen_dart.js";
51
53
  import { finishCount } from "./count.js";
52
54
  import { finishSum } from "./sum.js";
53
55
  import { autoStampFields, domainEncryptionMap, type EncDomainMap, type InterfaceAggShape } from "./codegen_ts.js";
54
56
  import { isNamespacedAggregate, qualifyReadProjectionType } from "./read_projection_namespace.js";
57
+ import { isBusinessIntent } from "./intent.js";
55
58
  import { publicClientInterface, type DomainInterface } from "./shape_compat.js";
56
59
  import { BUSINESS_CORRECTION_DIRECTIVE } from "./framework/business_corrections.js";
57
60
  import { deriveDirectiveRecordTarget } from "./workspace_routing.js";
58
61
  import { buildNomosDescribeModel, type NomosDescribeModel } from "./describe_model.js";
59
62
  import { assertModelClientMemberAvailable } from "./generated_client_names.js";
60
63
  import { ownedRecordActionDirectiveId } from "./framework/owned_custody.js";
64
+ import { contractTypeName } from "./contract.js";
61
65
 
62
66
  const camel = (s: string) => s.replace(/[_\s-]+(\w)/g, (_m, c: string) => c.toUpperCase());
63
67
  const lcFirst = (s: string) => (s.length ? s[0]!.toLowerCase() + s.slice(1) : s);
@@ -92,11 +96,31 @@ function dartRawJson(value: unknown): string {
92
96
 
93
97
  const dartStr = (s: string) => `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
94
98
 
95
- /** The Dart param type for a query index key (int-kinded keys → `int`, else `String`). */
99
+ /** The Dart param type for a query index key. Aggregate relations keep their canonical typed ref. */
96
100
  function dartKeyType(agg: AggregateHandle | undefined, key: string): string {
97
101
  const lead = key.includes(".") ? key.split(".")[0]! : key;
98
102
  const f = agg?.fields[lead] as Field | undefined;
99
- return f && (f.kind === "int" || f.kind === "counter") ? "int" : "String";
103
+ if (f && (f.kind === "int" || f.kind === "counter")) return "int";
104
+ if (f?.kind === "ref") {
105
+ if (f.foreignRef !== undefined) {
106
+ const target = f.foreignRef.targetIsContract === true
107
+ ? contractTypeName(f.foreignRef.targetAggregateId)
108
+ : concreteClassName(f.foreignRef.targetAggregateId);
109
+ return `ForeignRef<${target}>`;
110
+ }
111
+ if (f.refAggregateId !== undefined) return `NomosRef<${concreteClassName(f.refAggregateId)}>`;
112
+ }
113
+ return "String";
114
+ }
115
+
116
+ function dartKeyExpr(agg: AggregateHandle | undefined, key: string): string {
117
+ const lead = key.includes(".") ? key.split(".")[0]! : key;
118
+ const field = agg?.fields[lead] as Field | undefined;
119
+ const param = dartKeyParam(key);
120
+ if (field?.kind !== "ref") return param;
121
+ return field.foreignRef !== undefined
122
+ ? `NmsInternalNomosRefs.id(${param}.ref)`
123
+ : `NmsInternalNomosRefs.id(${param})`;
100
124
  }
101
125
 
102
126
  /** A Dart-safe param identifier from a (possibly dotted) index key: `a.b.c` → `aBC`. */
@@ -112,7 +136,7 @@ function dartKeyParam(key: string): string {
112
136
  * session workspace (`_ws`, a getter on the client) + the row's type/id. Works for a `Map` (one-shot
113
137
  * `query`/`queryById` rows) or a `dynamic` (`watch` stream rows) — indexing resolves on both. */
114
138
  function rowToModel(model: string, rowVar: string, workspace = "_ws"): string {
115
- return `${model}.fromProjected((${rowVar}['data'] as Map).cast<String, dynamic>(), (${rowVar}['id'] ?? '').toString(), ${workspace}, (${rowVar}['type'] ?? '').toString())`;
139
+ return `NmsInternalRecordOrigins.remember(${model}.fromProjected((${rowVar}['data'] as Map).cast<String, dynamic>(), (${rowVar}['id'] ?? '').toString(), ${workspace}, (${rowVar}['type'] ?? '').toString()), workspace: ${workspace}, type: (${rowVar}['type'] ?? '').toString(), id: (${rowVar}['id'] ?? '').toString())`;
116
140
  }
117
141
 
118
142
  export interface DartBridgeClientOptions {
@@ -186,10 +210,11 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
186
210
  (a) => (a as { businessBirthInternal?: unknown }).businessBirthInternal !== true,
187
211
  );
188
212
  const publicAggregateIds = new Set(publicAggregates.map((a) => a.id));
213
+ const publicDirectives = mod.applicationIntents ?? mod.directives;
189
214
  mod = {
190
215
  ...mod,
191
216
  aggregates: publicAggregates,
192
- directives: mod.directives.filter(
217
+ directives: publicDirectives.filter(
193
218
  (d) => (d as { businessBirthInternal?: unknown }).businessBirthInternal !== true,
194
219
  ),
195
220
  ...(mod.queries === undefined
@@ -214,7 +239,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
214
239
  const requiresKernelFeats = requiredKernelFeatures([mod]);
215
240
  const supportImport =
216
241
  opts.supportImport === "package"
217
- ? "package:nomos_client/nomos_client.dart"
242
+ ? "package:nomos_client/src/nms_generated_runtime.dart"
218
243
  : "nomos_client.dart";
219
244
  const aggById = new Map<string, AggregateHandle>();
220
245
  for (const a of mod.aggregates) aggById.set(a.id, a);
@@ -255,17 +280,23 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
255
280
  };
256
281
  const scopesExpr = (scopes: readonly { scope: string; owned?: true }[]): string =>
257
282
  `[${scopes.map((s) => `{${dartStr("scope")}: ${dartStr(s.scope)}${s.owned === true ? `, ${dartStr("owned")}: true` : ""}}`).join(", ")}]`;
283
+ const needsReadPrincipal = (typeId: string): boolean => {
284
+ const audience = aggById.get(typeId)?.audience;
285
+ return audience?.kind === "readableBy" || audience?.kind === "owned";
286
+ };
258
287
  const keysArg = (typeId: string): string => {
259
288
  const scopes = readScopesFor(typeId);
260
- return scopes.length
261
- ? `, await _readKeys(${scopesExpr(scopes)})`
262
- : "";
289
+ if (scopes.length) {
290
+ return `, await _readKeys(${scopesExpr(scopes)})${needsReadPrincipal(typeId) ? ", actor" : ""}`;
291
+ }
292
+ return needsReadPrincipal(typeId) ? ", null, actor" : "";
263
293
  };
264
294
  const pastKeysArg = (typeId: string): string => {
265
295
  const scopes = readScopesFor(typeId);
266
- return scopes.length
267
- ? `, await _client._readKeys(${scopesExpr(scopes)})`
268
- : "";
296
+ if (scopes.length) {
297
+ return `, await _client._readKeys(${scopesExpr(scopes)})${needsReadPrincipal(typeId) ? ", _client.actor" : ""}`;
298
+ }
299
+ return needsReadPrincipal(typeId) ? ", null, _client.actor" : "";
269
300
  };
270
301
  // The DISTINCT encryption scopes this domain defines (across encrypted reads + sealing directives) — the
271
302
  // set the owner ceremony rotates. Empty ⇒ no `encryption` getter is emitted for this domain.
@@ -310,13 +341,13 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
310
341
  if (ownedScope !== undefined && Object.keys(ownedActions).length > 0) {
311
342
  methods.push(
312
343
  ` /// Share one record. The peer can read its history and future changes; Nomos owns the keys and policy.`,
313
- ` Future<NomosOfferOutcome> share(NomosRef record, String peer) => _ownedRecordAction('share', record, peer);`,
344
+ ` Future<NomosOfferOutcome> share<TAggregate>(NomosRef<TAggregate> record, String peer) => _ownedRecordAction('share', record, peer);`,
314
345
  ``,
315
346
  ` /// Stop sharing one record. Earlier knowledge cannot be erased; future changes use a fresh private key.`,
316
- ` Future<NomosOfferOutcome> unshare(NomosRef record, String peer) => _ownedRecordAction('unshare', record, peer);`,
347
+ ` Future<NomosOfferOutcome> unshare<TAggregate>(NomosRef<TAggregate> record, String peer) => _ownedRecordAction('unshare', record, peer);`,
317
348
  ``,
318
349
  ` /// Hand ownership, readable history and future authority for one record to another person.`,
319
- ` Future<NomosOfferOutcome> transfer(NomosRef record, String peer) => _ownedRecordAction('transfer', record, peer);`,
350
+ ` Future<NomosOfferOutcome> transfer<TAggregate>(NomosRef<TAggregate> record, String peer) => _ownedRecordAction('transfer', record, peer);`,
320
351
  ``,
321
352
  );
322
353
  }
@@ -381,7 +412,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
381
412
  );
382
413
  }
383
414
  for (const d of dirs) {
384
- const payloadClass = `${cap(d.id)}Payload`;
415
+ const payloadClass = dartActionInputClassName(d);
385
416
  const stamps = autoStampFields((d as unknown as { payloadSchema: z.ZodTypeAny }).payloadSchema);
386
417
  const method = safeMethod(d.id);
387
418
  // THE AUTHORITY GATE (codegen-time): a directive carrying `.requires(relation)` is GATED — its method
@@ -411,6 +442,28 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
411
442
  const createsDoc = (d as { marker?: string }).marker === "creates"
412
443
  ? ` The LAW mints the ${(d as { aggregateId?: string }).aggregateId ?? "aggregate"} id inside the sealed intent — it rides back on \`outcome.created\` (no id in the payload, no query-after).`
413
444
  : "";
445
+ const recordInputs = dartBusinessRecordInputs(d, mod.aggregates);
446
+ const principalField = d.businessPrincipalField;
447
+ const principalPrelude = principalField === undefined
448
+ ? []
449
+ : [
450
+ ` final nmsInternalPrincipal = actor ?? bridge.principal;`,
451
+ ` if (nmsInternalPrincipal == null || nmsInternalPrincipal.trim().isEmpty) {`,
452
+ ` throw MissingOfferAuthority(domain: ${dartStr(domain)}, directiveId: ${dartStr(d.id)}, requires: 'the signed-in Nomos principal');`,
453
+ ` }`,
454
+ ];
455
+ const payloadJsonArgs = [
456
+ ...(principalField === undefined ? [] : ["nmsInternalPrincipal: nmsInternalPrincipal"]),
457
+ ...(recordInputs.length === 0
458
+ ? []
459
+ : [
460
+ "nmsInternalLocationOf: (record) => NmsInternalRecordOrigins.require(record).workspace",
461
+ "nmsInternalIdOf: (record) => NmsInternalRecordOrigins.require(record).id",
462
+ ]),
463
+ ];
464
+ const payloadJson = payloadJsonArgs.length === 0
465
+ ? "payload.nmsInternalToPayloadJson()"
466
+ : `payload.nmsInternalToPayloadJson(${payloadJsonArgs.join(", ")})`;
414
467
  const stampsDoc = stamps.length > 0 ? `\n /// Omitted ${stamps.map((s) => `\`${s}\``).join(" / ")} auto-stamp(s) ISO now() at offer.` : "";
415
468
  const directiveEncryption = encMap?.directives?.[d.id];
416
469
  if (directiveEncryption !== undefined) {
@@ -453,7 +506,8 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
453
506
  ...(gateDoc ? [gateDoc] : []),
454
507
  ` Future<NomosOfferOutcome> ${method}(${payloadClass} payload${ownedSeal && !wantAttest ? "" : `, {${ownedSeal ? "" : "bool seal = true"}${wantAttest ? `${ownedSeal ? "" : ", "}${attNamed}` : ""}}`}) async {`,
455
508
  ...(gateGuard ? [gateGuard] : []),
456
- ` final data = payload.toPayloadJson();`,
509
+ ...principalPrelude,
510
+ ` final data = ${payloadJson};`,
457
511
  ...(stamps.length > 0
458
512
  ? [
459
513
  ` final now = DateTime.now().toUtc().toIso8601String();`,
@@ -474,21 +528,24 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
474
528
  ...(gateDoc ? [gateDoc] : []),
475
529
  ` Future<NomosOfferOutcome> ${method}(${payloadClass} payload${wantAttest ? ", {" + attNamed + "}" : ""}) {`,
476
530
  ...(gateGuard ? [gateGuard] : []),
477
- ` final data = payload.toPayloadJson();`,
531
+ ...principalPrelude,
532
+ ` final data = ${payloadJson};`,
478
533
  ` final now = DateTime.now().toUtc().toIso8601String();`,
479
534
  ...stamps.map((s) => ` data.putIfAbsent(${dartStr(s)}, () => now);`),
480
535
  ` return _offer(${dartStr(d.id)}, data${attArg});`,
481
536
  ` }`,
482
537
  ``,
483
538
  );
484
- } else if (gateGuard) {
485
- // A gated directive with no `…At` sugar still needs a block body for the throw guard.
539
+ } else if (gateGuard || principalPrelude.length > 0) {
540
+ // A gated or principal-bound directive with no timestamp sugar still needs a block body
541
+ // for the framework-owned identity guard and payload binding.
486
542
  methods.push(
487
543
  ` /// Author \`${domain}/${d.id}\` locally under the installed law; returns the typed [NomosOfferOutcome].${createsDoc}`,
488
544
  gateDoc,
489
545
  ` Future<NomosOfferOutcome> ${method}(${payloadClass} payload${wantAttest ? ", {" + attNamed + "}" : ""}) {`,
490
- gateGuard,
491
- ` return _offer(${dartStr(d.id)}, payload.toPayloadJson()${attArg});`,
546
+ ...(gateGuard ? [gateGuard] : []),
547
+ ...principalPrelude,
548
+ ` return _offer(${dartStr(d.id)}, ${payloadJson}${attArg});`,
492
549
  ` }`,
493
550
  ``,
494
551
  );
@@ -497,7 +554,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
497
554
  ` /// Author \`${domain}/${d.id}\` locally under the installed law; returns the typed [NomosOfferOutcome].${createsDoc}`,
498
555
  ...(gateDoc ? [gateDoc] : []),
499
556
  ` Future<NomosOfferOutcome> ${method}(${payloadClass} payload${wantAttest ? ", {" + attNamed + "}" : ""}) =>`,
500
- ` _offer(${dartStr(d.id)}, payload.toPayloadJson()${attArg});`,
557
+ ` _offer(${dartStr(d.id)}, ${payloadJson}${attArg});`,
501
558
  ``,
502
559
  );
503
560
  }
@@ -509,12 +566,13 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
509
566
  // domain's key + directiveId + baked domainHash are all bound at codegen time, so a frontend dev
510
567
  // never hand-writes the four raw strings this replaces (the co2 production bug).
511
568
  for (const d of birthDirs) {
512
- const payloadClass = `${cap(d.id)}Payload`;
513
569
  const method = safeMethod(d.id);
570
+ const publicMethod = isBusinessIntent(d) ? method : "birth";
514
571
  const gate = (d as { requiresRelationGate?: { relation: string } }).requiresRelationGate;
515
572
  const businessBirth = (d as unknown as {
516
573
  businessBirth?: { aggregateId: string; rootId: string; namespace: string; keyField: string; publicPayloadSchema: z.ZodTypeAny };
517
574
  }).businessBirth;
575
+ const payloadClass = dartActionInputClassName(d);
518
576
  if (businessBirth !== undefined) {
519
577
  const birthEncryption = encMap?.directives?.[d.id];
520
578
  const ownedBirthDescriptor = birthEncryption === undefined
@@ -523,12 +581,12 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
523
581
  methods.push(
524
582
  ` /// Give one ${businessBirth.aggregateId} its own durable life. Nomos owns identity, authorship,`,
525
583
  ` /// provenance, persistence and recovery; the app supplies only business facts.`,
526
- ` Future<NomosRef> birth(${payloadClass} payload) async {`,
584
+ ` Future<NomosRef<${concreteClassName(businessBirth.aggregateId)}>> ${publicMethod}(${payloadClass} payload) async {`,
527
585
  ` final principal = actor ?? bridge.principal;`,
528
586
  ` if (principal == null || principal.trim().isEmpty) {`,
529
587
  ` throw MissingOfferAuthority(domain: ${dartStr(domain)}, directiveId: ${dartStr(d.id)}, requires: 'a signed-in Nomos session');`,
530
588
  ` }`,
531
- ` final data = payload.toPayloadJson();`,
589
+ ` final data = payload.nmsInternalToPayloadJson();`,
532
590
  ...(ownedBirthDescriptor === undefined
533
591
  ? []
534
592
  : [
@@ -558,8 +616,10 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
558
616
  ` throw StateError('birth() returned a workspace different from the deterministic owned-custody address');`,
559
617
  ` }`,
560
618
  ]),
561
- ` await bridge.sync();`,
562
- ` return NomosRef(workspace: outcome.born.single, type: ${dartStr(businessBirth.aggregateId)}, id: ${dartStr(businessBirth.rootId)});`,
619
+ // Birth is a local, durable business commit. The application host's continuous custody lifecycle
620
+ // pushes it immediately when online and retries when offline; awaiting a network round here makes
621
+ // the supposedly offline-first business action hang behind transport availability.
622
+ ` return NmsInternalNomosRefs.create<${concreteClassName(businessBirth.aggregateId)}>(workspace: outcome.born.single, type: ${dartStr(businessBirth.aggregateId)}, id: ${dartStr(businessBirth.rootId)});`,
563
623
  ` }`,
564
624
  ``,
565
625
  );
@@ -600,7 +660,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
600
660
  ` parent: explicitParent,`,
601
661
  ` actor: actor.wire,`,
602
662
  ` authorSecret: authorSecret?.wire,`,
603
- ` payload: payload.toPayloadJson(),`,
663
+ ` payload: payload.nmsInternalToPayloadJson(),`,
604
664
  ` authToken: authToken,`,
605
665
  ` );`,
606
666
  ` return NomosOfferOutcome(`,
@@ -623,7 +683,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
623
683
  ]
624
684
  : []),
625
685
  ` await _preflightOnce();`,
626
- ` return bridge.offerOutcome(domain: ${dartStr(domain)}, directiveId: ${dartStr(d.id)}, payload: payload.toPayloadJson(), actor: effActor, domainHash: domainHash);`,
686
+ ` return bridge.offerOutcome(domain: ${dartStr(domain)}, directiveId: ${dartStr(d.id)}, payload: payload.nmsInternalToPayloadJson(), actor: effActor, domainHash: domainHash);`,
627
687
  ` }`,
628
688
  ``,
629
689
  );
@@ -634,30 +694,31 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
634
694
  const model = readModelClassName(q.returns);
635
695
  const agg = aggById.get(q.returns);
636
696
  const params = q.key.map((k) => `required ${dartKeyType(agg, k)} ${dartKeyParam(k)}`).join(", ");
637
- const argMap = `{${q.key.map((k) => `${dartStr(k)}: ${dartKeyParam(k)}`).join(", ")}}`;
697
+ const argMap = `{${q.key.map((k) => `${dartStr(k)}: ${dartKeyExpr(agg, k)}`).join(", ")}}`;
638
698
  const m = safeMethod(lcFirst(camel(q.id)));
639
699
  const qScopes = readScopesFor(q.returns);
640
700
  const qOwned = qScopes.some((scope) => scope.owned === true);
701
+ const qPrivate = needsReadPrincipal(q.returns);
641
702
  const qScopesExpr = scopesExpr(qScopes);
642
703
  methods.push(
643
704
  ` /// Declared query \`${q.id}\` (indexed probe — routed by the read manifest).${readScopesFor(q.returns).length ? " Encrypted field(s) decrypt when the bound [keyStore] holds the scope key; else they stay opaque envelopes." : ""}`,
644
705
  ` Future<List<${model}>> ${m}({${params}}) async =>`,
645
706
  qOwned
646
- ? ` (await _readWithOwnedKeys(${qScopesExpr}, (keys) => bridge.query(${dartStr(q.id)}, ${argMap}, keys))).map((r) => ${rowToModel(model, "r")}).toList();`
707
+ ? ` (await _readWithOwnedKeys(${qScopesExpr}, (keys) => bridge.query(${dartStr(q.id)}, ${argMap}, keys${qPrivate ? ", actor" : ""}))).map((r) => ${rowToModel(model, "r")}).toList();`
647
708
  : ` (await bridge.query(${dartStr(q.id)}, ${argMap}${keysArg(q.returns)})).map((r) => ${rowToModel(model, "r")}).toList();`,
648
709
  ``,
649
710
  ` /// Reactive \`${q.id}\` — re-emits on every local change (cancel the subscription to stop).`,
650
711
  ` Stream<List<${model}>> watch${cap(camel(q.id))}({${params}}) =>`,
651
712
  qOwned
652
- ? ` bridge.watch(${dartStr(q.id)}, ${argMap}).asyncMap((_) => _readWithOwnedKeys(${qScopesExpr}, (keys) => bridge.query(${dartStr(q.id)}, ${argMap}, keys))).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`
653
- : ` bridge.watch(${dartStr(q.id)}, ${argMap}).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`,
713
+ ? ` bridge.watch(${dartStr(q.id)}, ${argMap}, null${qPrivate ? ", actor" : ""}).asyncMap((_) => _readWithOwnedKeys(${qScopesExpr}, (keys) => bridge.query(${dartStr(q.id)}, ${argMap}, keys${qPrivate ? ", actor" : ""}))).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`
714
+ : ` bridge.watch(${dartStr(q.id)}, ${argMap}${qPrivate ? ", null, actor" : ""}).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`,
654
715
  ``,
655
716
  );
656
717
  pastMethods.push(
657
718
  ` /// Declared query \`${q.id}\` in the verified world at [moment].`,
658
719
  ` Future<List<${model}>> ${m}({${params}}) async =>`,
659
720
  qOwned
660
- ? ` (await _client._readWithOwnedKeys(${qScopesExpr}, (keys) => _client.bridge.queryAt(moment, ${dartStr(q.id)}, ${argMap}, keys))).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`
721
+ ? ` (await _client._readWithOwnedKeys(${qScopesExpr}, (keys) => _client.bridge.queryAt(moment, ${dartStr(q.id)}, ${argMap}, keys${qPrivate ? ", _client.actor" : ""}))).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`
661
722
  : ` (await _client.bridge.queryAt(moment, ${dartStr(q.id)}, ${argMap}${pastKeysArg(q.returns)})).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`,
662
723
  ``,
663
724
  );
@@ -683,30 +744,36 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
683
744
  // ── counts / sums → O(1) typed reads ──
684
745
  for (const c of (mod.counts ?? []).map((raw) => finishCount(raw))) {
685
746
  const m = safeMethod(lcFirst(camel(c.id)));
747
+ const aggregate = aggById.get(c.of);
748
+ const groupType = c.by == null ? "" : dartKeyType(aggregate, c.by);
749
+ const groupValue = c.by == null ? "" : dartKeyExpr(aggregate, c.by);
686
750
  methods.push(
687
751
  c.by != null
688
- ? ` /// Declared count \`${c.id}\` — the maintained O(1) tally per \`${c.by}\`.\n Future<int> ${m}(String ${dartKeyParam(c.by)}) => bridge.count(${dartStr(c.id)}, ${dartKeyParam(c.by)});`
752
+ ? ` /// Declared count \`${c.id}\` — the maintained O(1) tally per \`${c.by}\`.\n Future<int> ${m}(${groupType} ${dartKeyParam(c.by)}) => bridge.count(${dartStr(c.id)}, ${groupValue});`
689
753
  : ` /// Declared count \`${c.id}\` — the maintained O(1) grand total.\n Future<int> ${m}() => bridge.count(${dartStr(c.id)});`,
690
754
  ``,
691
755
  );
692
756
  pastMethods.push(
693
757
  c.by != null
694
- ? ` /// Declared count \`${c.id}\` at [moment].\n Future<int> ${m}(String ${dartKeyParam(c.by)}) => _client.bridge.countAt(moment, ${dartStr(c.id)}, ${dartKeyParam(c.by)});`
758
+ ? ` /// Declared count \`${c.id}\` at [moment].\n Future<int> ${m}(${groupType} ${dartKeyParam(c.by)}) => _client.bridge.countAt(moment, ${dartStr(c.id)}, ${groupValue});`
695
759
  : ` /// Declared count \`${c.id}\` at [moment].\n Future<int> ${m}() => _client.bridge.countAt(moment, ${dartStr(c.id)});`,
696
760
  ``,
697
761
  );
698
762
  }
699
763
  for (const s of (mod.sums ?? []).map((raw) => finishSum(raw))) {
700
764
  const m = safeMethod(lcFirst(camel(s.id)));
765
+ const aggregate = aggById.get(s.of);
766
+ const groupType = s.by == null ? "" : dartKeyType(aggregate, s.by);
767
+ const groupValue = s.by == null ? "" : dartKeyExpr(aggregate, s.by);
701
768
  methods.push(
702
769
  s.by != null
703
- ? ` /// Declared sum \`${s.id}\` — the maintained O(1) total per \`${s.by}\`.\n Future<int> ${m}(String ${dartKeyParam(s.by)}) => bridge.sum(${dartStr(s.id)}, ${dartKeyParam(s.by)});`
770
+ ? ` /// Declared sum \`${s.id}\` — the maintained O(1) total per \`${s.by}\`.\n Future<int> ${m}(${groupType} ${dartKeyParam(s.by)}) => bridge.sum(${dartStr(s.id)}, ${groupValue});`
704
771
  : ` /// Declared sum \`${s.id}\` — the maintained O(1) grand total.\n Future<int> ${m}() => bridge.sum(${dartStr(s.id)});`,
705
772
  ``,
706
773
  );
707
774
  pastMethods.push(
708
775
  s.by != null
709
- ? ` /// Declared sum \`${s.id}\` at [moment].\n Future<int> ${m}(String ${dartKeyParam(s.by)}) => _client.bridge.sumAt(moment, ${dartStr(s.id)}, ${dartKeyParam(s.by)});`
776
+ ? ` /// Declared sum \`${s.id}\` at [moment].\n Future<int> ${m}(${groupType} ${dartKeyParam(s.by)}) => _client.bridge.sumAt(moment, ${dartStr(s.id)}, ${groupValue});`
710
777
  : ` /// Declared sum \`${s.id}\` at [moment].\n Future<int> ${m}() => _client.bridge.sumAt(moment, ${dartStr(s.id)});`,
711
778
  ``,
712
779
  );
@@ -946,17 +1013,18 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
946
1013
  const Cap = cap(camel(name));
947
1014
  const aScopes = readScopesFor(agg.id);
948
1015
  const aOwned = aScopes.some((scope) => scope.owned === true);
1016
+ const aPrivate = needsReadPrincipal(agg.id);
949
1017
  const aScopesExpr = scopesExpr(aScopes);
950
1018
  const runtimeType = isNamespacedAggregate(agg) ? qualifyReadProjectionType(domain, agg.id) : agg.id;
951
1019
  const byIdKeys = aScopes.length === 0
952
- ? ""
1020
+ ? (aPrivate ? ", null, actor" : "")
953
1021
  : aOwned
954
- ? `, await _readKeys(${aScopesExpr}, [{${dartStr("type")}: ${dartStr(runtimeType)}, ${dartStr("id")}: id}])`
1022
+ ? `, await _readKeys(${aScopesExpr}, [{${dartStr("type")}: ${dartStr(runtimeType)}, ${dartStr("id")}: id}])${aPrivate ? ", actor" : ""}`
955
1023
  : keysArg(agg.id);
956
1024
  const pastByIdKeys = aScopes.length === 0
957
- ? ""
1025
+ ? (aPrivate ? ", null, _client.actor" : "")
958
1026
  : aOwned
959
- ? `, await _client._readKeys(${aScopesExpr}, [{${dartStr("type")}: ${dartStr(runtimeType)}, ${dartStr("id")}: id}])`
1027
+ ? `, await _client._readKeys(${aScopesExpr}, [{${dartStr("type")}: ${dartStr(runtimeType)}, ${dartStr("id")}: id}])${aPrivate ? ", _client.actor" : ""}`
960
1028
  : pastKeysArg(agg.id);
961
1029
  methods.push(
962
1030
  ` /// Read one ${agg.id} by aggregate id.${readScopesFor(agg.id).length ? " Encrypted field(s) decrypt when the bound [keyStore] holds the scope key." : ""}`,
@@ -966,14 +1034,20 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
966
1034
  ` /// Watch one ${agg.id} by aggregate id (local reactive read).`,
967
1035
  ` Stream<List<${model}>> watch${Cap}ById(String id) =>`,
968
1036
  aOwned
969
- ? ` bridge.watchById(id).asyncMap((_) async => bridge.queryById(id, await _readKeys(${aScopesExpr}, [{${dartStr("type")}: ${dartStr(runtimeType)}, ${dartStr("id")}: id}]))).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`
970
- : ` bridge.watchById(id).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`,
1037
+ ? ` bridge.watchById(id, null${aPrivate ? ", actor" : ""}).asyncMap((_) async => bridge.queryById(id, await _readKeys(${aScopesExpr}, [{${dartStr("type")}: ${dartStr(runtimeType)}, ${dartStr("id")}: id}])${aPrivate ? ", actor" : ""})).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`
1038
+ : ` bridge.watchById(id${aPrivate ? ", null, actor" : ""}).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`,
971
1039
  ``,
972
1040
  ` /// Every ${agg.id} (the type-index probe — O(result), not a scan).`,
973
1041
  ` Future<List<${model}>> ${safeMethod(`list${Cap}s`)}() async =>`,
974
1042
  aOwned
975
- ? ` (await _readWithOwnedKeys(${aScopesExpr}, (keys) => bridge.query('aggregatesByType', {'__type': ${dartStr(agg.id)}}, keys))).map((r) => ${rowToModel(model, "r")}).toList();`
976
- : ` (await bridge.query('aggregatesByType', {'__type': ${dartStr(agg.id)}}${keysArg(agg.id)})).map((r) => ${rowToModel(model, "r")}).toList();`,
1043
+ ? ` (await _readWithOwnedKeys(${aScopesExpr}, (keys) => bridge.query('aggregatesByType', {'__type': ${dartStr(runtimeType)}}, keys${aPrivate ? ", actor" : ""}))).map((r) => ${rowToModel(model, "r")}).toList();`
1044
+ : ` (await bridge.query('aggregatesByType', {'__type': ${dartStr(runtimeType)}}${keysArg(agg.id)})).map((r) => ${rowToModel(model, "r")}).toList();`,
1045
+ ``,
1046
+ ` /// Watch every ${agg.id} (the same indexed local read, re-emitted after each change).`,
1047
+ ` Stream<List<${model}>> ${safeMethod(`watchAll${Cap}s`)}() =>`,
1048
+ aOwned
1049
+ ? ` bridge.watch('aggregatesByType', {'__type': ${dartStr(runtimeType)}}, null${aPrivate ? ", actor" : ""}).asyncMap((_) => _readWithOwnedKeys(${aScopesExpr}, (keys) => bridge.query('aggregatesByType', {'__type': ${dartStr(runtimeType)}}, keys${aPrivate ? ", actor" : ""}))).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`
1050
+ : ` bridge.watch('aggregatesByType', {'__type': ${dartStr(runtimeType)}}${aPrivate ? ", null, actor" : ""}).map((rows) => rows.map((r) => ${rowToModel(model, "r")}).toList());`,
977
1051
  ``,
978
1052
  );
979
1053
  pastMethods.push(
@@ -984,8 +1058,8 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
984
1058
  ` /// Every ${agg.id} in the verified world at [moment].`,
985
1059
  ` Future<List<${model}>> ${safeMethod(`list${Cap}s`)}() async =>`,
986
1060
  aOwned
987
- ? ` (await _client._readWithOwnedKeys(${aScopesExpr}, (keys) => _client.bridge.queryAt(moment, 'aggregatesByType', {'__type': ${dartStr(agg.id)}}, keys))).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`
988
- : ` (await _client.bridge.queryAt(moment, 'aggregatesByType', {'__type': ${dartStr(agg.id)}}${pastKeysArg(agg.id)})).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`,
1061
+ ? ` (await _client._readWithOwnedKeys(${aScopesExpr}, (keys) => _client.bridge.queryAt(moment, 'aggregatesByType', {'__type': ${dartStr(runtimeType)}}, keys${aPrivate ? ", _client.actor" : ""}))).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`
1062
+ : ` (await _client.bridge.queryAt(moment, 'aggregatesByType', {'__type': ${dartStr(runtimeType)}}${pastKeysArg(agg.id)})).map((r) => ${rowToModel(model, "r", "_client._ws")}).toList();`,
989
1063
  ``,
990
1064
  );
991
1065
  }
@@ -1116,7 +1190,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1116
1190
  ` return moments.where((moment) =>`,
1117
1191
  ` moment.domain == ${dartStr(domain)} && moment.action != null && actions.contains(moment.action)).map((moment) =>`,
1118
1192
  ` moment.action == ${dartStr(BUSINESS_CORRECTION_DIRECTIVE)} ? NomosMoment(`,
1119
- ` id: moment.id, occurredAt: moment.occurredAt, actorSubject: moment.actorSubject, domain: moment.domain, action: 'correction') : moment).toList();`,
1193
+ ` id: moment.id, occurredAt: moment.occurredAt, performedBy: moment.performedBy, domain: moment.domain, action: 'correction') : moment).toList();`,
1120
1194
  ` }`,
1121
1195
  ` ${atClass} at(NomosMoment moment) => ${atClass}(_client, moment);`,
1122
1196
  `}`,
@@ -1203,9 +1277,9 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1203
1277
  ? [
1204
1278
  ` final id = ${member};`,
1205
1279
  ` if (id == null) return null;`,
1206
- ` final rows = await client.${byIdMethod}(id.value);`,
1280
+ ` final rows = await client.${byIdMethod}(NmsInternalNomosRefs.id(id));`,
1207
1281
  ]
1208
- : [` final rows = await client.${byIdMethod}(${member}.value);`]),
1282
+ : [` final rows = await client.${byIdMethod}(NmsInternalNomosRefs.id(${member}));`]),
1209
1283
  ` return rows.isEmpty ? null : rows.first;`,
1210
1284
  ` }`,
1211
1285
  ``,
@@ -1238,9 +1312,9 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1238
1312
  ? [
1239
1313
  ` final id = ${member};`,
1240
1314
  ` if (id == null) return null;`,
1241
- ` final rows = await client.${byIdMethod}(id.value);`,
1315
+ ` final rows = await client.${byIdMethod}(NmsInternalNomosRefs.id(id));`,
1242
1316
  ]
1243
- : [` final rows = await client.${byIdMethod}(${member}.value);`]),
1317
+ : [` final rows = await client.${byIdMethod}(NmsInternalNomosRefs.id(${member}));`]),
1244
1318
  ` return rows.isEmpty ? null : rows.first;`,
1245
1319
  ` }`,
1246
1320
  ``,
@@ -1249,7 +1323,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1249
1323
  for (const [fieldName, f] of foreignRefs) {
1250
1324
  const fr = f.foreignRef!;
1251
1325
  const targetType = fr.targetAggregateId;
1252
- // The resolver returns the target's CONCRETE class (what `ForeignRef<T>.resolve` decodes to). We can
1326
+ // The resolver returns the target's CONCRETE class. We can
1253
1327
  // only reference it when it is reachable from this file: SAME-domain (already in the imported types),
1254
1328
  // or a CROSS-DOMAIN concrete target in the package (import its sibling `<name>.dart` `show`-limited).
1255
1329
  // A contract target (its DTO lives in the shared contracts file) or an unmapped target is left as the
@@ -1272,15 +1346,13 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1272
1346
  const method = safeMethod(`remote${cap(camel(member))}`);
1273
1347
  lines.push(
1274
1348
  ` /// Resolve \`${fieldName}\` (${agg.id}.${fieldName} -> ${targetType} @ another workspace, a`,
1275
- ` /// \`t.foreignRef\` locator) over the session-bound multi-workspace plane —`,
1276
- ` /// \`${member}.resolve(engine.foreignReader())\`, which opens the foreign workspace ON DEMAND`,
1277
- ` /// (no clone). This is the informational follow+read lane, NOT the law-grade attested-read one`,
1278
- ` /// (use \`${member}!.attest(engine.foreignReader())\` when your law depends on the foreign fact).`,
1349
+ ` /// \`t.foreignRef\` locator) over the session-bound multi-workspace plane. The generated`,
1350
+ ` /// implementation opens the foreign workspace on demand; tenant code sees only this business method.`,
1279
1351
  ` /// Null locator (absent / empty id or workspace) ⇒ null.`,
1280
1352
  ` Future<${targetConcrete}?> ${method}(NomosEngine engine, {String? cloud}) {`,
1281
1353
  ` final ref = ${member};`,
1282
1354
  ` if (ref == null) return Future<${targetConcrete}?>.value(null);`,
1283
- ` return ref.resolve(engine.foreignReader(cloud: cloud));`,
1355
+ ` return NmsInternalForeignRefs.resolve(ref, engine.foreignReader(cloud: cloud));`,
1284
1356
  ` }`,
1285
1357
  ``,
1286
1358
  );
@@ -1313,14 +1385,14 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1313
1385
  ` /// history, decisions and evidence. The old events/transcript fields remain on [NomosDescription].`,
1314
1386
  ` Future<NomosDescription> describe({`,
1315
1387
  ` NomosDescribeSection section = NomosDescribeSection.root,`,
1316
- ` String? since, String? actor, String? category, int? limit,`,
1388
+ ` String? since, String? performedBy, String? category, int? limit,`,
1317
1389
  ` }) async {`,
1318
1390
  ` final raw = await bridge.activityLog(limit: limit);`,
1319
1391
  ` var events = raw`,
1320
1392
  ` .map((r) => renderActivity(r.cast<String, dynamic>()))`,
1321
1393
  ` .whereType<ActivityEvent>()`,
1322
1394
  ` .toList();`,
1323
- ` if (actor != null) events = events.where((e) => e.actorSubject == actor).toList();`,
1395
+ ` if (performedBy != null) events = events.where((e) => e.performedBy == performedBy).toList();`,
1324
1396
  ` if (category != null) events = events.where((e) => e.category == category).toList();`,
1325
1397
  ` if (since != null) events = events.where((e) => e.occurredAt.compareTo(since) >= 0).toList();`,
1326
1398
  ` final narrative = activityNarrative(events);`,
@@ -1359,8 +1431,8 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1359
1431
  ` summary: item['summary'] as String,`,
1360
1432
  ` details: item['details'] == null ? null : (item['details'] as Map).cast<String, dynamic>());`,
1361
1433
  ` }`,
1362
- ` List<NomosRef> eventRefs(ActivityEvent event) => event.refs.values`,
1363
- ` .map((ref) => NomosRef(workspace: ref.workspace, type: ref.type, id: ref.id)).toList();`,
1434
+ ` List<NomosRef<Object?>> eventRefs(ActivityEvent event) => event.refs.values`,
1435
+ ` .map((ref) => NmsInternalNomosRefs.create<Object?>(workspace: ref.workspace, type: ref.type, id: ref.id)).toList();`,
1364
1436
  ` String refusalReason(Object? raw) {`,
1365
1437
  ` final text = (raw ?? '').toString().toLowerCase();`,
1366
1438
  ` bool has(List<String> parts) => parts.any(text.contains);`,
@@ -1398,7 +1470,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1398
1470
  ` final label = aggregate['label'] as String;`,
1399
1471
  ` try {`,
1400
1472
  ` final rows = await bridge.query('aggregatesByType', {'__type': queryType});`,
1401
- ` final refs = rows.map((row) => NomosRef(`,
1473
+ ` final refs = rows.map((row) => NmsInternalNomosRefs.create<Object?>(`,
1402
1474
  ` workspace: _ws, type: (row['type'] ?? type).toString(), id: (row['id'] ?? '').toString())).toList();`,
1403
1475
  ` final exact = aggregate['audience'] == 'public' || rows.isNotEmpty;`,
1404
1476
  ` items.add(NomosDescribeItem(`,
@@ -1417,14 +1489,14 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1417
1489
  ` summary = 'What changed, who changed it and when, read from verified committed testimony.';`,
1418
1490
  ` items = events.map((event) => NomosDescribeItem(`,
1419
1491
  ` kind: 'change', id: event.eventId, label: event.title, summary: event.message,`,
1420
- ` details: {'actor': event.actorSubject, 'occurredAt': event.occurredAt, 'domain': event.domain, 'kind': event.kind},`,
1492
+ ` details: {'performedBy': event.performedBy, 'occurredAt': event.occurredAt, 'domain': event.domain, 'kind': event.kind},`,
1421
1493
  ` refs: eventRefs(event))).toList();`,
1422
1494
  ` } else if (section == NomosDescribeSection.decisions) {`,
1423
1495
  ` title = 'Decisions and work needing attention';`,
1424
1496
  ` summary = 'Recorded business reasons, pending merges and retained rejected work, plus declared conflict policy from the model.';`,
1425
1497
  ` items = events.where((event) => event.kind.endsWith('.correction')).map((event) => NomosDescribeItem(`,
1426
1498
  ` kind: 'decision', id: event.eventId, label: event.title, summary: event.message,`,
1427
- ` details: {'actor': event.actorSubject, 'occurredAt': event.occurredAt, 'domain': event.domain},`,
1499
+ ` details: {'performedBy': event.performedBy, 'occurredAt': event.occurredAt, 'domain': event.domain},`,
1428
1500
  ` refs: eventRefs(event))).toList();`,
1429
1501
  ` final aggregateTypes = ((model['aggregateTypes'] as List?) ?? const [])`,
1430
1502
  ` .map((raw) => (raw as Map).cast<String, dynamic>()).toList();`,
@@ -1454,7 +1526,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1454
1526
  ` id: 'decision:\${aggregate['domain']}.\${aggregate['type']}:\${conflict['aggregateId']}:$field',`,
1455
1527
  ` label: 'Review $subject', summary: conflictSummary,`,
1456
1528
  ` details: {'domain': aggregate['domain'], 'type': aggregate['type'], 'field': field, 'status': status, 'versions': versions, 'next': status == 'ready' ? 'merge' : 'update-model'},`,
1457
- ` refs: [NomosRef(workspace: _ws, type: aggregate['type'].toString(), id: conflict['aggregateId'].toString())]));`,
1529
+ ` refs: [NmsInternalNomosRefs.create<Object?>(workspace: _ws, type: aggregate['type'].toString(), id: conflict['aggregateId'].toString())]));`,
1458
1530
  ` }`,
1459
1531
  ` final modelPageItems = ((((model['pages'] as Map)['model'] as Map)['items'] as List?) ?? const [])`,
1460
1532
  ` .map((raw) => (raw as Map).cast<String, dynamic>()).where((item) => item['kind'] == 'verb').toList();`,
@@ -1481,7 +1553,7 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1481
1553
  ` NomosDescribeItem(kind: 'evidence', id: 'law', label: 'Generated law', summary: domainHash, details: {'domainHash': domainHash}),`,
1482
1554
  ` NomosDescribeItem(kind: 'evidence', id: 'reader', label: 'Verified reader', summary: this.actor ?? bridge.principal ?? 'anonymous', details: {'actor': this.actor ?? bridge.principal}),`,
1483
1555
  ` if (latest != null) NomosDescribeItem(kind: 'evidence', id: latest.eventId, label: 'Latest verified moment', summary: latest.eventId,`,
1484
- ` details: {'occurredAt': latest.occurredAt, 'actor': latest.actorSubject, 'domain': latest.domain, 'kind': latest.kind}),`,
1556
+ ` details: {'occurredAt': latest.occurredAt, 'performedBy': latest.performedBy, 'domain': latest.domain, 'kind': latest.kind}),`,
1485
1557
  ` ];`,
1486
1558
  ` }`,
1487
1559
  ` return NomosDescription(`,
@@ -1505,23 +1577,14 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1505
1577
  }
1506
1578
 
1507
1579
  return [
1508
- `// AUTO-GENERATED by nomos-compile — typed ASYNC Dart client for domain "${domain}".`,
1509
- `// Drives the REAL githolon over a NomosBridge (the WebView runner). Regenerated every compile; do`,
1510
- `// not edit. SESSION-BOUND (architecture/session_bound_clients.md): construct with a NomosSession —`,
1511
- `// one session, one workspace, one domain interface, one actor context:`,
1512
- `//`,
1580
+ `// AUTO-GENERATED by nomos-compile — private runtime implementation for domain "${domain}".`,
1581
+ `// Regenerated every compile; do not edit or teach this file as an application entry point.`,
1513
1582
  // GENERATED-CODE lints: the bridge read/watch surface returns dynamic (JSON rows), so typed accessors
1514
1583
  // do dynamic member access + casts by construction. Silence the lints that only make sense for
1515
1584
  // hand-written code, so this file never adds noise to a tenant's analyzer output (co2 feedback).
1516
1585
  // (deprecated_member_use*: the compatibility shims intentionally delegate to the deprecated
1517
1586
  // engine-level lanes for one minor version.)
1518
- `// ignore_for_file: avoid_dynamic_calls, unnecessary_this, prefer_const_constructors, unused_import, type_annotate_public_apis, always_specify_types, deprecated_member_use, deprecated_member_use_from_same_package`,
1519
- `//`,
1520
- `// final engine = NomosBridge(transport); // the device's local plane (NomosEngine)`,
1521
- `// await engine.ready;`,
1522
- `// final session = await engine.open(cloud: cloud, workspace: ws, clientId: deviceId);`,
1523
- `// final app = await ${className}.bind(session); // preflights law compatibility (ask 5)`,
1524
- `// await app.${dirs[0] ? safeMethod(dirs[0].id) : "someDirective"}(/* typed payload */);`,
1587
+ `// ignore_for_file: avoid_dynamic_calls, unnecessary_this, prefer_const_constructors, unused_import, type_annotate_public_apis, always_specify_types, deprecated_member_use, deprecated_member_use_from_same_package, invalid_use_of_internal_member`,
1525
1588
  ``,
1526
1589
  // `dart:convert` is needed ONLY for the interface block's `jsonDecode` — the offer lane no longer encodes
1527
1590
  // any envelope (it routes through `bridge.offerDirective` → THE ONE ENCODER). Omit it when no interface.
@@ -1549,11 +1612,10 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1549
1612
  ...[...crossDomainImports.entries()]
1550
1613
  .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
1551
1614
  .map(([uri, names]) => `import '${uri}' show ${[...names].sort().join(", ")};`),
1552
- `// Re-export the sibling types (read models + payloads + the bridge runtime) so ONE import of this`,
1553
- `// client file gives an app the whole typed surface.`,
1615
+ `// Re-export business types only. The runtime import above is an implementation dependency, never`,
1616
+ `// a tenant API: exporting it would create a second raw bridge/session/sync application lane.`,
1554
1617
  ...(opts.typesImportUri !== undefined ? [`export '${opts.typesImportUri}';`] : [`export '${mod.name}.dart';`]),
1555
1618
  ...(opts.typesImportUri === undefined && opts.frameworkImportUri !== undefined ? [`export '${opts.frameworkImportUri}';`] : []),
1556
- `export '${supportImport}' show NomosBridge, NomosEngine, NomosSession, NomosSessionCompat, BridgeTransport, NomosBridgeError, MissingOfferAuthority, kWebviewBridgeVersion, NomosCompat, NomosCompatMember, NomosOfferOutcome, NomosCreated, NomosRef, NomosMoment, NomosClientInterface, DomainClientSessionMismatch, DomainNotInstalledForSession, SessionMismatchCause${manualEncryptionPresent ? ", NomosScopeKey, NomosKeyStore, EncryptionKeyUnavailable, WrappedKeyStore, NomosEncryption, NomosEpochResult, EncryptionMemberKeyMissing, EncryptionRosterMismatch" : ""};`,
1557
1619
  ``,
1558
1620
  `/// sha256 of the deployed \`.package.usda\` — the installed law this client offers under.`,
1559
1621
  `const String ${hashConst} = ${dartStr(opts.domainHash)};`,
@@ -1650,10 +1712,10 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1650
1712
  ` /// \`await ${className}.open(bridge, ref: outcome.bornRefs.single)\` (or \`workspace: 'estate-42'\`).`,
1651
1713
  ` /// It ACQUIRES the workspace's session on [bridge] first (an already-open one is reused; a device-`,
1652
1714
  ` /// resident/parked/just-born one opens local-only in place) and THEN binds — so a not-open workspace`,
1653
- ` /// fails HERE, at open, never later on the client's first query. For a genuinely-absent cloud workspace,`,
1654
- ` /// \`acquireSession(ws, ifAbsentCredentials: ...)\` it yourself then [bind].`,
1655
- ` static Future<${className}> open(NomosBridge bridge, {NomosRef? ref, String? workspace, String? actor${manualEncryptionPresent ? ", NomosKeyStore? keyStore" : ""}}) async {`,
1656
- ` final ws = ref?.workspace ?? workspace;`,
1715
+ ` /// fails HERE, at open, never later on the client's first query. The generated stateful application`,
1716
+ ` /// privately retains refreshable cloud access for a genuinely-absent authorized workspace.`,
1717
+ ` static Future<${className}> open<TAggregate>(NomosBridge bridge, {NomosRef<TAggregate>? ref, String? workspace, String? actor${manualEncryptionPresent ? ", NomosKeyStore? keyStore" : ""}}) async {`,
1718
+ ` final ws = ref == null ? workspace : NmsInternalNomosRefs.workspace(ref);`,
1657
1719
  ` if (ws == null || ws.isEmpty) {`,
1658
1720
  ` throw ArgumentError('${className}.open: pass a workspace: or ref: — the workspace to open and bind');`,
1659
1721
  ` }`,
@@ -1697,11 +1759,11 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1697
1759
  ` _ownedIdentityReady = true;`,
1698
1760
  ` }`,
1699
1761
  ``,
1700
- ` Future<NomosOfferOutcome> _ownedRecordAction(String action, NomosRef record, String peer) async {`,
1762
+ ` Future<NomosOfferOutcome> _ownedRecordAction<TAggregate>(String action, NomosRef<TAggregate> record, String peer) async {`,
1701
1763
  ` await _preflightOnce();`,
1702
1764
  ` await _ensureOwnedIdentity();`,
1703
- ` if (record.workspace != _ws) throw ArgumentError('$action() cannot use a record from another workspace');`,
1704
- ` final directiveId = _ownedRecordActions[record.type]?[action];`,
1765
+ ` if (NmsInternalNomosRefs.workspace(record) != _ws) throw ArgumentError('$action() cannot use a record from another workspace');`,
1766
+ ` final directiveId = _ownedRecordActions[NmsInternalNomosRefs.type(record)]?[action];`,
1705
1767
  ` if (directiveId == null) throw ArgumentError('$action() needs a generated owned record reference');`,
1706
1768
  ` if (peer.trim().isEmpty) throw ArgumentError('$action() needs the person to act with');`,
1707
1769
  ` final payload = await bridge.nomosPrepareOwnedRecordAction(action: action, scope: ${dartStr(ownedScope)}, record: record, peer: peer);`,
@@ -1791,7 +1853,6 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
1791
1853
  ? [
1792
1854
  `// ---- role policy (UI hints — the KERNEL GATE is the authority) ----`,
1793
1855
  roleHelpers,
1794
- ``,
1795
1856
  ]
1796
1857
  : []),
1797
1858
  ].join("\n");