@githolon/dsl 0.105.13 → 0.105.15
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 +13 -0
- package/dart/lib/src/runner/node-entry.mjs +19 -13
- package/dart/lib/src/runner/offline-install.mjs +25 -11
- package/dart/lib/src/session_bound.dart +7 -7
- package/dart/lib/src/webview_bridge.dart +4 -5
- package/dart/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +93 -34
- package/src/build_package.ts +37 -3
- package/src/check_package_main.ts +12 -10
- package/src/codegen_dart.ts +7 -4
- package/src/codegen_dart_client.ts +5 -16
- package/src/codegen_ts.ts +32 -4
- package/src/compile_package_main.ts +100 -9
- package/src/evolution.ts +313 -0
- package/src/evolution_files.ts +31 -0
- package/src/evolve_preview.ts +64 -55
- package/src/index.ts +10 -0
- package/src/law_graph.ts +58 -1
- package/src/law_graph_usda.ts +26 -0
- package/src/stable_ids_for_module.ts +1 -1
package/dart/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 0.64.31
|
|
2
|
+
|
|
3
|
+
- Restage the validated intent-offer byte gate and deterministic signer-posture reader into the immutable Dart runner.
|
|
4
|
+
|
|
5
|
+
## 0.64.30
|
|
6
|
+
|
|
7
|
+
- Recover an authenticated generated application's replacement device through the established repeated-birth compatibility lane when guardian policy refuses keyless enrolment.
|
|
8
|
+
- Resolve signer posture from the relation tuple's deterministic aggregate address so composed application law cannot make framework query aliases ambiguous.
|
|
9
|
+
|
|
10
|
+
## 0.64.29
|
|
11
|
+
|
|
12
|
+
- Restaged with the current kernel candidate: regenerated vendored assets (kernel release identity is baked into them). Published pub.dev archives are immutable, so regenerated bytes ride their own version.
|
|
13
|
+
|
|
1
14
|
## 0.64.28
|
|
2
15
|
|
|
3
16
|
- Restaged with the current kernel candidate: regenerated vendored assets (kernel release identity is baked into them). Published pub.dev archives are immutable, so regenerated bytes ride their own version.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// <define:__NOMOS_KERNEL_RELEASE__>
|
|
4
|
-
var define_NOMOS_KERNEL_RELEASE_default = { production: { hash: "
|
|
4
|
+
var define_NOMOS_KERNEL_RELEASE_default = { production: { hash: "d37253bcefd90a180a6a1af96422a9f0724dfca9efd9ae7cff070afa2c410f09", version: "kernel-d37253bc", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience", "temporalEnum"], protocol: 1 }, testMint: { hash: "b6bddd8d61390edbe2ee4e5f3c7f21108bdb7800af746d20f568936f63e2d517", version: "kernel-b6bddd8d", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience", "temporalEnum"], protocol: 1 } };
|
|
5
5
|
|
|
6
6
|
// runner/node-entry.ts
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
@@ -534,7 +534,7 @@ function createWebviewRunner({ post: post2, openRealm: openRealm2 }) {
|
|
|
534
534
|
// FRAMEWORK-PRIVATE: generated clients say model.adopt(); the runner/client owns proof + receipt assembly.
|
|
535
535
|
async adoptGeneratedModel(a) {
|
|
536
536
|
const rec = pickSession(a);
|
|
537
|
-
const r = await (await liveHolon(rec)).__nomosAdoptModel(a.domain, a.candidateHash, { because: a.because
|
|
537
|
+
const r = await (await liveHolon(rec)).__nomosAdoptModel(a.domain, a.candidateHash, { because: a.because });
|
|
538
538
|
if (r && r.ok && rec.autoStop && rec.autoStop.trigger) rec.autoStop.trigger("write");
|
|
539
539
|
return { verdict: r };
|
|
540
540
|
},
|
|
@@ -7667,7 +7667,7 @@ function prepareManagedPromotion(report, candidateHash, domain, opts = {}) {
|
|
|
7667
7667
|
domainHash: candidateHash,
|
|
7668
7668
|
...opts.replaces ? { replaces: opts.replaces } : {},
|
|
7669
7669
|
retireReplaced: opts.retireReplaced ?? false,
|
|
7670
|
-
...
|
|
7670
|
+
...report.dispositions ? { dispositions: report.dispositions } : {},
|
|
7671
7671
|
preflight
|
|
7672
7672
|
}
|
|
7673
7673
|
};
|
|
@@ -7683,7 +7683,6 @@ function prepareManagedRestoration(report, currentHash, priorHash, domain, opts
|
|
|
7683
7683
|
}
|
|
7684
7684
|
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
7685
7685
|
const prepared = prepareManagedPromotion(report, priorHash, domain, {
|
|
7686
|
-
dispositions: report.dispositions,
|
|
7687
7686
|
...acceptanceReason ? { acceptanceReason } : {}
|
|
7688
7687
|
});
|
|
7689
7688
|
if (!prepared.ok) {
|
|
@@ -8153,8 +8152,8 @@ function createGovernanceOffers(ctx) {
|
|
|
8153
8152
|
},
|
|
8154
8153
|
/**
|
|
8155
8154
|
* PARENT-AUTHORITY POSTURE (read-only diagnostic): is `identity:<principal>#signer@key:<keyHash>`
|
|
8156
|
-
* a LIVE tuple on `parent`'s chain? Reads the
|
|
8157
|
-
*
|
|
8155
|
+
* a LIVE tuple on `parent`'s chain? Reads the tuple's deterministic aggregate address over the
|
|
8156
|
+
* generic record lane — one O(1) read, no authoring and no ambiguous query alias in composed law. Returns
|
|
8158
8157
|
* `{ parent, principal, keyHash, object, relation, enrolled, revoked, checkedAt }`.
|
|
8159
8158
|
* `revoked: true` means the subject's leaf was flipped `status:revoked` (remove-wins — a lawful
|
|
8160
8159
|
* re-enroll of the SAME key is refused; mint + enroll a new device key instead).
|
|
@@ -8168,12 +8167,13 @@ function createGovernanceOffers(ctx) {
|
|
|
8168
8167
|
keyHash = await sha256hexBytes2(bytesUnb642(publicKey));
|
|
8169
8168
|
}
|
|
8170
8169
|
const object = signerObjectOf(p);
|
|
8170
|
+
const aggregateId = `reltuple-${object}-signer`;
|
|
8171
8171
|
let rows;
|
|
8172
8172
|
if (parent === workspace && !remote) {
|
|
8173
|
-
rows = JSON.parse(call("query", { queryBytes: qBytes2({
|
|
8173
|
+
rows = JSON.parse(call("query", { queryBytes: qBytes2({ op: "byId", aggregateId }) })) || [];
|
|
8174
8174
|
} else {
|
|
8175
8175
|
const headers = authToken ? { Authorization: `Bearer ${authToken}`, "x-nomos-auth": authToken } : authHeaders;
|
|
8176
|
-
const r = await _fetch(`${base}/v2/workspaces/${parent}/
|
|
8176
|
+
const r = await _fetch(`${base}/v2/workspaces/${parent}/aggregates/${encodeURIComponent(aggregateId)}`, { headers });
|
|
8177
8177
|
const text = await r.text();
|
|
8178
8178
|
let body;
|
|
8179
8179
|
try {
|
|
@@ -8181,7 +8181,7 @@ function createGovernanceOffers(ctx) {
|
|
|
8181
8181
|
} catch {
|
|
8182
8182
|
body = text;
|
|
8183
8183
|
}
|
|
8184
|
-
if (!r.ok) throw new Error(`parentSignerEnrollment: reading ${parent}'s
|
|
8184
|
+
if (!r.ok) throw new Error(`parentSignerEnrollment: reading ${parent}'s signer tuple failed (${r.status}): ${typeof body === "string" ? body.slice(0, 200) : JSON.stringify(body).slice(0, 200)}`);
|
|
8185
8185
|
rows = Array.isArray(body) ? body : body && Array.isArray(body.rows) ? body.rows : [];
|
|
8186
8186
|
}
|
|
8187
8187
|
let enrolled = false, revoked = false, verifiedVia;
|
|
@@ -8227,7 +8227,14 @@ function createGovernanceOffers(ctx) {
|
|
|
8227
8227
|
rows = JSON.parse(call("query", { queryBytes: qBytes2({ kind: "query", queryId: "relationTuplesByObject", paramsJson: JSON.stringify({ object }) }) })) || [];
|
|
8228
8228
|
} else {
|
|
8229
8229
|
const headers = authToken ? { Authorization: `Bearer ${authToken}`, "x-nomos-auth": authToken } : authHeaders;
|
|
8230
|
-
const
|
|
8230
|
+
const route = await resolveFrameworkRoute({
|
|
8231
|
+
parent: ws,
|
|
8232
|
+
operationId: "relationTuplesByObject",
|
|
8233
|
+
method: "get",
|
|
8234
|
+
token: authToken,
|
|
8235
|
+
principal: subj
|
|
8236
|
+
});
|
|
8237
|
+
const r = await _fetch(`${base}/v2/workspaces/${ws}${route.path}?object=${encodeURIComponent(object)}`, { headers });
|
|
8231
8238
|
const text = await r.text();
|
|
8232
8239
|
let body;
|
|
8233
8240
|
try {
|
|
@@ -10234,7 +10241,7 @@ ${String(commit).toLowerCase()}`;
|
|
|
10234
10241
|
domain,
|
|
10235
10242
|
candidateHash,
|
|
10236
10243
|
atHash,
|
|
10237
|
-
|
|
10244
|
+
ackBy: connectionPrincipal
|
|
10238
10245
|
})
|
|
10239
10246
|
}));
|
|
10240
10247
|
});
|
|
@@ -10247,8 +10254,7 @@ ${String(commit).toLowerCase()}`;
|
|
|
10247
10254
|
}
|
|
10248
10255
|
const prepared = prepareManagedPromotion(report, candidateHash, domain, {
|
|
10249
10256
|
...currentHash && currentHash !== candidateHash ? { replaces: currentHash } : {},
|
|
10250
|
-
...opts.because !== void 0 ? { acceptanceReason: opts.because } : {}
|
|
10251
|
-
...opts.dispositions ? { dispositions: opts.dispositions } : {}
|
|
10257
|
+
...opts.because !== void 0 ? { acceptanceReason: opts.because } : {}
|
|
10252
10258
|
});
|
|
10253
10259
|
if (!prepared.ok) return prepared;
|
|
10254
10260
|
try {
|
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// <define:__NOMOS_KERNEL_RELEASE__>
|
|
9
|
-
var define_NOMOS_KERNEL_RELEASE_default = { production: { hash: "
|
|
9
|
+
var define_NOMOS_KERNEL_RELEASE_default = { production: { hash: "d37253bcefd90a180a6a1af96422a9f0724dfca9efd9ae7cff070afa2c410f09", version: "kernel-d37253bc", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience", "temporalEnum"], protocol: 1 }, testMint: { hash: "b6bddd8d61390edbe2ee4e5f3c7f21108bdb7800af746d20f568936f63e2d517", version: "kernel-b6bddd8d", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience", "temporalEnum"], protocol: 1 } };
|
|
10
10
|
|
|
11
11
|
// runner/offline-install.ts
|
|
12
12
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync } from "node:fs";
|
|
@@ -102,6 +102,8 @@ async function refreshRuntimeDir(cloud, dir, { fetchImpl = globalThis.fetch, log
|
|
|
102
102
|
// src/_adapter/engine.ts
|
|
103
103
|
var engine_exports = {};
|
|
104
104
|
__export(engine_exports, {
|
|
105
|
+
MAX_INLINE_INTENT_OFFER_BYTES: () => MAX_INLINE_INTENT_OFFER_BYTES,
|
|
106
|
+
MAX_STAGED_INTENT_OFFER_BYTES: () => MAX_STAGED_INTENT_OFFER_BYTES,
|
|
105
107
|
NOMOS_SHARD_ROWS_READ: () => NOMOS_SHARD_ROWS_READ,
|
|
106
108
|
admitAll: () => admitAll,
|
|
107
109
|
admitIntentOffers: () => admitIntentOffers,
|
|
@@ -164,6 +166,7 @@ __export(engine_exports, {
|
|
|
164
166
|
ingestPackAsCustody: () => ingestPackAsCustody,
|
|
165
167
|
installedLaw: () => installedLaw,
|
|
166
168
|
intentOfferResidencies: () => intentOfferResidencies,
|
|
169
|
+
intentOfferSizeRefusal: () => intentOfferSizeRefusal,
|
|
167
170
|
isDirty: () => isDirty,
|
|
168
171
|
isWarranted: () => isWarranted,
|
|
169
172
|
kernelStamp: () => kernelStamp,
|
|
@@ -2009,7 +2012,7 @@ function prepareManagedPromotion(report, candidateHash, domain, opts = {}) {
|
|
|
2009
2012
|
domainHash: candidateHash,
|
|
2010
2013
|
...opts.replaces ? { replaces: opts.replaces } : {},
|
|
2011
2014
|
retireReplaced: opts.retireReplaced ?? false,
|
|
2012
|
-
...
|
|
2015
|
+
...report.dispositions ? { dispositions: report.dispositions } : {},
|
|
2013
2016
|
preflight
|
|
2014
2017
|
}
|
|
2015
2018
|
};
|
|
@@ -2025,7 +2028,6 @@ function prepareManagedRestoration(report, currentHash, priorHash, domain, opts
|
|
|
2025
2028
|
}
|
|
2026
2029
|
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
2027
2030
|
const prepared = prepareManagedPromotion(report, priorHash, domain, {
|
|
2028
|
-
dispositions: report.dispositions,
|
|
2029
2031
|
...acceptanceReason ? { acceptanceReason } : {}
|
|
2030
2032
|
});
|
|
2031
2033
|
if (!prepared.ok) {
|
|
@@ -6782,6 +6784,12 @@ async function replicateIntents(eng2, ws, ledger, intents, { push = true } = {})
|
|
|
6782
6784
|
log("replicate-globals", { ws, replicated: replicated.length, skipped: skipped.length, refused: refused.length });
|
|
6783
6785
|
return { replicated, skipped, refused };
|
|
6784
6786
|
}
|
|
6787
|
+
var MAX_INLINE_INTENT_OFFER_BYTES = 32 * 1024 * 1024;
|
|
6788
|
+
var MAX_STAGED_INTENT_OFFER_BYTES = 64 * 1024 * 1024;
|
|
6789
|
+
function intentOfferSizeRefusal(staged, byteLength) {
|
|
6790
|
+
const maxOfferBytes = staged ? MAX_STAGED_INTENT_OFFER_BYTES : MAX_INLINE_INTENT_OFFER_BYTES;
|
|
6791
|
+
return byteLength <= 0 || byteLength > maxOfferBytes ? `intent offer must carry changeB64 <= ${maxOfferBytes / (1024 * 1024)} MiB` : null;
|
|
6792
|
+
}
|
|
6785
6793
|
async function admitIntentOffers(eng2, ws, ledger, offers, { receiptFence = null, shardRouting = null, clientBase = null } = {}) {
|
|
6786
6794
|
const main = await mainIntentIds(eng2, ws);
|
|
6787
6795
|
const sessions = /* @__PURE__ */ new Map();
|
|
@@ -6853,9 +6861,16 @@ async function admitIntentOffers(eng2, ws, ledger, offers, { receiptFence = null
|
|
|
6853
6861
|
let blob = offer?.blob instanceof Uint8Array ? offer.blob : null;
|
|
6854
6862
|
try {
|
|
6855
6863
|
if (!blob && typeof offer?.changeB64 === "string") blob = Uint8Array.from(atob(offer.changeB64), (c) => c.charCodeAt(0));
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6864
|
+
if (!blob) {
|
|
6865
|
+
rec.rejected.push({
|
|
6866
|
+
oid: String(offer?.oid || "").slice(0, 10),
|
|
6867
|
+
error: intentOfferSizeRefusal(!!offer?.staged, 0)
|
|
6868
|
+
});
|
|
6869
|
+
continue;
|
|
6870
|
+
}
|
|
6871
|
+
const sizeRefusal = intentOfferSizeRefusal(!!offer?.staged, blob.byteLength);
|
|
6872
|
+
if (sizeRefusal !== null) {
|
|
6873
|
+
rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: sizeRefusal });
|
|
6859
6874
|
continue;
|
|
6860
6875
|
}
|
|
6861
6876
|
const inspected = kgit.inspectChange(eng2, blob);
|
|
@@ -7115,7 +7130,7 @@ async function mountWorkspace(eng2, ws, ledger) {
|
|
|
7115
7130
|
throw new Error(`kernel refused restored main ${remoteMain}: ${JSON.stringify(mounted)}`);
|
|
7116
7131
|
}
|
|
7117
7132
|
restored = true;
|
|
7118
|
-
if (!seeded?.seeded) {
|
|
7133
|
+
if (!seeded?.seeded && ledger.readOnly !== true) {
|
|
7119
7134
|
void pushCheckpoint(eng2, ws, ledger).catch(() => {
|
|
7120
7135
|
});
|
|
7121
7136
|
}
|
|
@@ -8580,12 +8595,12 @@ async function verifyChain(eng2, ws, ledger) {
|
|
|
8580
8595
|
function verifyChainLocal(eng2, ws) {
|
|
8581
8596
|
return namedQueryProto(eng2, ws, QueryOperation.VERIFY_CHAIN);
|
|
8582
8597
|
}
|
|
8583
|
-
function historyPreflight(eng2, ws, domain, candidateHash, atHash,
|
|
8598
|
+
function historyPreflight(eng2, ws, domain, candidateHash, atHash, actor = "") {
|
|
8584
8599
|
return namedQueryProto(eng2, ws, QueryOperation.HISTORY_PREFLIGHT, {
|
|
8585
8600
|
domain,
|
|
8586
8601
|
candidateHash,
|
|
8587
8602
|
atHash,
|
|
8588
|
-
...
|
|
8603
|
+
...actor.trim() ? { ackBy: actor.trim() } : {}
|
|
8589
8604
|
});
|
|
8590
8605
|
}
|
|
8591
8606
|
function historyRestorePreflight(eng2, ws, domain, currentHash, priorHash, atHash, actor) {
|
|
@@ -8612,7 +8627,7 @@ function promotePreflighted(eng2, ws, domain, candidateHash, opts = {}) {
|
|
|
8612
8627
|
}
|
|
8613
8628
|
let report;
|
|
8614
8629
|
try {
|
|
8615
|
-
report = historyPreflight(eng2, ws, domain, candidateHash, atHash,
|
|
8630
|
+
report = historyPreflight(eng2, ws, domain, candidateHash, atHash, actingPrincipal);
|
|
8616
8631
|
} catch (error) {
|
|
8617
8632
|
return { ok: false, stage: "preflight", error: String(error?.message || error) };
|
|
8618
8633
|
}
|
|
@@ -8621,7 +8636,6 @@ function promotePreflighted(eng2, ws, domain, candidateHash, opts = {}) {
|
|
|
8621
8636
|
const {
|
|
8622
8637
|
replaces: _replaces,
|
|
8623
8638
|
retireReplaced: _retireReplaced,
|
|
8624
|
-
dispositions: _dispositions,
|
|
8625
8639
|
acceptanceReason: _acceptance,
|
|
8626
8640
|
...authorOpts
|
|
8627
8641
|
} = opts;
|
|
@@ -191,7 +191,7 @@ class DomainClientModelAdoptionRequired implements Exception {
|
|
|
191
191
|
final String summary;
|
|
192
192
|
final DomainModelReview review;
|
|
193
193
|
final Future<void> Function()? _stage;
|
|
194
|
-
final Future<void> Function(String reason
|
|
194
|
+
final Future<void> Function(String reason)? _accept;
|
|
195
195
|
|
|
196
196
|
const DomainClientModelAdoptionRequired({
|
|
197
197
|
required this.expectedDomainKey,
|
|
@@ -200,7 +200,7 @@ class DomainClientModelAdoptionRequired implements Exception {
|
|
|
200
200
|
required this.summary,
|
|
201
201
|
required this.review,
|
|
202
202
|
Future<void> Function()? stage,
|
|
203
|
-
Future<void> Function(String reason
|
|
203
|
+
Future<void> Function(String reason)? accept,
|
|
204
204
|
}) : _stage = stage,
|
|
205
205
|
_accept = accept;
|
|
206
206
|
|
|
@@ -216,10 +216,10 @@ class DomainClientModelAdoptionRequired implements Exception {
|
|
|
216
216
|
|
|
217
217
|
bool get canAccept => _accept != null;
|
|
218
218
|
|
|
219
|
-
///
|
|
220
|
-
///
|
|
221
|
-
///
|
|
222
|
-
Future<void> accept(String reason
|
|
219
|
+
/// Accept the candidate after reviewing the compiler-derived consequences.
|
|
220
|
+
/// Stable identities, retirements and value evolutions come from candidate
|
|
221
|
+
/// law; application code supplies accountability, never mechanical waivers.
|
|
222
|
+
Future<void> accept(String reason) {
|
|
223
223
|
final value = reason.trim();
|
|
224
224
|
if (value.isEmpty) {
|
|
225
225
|
throw ArgumentError.value(
|
|
@@ -232,7 +232,7 @@ class DomainClientModelAdoptionRequired implements Exception {
|
|
|
232
232
|
if (accept == null) {
|
|
233
233
|
throw StateError('This generated model change cannot be accepted.');
|
|
234
234
|
}
|
|
235
|
-
return accept(value
|
|
235
|
+
return accept(value);
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
@override
|
|
@@ -2761,13 +2761,11 @@ class NomosBridge {
|
|
|
2761
2761
|
required String domain,
|
|
2762
2762
|
required String candidateHash,
|
|
2763
2763
|
String? because,
|
|
2764
|
-
Map<String, Object?>? dispositions,
|
|
2765
2764
|
}) async {
|
|
2766
2765
|
final r = _asMap(await _call('adoptGeneratedModel', {
|
|
2767
2766
|
'domain': domain,
|
|
2768
2767
|
'candidateHash': candidateHash,
|
|
2769
2768
|
if (because != null) 'because': because,
|
|
2770
|
-
if (dispositions != null) 'dispositions': dispositions,
|
|
2771
2769
|
}));
|
|
2772
2770
|
return ((r['verdict'] as Map?) ?? const <String, Object?>{})
|
|
2773
2771
|
.cast<String, Object?>();
|
|
@@ -4057,7 +4055,8 @@ class NomosBridge {
|
|
|
4057
4055
|
if (!_syncEvents.isClosed) await _syncEvents.close();
|
|
4058
4056
|
if (!_signalEvents.isClosed) await _signalEvents.close();
|
|
4059
4057
|
if (!_custodyEvents.isClosed) await _custodyEvents.close();
|
|
4060
|
-
if (!_localWorkRejectedEvents.isClosed)
|
|
4058
|
+
if (!_localWorkRejectedEvents.isClosed)
|
|
4059
|
+
await _localWorkRejectedEvents.close();
|
|
4061
4060
|
if (!_flameEvents.isClosed) await _flameEvents.close();
|
|
4062
4061
|
if (!_spanEvents.isClosed) await _spanEvents.close();
|
|
4063
4062
|
if (!_transferEvents.isClosed) await _transferEvents.close();
|
|
@@ -4382,8 +4381,8 @@ class _BridgeForeignWorkspaceReader implements NomosForeignWorkspaceReader {
|
|
|
4382
4381
|
String? nomosInternalResidencyRequiredWorkspace(Object error) {
|
|
4383
4382
|
final text = error.toString();
|
|
4384
4383
|
if (!text.contains('foreign-read-not-ready')) return null;
|
|
4385
|
-
final match =
|
|
4386
|
-
.firstMatch(text);
|
|
4384
|
+
final match =
|
|
4385
|
+
RegExp(r"source workspace '([^']+)' is not resident").firstMatch(text);
|
|
4387
4386
|
final workspace = match?.group(1)?.trim();
|
|
4388
4387
|
return (workspace == null || workspace.isEmpty) ? null : workspace;
|
|
4389
4388
|
}
|
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.31
|
|
11
11
|
|
|
12
12
|
environment:
|
|
13
13
|
sdk: ^3.5.0
|
package/package.json
CHANGED
|
@@ -6698,7 +6698,7 @@ function prepareManagedPromotion(report, candidateHash, domain, opts = {}) {
|
|
|
6698
6698
|
domainHash: candidateHash,
|
|
6699
6699
|
...opts.replaces ? { replaces: opts.replaces } : {},
|
|
6700
6700
|
retireReplaced: opts.retireReplaced ?? false,
|
|
6701
|
-
...
|
|
6701
|
+
...report.dispositions ? { dispositions: report.dispositions } : {},
|
|
6702
6702
|
preflight
|
|
6703
6703
|
}
|
|
6704
6704
|
};
|
|
@@ -6714,7 +6714,6 @@ function prepareManagedRestoration(report, currentHash, priorHash, domain, opts
|
|
|
6714
6714
|
}
|
|
6715
6715
|
const acceptanceReason = opts.acceptanceReason?.trim();
|
|
6716
6716
|
const prepared = prepareManagedPromotion(report, priorHash, domain, {
|
|
6717
|
-
dispositions: report.dispositions,
|
|
6718
6717
|
...acceptanceReason ? { acceptanceReason } : {}
|
|
6719
6718
|
});
|
|
6720
6719
|
if (!prepared.ok) {
|
|
@@ -7184,8 +7183,8 @@ function createGovernanceOffers(ctx) {
|
|
|
7184
7183
|
},
|
|
7185
7184
|
/**
|
|
7186
7185
|
* PARENT-AUTHORITY POSTURE (read-only diagnostic): is `identity:<principal>#signer@key:<keyHash>`
|
|
7187
|
-
* a LIVE tuple on `parent`'s chain? Reads the
|
|
7188
|
-
*
|
|
7186
|
+
* a LIVE tuple on `parent`'s chain? Reads the tuple's deterministic aggregate address over the
|
|
7187
|
+
* generic record lane — one O(1) read, no authoring and no ambiguous query alias in composed law. Returns
|
|
7189
7188
|
* `{ parent, principal, keyHash, object, relation, enrolled, revoked, checkedAt }`.
|
|
7190
7189
|
* `revoked: true` means the subject's leaf was flipped `status:revoked` (remove-wins — a lawful
|
|
7191
7190
|
* re-enroll of the SAME key is refused; mint + enroll a new device key instead).
|
|
@@ -7199,12 +7198,13 @@ function createGovernanceOffers(ctx) {
|
|
|
7199
7198
|
keyHash = await sha256hexBytes2(bytesUnb642(publicKey));
|
|
7200
7199
|
}
|
|
7201
7200
|
const object = signerObjectOf(p);
|
|
7201
|
+
const aggregateId = `reltuple-${object}-signer`;
|
|
7202
7202
|
let rows;
|
|
7203
7203
|
if (parent === workspace && !remote) {
|
|
7204
|
-
rows = JSON.parse(call("query", { queryBytes: qBytes2({
|
|
7204
|
+
rows = JSON.parse(call("query", { queryBytes: qBytes2({ op: "byId", aggregateId }) })) || [];
|
|
7205
7205
|
} else {
|
|
7206
7206
|
const headers = authToken ? { Authorization: `Bearer ${authToken}`, "x-nomos-auth": authToken } : authHeaders;
|
|
7207
|
-
const r = await _fetch(`${base}/v2/workspaces/${parent}/
|
|
7207
|
+
const r = await _fetch(`${base}/v2/workspaces/${parent}/aggregates/${encodeURIComponent(aggregateId)}`, { headers });
|
|
7208
7208
|
const text2 = await r.text();
|
|
7209
7209
|
let body;
|
|
7210
7210
|
try {
|
|
@@ -7212,7 +7212,7 @@ function createGovernanceOffers(ctx) {
|
|
|
7212
7212
|
} catch {
|
|
7213
7213
|
body = text2;
|
|
7214
7214
|
}
|
|
7215
|
-
if (!r.ok) throw new Error(`parentSignerEnrollment: reading ${parent}'s
|
|
7215
|
+
if (!r.ok) throw new Error(`parentSignerEnrollment: reading ${parent}'s signer tuple failed (${r.status}): ${typeof body === "string" ? body.slice(0, 200) : JSON.stringify(body).slice(0, 200)}`);
|
|
7216
7216
|
rows = Array.isArray(body) ? body : body && Array.isArray(body.rows) ? body.rows : [];
|
|
7217
7217
|
}
|
|
7218
7218
|
let enrolled = false, revoked = false, verifiedVia;
|
|
@@ -7258,7 +7258,14 @@ function createGovernanceOffers(ctx) {
|
|
|
7258
7258
|
rows = JSON.parse(call("query", { queryBytes: qBytes2({ kind: "query", queryId: "relationTuplesByObject", paramsJson: JSON.stringify({ object }) }) })) || [];
|
|
7259
7259
|
} else {
|
|
7260
7260
|
const headers = authToken ? { Authorization: `Bearer ${authToken}`, "x-nomos-auth": authToken } : authHeaders;
|
|
7261
|
-
const
|
|
7261
|
+
const route = await resolveFrameworkRoute({
|
|
7262
|
+
parent: ws,
|
|
7263
|
+
operationId: "relationTuplesByObject",
|
|
7264
|
+
method: "get",
|
|
7265
|
+
token: authToken,
|
|
7266
|
+
principal: subj
|
|
7267
|
+
});
|
|
7268
|
+
const r = await _fetch(`${base}/v2/workspaces/${ws}${route.path}?object=${encodeURIComponent(object)}`, { headers });
|
|
7262
7269
|
const text2 = await r.text();
|
|
7263
7270
|
let body;
|
|
7264
7271
|
try {
|
|
@@ -9265,7 +9272,7 @@ ${String(commit).toLowerCase()}`;
|
|
|
9265
9272
|
domain,
|
|
9266
9273
|
candidateHash,
|
|
9267
9274
|
atHash,
|
|
9268
|
-
|
|
9275
|
+
ackBy: connectionPrincipal
|
|
9269
9276
|
})
|
|
9270
9277
|
}));
|
|
9271
9278
|
});
|
|
@@ -9278,8 +9285,7 @@ ${String(commit).toLowerCase()}`;
|
|
|
9278
9285
|
}
|
|
9279
9286
|
const prepared = prepareManagedPromotion(report, candidateHash, domain, {
|
|
9280
9287
|
...currentHash && currentHash !== candidateHash ? { replaces: currentHash } : {},
|
|
9281
|
-
...opts.because !== void 0 ? { acceptanceReason: opts.because } : {}
|
|
9282
|
-
...opts.dispositions ? { dispositions: opts.dispositions } : {}
|
|
9288
|
+
...opts.because !== void 0 ? { acceptanceReason: opts.because } : {}
|
|
9283
9289
|
});
|
|
9284
9290
|
if (!prepared.ok) return prepared;
|
|
9285
9291
|
try {
|
|
@@ -13492,16 +13498,55 @@ function applicationError(message, code, cause) {
|
|
|
13492
13498
|
if (cause !== void 0) error.cause = cause;
|
|
13493
13499
|
return error;
|
|
13494
13500
|
}
|
|
13495
|
-
|
|
13501
|
+
function applicationOpenFailure(application, requestedModel, cause) {
|
|
13502
|
+
const typed = cause;
|
|
13503
|
+
if (typed?.name === "NomosApplicationError" && typeof typed.code === "string") {
|
|
13504
|
+
return cause;
|
|
13505
|
+
}
|
|
13506
|
+
const raw = String(cause?.message ?? cause ?? "unknown failure");
|
|
13507
|
+
if (/birth-current-law-unavailable|birth install target|\[nomos\.birth\.model_not_active\]/i.test(raw)) {
|
|
13508
|
+
const model = /(?:birth install target|under model)\s+([0-9a-f]{64})/i.exec(raw)?.[1] ?? requestedModel;
|
|
13509
|
+
const shortModel = /^[0-9a-f]{64}$/i.test(model) ? `${model.slice(0, 16)}\u2026` : "the requested model";
|
|
13510
|
+
return applicationError(
|
|
13511
|
+
`Nomos application '${application}' cannot create this private workspace because its parent does not currently serve model ${shortModel}. No workspace was created. A current generated client should inherit the parent's active model at birth and then govern adoption of its packaged model; regenerate the application client before retrying, or have an authorised application release adopt that model on the parent.`,
|
|
13512
|
+
"nomos.application.bootstrap_model_not_active",
|
|
13513
|
+
cause
|
|
13514
|
+
);
|
|
13515
|
+
}
|
|
13516
|
+
return applicationError(
|
|
13517
|
+
`Nomos could not finish preparing the signed-in '${application}' application: ${raw}`,
|
|
13518
|
+
"nomos.application.open_failed",
|
|
13519
|
+
cause
|
|
13520
|
+
);
|
|
13521
|
+
}
|
|
13522
|
+
async function ensureGeneratedModelCurrent(application, approveModel) {
|
|
13496
13523
|
if (application.model?.adopt === void 0) {
|
|
13497
13524
|
throw applicationError(
|
|
13498
13525
|
"This generated application has no model lifecycle surface and cannot prove its plans are current.",
|
|
13499
13526
|
"nomos.application.model_lifecycle_missing"
|
|
13500
13527
|
);
|
|
13501
13528
|
}
|
|
13502
|
-
|
|
13529
|
+
let adoption = await application.model.adopt();
|
|
13530
|
+
if (adoption.status === "needs-staging" && adoption.stage !== void 0) {
|
|
13531
|
+
adoption = await adoption.stage();
|
|
13532
|
+
}
|
|
13503
13533
|
if (adoption.status === "adopted") return;
|
|
13504
13534
|
if (adoption.status === "needs-decision") {
|
|
13535
|
+
if (approveModel !== void 0 && adoption.accept !== void 0) {
|
|
13536
|
+
const approval = await approveModel({
|
|
13537
|
+
summary: adoption.summary,
|
|
13538
|
+
review: adoption.review
|
|
13539
|
+
});
|
|
13540
|
+
const because = approval.because.trim();
|
|
13541
|
+
if (!because) {
|
|
13542
|
+
throw applicationError(
|
|
13543
|
+
"Model approval must state the business reason for the change.",
|
|
13544
|
+
"nomos.application.model_decision_reason_missing"
|
|
13545
|
+
);
|
|
13546
|
+
}
|
|
13547
|
+
adoption = await adoption.accept(because);
|
|
13548
|
+
if (adoption.status === "adopted") return;
|
|
13549
|
+
}
|
|
13505
13550
|
throw applicationError(
|
|
13506
13551
|
"This application model changes prior business outcomes and needs an attributed migration decision before the app can write.",
|
|
13507
13552
|
"nomos.application.model_decision_required",
|
|
@@ -13624,7 +13669,7 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13624
13669
|
...environment?.NOMOS_TEST_K_ROOT_PUBLIC ? { __testKRootPublic: environment.NOMOS_TEST_K_ROOT_PUBLIC } : {}
|
|
13625
13670
|
});
|
|
13626
13671
|
const applicationObject = measureOpenSync("bind generated business API", () => bind(holon2, user));
|
|
13627
|
-
await ensureGeneratedModelCurrent(applicationObject);
|
|
13672
|
+
await ensureGeneratedModelCurrent(applicationObject, options.approveModel);
|
|
13628
13673
|
await measureOpen("prepare generated entry commands", () => prepareGeneratedEntryCommands(holon2, options.readyCommands, options.onPerformance));
|
|
13629
13674
|
const stop = holon2.autoSync({
|
|
13630
13675
|
onResult: (result) => {
|
|
@@ -13861,17 +13906,11 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13861
13906
|
}
|
|
13862
13907
|
authToken = deviceToken;
|
|
13863
13908
|
if (!completed) {
|
|
13864
|
-
|
|
13865
|
-
try {
|
|
13866
|
-
homeAvailable = Boolean(await measureOpen("check private application custody", () => authorityHolon.head()));
|
|
13867
|
-
} catch {
|
|
13868
|
-
}
|
|
13869
|
-
if (!homeAvailable) {
|
|
13909
|
+
const birthOrRepeat = async () => {
|
|
13870
13910
|
const birth = await measureOpen("establish private application custody", () => authorityHolon.nomosInternalBirthReceivingGroup({
|
|
13871
13911
|
parent: application,
|
|
13872
13912
|
principal,
|
|
13873
13913
|
subject,
|
|
13874
|
-
lawHash: options.lawHash,
|
|
13875
13914
|
device: { secret, public: publicKey },
|
|
13876
13915
|
authToken,
|
|
13877
13916
|
idToken: authToken,
|
|
@@ -13881,16 +13920,36 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13881
13920
|
}));
|
|
13882
13921
|
const verdict = birth.verify;
|
|
13883
13922
|
if (verdict !== void 0 && verdict.valid !== true) throw new Error(`the born application failed replay verification: ${String(verdict.error ?? "unknown")}`);
|
|
13923
|
+
};
|
|
13924
|
+
let homeAvailable = false;
|
|
13925
|
+
try {
|
|
13926
|
+
homeAvailable = Boolean(await measureOpen("check private application custody", () => authorityHolon.head()));
|
|
13927
|
+
} catch {
|
|
13928
|
+
}
|
|
13929
|
+
if (!homeAvailable) {
|
|
13930
|
+
await birthOrRepeat();
|
|
13884
13931
|
} else if (!hadDurableSecret) {
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
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
|
+
}
|
|
13894
13953
|
}
|
|
13895
13954
|
await measureOpen("save application bootstrap progress", () => store.saveText(journalState, "home-available"));
|
|
13896
13955
|
authorityHolon = await measureOpen("rebind durable application authority", () => mountAuthority(secret, authToken));
|
|
@@ -13904,8 +13963,8 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13904
13963
|
if (verified.valid !== true) throw new Error(`the private authority context failed replay verification: ${String(verified.error ?? "unknown")}`);
|
|
13905
13964
|
await measureOpen("save application bootstrap progress", () => store.saveText(journalState, "verified"));
|
|
13906
13965
|
try {
|
|
13907
|
-
await measureOpen("confirm
|
|
13908
|
-
parent:
|
|
13966
|
+
await measureOpen("confirm private-custody signer enrolment", () => authorityHolon.ensureParentSignerEnrollment({
|
|
13967
|
+
parent: receivingGroup,
|
|
13909
13968
|
principal: subject,
|
|
13910
13969
|
authorSecret: secret,
|
|
13911
13970
|
authToken,
|
|
@@ -13930,7 +13989,7 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
13930
13989
|
} catch {
|
|
13931
13990
|
}
|
|
13932
13991
|
const applicationObject = measureOpenSync("bind generated business API", () => bind(holon, user));
|
|
13933
|
-
await measureOpen("confirm generated model is current", () => ensureGeneratedModelCurrent(applicationObject));
|
|
13992
|
+
await measureOpen("confirm generated model is current", () => ensureGeneratedModelCurrent(applicationObject, options.approveModel));
|
|
13934
13993
|
await measureOpen("prepare generated entry commands", () => prepareGeneratedEntryCommands(holon, options.readyCommands, options.onPerformance));
|
|
13935
13994
|
phase = "current";
|
|
13936
13995
|
autoSync = holon.autoSync({
|
|
@@ -14009,7 +14068,7 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
|
|
|
14009
14068
|
} catch (cause) {
|
|
14010
14069
|
await closeRealm().catch(() => {
|
|
14011
14070
|
});
|
|
14012
|
-
throw
|
|
14071
|
+
throw applicationOpenFailure(application, options.lawHash, cause);
|
|
14013
14072
|
}
|
|
14014
14073
|
}
|
|
14015
14074
|
export {
|