@githolon/dsl 0.105.15 → 0.105.17
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 +4 -0
- package/dart/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +39 -52
- package/src/codegen_ts.ts +43 -9
- package/src/compile_package_main.ts +19 -5
package/dart/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 0.64.32
|
|
2
|
+
|
|
3
|
+
- Prove a restored generated-application device is enrolled before exposing business APIs, including recovery from an interrupted bootstrap journal.
|
|
4
|
+
|
|
1
5
|
## 0.64.31
|
|
2
6
|
|
|
3
7
|
- Restage the validated intent-offer byte gate and deterministic signer-posture reader into the immutable Dart runner.
|
package/dart/pubspec.yaml
CHANGED
|
@@ -7,7 +7,7 @@ repository: https://github.com/Captain-App/nomos2
|
|
|
7
7
|
description: >-
|
|
8
8
|
Nomos 2 Dart client — generated domain values, intent payloads and application
|
|
9
9
|
lifecycle types over the typed Nomos kernel protocol and USDA custody model.
|
|
10
|
-
version: 0.64.
|
|
10
|
+
version: 0.64.32
|
|
11
11
|
|
|
12
12
|
environment:
|
|
13
13
|
sdk: ^3.5.0
|
package/package.json
CHANGED
|
@@ -13884,7 +13884,6 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13884
13884
|
let authorityHolon = await measureOpen("open private application custody", () => mountAuthority(secret, authToken));
|
|
13885
13885
|
const storedJournal = await measureOpen("load application bootstrap state", () => store.loadText(journalState));
|
|
13886
13886
|
const completed = storedJournal === "complete";
|
|
13887
|
-
const hadDurableSecret = secret !== null;
|
|
13888
13887
|
let publicKey;
|
|
13889
13888
|
if (secret === null) {
|
|
13890
13889
|
const device = await measureOpen("create application device identity", () => authorityHolon.authorKeygen());
|
|
@@ -13905,22 +13904,44 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13905
13904
|
throw applicationError("Sign in changed authority while preparing this application device.", "nomos.authority.changed_during_open");
|
|
13906
13905
|
}
|
|
13907
13906
|
authToken = deviceToken;
|
|
13907
|
+
const birthOrRepeat = async () => {
|
|
13908
|
+
const birth = await measureOpen("establish private application custody", () => authorityHolon.nomosInternalBirthReceivingGroup({
|
|
13909
|
+
parent: application,
|
|
13910
|
+
principal,
|
|
13911
|
+
subject,
|
|
13912
|
+
device: { secret, public: publicKey },
|
|
13913
|
+
authToken,
|
|
13914
|
+
idToken: authToken,
|
|
13915
|
+
verifiedVia: issuer,
|
|
13916
|
+
bornAt: now().toISOString(),
|
|
13917
|
+
confirm: true
|
|
13918
|
+
}));
|
|
13919
|
+
const verdict = birth.verify;
|
|
13920
|
+
if (verdict !== void 0 && verdict.valid !== true) throw new Error(`the born application failed replay verification: ${String(verdict.error ?? "unknown")}`);
|
|
13921
|
+
};
|
|
13922
|
+
const ensureSignerEnrollment = async () => {
|
|
13923
|
+
const enroll = () => authorityHolon.ensureParentSignerEnrollment({
|
|
13924
|
+
// The write gate that this device will use is the receiving-group workspace itself.
|
|
13925
|
+
// The application root authorises/births that home; it is not a substitute signer index.
|
|
13926
|
+
parent: receivingGroup,
|
|
13927
|
+
// The author gate speaks canonical Nomos principals. A provider subject is deliberately
|
|
13928
|
+
// opaque and may contain its own namespace separators; never enrol that raw value as the actor.
|
|
13929
|
+
principal: subject,
|
|
13930
|
+
publicKey,
|
|
13931
|
+
authorSecret: secret,
|
|
13932
|
+
authToken,
|
|
13933
|
+
idToken: authToken,
|
|
13934
|
+
verifiedVia: issuer
|
|
13935
|
+
});
|
|
13936
|
+
try {
|
|
13937
|
+
await measureOpen("confirm private-custody signer enrolment", enroll);
|
|
13938
|
+
} catch (error) {
|
|
13939
|
+
if (!String(error).includes("receiving-group-additional-device-requires-current-device-or-guardian")) throw error;
|
|
13940
|
+
await birthOrRepeat();
|
|
13941
|
+
await measureOpen("verify recovered private-custody signer enrolment", enroll);
|
|
13942
|
+
}
|
|
13943
|
+
};
|
|
13908
13944
|
if (!completed) {
|
|
13909
|
-
const birthOrRepeat = async () => {
|
|
13910
|
-
const birth = await measureOpen("establish private application custody", () => authorityHolon.nomosInternalBirthReceivingGroup({
|
|
13911
|
-
parent: application,
|
|
13912
|
-
principal,
|
|
13913
|
-
subject,
|
|
13914
|
-
device: { secret, public: publicKey },
|
|
13915
|
-
authToken,
|
|
13916
|
-
idToken: authToken,
|
|
13917
|
-
verifiedVia: issuer,
|
|
13918
|
-
bornAt: now().toISOString(),
|
|
13919
|
-
confirm: true
|
|
13920
|
-
}));
|
|
13921
|
-
const verdict = birth.verify;
|
|
13922
|
-
if (verdict !== void 0 && verdict.valid !== true) throw new Error(`the born application failed replay verification: ${String(verdict.error ?? "unknown")}`);
|
|
13923
|
-
};
|
|
13924
13945
|
let homeAvailable = false;
|
|
13925
13946
|
try {
|
|
13926
13947
|
homeAvailable = Boolean(await measureOpen("check private application custody", () => authorityHolon.head()));
|
|
@@ -13928,28 +13949,6 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13928
13949
|
}
|
|
13929
13950
|
if (!homeAvailable) {
|
|
13930
13951
|
await birthOrRepeat();
|
|
13931
|
-
} else if (!hadDurableSecret) {
|
|
13932
|
-
try {
|
|
13933
|
-
await measureOpen("enrol application device in its private custody", () => authorityHolon.ensureParentSignerEnrollment({
|
|
13934
|
-
// The write gate that this device will use is the receiving-group workspace itself.
|
|
13935
|
-
// The application root authorises/births that home; it is not a substitute signer index.
|
|
13936
|
-
parent: receivingGroup,
|
|
13937
|
-
// The author gate speaks canonical Nomos principals. A provider subject is deliberately
|
|
13938
|
-
// opaque and may contain its own namespace separators; never enrol that raw value as the actor.
|
|
13939
|
-
principal: subject,
|
|
13940
|
-
publicKey,
|
|
13941
|
-
authorSecret: secret,
|
|
13942
|
-
authToken,
|
|
13943
|
-
idToken: authToken,
|
|
13944
|
-
verifiedVia: issuer
|
|
13945
|
-
}));
|
|
13946
|
-
} catch (error) {
|
|
13947
|
-
if (String(error).includes("receiving-group-additional-device-requires-current-device-or-guardian")) {
|
|
13948
|
-
await birthOrRepeat();
|
|
13949
|
-
} else {
|
|
13950
|
-
throw error;
|
|
13951
|
-
}
|
|
13952
|
-
}
|
|
13953
13952
|
}
|
|
13954
13953
|
await measureOpen("save application bootstrap progress", () => store.saveText(journalState, "home-available"));
|
|
13955
13954
|
authorityHolon = await measureOpen("rebind durable application authority", () => mountAuthority(secret, authToken));
|
|
@@ -13962,23 +13961,11 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13962
13961
|
const verified = await measureOpen("verify new application custody", () => authorityHolon.verifyChain());
|
|
13963
13962
|
if (verified.valid !== true) throw new Error(`the private authority context failed replay verification: ${String(verified.error ?? "unknown")}`);
|
|
13964
13963
|
await measureOpen("save application bootstrap progress", () => store.saveText(journalState, "verified"));
|
|
13965
|
-
|
|
13966
|
-
await measureOpen("confirm private-custody signer enrolment", () => authorityHolon.ensureParentSignerEnrollment({
|
|
13967
|
-
parent: receivingGroup,
|
|
13968
|
-
principal: subject,
|
|
13969
|
-
authorSecret: secret,
|
|
13970
|
-
authToken,
|
|
13971
|
-
idToken: authToken,
|
|
13972
|
-
verifiedVia: issuer
|
|
13973
|
-
}));
|
|
13974
|
-
} catch (error) {
|
|
13975
|
-
if (/revoked/i.test(String(error))) throw error;
|
|
13976
|
-
}
|
|
13977
|
-
await measureOpen("complete application bootstrap journal", async () => {
|
|
13964
|
+
await measureOpen("save verified application bootstrap journal", async () => {
|
|
13978
13965
|
await store.saveText(journalState, "complete");
|
|
13979
|
-
await store.remove(journalState);
|
|
13980
13966
|
});
|
|
13981
13967
|
}
|
|
13968
|
+
await ensureSignerEnrollment();
|
|
13982
13969
|
holon = authorityHolon;
|
|
13983
13970
|
const authorityVerified = await measureOpen("verify application custody", () => holon.verifyChain());
|
|
13984
13971
|
if (authorityVerified.valid !== true) throw new Error(`the private authority context failed replay verification: ${String(authorityVerified.error ?? "unknown")}`);
|
package/src/codegen_ts.ts
CHANGED
|
@@ -1598,7 +1598,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
1598
1598
|
// holon; `resolve`/`watch` use the application's captured shared-plane navigator.
|
|
1599
1599
|
// The reader is captured by the generated application. Tenant code receives navigation, never a reader.
|
|
1600
1600
|
`interface _NomosForeignWorkspace { queryById(id: string): Promise<unknown>; watchById?(id: string, cb: (rows: unknown) => void, opts?: { intervalMs?: number }): () => void }`,
|
|
1601
|
-
`interface NomosForeignReader { __nomosOpenChild?(workspace: string): Promise<_NomosForeignWorkspace> }`,
|
|
1601
|
+
`interface NomosForeignReader { readonly workspace?: string; __nomosOpenChild?(workspace: string): Promise<_NomosForeignWorkspace> }`,
|
|
1602
1602
|
`async function _openForeign(nomos: NomosForeignReader, workspace: string): Promise<_NomosForeignWorkspace> {`,
|
|
1603
1603
|
` if (nomos.__nomosOpenChild === undefined) throw new Error("Nomos cannot follow this business reference on the installed runtime");`,
|
|
1604
1604
|
` return nomos.__nomosOpenChild(workspace);`,
|
|
@@ -2329,8 +2329,16 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2329
2329
|
}
|
|
2330
2330
|
|
|
2331
2331
|
const aggByType = new Map<string, AggregateHandle>();
|
|
2332
|
+
const runtimeTypeByAggregate = new Map<string, string>();
|
|
2332
2333
|
for (const mod of modules) {
|
|
2333
|
-
|
|
2334
|
+
const domain = mod.domain ?? mod.name;
|
|
2335
|
+
for (const agg of mod.aggregates as AggregateHandle[]) {
|
|
2336
|
+
aggByType.set(agg.id, agg);
|
|
2337
|
+
runtimeTypeByAggregate.set(
|
|
2338
|
+
agg.id,
|
|
2339
|
+
isNamespacedAggregate(agg) ? qualifyReadProjectionType(domain, agg.id) : agg.id,
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2334
2342
|
}
|
|
2335
2343
|
|
|
2336
2344
|
const anyAutoStamp = modules.some((mod) =>
|
|
@@ -2533,6 +2541,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2533
2541
|
|
|
2534
2542
|
out.push(`// ── read models (projection \`data\` shapes; partial-fold optional, EXCEPT .fromBirth()`, `// fields — their presence is gate law, so the type is non-optional) ──`, ``);
|
|
2535
2543
|
const foreignRefFields: { agg: string; field: string; workspaceField: string; target: string }[] = [];
|
|
2544
|
+
const directRefFields: { agg: string; field: string; target: string; workspace?: string }[] = [];
|
|
2536
2545
|
const atomicRefFields: { agg: string; field: string }[] = [];
|
|
2537
2546
|
const versionedRefFields: { agg: string; field: string; currentField: string }[] = [];
|
|
2538
2547
|
// wrap a read accessor return expression through the foreignRef row-hydrator (identity + byte-identical
|
|
@@ -2540,9 +2549,9 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2540
2549
|
// Every read accessor's rows get their canonical `.ref` stamped from `holon.workspace` (additive); a
|
|
2541
2550
|
// foreignRef-declaring package ALSO hydrates its foreignRef fields into typed locators first.
|
|
2542
2551
|
const wrapP = (expr: string): string =>
|
|
2543
|
-
`_businessRecordsP(_stampRefsP(holon.workspace, ${foreignRefFields.length + atomicRefFields.length + versionedRefFields.length > 0 ? `_hydrateP(holon, ${expr})` : expr}))`;
|
|
2552
|
+
`_businessRecordsP(_stampRefsP(holon.workspace, ${foreignRefFields.length + directRefFields.length + atomicRefFields.length + versionedRefFields.length > 0 ? `_hydrateP(holon, ${expr})` : expr}))`;
|
|
2544
2553
|
const wrapRows = (expr: string): string =>
|
|
2545
|
-
`_businessRecords(_stampRefs(holon.workspace, ${foreignRefFields.length + atomicRefFields.length + versionedRefFields.length > 0 ? `_hydrateRows(holon, ${expr})` : expr}))`;
|
|
2554
|
+
`_businessRecords(_stampRefs(holon.workspace, ${foreignRefFields.length + directRefFields.length + atomicRefFields.length + versionedRefFields.length > 0 ? `_hydrateRows(holon, ${expr})` : expr}))`;
|
|
2546
2555
|
// ATTRIBUTED READS (architecture/field_provenance.md): the shared provenance shape +
|
|
2547
2556
|
// per-aggregate accessors — emitted ONLY when the package declares ≥1 `.attributed()`
|
|
2548
2557
|
// field, so a provenance-free package's client is byte-identical (the era rule).
|
|
@@ -2571,6 +2580,19 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2571
2580
|
out.push(` ${tsKey(name)}${required ? "" : "?"}: ${tsTypeOfField(field as Field)};`);
|
|
2572
2581
|
const fr = (field as { foreignRef?: { workspaceField: string; targetAggregateId: string } }).foreignRef;
|
|
2573
2582
|
if (fr !== undefined) foreignRefFields.push({ agg: typeId, field: name, workspaceField: fr.workspaceField, target: fr.targetAggregateId });
|
|
2583
|
+
if (
|
|
2584
|
+
(field as Field).refAggregateId !== undefined &&
|
|
2585
|
+
(field as Field).foreignRef === undefined &&
|
|
2586
|
+
(field as Field).nomosRef === undefined &&
|
|
2587
|
+
(field as Field).versionedForeignRef === undefined
|
|
2588
|
+
) {
|
|
2589
|
+
directRefFields.push({
|
|
2590
|
+
agg: typeId,
|
|
2591
|
+
field: name,
|
|
2592
|
+
target: runtimeTypeByAggregate.get((field as Field).refAggregateId!) ?? (field as Field).refAggregateId!,
|
|
2593
|
+
...((field as Field).refWorkspace === undefined ? {} : { workspace: (field as Field).refWorkspace }),
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2574
2596
|
if ((field as Field).nomosRef !== undefined) atomicRefFields.push({ agg: typeId, field: name });
|
|
2575
2597
|
const vr = (field as Field).versionedForeignRef;
|
|
2576
2598
|
if (vr !== undefined) versionedRefFields.push({ agg: typeId, field: name, currentField: vr.currentField });
|
|
@@ -2614,7 +2636,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2614
2636
|
// row into a `ForeignRef<TargetAggregate>` — reading the foreign id (the field) + the foreign workspace id (the
|
|
2615
2637
|
// declared sibling field). The read model stays honest (the field is the raw stored id string); this gives
|
|
2616
2638
|
// the TYPED locator with resolve/watch on top, without cloning the other holon.
|
|
2617
|
-
if (foreignRefFields.length + atomicRefFields.length + versionedRefFields.length > 0) {
|
|
2639
|
+
if (foreignRefFields.length + directRefFields.length + atomicRefFields.length + versionedRefFields.length > 0) {
|
|
2618
2640
|
const byAgg = new Map<string, typeof foreignRefFields>();
|
|
2619
2641
|
for (const f of foreignRefFields) { const l = byAgg.get(f.agg) ?? []; l.push(f); byAgg.set(f.agg, l); }
|
|
2620
2642
|
out.push(`// ── foreign-ref locators (t.foreignRef): typed cross-workspace edges (resolve/watch on demand) ──`);
|
|
@@ -2637,23 +2659,35 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2637
2659
|
// `row.data.<field>.id` is still the raw id. Identity for any aggregate without foreignRefs.
|
|
2638
2660
|
const hydrateSpecs: Record<string, { field: string; wsField: string; target: string }[]> = {};
|
|
2639
2661
|
for (const f of foreignRefFields) { (hydrateSpecs[f.agg] ??= []).push({ field: f.field, wsField: f.workspaceField, target: f.target }); }
|
|
2662
|
+
const directSpecs: Record<string, { field: string; target: string; workspace?: string }[]> = {};
|
|
2663
|
+
for (const f of directRefFields) {
|
|
2664
|
+
(directSpecs[f.agg] ??= []).push({
|
|
2665
|
+
field: f.field,
|
|
2666
|
+
target: f.target,
|
|
2667
|
+
...(f.workspace === undefined ? {} : { workspace: f.workspace }),
|
|
2668
|
+
});
|
|
2669
|
+
}
|
|
2640
2670
|
const atomicSpecs: Record<string, { field: string }[]> = {};
|
|
2641
2671
|
for (const f of atomicRefFields) { (atomicSpecs[f.agg] ??= []).push({ field: f.field }); }
|
|
2642
2672
|
const versionedSpecs: Record<string, { field: string; currentField: string }[]> = {};
|
|
2643
2673
|
for (const f of versionedRefFields) { (versionedSpecs[f.agg] ??= []).push({ field: f.field, currentField: f.currentField }); }
|
|
2644
2674
|
out.push(
|
|
2645
2675
|
`const _FOREIGN_REFS: Record<string, { field: string; wsField: string; target: string }[]> = ${JSON.stringify(hydrateSpecs)};`,
|
|
2676
|
+
`const _DIRECT_REFS: Record<string, { field: string; target: string; workspace?: string }[]> = ${JSON.stringify(directSpecs)};`,
|
|
2646
2677
|
`const _ATOMIC_REFS: Record<string, { field: string }[]> = ${JSON.stringify(atomicSpecs)};`,
|
|
2647
2678
|
`const _VERSIONED_REFS: Record<string, { field: string; currentField: string }[]> = ${JSON.stringify(versionedSpecs)};`,
|
|
2648
2679
|
`function _hydrateRows<T>(nomos: NomosForeignReader, rows: Row<T>[]): Row<T>[] {`,
|
|
2649
2680
|
` return rows.map((row) => {`,
|
|
2650
2681
|
` const raw = row as Row<T> & { type: string };`,
|
|
2651
|
-
` const
|
|
2652
|
-
` const
|
|
2653
|
-
` const
|
|
2654
|
-
`
|
|
2682
|
+
` const localType = raw.type.slice(raw.type.lastIndexOf(".") + 1);`,
|
|
2683
|
+
` const specs = _FOREIGN_REFS[raw.type] ?? _FOREIGN_REFS[localType] ?? [];`,
|
|
2684
|
+
` const direct = _DIRECT_REFS[raw.type] ?? _DIRECT_REFS[localType] ?? [];`,
|
|
2685
|
+
` const atomic = _ATOMIC_REFS[raw.type] ?? _ATOMIC_REFS[localType] ?? [];`,
|
|
2686
|
+
` const versioned = _VERSIONED_REFS[raw.type] ?? _VERSIONED_REFS[localType] ?? [];`,
|
|
2687
|
+
` if ((specs.length + direct.length + atomic.length + versioned.length) === 0 || row.data == null) return row;`,
|
|
2655
2688
|
` const data: Record<string, unknown> = { ...(row.data as Record<string, unknown>) };`,
|
|
2656
2689
|
` for (const s of specs) { const v = data[s.field]; if (typeof v === "string") data[s.field] = foreignRef(nomos, s.target, v, String(data[s.wsField] ?? "")); }`,
|
|
2690
|
+
` for (const s of direct) { const v = data[s.field]; if (typeof v === "string") data[s.field] = _nmsRef(s.workspace ?? nomos.workspace ?? "", s.target, v); }`,
|
|
2657
2691
|
` for (const s of atomic) { const v = data[s.field] as { workspace: string; type: string; id: string } | undefined; if (v && typeof v === "object") data[s.field] = _nmsRef(v.workspace, v.type, v.id); }`,
|
|
2658
2692
|
...(hasVersionedRefs
|
|
2659
2693
|
? [` for (const s of versioned) { const v = data[s.field] as { pinned: _NomosRawAddress; series: _NomosRawAddress } | undefined; if (v && typeof v === "object") data[s.field] = _versionedNomosRef(nomos as NomosHolon, v, s.currentField); }`]
|
|
@@ -1664,8 +1664,8 @@ const NOMOS_TYPES_DEP = "^0.8.7";
|
|
|
1664
1664
|
// 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
|
|
1665
1665
|
// DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
|
|
1666
1666
|
// REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
|
|
1667
|
-
const NOMOS_CLIENT_DEP = "^0.64.
|
|
1668
|
-
const NOMOS_FLUTTER_DEP = "^0.63.
|
|
1667
|
+
const NOMOS_CLIENT_DEP = "^0.64.32";
|
|
1668
|
+
const NOMOS_FLUTTER_DEP = "^0.63.56";
|
|
1669
1669
|
// DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in dsl/dart/pubspec.yaml
|
|
1670
1670
|
// and dsl/dart_types/pubspec.yaml — a Dart release without this bump fails the suite, so tenants never
|
|
1671
1671
|
// land back in dependency_overrides (the exact co2 report this closes, third occurrence).
|
|
@@ -3936,12 +3936,26 @@ async function main(): Promise<void> {
|
|
|
3936
3936
|
const domainKey = mod.domain ?? mod.name;
|
|
3937
3937
|
const locked = priorLock.domains[mod.name] ?? priorLock.domains[domainKey];
|
|
3938
3938
|
if (locked !== undefined) {
|
|
3939
|
+
const currentImplementationDetailAggregateIds = new Set(
|
|
3940
|
+
mod.aggregates
|
|
3941
|
+
.filter(
|
|
3942
|
+
(aggregate) =>
|
|
3943
|
+
(aggregate as { businessBirthInternal?: unknown }).businessBirthInternal === true,
|
|
3944
|
+
)
|
|
3945
|
+
.map((aggregate) => aggregate.id),
|
|
3946
|
+
);
|
|
3939
3947
|
// Framework aggregates are shared implementation law, reconciled under @framework rather
|
|
3940
|
-
// than owned by this tenant domain.
|
|
3941
|
-
//
|
|
3948
|
+
// than owned by this tenant domain. Domain-scoped implementation aggregates such as
|
|
3949
|
+
// NomosSourceFrontier deliberately retain the tenant domain's law namespace, but are still
|
|
3950
|
+
// hidden from its structural interface. A package may compose a different framework subset
|
|
3951
|
+
// as its topology changes; never instruct a tenant to author a retirement for Nomos internals.
|
|
3942
3952
|
const localAggregates = Object.fromEntries(
|
|
3943
3953
|
Object.entries(locked.stableIds.aggregates)
|
|
3944
|
-
.filter(
|
|
3954
|
+
.filter(
|
|
3955
|
+
([aggregateId, aggregate]) =>
|
|
3956
|
+
!frameworkAggregateSids.has(aggregate.sid) &&
|
|
3957
|
+
!currentImplementationDetailAggregateIds.has(aggregateId),
|
|
3958
|
+
),
|
|
3945
3959
|
);
|
|
3946
3960
|
priorDomainsForPackage[domainKey] = {
|
|
3947
3961
|
stableIds: { ...locked.stableIds, aggregates: localAggregates },
|