@githolon/dsl 0.108.0 → 0.108.2

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 (95) hide show
  1. package/dart/CHANGELOG.md +5 -0
  2. package/dart/lib/src/application_framework_calls.dart +299 -0
  3. package/dart/lib/src/generated_call.dart +96 -0
  4. package/dart/lib/src/nms_generated_runtime.dart +29 -0
  5. package/dart/lib/src/node_runner_transport.dart +77 -1
  6. package/dart/lib/src/result_usda.dart +487 -0
  7. package/dart/lib/src/runner/node-entry.mjs +6401 -2102
  8. package/dart/lib/src/runner/offline-install.mjs +1538 -163
  9. package/dart/lib/src/runtime_v2_gateway.dart +54 -0
  10. package/dart/lib/src/runtime_v2_transport.dart +117 -0
  11. package/dart/lib/src/session_bound.dart +7 -2
  12. package/dart/lib/src/test_harness.dart +193 -112
  13. package/dart/lib/src/webview_bridge.dart +2120 -569
  14. package/dart/pubspec.yaml +2 -2
  15. package/dart/test/acquire_session_credentials_test.dart +1 -1
  16. package/dart/test/acquire_session_test.dart +68 -14
  17. package/dart/test/adv_realm_interference_test.dart +6 -4
  18. package/dart/test/cluster_births_test.dart +11 -8
  19. package/dart/test/cluster_local_autosync_test.dart +1 -1
  20. package/dart/test/cluster_scale_test.dart +3 -2
  21. package/dart/test/dlq_session_surface_test.dart +52 -35
  22. package/dart/test/first_app_gauntlet_test.dart +1 -1
  23. package/dart/test/local_sync_inert_test.dart +23 -26
  24. package/dart/test/offer_authentication_proof_test.dart +193 -0
  25. package/dart/test/result_usda_test.dart +49 -0
  26. package/dart/test/session_bound_test.dart +8 -11
  27. package/dart/test/stale_bundle_test.dart +18 -3
  28. package/dart/test/test_harness_test.dart +14 -27
  29. package/dart/test/webview_bridge_test.dart +504 -83
  30. package/dart_types/CHANGELOG.md +7 -0
  31. package/dart_types/lib/nomos_kernel_protocol.dart +3 -2
  32. package/dart_types/lib/src/custody.dart +64 -19
  33. package/dart_types/lib/src/local_work_rejected.dart +30 -45
  34. package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pb.dart +169 -0
  35. package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pbenum.dart +11 -0
  36. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +2021 -234
  37. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +175 -8
  38. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +8664 -0
  39. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +369 -0
  40. package/dart_types/lib/src/surfaced.dart +30 -25
  41. package/dart_types/pubspec.yaml +1 -1
  42. package/dart_types/test/surfaced_test.dart +2 -1
  43. package/package.json +1 -1
  44. package/runtime/generated-application-host.js +5736 -2047
  45. package/src/authoring.ts +3 -2
  46. package/src/births.ts +21 -0
  47. package/src/build_package.ts +30 -0
  48. package/src/business_birth.ts +39 -35
  49. package/src/codegen_call_usda.ts +1111 -0
  50. package/src/codegen_dart.ts +207 -282
  51. package/src/codegen_dart_application.ts +195 -252
  52. package/src/codegen_dart_client.ts +1978 -593
  53. package/src/codegen_dart_framework_calls.ts +291 -0
  54. package/src/codegen_dart_scenario.ts +7 -0
  55. package/src/codegen_proof.ts +3 -4
  56. package/src/codegen_provider_dart.ts +21 -7
  57. package/src/codegen_query_usda.ts +214 -0
  58. package/src/codegen_result_usda.ts +685 -0
  59. package/src/codegen_ts.ts +3945 -1111
  60. package/src/compile_package_main.ts +360 -32
  61. package/src/directive.ts +19 -4
  62. package/src/engine_entry.ts +45 -4
  63. package/src/framework/application_home.ts +2 -0
  64. package/src/framework/auth_provider_law.ts +262 -20
  65. package/src/framework/home.ts +32 -28
  66. package/src/framework/owned_custody.ts +19 -11
  67. package/src/framework/owned_custody_value.ts +51 -0
  68. package/src/framework/relations.ts +57 -21
  69. package/src/framework/signing_identity.ts +34 -0
  70. package/src/framework/workspaces.ts +31 -9
  71. package/src/framework_call_definitions.ts +53 -0
  72. package/src/framework_read_definitions.ts +45 -0
  73. package/src/identity_frontier.ts +58 -0
  74. package/src/index.ts +20 -1
  75. package/src/intent.ts +216 -16
  76. package/src/law_check.ts +19 -1
  77. package/src/law_graph.ts +57 -8
  78. package/src/law_graph_usda.ts +73 -5
  79. package/src/law_value_type.ts +106 -19
  80. package/src/read.ts +47 -0
  81. package/src/read_projection_namespace.ts +7 -0
  82. package/src/shape_compat.ts +38 -39
  83. package/src/stable_ids.ts +37 -2
  84. package/src/stable_ids_for_module.ts +64 -4
  85. package/src/test_call_usda.ts +83 -0
  86. package/src/wire.ts +36 -2
  87. package/src/wire_encode.ts +45 -1
  88. package/src/workspace_sharing.ts +27 -10
  89. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbjson.dart +0 -6096
  90. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbserver.dart +0 -50
  91. package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pbjson.dart +0 -178
  92. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pb.dart +0 -828
  93. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbenum.dart +0 -465
  94. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbjson.dart +0 -573
  95. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbserver.dart +0 -50
@@ -7,7 +7,11 @@ import type { z } from "zod";
7
7
 
8
8
  import type { AggregateHandle } from "./aggregate.js";
9
9
  import type { Directive } from "./directive.js";
10
- import { isGitObjectIdSchema, isSha256DigestSchema, type Field } from "./fields.js";
10
+ import {
11
+ isGitObjectIdSchema,
12
+ isSha256DigestSchema,
13
+ type Field,
14
+ } from "./fields.js";
11
15
  import type { QueryDecl } from "./query.js";
12
16
  import type { DomainModule } from "./codegen_dart.js";
13
17
  import {
@@ -22,7 +26,11 @@ import {
22
26
  collectDartEnums,
23
27
  dartEnumTypeForField,
24
28
  } from "./codegen_dart.js";
25
- import { dartClientClassName } from "./codegen_dart_client.js";
29
+ import {
30
+ dartClientClassName,
31
+ dartInternalSourceTrustMethod,
32
+ dartInternalWorkspaceSharingReceiptMethod,
33
+ } from "./codegen_dart_client.js";
26
34
  import { finishCount } from "./count.js";
27
35
  import { finishSum } from "./sum.js";
28
36
  import {
@@ -114,7 +122,7 @@ function keyParam(key: string): string {
114
122
  function keyType(
115
123
  aggregate: AggregateHandle | undefined,
116
124
  key: string,
117
- enumDartTypes: ReadonlyMap<string, string>,
125
+ enumDartTypes: ReadonlyMap<string, string>
118
126
  ): string {
119
127
  const first = key.includes(".") ? key.split(".")[0]! : key;
120
128
  const field = aggregate?.fields[first] as Field | undefined;
@@ -194,39 +202,44 @@ function sharingReceiptCondition(
194
202
  function sharingReceiptPayload(
195
203
  policy: WorkspaceSharingPolicy,
196
204
  receipt: WorkspaceSharingReceipt,
197
- refused: boolean
205
+ refused: boolean,
206
+ enumDartTypes: ReadonlyMap<string, string>,
198
207
  ): string[] {
199
208
  const fields = introspectPayload(
200
209
  receipt.records.payloadSchema as z.ZodTypeAny,
201
- new Map()
210
+ new Map(enumDartTypes)
202
211
  );
203
212
  return fields.flatMap((target) => {
204
213
  if (target.name === "failureReason") {
205
214
  return refused
206
215
  ? [
207
- ` 'failureReason': share.message ?? 'shareDeliveryRefused',`,
216
+ ` failureReason: share.message ?? 'shareDeliveryRefused',`,
208
217
  ]
209
218
  : target.optional
210
- ? []
219
+ ? [` ${member(target.name)}: null,`]
211
220
  : (() => {
212
221
  throw new Error(
213
222
  `workspaceSharing(${policy.orders.id}): delivered receipt '${receipt.records.id}' requires failureReason`
214
223
  );
215
224
  })();
216
225
  }
217
- if (target.name === "deliveryHead" && target.optional) return [];
226
+ if (target.name === "deliveryHead" && target.optional) {
227
+ return [` ${member(target.name)}: null,`];
228
+ }
218
229
  const sourceName = receipt.payload?.[target.name] ?? target.name;
219
230
  const source = policy.orders.fields[sourceName];
220
231
  if (source === undefined) {
221
- if (target.optional) return [];
232
+ if (target.optional) return [` ${member(target.name)}: null,`];
222
233
  throw new Error(
223
234
  `workspaceSharing(${policy.orders.id}): receipt '${receipt.records.id}' requires '${target.name}', ` +
224
235
  `but the durable order does not record '${sourceName}'`
225
236
  );
226
237
  }
227
238
  const raw = sharingOrderValue(policy, sourceName);
228
- const expression = source.kind === "enum" ? `${raw}.wire` : raw;
229
- return [` ${JSON.stringify(target.name)}: ${expression},`];
239
+ const expression = source.kind === "enum"
240
+ ? `${target.dartType}.fromWire(${raw}.wire)`
241
+ : raw;
242
+ return [` ${member(target.name)}: ${expression},`];
230
243
  });
231
244
  }
232
245
 
@@ -324,7 +337,7 @@ function dartConflictPublicClassNames(mod: DomainModule): string[] {
324
337
  names.add(
325
338
  `${aggregateName}${cap(
326
339
  camel(binding.field)
327
- )}ConflictModelUpdateRequired`
340
+ )}ConflictEvolutionRequired`
328
341
  );
329
342
  }
330
343
  }
@@ -385,6 +398,8 @@ export interface DartApplicationOptions {
385
398
  /// Multi-domain package children remain stateful business handles, but only
386
399
  /// the generated package application may mount or expose application status.
387
400
  readonly tenantRoot?: boolean;
401
+ /** Relative compiler-generated framework-call implementation for this exact application closure. */
402
+ readonly applicationFrameworkCallsImportUri?: string;
388
403
  }
389
404
 
390
405
  /**
@@ -405,7 +420,7 @@ export function generateDartApplication(
405
420
  mod.directives,
406
421
  domain,
407
422
  mod.valueObjects ?? [],
408
- mod.deriveds ?? [],
423
+ mod.deriveds ?? []
409
424
  ).dartTypes;
410
425
  const application = dartApplicationClassName(domain);
411
426
  const activity = dartApplicationActivityClassName(domain);
@@ -437,6 +452,7 @@ export function generateDartApplication(
437
452
  let usesAffectedReferences = false;
438
453
  let usesAffectedReferenceOrNull = false;
439
454
  const actionResultDeclarations: string[] = [];
455
+ const internalFrameworkActionDeclarations: string[] = [];
440
456
  const conflictDeclarations: string[] = [];
441
457
  const resolverBindings: readonly SurfacedResolverBinding[] =
442
458
  mod.surfacedResolvers ?? [];
@@ -480,7 +496,7 @@ export function generateDartApplication(
480
496
  new Map()
481
497
  )) {
482
498
  if (
483
- spec.toJson !== "versionedRef" ||
499
+ spec.shape !== "versionedRef" ||
484
500
  spec.versionedRefTarget === undefined ||
485
501
  spec.versionedRefSeries === undefined ||
486
502
  spec.versionedRefTargetInput === undefined ||
@@ -606,45 +622,46 @@ export function generateDartApplication(
606
622
  )
607
623
  );
608
624
  const targetBinding = directive.targetBinding;
609
- const targetChecks = targetBinding === undefined
610
- ? []
611
- : [
612
- ` _nmsRequireReference(target, ${JSON.stringify(
613
- targetBinding.aggregateId
614
- )}, _client.session?.workspace ?? '');`,
615
- ];
625
+ const targetChecks =
626
+ targetBinding === undefined
627
+ ? []
628
+ : [
629
+ ` _nmsRequireReference(target, ${JSON.stringify(
630
+ targetBinding.aggregateId
631
+ )}, _client.session?.workspace ?? '');`,
632
+ ];
616
633
  return [
617
634
  ...targetChecks,
618
635
  ...specs
619
- .filter(
620
- (spec) =>
621
- (spec.toJson === "ref" || spec.toJson === "addressRef") &&
622
- spec.name !== targetBinding?.field &&
623
- !recordInputIds.has(spec.name)
624
- )
625
- .map((spec) => {
626
- const targetClass =
627
- spec.dartType.match(/^NomosRef<(.*)>$/)?.[1] ?? "Object?";
628
- const targetWire =
629
- spec.referenceType ??
630
- [...aggregates.values()].find(
631
- (aggregate) => concreteClassName(aggregate.id) === targetClass
632
- )?.id ??
633
- targetClass;
634
- const expectedWorkspace =
635
- spec.toJson === "addressRef" || foreignReferenceIds.has(spec.name)
636
- ? "''"
637
- : "_client.session?.workspace ?? ''";
638
- const value = `facts.${member(spec.name)}`;
639
- const check = `_nmsRequireReference(${value}, ${JSON.stringify(
640
- targetWire
641
- )}, ${expectedWorkspace});`;
642
- return spec.optional
643
- ? ` ${value}.when(absent: () {}, present: (reference) => _nmsRequireReference(reference, ${JSON.stringify(
644
- targetWire
645
- )}, ${expectedWorkspace}));`
646
- : ` ${check}`;
647
- }),
636
+ .filter(
637
+ (spec) =>
638
+ (spec.shape === "ref" || spec.shape === "addressRef") &&
639
+ spec.name !== targetBinding?.field &&
640
+ !recordInputIds.has(spec.name)
641
+ )
642
+ .map((spec) => {
643
+ const targetClass =
644
+ spec.dartType.match(/^NomosRef<(.*)>$/)?.[1] ?? "Object?";
645
+ const targetWire =
646
+ spec.referenceType ??
647
+ [...aggregates.values()].find(
648
+ (aggregate) => concreteClassName(aggregate.id) === targetClass
649
+ )?.id ??
650
+ targetClass;
651
+ const expectedWorkspace =
652
+ spec.shape === "addressRef" || foreignReferenceIds.has(spec.name)
653
+ ? "''"
654
+ : "_client.session?.workspace ?? ''";
655
+ const value = `facts.${member(spec.name)}`;
656
+ const check = `_nmsRequireReference(${value}, ${JSON.stringify(
657
+ targetWire
658
+ )}, ${expectedWorkspace});`;
659
+ return spec.optional
660
+ ? ` ${value}.when(absent: () {}, present: (reference) => _nmsRequireReference(reference, ${JSON.stringify(
661
+ targetWire
662
+ )}, ${expectedWorkspace}));`
663
+ : ` ${check}`;
664
+ }),
648
665
  ];
649
666
  };
650
667
 
@@ -659,167 +676,13 @@ export function generateDartApplication(
659
676
  collectionMembers.set(aggregate.id, new Set());
660
677
  }
661
678
 
662
- // Conflicts are business decisions, so the application facade keeps the useful chain while the
663
- // heterogeneous index, immutable proof snapshot and offer result remain implementation details.
679
+ // The compiler-generated client already owns the exact USDA decoders and typed
680
+ // merge decisions. The application facade aliases that one surface instead of
681
+ // rebuilding a second, inevitably drifting conflict type system.
664
682
  if (resolverBindings.length > 0) {
665
683
  const conflictsClass = `${cap(camel(domain))}Conflicts`;
666
- const summaryClass = `${cap(camel(domain))}ConflictSummary`;
667
- const rowClass = `_${cap(camel(domain))}PendingConflictRow`;
668
- const byAggregate = new Map<string, SurfacedResolverBinding[]>();
669
- for (const binding of resolverBindings) {
670
- byAggregate.set(binding.aggregateId, [
671
- ...(byAggregate.get(binding.aggregateId) ?? []),
672
- binding,
673
- ]);
674
- }
675
684
  claimApplicationMember("conflicts", "the generated conflict policy");
676
685
  appLines.push(` final ${conflictsClass} conflicts;`);
677
-
678
- conflictDeclarations.push(
679
- `/// Pending business decisions across this application.`,
680
- `final class ${summaryClass} {`,
681
- ` final int total;`,
682
- ` final int ready;`,
683
- ` final int modelUpdatesRequired;`,
684
- ` final Map<String, int> byAggregate;`,
685
- ` const ${summaryClass}({required this.total, required this.ready, required this.modelUpdatesRequired, required this.byAggregate});`,
686
- `}`,
687
- ``,
688
- `/// Summary -> aggregate -> typed conflict -> merge.`,
689
- `final class ${conflictsClass} {`,
690
- ` final ${client} _client;`,
691
- ` const ${conflictsClass}._(this._client);`,
692
- ``,
693
- ` Future<${summaryClass}> summary() async {`,
694
- ` final summary = await _client.bridge.pendingConflictSummary();`,
695
- ` final byAggregate = (summary['byAggregate'] as Map? ?? const {}).map(`,
696
- ` (key, value) => MapEntry(key.toString(), (value as num).toInt()));`,
697
- ` return ${summaryClass}(`,
698
- ` total: (summary['total'] as num? ?? 0).toInt(),`,
699
- ` ready: (summary['ready'] as num? ?? 0).toInt(),`,
700
- ` modelUpdatesRequired: (summary['evolutionRequired'] as num? ?? 0).toInt(),`,
701
- ` byAggregate: Map.unmodifiable(byAggregate),`,
702
- ` );`,
703
- ` }`,
704
- ...[...byAggregate.keys()].map(
705
- (aggregateId) =>
706
- ` ${aggregateConflictsClassName(domain, aggregateId)} get ${member(
707
- concreteClassName(aggregateId)
708
- )} => ${aggregateConflictsClassName(domain, aggregateId)}._(_client);`
709
- ),
710
- `}`,
711
- ``
712
- );
713
-
714
- for (const [aggregateId, bindings] of byAggregate) {
715
- const aggregate = aggregates.get(aggregateId);
716
- if (aggregate === undefined) {
717
- throw new Error(
718
- `generated conflict policy refers to unknown aggregate '${aggregateId}' in domain '${domain}'`
719
- );
720
- }
721
- const runtimeAggregateType = isNamespacedAggregate(aggregate)
722
- ? qualifyReadProjectionType(domain, aggregateId)
723
- : aggregateId;
724
- const aggregateName = cap(camel(concreteClassName(aggregateId)));
725
- const pendingClass = `${aggregateName}PendingConflict`;
726
- const aggregateClass = aggregateConflictsClassName(domain, aggregateId);
727
- conflictDeclarations.push(
728
- `sealed class ${pendingClass} {`,
729
- ` const ${pendingClass}();`,
730
- ` String get aggregateId;`,
731
- ` String get field;`,
732
- `}`,
733
- ``
734
- );
735
- for (const binding of bindings) {
736
- if (
737
- binding.valuePayloadField === undefined ||
738
- binding.idPayloadField === undefined
739
- )
740
- continue;
741
- const fieldKind = aggregate.fields[binding.field]?.kind;
742
- const mergedType =
743
- fieldKind === "string" || fieldKind === "ref" || fieldKind === "enum"
744
- ? "String"
745
- : fieldKind === "int"
746
- ? "int"
747
- : fieldKind === "bool"
748
- ? "bool"
749
- : "Object?";
750
- const typeName = `${aggregateName}${cap(camel(binding.field))}Conflict`;
751
- const evolutionTypeName = `${typeName}ModelUpdateRequired`;
752
- const helper = `_merge${aggregateName}${cap(camel(binding.field))}`;
753
- conflictDeclarations.push(
754
- `/// Merge every observed business version into one result.`,
755
- `final class ${typeName} extends ${pendingClass} {`,
756
- ` final ${rowClass} _details;`,
757
- ` final ${client} _client;`,
758
- ` const ${typeName}._(this._details, this._client);`,
759
- ` @override String get aggregateId => _details.aggregateId;`,
760
- ` @override String get field => _details.field;`,
761
- ` List<SurfacedObservation<${mergedType}>> get versions => List.unmodifiable(`,
762
- ` _details.observations.map((item) => SurfacedObservation<${mergedType}>(`,
763
- ` value: item.value as ${mergedType}, occurredAt: item.occurredAt, author: item.author)));`,
764
- ` Future<void> merge(`,
765
- ` ${mergedType} Function(List<SurfacedObservation<${mergedType}>> versions) reconcile,`,
766
- ` {Map<String, Object?> rest = const {}}) async {`,
767
- ` await _client.${helper}(_details, reconcile(versions), rest: rest);`,
768
- ` }`,
769
- `}`,
770
- ``,
771
- `/// This disagreement remains pending because the business model cannot yet compare every`,
772
- `/// retained version. Unrelated work continues; update the model's evolution policy to unlock it.`,
773
- `final class ${evolutionTypeName} extends ${pendingClass} {`,
774
- ` final ${rowClass} _details;`,
775
- ` const ${evolutionTypeName}._(this._details);`,
776
- ` @override String get aggregateId => _details.aggregateId;`,
777
- ` @override String get field => _details.field;`,
778
- ` String get reason => _details.evolution?['reason']?.toString() ??`,
779
- ` 'The business model cannot yet compare every retained version. Update its evolution policy; unrelated work can continue.';`,
780
- `}`,
781
- ``
782
- );
783
- }
784
- conflictDeclarations.push(
785
- `final class ${aggregateClass} {`,
786
- ` final ${client} _client;`,
787
- ` const ${aggregateClass}._(this._client);`,
788
- ` Future<List<${pendingClass}>> pending() async {`,
789
- ` final rows = await _client._pendingConflictRows(${JSON.stringify(
790
- runtimeAggregateType
791
- )});`,
792
- ` final decisions = <${pendingClass}>[];`,
793
- ` for (final row in rows) {`,
794
- ` switch (row.field) {`,
795
- ...bindings.flatMap((binding) => {
796
- if (
797
- binding.valuePayloadField === undefined ||
798
- binding.idPayloadField === undefined
799
- )
800
- return [];
801
- const typeName = `${aggregateName}${cap(
802
- camel(binding.field)
803
- )}Conflict`;
804
- return [
805
- ` case ${JSON.stringify(binding.field)}:`,
806
- ` if (row.status == 'ready') {`,
807
- ` decisions.add(${typeName}._(row, _client));`,
808
- ` } else if (row.status == 'evolutionRequired') {`,
809
- ` decisions.add(${typeName}ModelUpdateRequired._(row));`,
810
- ` } else {`,
811
- ` throw StateError('Nomos returned an unknown conflict status: \${row.status}');`,
812
- ` }`,
813
- ];
814
- }),
815
- ` }`,
816
- ` }`,
817
- ` return List.unmodifiable(decisions);`,
818
- ` }`,
819
- `}`,
820
- ``
821
- );
822
- }
823
686
  }
824
687
 
825
688
  const addCollectionMember = (
@@ -850,10 +713,7 @@ export function generateDartApplication(
850
713
  path
851
714
  .split(".")
852
715
  .reduce((expr, part) => `${expr}.${member(part)}`, "facts");
853
- const foreignInputs = dartForeignReferenceInputs(
854
- directive,
855
- mod.aggregates
856
- );
716
+ const foreignInputs = dartForeignReferenceInputs(directive, mod.aggregates);
857
717
  // A generated input collapses a foreign `(workspace, id)` pair into one
858
718
  // NomosRef. Source-trust orchestration must follow that public shape too:
859
719
  // deriving the locator from the typed reference, rather than reaching for
@@ -880,33 +740,67 @@ export function generateDartApplication(
880
740
  };
881
741
  const trust = directive.businessSourceTrust;
882
742
  const method = member(directive.id);
883
- const call = directive.targetBinding === undefined
884
- ? `_client.${method}(facts)`
885
- : `_client.${method}(target, facts)`;
743
+ const call =
744
+ directive.targetBinding === undefined
745
+ ? `_client.${method}(facts)`
746
+ : `_client.${method}(target, facts)`;
886
747
  if (trust === undefined) {
887
748
  return { prelude: [], call };
888
749
  }
889
- const copied = Object.entries(trust.copy)
750
+ const copiedEntries = Object.entries(trust.copy)
890
751
  .sort(([a], [b]) => a.localeCompare(b))
891
- .map(
892
- ([target, field]) =>
893
- ` ${JSON.stringify(target)}: ${factValue(field)},`
752
+ const copied = copiedEntries.map(
753
+ ([target, field]) => ` ${member(target)}: ${factValue(field)},`
754
+ );
755
+ const trustDirective = (mod.directives as AnyDirective[]).find(
756
+ (candidate) => candidate.id === trust.viaDirectiveId
757
+ );
758
+ if (trustDirective === undefined) {
759
+ throw new Error(
760
+ `Dart source-trust codegen: '${directive.id}' names missing trust directive '${trust.viaDirectiveId}'`
761
+ );
762
+ }
763
+ const trustFields = introspectPayload(
764
+ trustDirective.payloadSchema as z.ZodTypeAny,
765
+ enumDartTypes
766
+ );
767
+ const supplied = new Set([
768
+ ...copiedEntries.map(([target]) => target),
769
+ trust.genesisField,
770
+ trust.keyHashesField,
771
+ ]);
772
+ const missingRequired = trustFields.filter(
773
+ (field) => !supplied.has(field.name) && !field.optional
774
+ );
775
+ if (missingRequired.length > 0) {
776
+ throw new Error(
777
+ `Dart source-trust codegen: '${directive.id}' cannot construct '${trust.viaDirectiveId}'; ` +
778
+ `missing required typed field(s): ${missingRequired.map((field) => field.name).join(", ")}`
894
779
  );
780
+ }
781
+ const omittedOptionals = trustFields
782
+ .filter((field) => !supplied.has(field.name) && field.optional)
783
+ .map((field) => ` ${member(field.name)}: null,`);
784
+ const keyHashesType = trustFields.find(
785
+ (field) => field.name === trust.keyHashesField
786
+ )?.dartType;
787
+ const keyElementType = keyHashesType?.match(/^List<(.+)>$/)?.[1] ?? "Never";
895
788
  return {
896
789
  prelude: [
897
790
  ` final sourceGenesis = await _client.bridge.nomosWorkspaceGenesis(${factValue(
898
791
  trust.fromPayload
899
792
  )});`,
900
- ` await _client._offer(`,
901
- ` ${JSON.stringify(trust.viaDirectiveId)},`,
902
- ` {`,
793
+ ` await _client.${dartInternalSourceTrustMethod(
794
+ trust.viaDirectiveId
795
+ )}((`,
903
796
  ...copied,
904
- ` ${JSON.stringify(trust.genesisField)}: sourceGenesis,`,
905
- ` ${JSON.stringify(trust.keyHashesField)}: [${JSON.stringify(
906
- "0".repeat(64)
907
- )}],`,
908
- ` },`,
909
- ` );`,
797
+ ...omittedOptionals,
798
+ ` ${member(trust.genesisField)}: sourceGenesis,`,
799
+ // Custody-native v2 proves the sibling by genesis + authenticated Git position and has no
800
+ // signing key. Never fabricate a v1 attestor identity; an operator must explicitly enroll
801
+ // real keys before a signed v1 read can pass.
802
+ ` ${member(trust.keyHashesField)}: const <${keyElementType}>[],`,
803
+ ` ));`,
910
804
  ],
911
805
  call,
912
806
  };
@@ -929,6 +823,7 @@ export function generateDartApplication(
929
823
  ` Future<void> redeemInvitation(String link) =>`,
930
824
  ` NmsInternalApplicationHost.redeemInvitation<User>(`,
931
825
  ` _client.bridge,`,
826
+ ` frameworkCalls: nomosInternalApplicationFrameworkCalls,`,
932
827
  ` link: link,`,
933
828
  ` identity: _client.actor,`,
934
829
  ` policies: [`,
@@ -965,7 +860,7 @@ export function generateDartApplication(
965
860
  ? `${keyType(
966
861
  pendingAggregate,
967
862
  pendingKey,
968
- enumDartTypes,
863
+ enumDartTypes
969
864
  )}.fromWire(${JSON.stringify(policy.pendingValue)})`
970
865
  : JSON.stringify(policy.pendingValue);
971
866
  const person = sharingOrderValue(policy, policy.person, "wire");
@@ -977,12 +872,11 @@ export function generateDartApplication(
977
872
  ): string[] => {
978
873
  const condition = sharingReceiptCondition(policy, receipt);
979
874
  const body = [
980
- ` await _client._offer(`,
981
- ` ${JSON.stringify(receipt.records.id)},`,
982
- ` <String, Object?>{`,
983
- ...sharingReceiptPayload(policy, receipt, refused),
984
- ` },`,
985
- ` );`,
875
+ ` await _client.${dartInternalWorkspaceSharingReceiptMethod(
876
+ receipt.records.id
877
+ )}((`,
878
+ ...sharingReceiptPayload(policy, receipt, refused, enumDartTypes),
879
+ ` ));`,
986
880
  ` continue;`,
987
881
  ];
988
882
  // A receipt with no `when` is the policy's exhaustive fallback. Emitting `if (true)` makes both
@@ -1210,7 +1104,9 @@ export function generateDartApplication(
1210
1104
  ` /// Open the workspace named by a typed ${rootType} custody reference.`,
1211
1105
  ` /// The reference supplies identity and routing only; normal authority checks still apply.`,
1212
1106
  ` Future<${targetApplication}> openReference(NomosRef<${rootType}> reference) {`,
1213
- ` _nmsRequireReference(reference, ${JSON.stringify(birth.aggregateId)}, '');`,
1107
+ ` _nmsRequireReference(reference, ${JSON.stringify(
1108
+ birth.aggregateId
1109
+ )}, '');`,
1214
1110
  ` return _nmsOpenReference(reference);`,
1215
1111
  ` }`,
1216
1112
  ``,
@@ -1368,24 +1264,57 @@ export function generateDartApplication(
1368
1264
  }
1369
1265
  continue;
1370
1266
  }
1371
- // Lowered cross-workspace governance births are framework implementation, never tenant actions.
1372
- if ((directive as { birthsChild?: boolean }).birthsChild === true) continue;
1267
+ // Lowered cross-workspace governance births are framework implementation,
1268
+ // never tenant actions. Generated framework tests and ceremonies still
1269
+ // need one nominal path to their compiler-authored USDA encoder; otherwise
1270
+ // they are forced back through a generic payload map. Keep that path out of
1271
+ // the application object and package barrel, and make its framework-only
1272
+ // status explicit in the generated symbol name.
1273
+ if ((directive as { birthsChild?: boolean }).birthsChild === true) {
1274
+ const method = member(directive.id);
1275
+ internalFrameworkActionDeclarations.push(
1276
+ `/// Framework-only typed entry point for the law-declared ${directive.id} birth effect.`,
1277
+ `/// Generated infrastructure may use this; tenant applications do not receive it as an application member.`,
1278
+ `Future<NomosOfferOutcome> nomosInternal${cap(camel(domain))}${cap(
1279
+ camel(directive.id)
1280
+ )}(`,
1281
+ ` ${application} application, ${dartActionInputClassName(
1282
+ directive
1283
+ )} facts) =>`,
1284
+ ` application._client.${method}(facts);`,
1285
+ ``
1286
+ );
1287
+ continue;
1288
+ }
1373
1289
 
1374
1290
  const method = member(directive.id);
1375
1291
  const payload = dartActionInputClassName(directive);
1376
- const targetOnly = directive.targetBinding !== undefined &&
1377
- introspectPayload(directive.payloadSchema as z.ZodTypeAny, new Map()).every(
1292
+ const payloadSpecs = introspectPayload(
1293
+ directive.payloadSchema as z.ZodTypeAny,
1294
+ new Map(),
1295
+ );
1296
+ const emptyPayload = directive.targetBinding === undefined && payloadSpecs.length === 0;
1297
+ const targetOnly =
1298
+ directive.targetBinding !== undefined &&
1299
+ payloadSpecs.every(
1378
1300
  (spec) =>
1379
1301
  spec.name === directive.targetBinding?.field ||
1380
- spec.name === directive.businessPrincipalField,
1302
+ spec.name === directive.businessPrincipalField
1381
1303
  ) &&
1382
1304
  (directive.businessRecordInputs?.length ?? 0) === 0;
1383
- const targetParameter = directive.targetBinding === undefined
1384
- ? `${payload} facts`
1385
- : targetOnly
1386
- ? `NomosRef<${concreteClassName(directive.targetBinding.aggregateId)}> target`
1387
- : `NomosRef<${concreteClassName(directive.targetBinding.aggregateId)}> target, ${payload} facts`;
1388
- const factsPrelude = targetOnly ? [` const facts = ${payload}();`] : [];
1305
+ const targetParameter =
1306
+ emptyPayload
1307
+ ? ""
1308
+ : directive.targetBinding === undefined
1309
+ ? `${payload} facts`
1310
+ : targetOnly
1311
+ ? `NomosRef<${concreteClassName(
1312
+ directive.targetBinding.aggregateId
1313
+ )}> target`
1314
+ : `NomosRef<${concreteClassName(
1315
+ directive.targetBinding.aggregateId
1316
+ )}> target, ${payload} facts`;
1317
+ const factsPrelude = targetOnly || emptyPayload ? [` const facts = ${payload}();`] : [];
1389
1318
  const referenceChecks = actionReferenceChecks(directive);
1390
1319
  const outputs = dartActionOutputs(directive, mod.aggregates);
1391
1320
  const resultClass = dartActionResultClassName(directive.id);
@@ -1520,7 +1449,10 @@ export function generateDartApplication(
1520
1449
  const model = readModelClassName(query.returns);
1521
1450
  const aggregate = aggregates.get(query.returns);
1522
1451
  const params = query.key
1523
- .map((key) => `required ${keyType(aggregate, key, enumDartTypes)} ${keyParam(key)}`)
1452
+ .map(
1453
+ (key) =>
1454
+ `required ${keyType(aggregate, key, enumDartTypes)} ${keyParam(key)}`
1455
+ )
1524
1456
  .join(", ");
1525
1457
  const args = query.key
1526
1458
  .map((key) => `${keyParam(key)}: ${keyParam(key)}`)
@@ -2026,9 +1958,7 @@ export function generateDartApplication(
2026
1958
  "_client = client",
2027
1959
  ...(tenantRoot ? ["currentUser = currentUser"] : []),
2028
1960
  `activity = ${activity}._(client)`,
2029
- ...(resolverBindings.length > 0
2030
- ? [`conflicts = ${cap(camel(domain))}Conflicts._(client)`]
2031
- : []),
1961
+ ...(resolverBindings.length > 0 ? [`conflicts = client.conflicts`] : []),
2032
1962
  ...initializers,
2033
1963
  ];
2034
1964
  return [
@@ -2062,7 +1992,9 @@ export function generateDartApplication(
2062
1992
  ]
2063
1993
  : []),
2064
1994
  `import 'package:nomos_flutter/src/generated_application_host.dart' show ${
2065
- tenantRoot ? "ApplicationModelChange, NomosApplicationStartupState, " : ""
1995
+ tenantRoot
1996
+ ? "ApplicationModelChange, NomosApplicationStartupState, "
1997
+ : ""
2066
1998
  }NmsInternalApplicationUserBinding${
2067
1999
  opts.flutterHost === true || sharingPolicies.length > 0
2068
2000
  ? ", NmsInternalApplicationHost"
@@ -2073,8 +2005,15 @@ export function generateDartApplication(
2073
2005
  ]
2074
2006
  : []),
2075
2007
  `import '${typesImport}';`,
2008
+ ...(opts.applicationFrameworkCallsImportUri !== undefined
2009
+ ? [
2010
+ `import '${opts.applicationFrameworkCallsImportUri}' show nomosInternalApplicationFrameworkCalls;`,
2011
+ ]
2012
+ : []),
2076
2013
  ...[...explicitTypeImportUris].sort().map((uri) => `import '${uri}';`),
2077
- `import '${mod.name}.client.dart' show ${client};`,
2014
+ `import '${mod.name}.client.dart' show ${client}${
2015
+ resolverBindings.length > 0 ? `, ${cap(camel(domain))}Conflicts` : ""
2016
+ };`,
2078
2017
  ...imports,
2079
2018
  ``,
2080
2019
  ...(tenantRoot
@@ -2155,6 +2094,9 @@ export function generateDartApplication(
2155
2094
  ` Duration startupTimeout = const Duration(minutes: 3),`,
2156
2095
  ` }) => NmsInternalApplicationHost.home<${application}>(`,
2157
2096
  ` key: key, cloud: cloud, application: application, signIn: signIn,`,
2097
+ ...(opts.applicationFrameworkCallsImportUri === undefined
2098
+ ? []
2099
+ : [` frameworkCalls: nomosInternalApplicationFrameworkCalls,`]),
2158
2100
  ` bind: nomosInternalBind${application}, builder: builder,`,
2159
2101
  ` loadingBuilder: loadingBuilder, errorBuilder: errorBuilder,`,
2160
2102
  ` onModelChange: onModelChange,`,
@@ -2165,6 +2107,7 @@ export function generateDartApplication(
2165
2107
  : []),
2166
2108
  `}`,
2167
2109
  ``,
2110
+ ...internalFrameworkActionDeclarations,
2168
2111
  `/// The verified recent business activity of this application, newest first.`,
2169
2112
  `final class ${activity} {`,
2170
2113
  ` final ${client} _client;`,