@githolon/dsl 0.108.0 → 0.108.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dart/CHANGELOG.md +5 -0
- package/dart/lib/src/application_framework_calls.dart +299 -0
- package/dart/lib/src/generated_call.dart +96 -0
- package/dart/lib/src/nms_generated_runtime.dart +29 -0
- package/dart/lib/src/node_runner_transport.dart +77 -1
- package/dart/lib/src/result_usda.dart +487 -0
- package/dart/lib/src/runner/node-entry.mjs +6401 -2102
- package/dart/lib/src/runner/offline-install.mjs +1538 -163
- package/dart/lib/src/runtime_v2_gateway.dart +54 -0
- package/dart/lib/src/runtime_v2_transport.dart +117 -0
- package/dart/lib/src/session_bound.dart +7 -2
- package/dart/lib/src/test_harness.dart +193 -112
- package/dart/lib/src/webview_bridge.dart +2120 -569
- package/dart/pubspec.yaml +2 -2
- package/dart/test/acquire_session_credentials_test.dart +1 -1
- package/dart/test/acquire_session_test.dart +68 -14
- package/dart/test/adv_realm_interference_test.dart +6 -4
- package/dart/test/cluster_births_test.dart +11 -8
- package/dart/test/cluster_local_autosync_test.dart +1 -1
- package/dart/test/cluster_scale_test.dart +3 -2
- package/dart/test/dlq_session_surface_test.dart +52 -35
- package/dart/test/first_app_gauntlet_test.dart +1 -1
- package/dart/test/local_sync_inert_test.dart +23 -26
- package/dart/test/offer_authentication_proof_test.dart +193 -0
- package/dart/test/result_usda_test.dart +49 -0
- package/dart/test/session_bound_test.dart +8 -11
- package/dart/test/stale_bundle_test.dart +18 -3
- package/dart/test/test_harness_test.dart +14 -27
- package/dart/test/webview_bridge_test.dart +504 -83
- package/dart_types/CHANGELOG.md +7 -0
- package/dart_types/lib/nomos_kernel_protocol.dart +3 -2
- package/dart_types/lib/src/custody.dart +64 -19
- package/dart_types/lib/src/local_work_rejected.dart +30 -45
- package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pb.dart +169 -0
- package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +2021 -234
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +175 -8
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +8664 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +369 -0
- package/dart_types/lib/src/surfaced.dart +30 -25
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/surfaced_test.dart +2 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +5736 -2047
- package/src/authoring.ts +3 -2
- package/src/births.ts +21 -0
- package/src/build_package.ts +30 -0
- package/src/business_birth.ts +39 -35
- package/src/codegen_call_usda.ts +1111 -0
- package/src/codegen_dart.ts +207 -282
- package/src/codegen_dart_application.ts +195 -252
- package/src/codegen_dart_client.ts +1978 -593
- package/src/codegen_dart_framework_calls.ts +291 -0
- package/src/codegen_dart_scenario.ts +7 -0
- package/src/codegen_proof.ts +3 -4
- package/src/codegen_provider_dart.ts +21 -7
- package/src/codegen_query_usda.ts +214 -0
- package/src/codegen_result_usda.ts +685 -0
- package/src/codegen_ts.ts +3945 -1111
- package/src/compile_package_main.ts +360 -32
- package/src/directive.ts +19 -4
- package/src/engine_entry.ts +45 -4
- package/src/framework/application_home.ts +2 -0
- package/src/framework/auth_provider_law.ts +262 -20
- package/src/framework/home.ts +32 -28
- package/src/framework/owned_custody.ts +19 -11
- package/src/framework/owned_custody_value.ts +51 -0
- package/src/framework/relations.ts +47 -21
- package/src/framework/signing_identity.ts +34 -0
- package/src/framework/workspaces.ts +31 -9
- package/src/framework_call_definitions.ts +53 -0
- package/src/framework_read_definitions.ts +45 -0
- package/src/identity_frontier.ts +58 -0
- package/src/index.ts +20 -1
- package/src/intent.ts +216 -16
- package/src/law_check.ts +19 -1
- package/src/law_graph.ts +57 -8
- package/src/law_graph_usda.ts +73 -5
- package/src/law_value_type.ts +106 -19
- package/src/read.ts +47 -0
- package/src/read_projection_namespace.ts +7 -0
- package/src/shape_compat.ts +38 -39
- package/src/stable_ids.ts +37 -2
- package/src/test_call_usda.ts +83 -0
- package/src/wire.ts +36 -2
- package/src/wire_encode.ts +45 -1
- package/src/workspace_sharing.ts +27 -10
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbjson.dart +0 -6096
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbserver.dart +0 -50
- package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pbjson.dart +0 -178
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pb.dart +0 -828
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbenum.dart +0 -465
- package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbjson.dart +0 -573
- 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 {
|
|
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 {
|
|
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
|
-
`
|
|
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)
|
|
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"
|
|
229
|
-
|
|
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
|
-
)}
|
|
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.
|
|
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 =
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
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
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
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
|
-
//
|
|
663
|
-
//
|
|
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 =
|
|
884
|
-
|
|
885
|
-
|
|
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
|
|
750
|
+
const copiedEntries = Object.entries(trust.copy)
|
|
890
751
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
891
|
-
|
|
892
|
-
([target, field]) =>
|
|
893
|
-
|
|
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
|
|
901
|
-
|
|
902
|
-
|
|
793
|
+
` await _client.${dartInternalSourceTrustMethod(
|
|
794
|
+
trust.viaDirectiveId
|
|
795
|
+
)}((`,
|
|
903
796
|
...copied,
|
|
904
|
-
|
|
905
|
-
` ${
|
|
906
|
-
|
|
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
|
|
981
|
-
|
|
982
|
-
|
|
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(
|
|
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,
|
|
1372
|
-
|
|
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
|
|
1377
|
-
|
|
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 =
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
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(
|
|
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
|
|
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;`,
|