@githolon/dsl 0.103.3 → 0.103.5
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 +15 -0
- package/dart/lib/src/runner/node-entry.mjs +411 -149
- package/dart/lib/src/runner/offline-install.mjs +222 -99
- package/dart/lib/src/session_bound.dart +111 -2
- package/dart/lib/src/test_harness.dart +117 -66
- package/dart/lib/src/webview_bridge.dart +726 -61
- package/dart/pubspec.lock +1 -1
- package/dart/pubspec.yaml +4 -5
- package/dart/test/acquire_session_test.dart +62 -5
- package/dart/test/cloud_bound_topology_test.dart +59 -38
- package/dart/test/session_bound_test.dart +25 -10
- package/dart/test/webview_bridge_test.dart +357 -9
- package/dart_types/CHANGELOG.md +5 -0
- package/dart_types/lib/nomos_types.dart +1 -0
- package/dart_types/lib/src/git_object_id.dart +37 -0
- package/dart_types/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +425 -145
- package/src/births.ts +16 -1
- package/src/business_birth.ts +67 -46
- package/src/codegen_dart.ts +68 -12
- package/src/codegen_dart_application.ts +114 -19
- package/src/codegen_dart_client.ts +149 -6
- package/src/codegen_proof.ts +16 -9
- package/src/codegen_provider_dart.ts +5 -0
- package/src/codegen_ts.ts +115 -19
- package/src/compile_package_main.ts +142 -40
- package/src/fields.ts +43 -0
- package/src/framework/attested_receipts.ts +34 -1
- package/src/framework/domain_lifecycle.ts +140 -83
- package/src/framework/genesis.ts +2 -1
- package/src/framework/home.ts +20 -45
- package/src/framework/workspaces.ts +62 -29
- package/src/idof_lint.ts +65 -51
- package/src/index.ts +21 -1
- package/src/intent.ts +11 -1
- package/src/law_graph.ts +81 -11
- package/src/law_graph_usda.ts +45 -54
- package/src/relation_schema.ts +18 -0
- package/src/shape_compat.ts +3 -0
- package/src/stable_ids_for_module.ts +7 -1
- package/src/value_object.ts +40 -0
package/src/births.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { z } from "zod";
|
|
|
7
7
|
import type { AggregateHandle } from "./aggregate.js";
|
|
8
8
|
import type { AggregateRef } from "./authoring.js";
|
|
9
9
|
import type { Ports } from "./ctx.js";
|
|
10
|
-
import type { Field, FieldValue } from "./fields.js";
|
|
10
|
+
import type { Field, FieldValue, NomosRefValue } from "./fields.js";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* THE BIRTH EFFECT — birth is an EXPLICIT, DECLARED kernel primitive (G3, the unix model).
|
|
@@ -76,6 +76,9 @@ export interface BusinessBirthDecl<
|
|
|
76
76
|
readonly payloadSchema: z.ZodObject<z.ZodRawShape> & z.ZodType<P>;
|
|
77
77
|
/** A stable business key the caller already knows (an estate reference, account number, etc.). */
|
|
78
78
|
readonly key: (payload: P) => string;
|
|
79
|
+
/** The complete custody address this declaration gives the born root.
|
|
80
|
+
* Carry it in parent projections instead of reconstructing workspace names in tenant code. */
|
|
81
|
+
readonly reference: (payload: P) => NomosRefValue;
|
|
79
82
|
/** The declared business fact used by {@link key}; retained for generated clients to pre-address custody. */
|
|
80
83
|
readonly keyField: string;
|
|
81
84
|
/** Framework-derived initial authoring. Tenant code marks aggregate fields `.fromBirth()` instead. */
|
|
@@ -192,11 +195,23 @@ export function birth<F extends Record<string, Field>>(
|
|
|
192
195
|
);
|
|
193
196
|
}
|
|
194
197
|
type Payload = BusinessBirthPayload<F>;
|
|
198
|
+
const aggregateNoun = aggregate.id
|
|
199
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
200
|
+
.toLowerCase();
|
|
201
|
+
const namespace = (spec.namespace ?? aggregateNoun)
|
|
202
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
203
|
+
.toLowerCase();
|
|
204
|
+
const rootId = `${aggregateNoun}:self`;
|
|
195
205
|
const declaration = {
|
|
196
206
|
__isBusinessBirth: true,
|
|
197
207
|
aggregate,
|
|
198
208
|
payloadSchema,
|
|
199
209
|
key: (payload: Payload) => String(payload[spec.key]),
|
|
210
|
+
reference: (payload: Payload): NomosRefValue => ({
|
|
211
|
+
workspace: workspaceNameForKey(namespace, String(payload[spec.key])),
|
|
212
|
+
type: aggregate.id,
|
|
213
|
+
id: rootId,
|
|
214
|
+
}),
|
|
200
215
|
keyField: spec.key,
|
|
201
216
|
plan: (root: AggregateRef<F>, payload: Payload, ctx: Ports) => {
|
|
202
217
|
const writable = root as unknown as { set(field: string, value: unknown): unknown };
|
package/src/business_birth.ts
CHANGED
|
@@ -48,16 +48,36 @@ import {
|
|
|
48
48
|
identityRelations,
|
|
49
49
|
signerDelegationByUser,
|
|
50
50
|
} from "./framework/signing_identity.js";
|
|
51
|
+
import {
|
|
52
|
+
DomainInstallExecutor,
|
|
53
|
+
currentLawReference,
|
|
54
|
+
domainInstallGenesisOffer,
|
|
55
|
+
} from "./framework/domain_lifecycle.js";
|
|
51
56
|
|
|
52
|
-
/** Private recipe selectors. The kernel resolves these against the parent's current installed law. */
|
|
53
|
-
export const CURRENT_LAW_PREFIX = "nomos:current-law:";
|
|
54
57
|
/** @internal Compiler-only domain enumeration. It carries no allowance or authority. */
|
|
55
58
|
export const BUSINESS_BIRTH_POLICY_DOMAINS_EXPORT = "__nomos_birth_policy_domains_c9f14a";
|
|
56
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Typed compiler seam carried by an already-lowered birth consequence.
|
|
62
|
+
*
|
|
63
|
+
* A narrow plan can retain a public intent whose closure contains a child birth
|
|
64
|
+
* without retaining the child module's top-level declaration export. The
|
|
65
|
+
* symbol keeps the compiler's namespace binding attached to that executable
|
|
66
|
+
* value, without another string-key convention or a scan of function source.
|
|
67
|
+
*/
|
|
68
|
+
export const BUSINESS_BIRTH_POLICY_BINDING = Symbol("nomos.business-birth-policy-binding");
|
|
69
|
+
|
|
70
|
+
export interface BusinessBirthPolicyBinding {
|
|
71
|
+
readonly [BUSINESS_BIRTH_POLICY_BINDING]: (domains: readonly string[]) => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
57
74
|
export interface BusinessBirthMetadata {
|
|
58
75
|
readonly aggregateId: string;
|
|
59
76
|
/** Owning law domain for closure-safe cross-workspace intent linking. */
|
|
60
77
|
readonly domain: string;
|
|
78
|
+
/** The born root uses Nomos-owned custody, so the compiler must type the private
|
|
79
|
+
* authoring facts carried beside (but never exposed as) the tenant payload. */
|
|
80
|
+
readonly owned: boolean;
|
|
61
81
|
readonly publicPayloadSchema: z.ZodObject<z.ZodRawShape>;
|
|
62
82
|
readonly rootId: string;
|
|
63
83
|
readonly namespace: string;
|
|
@@ -71,7 +91,8 @@ export interface BusinessBirthMetadata {
|
|
|
71
91
|
readonly founderScope: string;
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
export interface BusinessBirthDirective
|
|
94
|
+
export interface BusinessBirthDirective
|
|
95
|
+
extends Directive<Record<string, unknown>>, BusinessBirthPolicyBinding {
|
|
75
96
|
readonly businessBirth: BusinessBirthMetadata;
|
|
76
97
|
}
|
|
77
98
|
|
|
@@ -92,11 +113,8 @@ function internalSurface<T extends object>(value: T): T & { readonly businessBir
|
|
|
92
113
|
const INTERNAL_FIELDS = [
|
|
93
114
|
"principal",
|
|
94
115
|
"bornAt",
|
|
95
|
-
"ownerKeyHash",
|
|
96
|
-
"birthCert",
|
|
97
116
|
BUSINESS_BIRTH_SEED_PAYLOAD_FIELD,
|
|
98
117
|
] as const;
|
|
99
|
-
const sha256Hex = z.string().regex(/^[0-9a-f]{64}$/);
|
|
100
118
|
|
|
101
119
|
/**
|
|
102
120
|
* Every business-born workspace verifies its own travelling birth certificate against its warrant owner.
|
|
@@ -117,6 +135,14 @@ function businessBirthsOf(mod: Record<string, unknown>): BusinessBirthDecl[] {
|
|
|
117
135
|
);
|
|
118
136
|
}
|
|
119
137
|
|
|
138
|
+
function businessBirthPolicyBindingsOf(mod: Record<string, unknown>): BusinessBirthPolicyBinding[] {
|
|
139
|
+
return Object.values(mod).filter((value): value is BusinessBirthPolicyBinding =>
|
|
140
|
+
value !== null &&
|
|
141
|
+
typeof value === "object" &&
|
|
142
|
+
BUSINESS_BIRTH_POLICY_BINDING in value
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
120
146
|
// A declared birth remains reusable as framework law, but once a wider business
|
|
121
147
|
// intent composes it there must not also be a generated direct-birth lane. That
|
|
122
148
|
// second lane could skip the intent's parent-workspace consequences and let two
|
|
@@ -151,8 +177,6 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
151
177
|
const seedSchema = publicSchema.extend({
|
|
152
178
|
principal: z.string().min(1),
|
|
153
179
|
bornAt: z.string().min(1),
|
|
154
|
-
ownerKeyHash: sha256Hex.optional(),
|
|
155
|
-
birthCert: z.string().optional(),
|
|
156
180
|
});
|
|
157
181
|
const parentSchema = seedSchema.extend({
|
|
158
182
|
...(encryptedBirth ? { [BUSINESS_BIRTH_SEED_PAYLOAD_FIELD]: z.string().min(1) } : {}),
|
|
@@ -234,20 +258,16 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
234
258
|
}
|
|
235
259
|
delete childPayload[BUSINESS_BIRTH_SEED_PAYLOAD_FIELD];
|
|
236
260
|
const chain: Array<Record<string, unknown>> = [
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
actor: founder,
|
|
248
|
-
payload: { domainHash: `${CURRENT_LAW_PREFIX}${domain}` },
|
|
249
|
-
domainHash: `${CURRENT_LAW_PREFIX}${domain}`,
|
|
250
|
-
},
|
|
261
|
+
domainInstallGenesisOffer(
|
|
262
|
+
DomainInstallExecutor.StageZero,
|
|
263
|
+
currentLawReference("nomos"),
|
|
264
|
+
founder,
|
|
265
|
+
),
|
|
266
|
+
domainInstallGenesisOffer(
|
|
267
|
+
DomainInstallExecutor.LifecycleController,
|
|
268
|
+
currentLawReference(domain),
|
|
269
|
+
founder,
|
|
270
|
+
),
|
|
251
271
|
...(decl.__nomosBirthPolicyDomains ?? initialBirthPolicyDomains).map((policyDomain) => ({
|
|
252
272
|
domain: policyDomain,
|
|
253
273
|
directiveId: "seedBirthPolicy",
|
|
@@ -275,21 +295,6 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
275
295
|
const v = ap?.[k];
|
|
276
296
|
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
277
297
|
};
|
|
278
|
-
let verified = false;
|
|
279
|
-
try { verified = typeof p.birthCert === "string" && JSON.parse(p.birthCert).verified === true; } catch {}
|
|
280
|
-
if (typeof p.ownerKeyHash === "string") {
|
|
281
|
-
chain.push({
|
|
282
|
-
domain,
|
|
283
|
-
directiveId: "enrollSigner",
|
|
284
|
-
actor: founder,
|
|
285
|
-
payload: {
|
|
286
|
-
keyHash: p.ownerKeyHash,
|
|
287
|
-
grantedBy: founder,
|
|
288
|
-
grantedAt: 1,
|
|
289
|
-
...(verified && apStr("issuer") ? { verifiedVia: apStr("issuer") } : {}),
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
298
|
if (apStr("issuer")) {
|
|
294
299
|
chain.push({
|
|
295
300
|
domain,
|
|
@@ -319,6 +324,7 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
319
324
|
const metadata: BusinessBirthMetadata = {
|
|
320
325
|
aggregateId: decl.aggregate.id,
|
|
321
326
|
domain,
|
|
327
|
+
owned: decl.aggregate.audience?.kind === "owned",
|
|
322
328
|
publicPayloadSchema: publicSchema,
|
|
323
329
|
rootId,
|
|
324
330
|
namespace,
|
|
@@ -337,6 +343,9 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
|
|
|
337
343
|
const parent = {
|
|
338
344
|
...birthBase,
|
|
339
345
|
businessBirth: metadata,
|
|
346
|
+
[BUSINESS_BIRTH_POLICY_BINDING]: (domains: readonly string[]) => {
|
|
347
|
+
decl.__nomosBirthPolicyDomains = domains;
|
|
348
|
+
},
|
|
340
349
|
...(applicationIntentOnlyBirths.has(decl) ? { businessBirthInternal: true } : {}),
|
|
341
350
|
} as BusinessBirthDirective;
|
|
342
351
|
return {
|
|
@@ -417,7 +426,11 @@ export function bindBusinessBirthPolicyDomains(
|
|
|
417
426
|
domains: readonly string[],
|
|
418
427
|
): void {
|
|
419
428
|
const declarations = businessBirthsOf(mod);
|
|
420
|
-
|
|
429
|
+
const bindings = businessBirthPolicyBindingsOf(mod);
|
|
430
|
+
// Packages without a birth surface have no policy value to bind. In
|
|
431
|
+
// particular, an application-less package legitimately has no application
|
|
432
|
+
// birth-policy namespace inventory.
|
|
433
|
+
if (declarations.length === 0 && bindings.length === 0) return;
|
|
421
434
|
const unique = [...new Set(domains)];
|
|
422
435
|
if (unique.length === 0 || unique.some((value) => value.trim().length === 0)) {
|
|
423
436
|
throw new Error("birth policy namespaces must be a non-empty list of domain names");
|
|
@@ -425,6 +438,9 @@ export function bindBusinessBirthPolicyDomains(
|
|
|
425
438
|
for (const declaration of declarations) {
|
|
426
439
|
declaration.__nomosBirthPolicyDomains = unique;
|
|
427
440
|
}
|
|
441
|
+
for (const binding of bindings) {
|
|
442
|
+
binding[BUSINESS_BIRTH_POLICY_BINDING](unique);
|
|
443
|
+
}
|
|
428
444
|
}
|
|
429
445
|
|
|
430
446
|
/** Lower the one tenant-facing birth declaration into ordinary, gate-visible framework directives. */
|
|
@@ -434,13 +450,7 @@ export function expandBusinessBirthExports<M extends Record<string, unknown>>(
|
|
|
434
450
|
birthPolicyDomains?: readonly string[],
|
|
435
451
|
): Record<string, unknown> {
|
|
436
452
|
const declarations = businessBirthsOf(mod);
|
|
437
|
-
if (declarations.length === 0) return mod;
|
|
438
|
-
if (declarations.length > 1) {
|
|
439
|
-
throw new Error(
|
|
440
|
-
`domain '${domain}' declares ${declarations.length} business births; one generated birth(payload) cannot be ` +
|
|
441
|
-
"ambiguous — model one born aggregate root per domain",
|
|
442
|
-
);
|
|
443
|
-
}
|
|
453
|
+
if (declarations.length === 0 && businessBirthPolicyBindingsOf(mod).length === 0) return mod;
|
|
444
454
|
const compiledDomains = mod[BUSINESS_BIRTH_POLICY_DOMAINS_EXPORT];
|
|
445
455
|
const selectedDomains = birthPolicyDomains ?? (
|
|
446
456
|
Array.isArray(compiledDomains) && compiledDomains.every((value) => typeof value === "string")
|
|
@@ -449,9 +459,20 @@ export function expandBusinessBirthExports<M extends Record<string, unknown>>(
|
|
|
449
459
|
);
|
|
450
460
|
const policyDomains = [...new Set(selectedDomains)];
|
|
451
461
|
if (policyDomains.length === 0 || policyDomains.some((value) => value.trim().length === 0)) {
|
|
452
|
-
|
|
462
|
+
const subject = declarations[0]?.aggregate.id ?? `domain '${domain}'`;
|
|
463
|
+
throw new Error(`birth(${subject}): compiled law declares no policy namespaces`);
|
|
453
464
|
}
|
|
454
465
|
bindBusinessBirthPolicyDomains(mod, policyDomains);
|
|
466
|
+
// A sliced parent intent may carry an already-lowered child birth through the
|
|
467
|
+
// typed binding above while exporting no raw BusinessBirthDecl of its own.
|
|
468
|
+
// Binding that closure is the complete job for this domain.
|
|
469
|
+
if (declarations.length === 0) return mod;
|
|
470
|
+
if (declarations.length > 1) {
|
|
471
|
+
throw new Error(
|
|
472
|
+
`domain '${domain}' declares ${declarations.length} business births; one generated birth(payload) cannot be ` +
|
|
473
|
+
"ambiguous — model one born aggregate root per domain",
|
|
474
|
+
);
|
|
475
|
+
}
|
|
455
476
|
const lowered = lowerOne(declarations[0]!, domain, policyDomains);
|
|
456
477
|
for (const [key, generated] of Object.entries(lowered)) {
|
|
457
478
|
if (!Object.prototype.hasOwnProperty.call(mod, key)) continue;
|
package/src/codegen_dart.ts
CHANGED
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
* generated, so they stay reproducible from the domain definitions.
|
|
30
30
|
*/
|
|
31
31
|
import { z } from "zod";
|
|
32
|
-
import { voMetaOf, collectPayloadValueObjectDescriptors, idOfMetaOf, idOfTargetKindOf, versionedRefOfMetaOf, brandedIdMetaOf, NOMOS_UNIT_BRAND } from "./value_object.js";
|
|
32
|
+
import { voMetaOf, collectPayloadValueObjectDescriptors, idOfMetaOf, idOfTargetKindOf, refOfMetaOf, versionedRefOfMetaOf, brandedIdMetaOf, NOMOS_UNIT_BRAND } from "./value_object.js";
|
|
33
33
|
import { recursiveTypeBaseName, zodUnwrapLazy } from "./zod_lazy.js";
|
|
34
34
|
import type { AggregateHandle } from "./aggregate.js";
|
|
35
35
|
import type { WorkspaceInvariantDecl } from "./framework/workspace_invariant.js";
|
|
36
36
|
import type { RelationTypeDecl } from "./relation_schema.js";
|
|
37
|
-
import { isSha256DigestSchema, type Field, type FieldKind, type ValueObjectDescriptor, type ValueObjectFieldDescriptor } from "./fields.js";
|
|
37
|
+
import { isGitObjectIdSchema, isSha256DigestSchema, type Field, type FieldKind, type ValueObjectDescriptor, type ValueObjectFieldDescriptor } from "./fields.js";
|
|
38
38
|
import { admitsNull, nullMetaOf, nullDocLine } from "./null_meta.js";
|
|
39
39
|
import type { Directive } from "./directive.js";
|
|
40
40
|
import { executeDirectiveToIntent } from "./wire_encode.js";
|
|
@@ -84,6 +84,7 @@ export type ToJsonWrap =
|
|
|
84
84
|
| "voList" // a list of value objects — emit `.map((e) => e.toJson()).toList()`.
|
|
85
85
|
| "wrapped" // a standalone branded-id or unit extension type — emit `.value`.
|
|
86
86
|
| "ref" // an aggregate-specific NomosRef<T> — emit its `.id` wire scalar.
|
|
87
|
+
| "addressRef" // a workspace-qualified NomosRef<T> — preserve its complete typed address.
|
|
87
88
|
| "versionedRef" // a publication pin + stable series — emit the atomic address pair.
|
|
88
89
|
| "recipient"; // a framework-created Recipient<User> — emit its private delivery address.
|
|
89
90
|
|
|
@@ -426,7 +427,8 @@ export function collectPayloadIdOfTargets(directives: readonly { payloadSchema?:
|
|
|
426
427
|
continue;
|
|
427
428
|
}
|
|
428
429
|
for (const zt of Object.values(shape)) {
|
|
429
|
-
const target = idOfMetaOf(zt as z.ZodTypeAny)
|
|
430
|
+
const target = idOfMetaOf(zt as z.ZodTypeAny)
|
|
431
|
+
?? refOfMetaOf(zt as z.ZodTypeAny)?.aggregateType;
|
|
430
432
|
if (target !== undefined) out.add(target);
|
|
431
433
|
}
|
|
432
434
|
}
|
|
@@ -443,6 +445,18 @@ function introspectField(
|
|
|
443
445
|
enumDartTypes: Map<string, string>,
|
|
444
446
|
lazyNames?: Map<z.ZodTypeAny, string>,
|
|
445
447
|
): Omit<PayloadFieldSpec, "optional"> {
|
|
448
|
+
const addressed = refOfMetaOf(zt);
|
|
449
|
+
if (addressed !== undefined) {
|
|
450
|
+
const target = addressed.targetKind === "contract"
|
|
451
|
+
? contractTypeName(addressed.aggregateType)
|
|
452
|
+
: concreteClassName(addressed.aggregateType);
|
|
453
|
+
return {
|
|
454
|
+
name,
|
|
455
|
+
dartType: `NomosRef<${target}>`,
|
|
456
|
+
referenceType: addressed.aggregateType,
|
|
457
|
+
toJson: "addressRef",
|
|
458
|
+
};
|
|
459
|
+
}
|
|
446
460
|
const versioned = versionedRefOfMetaOf(zt);
|
|
447
461
|
if (versioned !== undefined) {
|
|
448
462
|
const target = versioned.targetKind === "contract"
|
|
@@ -518,6 +532,9 @@ function introspectField(
|
|
|
518
532
|
if (isSha256DigestSchema(zt)) {
|
|
519
533
|
return { name, dartType: "Sha256Digest", toJson: "wrapped", wrappedScalarKind: "string" };
|
|
520
534
|
}
|
|
535
|
+
if (isGitObjectIdSchema(zt)) {
|
|
536
|
+
return { name, dartType: "GitObjectId", toJson: "wrapped", wrappedScalarKind: "string" };
|
|
537
|
+
}
|
|
521
538
|
// brandedId("SiteId"): a standalone nominal string → the generated extension type.
|
|
522
539
|
const brand = brandedIdMetaOf(zt);
|
|
523
540
|
if (brand !== undefined) {
|
|
@@ -625,7 +642,7 @@ interface AggFieldSpec {
|
|
|
625
642
|
kind: MaterializedFieldKind;
|
|
626
643
|
dartType: string;
|
|
627
644
|
/** A canonical semantic string wrapper whose wire representation remains String. */
|
|
628
|
-
semanticString?: "sha256";
|
|
645
|
+
semanticString?: "sha256" | "git-object-id";
|
|
629
646
|
enumValues?: string[];
|
|
630
647
|
/** For an own-id string field represented as `NomosRef<TAggregate>`. */
|
|
631
648
|
valueClass?: string;
|
|
@@ -845,6 +862,9 @@ function readKeyParamSpec(
|
|
|
845
862
|
if (fieldSpec.semanticString === "sha256") {
|
|
846
863
|
return { dartType: "Sha256Digest", valueExpr: `${paramName}.value` };
|
|
847
864
|
}
|
|
865
|
+
if (fieldSpec.semanticString === "git-object-id") {
|
|
866
|
+
return { dartType: "GitObjectId", valueExpr: `${paramName}.value` };
|
|
867
|
+
}
|
|
848
868
|
return { dartType: "String", valueExpr: paramName };
|
|
849
869
|
}
|
|
850
870
|
|
|
@@ -954,12 +974,19 @@ function aggFieldSpec(
|
|
|
954
974
|
wireName,
|
|
955
975
|
kind: field.kind,
|
|
956
976
|
dartType: valueClass === undefined
|
|
957
|
-
? isSha256DigestSchema(field.zod as z.ZodTypeAny)
|
|
977
|
+
? isSha256DigestSchema(field.zod as z.ZodTypeAny)
|
|
978
|
+
? "Sha256Digest"
|
|
979
|
+
: isGitObjectIdSchema(field.zod as z.ZodTypeAny)
|
|
980
|
+
? "GitObjectId"
|
|
981
|
+
: "String"
|
|
958
982
|
: `NomosRef<${valueClass}>`,
|
|
959
983
|
optional,
|
|
960
984
|
...(valueClass === undefined && isSha256DigestSchema(field.zod as z.ZodTypeAny)
|
|
961
985
|
? { semanticString: "sha256" as const }
|
|
962
986
|
: {}),
|
|
987
|
+
...(valueClass === undefined && isGitObjectIdSchema(field.zod as z.ZodTypeAny)
|
|
988
|
+
? { semanticString: "git-object-id" as const }
|
|
989
|
+
: {}),
|
|
963
990
|
...(valueClass !== undefined && valueAggregateType !== undefined
|
|
964
991
|
? { valueClass, valueAggregateType }
|
|
965
992
|
: {}),
|
|
@@ -2610,19 +2637,29 @@ export function generateDartActivityRegistry(entries: readonly PackageActivityEn
|
|
|
2610
2637
|
` const NomosModelReview({required this.checkedActions, required this.candidateActions, required this.sameOutcome, required this.differences});`,
|
|
2611
2638
|
`}`,
|
|
2612
2639
|
``,
|
|
2613
|
-
`enum NomosModelAdoptionStatus { adopted, needsDecision, blocked }`,
|
|
2640
|
+
`enum NomosModelAdoptionStatus { adopted, needsStaging, needsDecision, blocked }`,
|
|
2614
2641
|
``,
|
|
2615
2642
|
`class NomosModelAdoption {`,
|
|
2616
2643
|
` final NomosModelAdoptionStatus status;`,
|
|
2617
2644
|
` final String summary;`,
|
|
2618
2645
|
` final NomosModelReview review;`,
|
|
2646
|
+
` final Future<NomosModelAdoption> Function()? _stage;`,
|
|
2619
2647
|
` final Future<NomosModelAdoption> Function(String)? _accept;`,
|
|
2620
2648
|
` const NomosModelAdoption.adopted({required this.summary, required this.review})`,
|
|
2621
|
-
` : status = NomosModelAdoptionStatus.adopted, _accept = null;`,
|
|
2649
|
+
` : status = NomosModelAdoptionStatus.adopted, _stage = null, _accept = null;`,
|
|
2622
2650
|
` const NomosModelAdoption.blocked({required this.summary, required this.review})`,
|
|
2623
|
-
` : status = NomosModelAdoptionStatus.blocked, _accept = null;`,
|
|
2651
|
+
` : status = NomosModelAdoptionStatus.blocked, _stage = null, _accept = null;`,
|
|
2652
|
+
` NomosModelAdoption.needsStaging({required this.summary, required this.review, required Future<NomosModelAdoption> Function() stage})`,
|
|
2653
|
+
` : status = NomosModelAdoptionStatus.needsStaging, _stage = stage, _accept = null;`,
|
|
2624
2654
|
` NomosModelAdoption.needsDecision({required this.summary, required this.review, required Future<NomosModelAdoption> Function(String) accept})`,
|
|
2625
|
-
` : status = NomosModelAdoptionStatus.needsDecision, _accept = accept;`,
|
|
2655
|
+
` : status = NomosModelAdoptionStatus.needsDecision, _stage = null, _accept = accept;`,
|
|
2656
|
+
` Future<NomosModelAdoption> stage() {`,
|
|
2657
|
+
` final stageCandidate = _stage;`,
|
|
2658
|
+
` if (status != NomosModelAdoptionStatus.needsStaging || stageCandidate == null) {`,
|
|
2659
|
+
` throw StateError('This model change is not waiting to be staged.');`,
|
|
2660
|
+
` }`,
|
|
2661
|
+
` return stageCandidate();`,
|
|
2662
|
+
` }`,
|
|
2626
2663
|
` Future<NomosModelAdoption> accept(String because) {`,
|
|
2627
2664
|
` final reason = because.trim();`,
|
|
2628
2665
|
` final acceptDecision = _accept;`,
|
|
@@ -2974,6 +3011,11 @@ function parseField(s: AggFieldSpec, aggregate: string): string {
|
|
|
2974
3011
|
? `() { final v = ${reader}; return v == null ? null : Sha256Digest(v); }()`
|
|
2975
3012
|
: `Sha256Digest(${reader})`;
|
|
2976
3013
|
}
|
|
3014
|
+
if (s.semanticString === "git-object-id") {
|
|
3015
|
+
return opt
|
|
3016
|
+
? `() { final v = ${reader}; return v == null ? null : GitObjectId(v); }()`
|
|
3017
|
+
: `GitObjectId(${reader})`;
|
|
3018
|
+
}
|
|
2977
3019
|
return reader;
|
|
2978
3020
|
}
|
|
2979
3021
|
case "json":
|
|
@@ -3060,7 +3102,9 @@ function slotDecodeCallback(s: AggFieldSpec, mode: "aggregate" | "readModel"): s
|
|
|
3060
3102
|
}
|
|
3061
3103
|
return s.semanticString === "sha256"
|
|
3062
3104
|
? `(v) => Sha256Digest(v as String)`
|
|
3063
|
-
:
|
|
3105
|
+
: s.semanticString === "git-object-id"
|
|
3106
|
+
? `(v) => GitObjectId(v as String)`
|
|
3107
|
+
: `(v) => v as String`;
|
|
3064
3108
|
case "json":
|
|
3065
3109
|
if (s.voClass !== undefined) {
|
|
3066
3110
|
return `(v) => ${s.voClass}.fromProjected((v as Map).cast<String, Object?>())`;
|
|
@@ -3208,6 +3252,11 @@ function parseReadModelField(s: AggFieldSpec, aggregate: string): string {
|
|
|
3208
3252
|
? `() { final v = ${reader}; return v == null ? null : Sha256Digest(v); }()`
|
|
3209
3253
|
: `Sha256Digest(${reader})`;
|
|
3210
3254
|
}
|
|
3255
|
+
if (s.semanticString === "git-object-id") {
|
|
3256
|
+
return opt
|
|
3257
|
+
? `() { final v = ${reader}; return v == null ? null : GitObjectId(v); }()`
|
|
3258
|
+
: `GitObjectId(${reader})`;
|
|
3259
|
+
}
|
|
3211
3260
|
return reader;
|
|
3212
3261
|
}
|
|
3213
3262
|
case "json":
|
|
@@ -3630,6 +3679,8 @@ export function toJsonExpr(spec: PayloadFieldSpec, accessor: string): string {
|
|
|
3630
3679
|
return `${accessor}.value`;
|
|
3631
3680
|
case "ref":
|
|
3632
3681
|
return `NmsInternalNomosRefs.id(${accessor})`;
|
|
3682
|
+
case "addressRef":
|
|
3683
|
+
return `NmsInternalNomosRefs.toJson(${accessor})`;
|
|
3633
3684
|
case "versionedRef":
|
|
3634
3685
|
return `{'pinned': NmsInternalNomosRefs.toJson(${accessor}.pinned), 'series': NmsInternalNomosRefs.toJson(${accessor}.series)}`;
|
|
3635
3686
|
case "recipient":
|
|
@@ -4309,7 +4360,8 @@ function buildProbePayload(
|
|
|
4309
4360
|
zt = zodInnerType(zt);
|
|
4310
4361
|
}
|
|
4311
4362
|
const sentinel = fieldBySentinel.get(name);
|
|
4312
|
-
out[name] = sentinel !== undefined && zodTypeName(zt) === "ZodString" &&
|
|
4363
|
+
out[name] = sentinel !== undefined && zodTypeName(zt) === "ZodString" &&
|
|
4364
|
+
!isSha256DigestSchema(zt) && !isGitObjectIdSchema(zt)
|
|
4313
4365
|
? sentinel
|
|
4314
4366
|
: sampleFromZod(zt);
|
|
4315
4367
|
}
|
|
@@ -4324,7 +4376,11 @@ function sampleFromZod(zt: z.ZodTypeAny): unknown {
|
|
|
4324
4376
|
}
|
|
4325
4377
|
switch (zodTypeName(t)) {
|
|
4326
4378
|
case "ZodString":
|
|
4327
|
-
return isSha256DigestSchema(t)
|
|
4379
|
+
return isSha256DigestSchema(t)
|
|
4380
|
+
? "0".repeat(64)
|
|
4381
|
+
: isGitObjectIdSchema(t)
|
|
4382
|
+
? "0".repeat(40)
|
|
4383
|
+
: "x";
|
|
4328
4384
|
case "ZodNumber":
|
|
4329
4385
|
return 1;
|
|
4330
4386
|
case "ZodBoolean":
|