@githolon/dsl 0.105.14 → 0.105.16

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 CHANGED
@@ -1,3 +1,16 @@
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
+
5
+ ## 0.64.31
6
+
7
+ - Restage the validated intent-offer byte gate and deterministic signer-posture reader into the immutable Dart runner.
8
+
9
+ ## 0.64.30
10
+
11
+ - Recover an authenticated generated application's replacement device through the established repeated-birth compatibility lane when guardian policy refuses keyless enrolment.
12
+ - Resolve signer posture from the relation tuple's deterministic aggregate address so composed application law cannot make framework query aliases ambiguous.
13
+
1
14
  ## 0.64.29
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.
@@ -8152,8 +8152,8 @@ function createGovernanceOffers(ctx) {
8152
8152
  },
8153
8153
  /**
8154
8154
  * PARENT-AUTHORITY POSTURE (read-only diagnostic): is `identity:<principal>#signer@key:<keyHash>`
8155
- * a LIVE tuple on `parent`'s chain? Reads the parent's declared `relationTuplesByObject` query over
8156
- * the open gateway — one O(1) relation read, no authoring. Returns
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
8157
8157
  * `{ parent, principal, keyHash, object, relation, enrolled, revoked, checkedAt }`.
8158
8158
  * `revoked: true` means the subject's leaf was flipped `status:revoked` (remove-wins — a lawful
8159
8159
  * re-enroll of the SAME key is refused; mint + enroll a new device key instead).
@@ -8167,19 +8167,13 @@ function createGovernanceOffers(ctx) {
8167
8167
  keyHash = await sha256hexBytes2(bytesUnb642(publicKey));
8168
8168
  }
8169
8169
  const object = signerObjectOf(p);
8170
+ const aggregateId = `reltuple-${object}-signer`;
8170
8171
  let rows;
8171
8172
  if (parent === workspace && !remote) {
8172
- rows = JSON.parse(call("query", { queryBytes: qBytes2({ kind: "query", queryId: "relationTuplesByObject", paramsJson: JSON.stringify({ object }) }) })) || [];
8173
+ rows = JSON.parse(call("query", { queryBytes: qBytes2({ op: "byId", aggregateId }) })) || [];
8173
8174
  } else {
8174
8175
  const headers = authToken ? { Authorization: `Bearer ${authToken}`, "x-nomos-auth": authToken } : authHeaders;
8175
- const route = await resolveFrameworkRoute({
8176
- parent,
8177
- operationId: "relationTuplesByObject",
8178
- method: "get",
8179
- token: authToken,
8180
- principal: p
8181
- });
8182
- const r = await _fetch(`${base}/v2/workspaces/${parent}${route.path}?object=${encodeURIComponent(object)}`, { headers });
8176
+ const r = await _fetch(`${base}/v2/workspaces/${parent}/aggregates/${encodeURIComponent(aggregateId)}`, { headers });
8183
8177
  const text = await r.text();
8184
8178
  let body;
8185
8179
  try {
@@ -8187,7 +8181,7 @@ function createGovernanceOffers(ctx) {
8187
8181
  } catch {
8188
8182
  body = text;
8189
8183
  }
8190
- if (!r.ok) throw new Error(`parentSignerEnrollment: reading ${parent}'s relationTuplesByObject failed (${r.status}): ${typeof body === "string" ? body.slice(0, 200) : JSON.stringify(body).slice(0, 200)}`);
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)}`);
8191
8185
  rows = Array.isArray(body) ? body : body && Array.isArray(body.rows) ? body.rows : [];
8192
8186
  }
8193
8187
  let enrolled = false, revoked = false, verifiedVia;
@@ -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,
@@ -6781,6 +6784,12 @@ async function replicateIntents(eng2, ws, ledger, intents, { push = true } = {})
6781
6784
  log("replicate-globals", { ws, replicated: replicated.length, skipped: skipped.length, refused: refused.length });
6782
6785
  return { replicated, skipped, refused };
6783
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
+ }
6784
6793
  async function admitIntentOffers(eng2, ws, ledger, offers, { receiptFence = null, shardRouting = null, clientBase = null } = {}) {
6785
6794
  const main = await mainIntentIds(eng2, ws);
6786
6795
  const sessions = /* @__PURE__ */ new Map();
@@ -6852,9 +6861,16 @@ async function admitIntentOffers(eng2, ws, ledger, offers, { receiptFence = null
6852
6861
  let blob = offer?.blob instanceof Uint8Array ? offer.blob : null;
6853
6862
  try {
6854
6863
  if (!blob && typeof offer?.changeB64 === "string") blob = Uint8Array.from(atob(offer.changeB64), (c) => c.charCodeAt(0));
6855
- const maxOfferBytes = offer?.staged ? 64 * 1024 * 1024 : 32 * 1024 * 1024;
6856
- if (!blob || blob.byteLength === 0 || blob.byteLength > maxOfferBytes) {
6857
- rec.rejected.push({ oid: String(offer?.oid || "").slice(0, 10), error: `intent offer must carry changeB64 <= ${maxOfferBytes / (1024 * 1024)} MiB` });
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 });
6858
6874
  continue;
6859
6875
  }
6860
6876
  const inspected = kgit.inspectChange(eng2, blob);
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.29
10
+ version: 0.64.32
11
11
 
12
12
  environment:
13
13
  sdk: ^3.5.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/dsl",
3
- "version": "0.105.14",
3
+ "version": "0.105.16",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
@@ -7183,8 +7183,8 @@ function createGovernanceOffers(ctx) {
7183
7183
  },
7184
7184
  /**
7185
7185
  * PARENT-AUTHORITY POSTURE (read-only diagnostic): is `identity:<principal>#signer@key:<keyHash>`
7186
- * a LIVE tuple on `parent`'s chain? Reads the parent's declared `relationTuplesByObject` query over
7187
- * the open gateway — one O(1) relation read, no authoring. Returns
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
7188
7188
  * `{ parent, principal, keyHash, object, relation, enrolled, revoked, checkedAt }`.
7189
7189
  * `revoked: true` means the subject's leaf was flipped `status:revoked` (remove-wins — a lawful
7190
7190
  * re-enroll of the SAME key is refused; mint + enroll a new device key instead).
@@ -7198,19 +7198,13 @@ function createGovernanceOffers(ctx) {
7198
7198
  keyHash = await sha256hexBytes2(bytesUnb642(publicKey));
7199
7199
  }
7200
7200
  const object = signerObjectOf(p);
7201
+ const aggregateId = `reltuple-${object}-signer`;
7201
7202
  let rows;
7202
7203
  if (parent === workspace && !remote) {
7203
- rows = JSON.parse(call("query", { queryBytes: qBytes2({ kind: "query", queryId: "relationTuplesByObject", paramsJson: JSON.stringify({ object }) }) })) || [];
7204
+ rows = JSON.parse(call("query", { queryBytes: qBytes2({ op: "byId", aggregateId }) })) || [];
7204
7205
  } else {
7205
7206
  const headers = authToken ? { Authorization: `Bearer ${authToken}`, "x-nomos-auth": authToken } : authHeaders;
7206
- const route = await resolveFrameworkRoute({
7207
- parent,
7208
- operationId: "relationTuplesByObject",
7209
- method: "get",
7210
- token: authToken,
7211
- principal: p
7212
- });
7213
- const r = await _fetch(`${base}/v2/workspaces/${parent}${route.path}?object=${encodeURIComponent(object)}`, { headers });
7207
+ const r = await _fetch(`${base}/v2/workspaces/${parent}/aggregates/${encodeURIComponent(aggregateId)}`, { headers });
7214
7208
  const text2 = await r.text();
7215
7209
  let body;
7216
7210
  try {
@@ -7218,7 +7212,7 @@ function createGovernanceOffers(ctx) {
7218
7212
  } catch {
7219
7213
  body = text2;
7220
7214
  }
7221
- if (!r.ok) throw new Error(`parentSignerEnrollment: reading ${parent}'s relationTuplesByObject failed (${r.status}): ${typeof body === "string" ? body.slice(0, 200) : JSON.stringify(body).slice(0, 200)}`);
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)}`);
7222
7216
  rows = Array.isArray(body) ? body : body && Array.isArray(body.rows) ? body.rows : [];
7223
7217
  }
7224
7218
  let enrolled = false, revoked = false, verifiedVia;
@@ -13504,6 +13498,27 @@ function applicationError(message, code, cause) {
13504
13498
  if (cause !== void 0) error.cause = cause;
13505
13499
  return error;
13506
13500
  }
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
+ }
13507
13522
  async function ensureGeneratedModelCurrent(application, approveModel) {
13508
13523
  if (application.model?.adopt === void 0) {
13509
13524
  throw applicationError(
@@ -13869,7 +13884,6 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
13869
13884
  let authorityHolon = await measureOpen("open private application custody", () => mountAuthority(secret, authToken));
13870
13885
  const storedJournal = await measureOpen("load application bootstrap state", () => store.loadText(journalState));
13871
13886
  const completed = storedJournal === "complete";
13872
- const hadDurableSecret = secret !== null;
13873
13887
  let publicKey;
13874
13888
  if (secret === null) {
13875
13889
  const device = await measureOpen("create application device identity", () => authorityHolon.authorKeygen());
@@ -13890,6 +13904,43 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
13890
13904
  throw applicationError("Sign in changed authority while preparing this application device.", "nomos.authority.changed_during_open");
13891
13905
  }
13892
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
+ };
13893
13944
  if (!completed) {
13894
13945
  let homeAvailable = false;
13895
13946
  try {
@@ -13897,33 +13948,7 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
13897
13948
  } catch {
13898
13949
  }
13899
13950
  if (!homeAvailable) {
13900
- const birth = await measureOpen("establish private application custody", () => authorityHolon.nomosInternalBirthReceivingGroup({
13901
- parent: application,
13902
- principal,
13903
- subject,
13904
- device: { secret, public: publicKey },
13905
- authToken,
13906
- idToken: authToken,
13907
- verifiedVia: issuer,
13908
- bornAt: now().toISOString(),
13909
- confirm: true
13910
- }));
13911
- const verdict = birth.verify;
13912
- if (verdict !== void 0 && verdict.valid !== true) throw new Error(`the born application failed replay verification: ${String(verdict.error ?? "unknown")}`);
13913
- } else if (!hadDurableSecret) {
13914
- await measureOpen("enrol application device in its private custody", () => authorityHolon.ensureParentSignerEnrollment({
13915
- // The write gate that this device will use is the receiving-group workspace itself.
13916
- // The application root authorises/births that home; it is not a substitute signer index.
13917
- parent: receivingGroup,
13918
- // The author gate speaks canonical Nomos principals. A provider subject is deliberately
13919
- // opaque and may contain its own namespace separators; never enrol that raw value as the actor.
13920
- principal: subject,
13921
- publicKey,
13922
- authorSecret: secret,
13923
- authToken,
13924
- idToken: authToken,
13925
- verifiedVia: issuer
13926
- }));
13951
+ await birthOrRepeat();
13927
13952
  }
13928
13953
  await measureOpen("save application bootstrap progress", () => store.saveText(journalState, "home-available"));
13929
13954
  authorityHolon = await measureOpen("rebind durable application authority", () => mountAuthority(secret, authToken));
@@ -13936,23 +13961,11 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
13936
13961
  const verified = await measureOpen("verify new application custody", () => authorityHolon.verifyChain());
13937
13962
  if (verified.valid !== true) throw new Error(`the private authority context failed replay verification: ${String(verified.error ?? "unknown")}`);
13938
13963
  await measureOpen("save application bootstrap progress", () => store.saveText(journalState, "verified"));
13939
- try {
13940
- await measureOpen("confirm private-custody signer enrolment", () => authorityHolon.ensureParentSignerEnrollment({
13941
- parent: receivingGroup,
13942
- principal: subject,
13943
- authorSecret: secret,
13944
- authToken,
13945
- idToken: authToken,
13946
- verifiedVia: issuer
13947
- }));
13948
- } catch (error) {
13949
- if (/revoked/i.test(String(error))) throw error;
13950
- }
13951
- await measureOpen("complete application bootstrap journal", async () => {
13964
+ await measureOpen("save verified application bootstrap journal", async () => {
13952
13965
  await store.saveText(journalState, "complete");
13953
- await store.remove(journalState);
13954
13966
  });
13955
13967
  }
13968
+ await ensureSignerEnrollment();
13956
13969
  holon = authorityHolon;
13957
13970
  const authorityVerified = await measureOpen("verify application custody", () => holon.verifyChain());
13958
13971
  if (authorityVerified.valid !== true) throw new Error(`the private authority context failed replay verification: ${String(authorityVerified.error ?? "unknown")}`);
@@ -14042,7 +14055,7 @@ async function nomosInternalOpenGeneratedApplication(options, bind, internals =
14042
14055
  } catch (cause) {
14043
14056
  await closeRealm().catch(() => {
14044
14057
  });
14045
- throw applicationError("Nomos could not finish preparing the signed-in business application.", "nomos.application.open_failed", cause);
14058
+ throw applicationOpenFailure(application, options.lawHash, cause);
14046
14059
  }
14047
14060
  }
14048
14061
  export {
@@ -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.29";
1668
- const NOMOS_FLUTTER_DEP = "^0.63.52";
1667
+ const NOMOS_CLIENT_DEP = "^0.64.32";
1668
+ const NOMOS_FLUTTER_DEP = "^0.63.55";
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).