@githolon/dsl 0.108.0 → 0.108.2

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.
Files changed (95) hide show
  1. package/dart/CHANGELOG.md +5 -0
  2. package/dart/lib/src/application_framework_calls.dart +299 -0
  3. package/dart/lib/src/generated_call.dart +96 -0
  4. package/dart/lib/src/nms_generated_runtime.dart +29 -0
  5. package/dart/lib/src/node_runner_transport.dart +77 -1
  6. package/dart/lib/src/result_usda.dart +487 -0
  7. package/dart/lib/src/runner/node-entry.mjs +6401 -2102
  8. package/dart/lib/src/runner/offline-install.mjs +1538 -163
  9. package/dart/lib/src/runtime_v2_gateway.dart +54 -0
  10. package/dart/lib/src/runtime_v2_transport.dart +117 -0
  11. package/dart/lib/src/session_bound.dart +7 -2
  12. package/dart/lib/src/test_harness.dart +193 -112
  13. package/dart/lib/src/webview_bridge.dart +2120 -569
  14. package/dart/pubspec.yaml +2 -2
  15. package/dart/test/acquire_session_credentials_test.dart +1 -1
  16. package/dart/test/acquire_session_test.dart +68 -14
  17. package/dart/test/adv_realm_interference_test.dart +6 -4
  18. package/dart/test/cluster_births_test.dart +11 -8
  19. package/dart/test/cluster_local_autosync_test.dart +1 -1
  20. package/dart/test/cluster_scale_test.dart +3 -2
  21. package/dart/test/dlq_session_surface_test.dart +52 -35
  22. package/dart/test/first_app_gauntlet_test.dart +1 -1
  23. package/dart/test/local_sync_inert_test.dart +23 -26
  24. package/dart/test/offer_authentication_proof_test.dart +193 -0
  25. package/dart/test/result_usda_test.dart +49 -0
  26. package/dart/test/session_bound_test.dart +8 -11
  27. package/dart/test/stale_bundle_test.dart +18 -3
  28. package/dart/test/test_harness_test.dart +14 -27
  29. package/dart/test/webview_bridge_test.dart +504 -83
  30. package/dart_types/CHANGELOG.md +7 -0
  31. package/dart_types/lib/nomos_kernel_protocol.dart +3 -2
  32. package/dart_types/lib/src/custody.dart +64 -19
  33. package/dart_types/lib/src/local_work_rejected.dart +30 -45
  34. package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pb.dart +169 -0
  35. package/dart_types/lib/src/proto/nomos/custody/v1/snapshot.pbenum.dart +11 -0
  36. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +2021 -234
  37. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +175 -8
  38. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +8664 -0
  39. package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +369 -0
  40. package/dart_types/lib/src/surfaced.dart +30 -25
  41. package/dart_types/pubspec.yaml +1 -1
  42. package/dart_types/test/surfaced_test.dart +2 -1
  43. package/package.json +1 -1
  44. package/runtime/generated-application-host.js +5736 -2047
  45. package/src/authoring.ts +3 -2
  46. package/src/births.ts +21 -0
  47. package/src/build_package.ts +30 -0
  48. package/src/business_birth.ts +39 -35
  49. package/src/codegen_call_usda.ts +1111 -0
  50. package/src/codegen_dart.ts +207 -282
  51. package/src/codegen_dart_application.ts +195 -252
  52. package/src/codegen_dart_client.ts +1978 -593
  53. package/src/codegen_dart_framework_calls.ts +291 -0
  54. package/src/codegen_dart_scenario.ts +7 -0
  55. package/src/codegen_proof.ts +3 -4
  56. package/src/codegen_provider_dart.ts +21 -7
  57. package/src/codegen_query_usda.ts +214 -0
  58. package/src/codegen_result_usda.ts +685 -0
  59. package/src/codegen_ts.ts +3945 -1111
  60. package/src/compile_package_main.ts +360 -32
  61. package/src/directive.ts +19 -4
  62. package/src/engine_entry.ts +45 -4
  63. package/src/framework/application_home.ts +2 -0
  64. package/src/framework/auth_provider_law.ts +262 -20
  65. package/src/framework/home.ts +32 -28
  66. package/src/framework/owned_custody.ts +19 -11
  67. package/src/framework/owned_custody_value.ts +51 -0
  68. package/src/framework/relations.ts +57 -21
  69. package/src/framework/signing_identity.ts +34 -0
  70. package/src/framework/workspaces.ts +31 -9
  71. package/src/framework_call_definitions.ts +53 -0
  72. package/src/framework_read_definitions.ts +45 -0
  73. package/src/identity_frontier.ts +58 -0
  74. package/src/index.ts +20 -1
  75. package/src/intent.ts +216 -16
  76. package/src/law_check.ts +19 -1
  77. package/src/law_graph.ts +57 -8
  78. package/src/law_graph_usda.ts +73 -5
  79. package/src/law_value_type.ts +106 -19
  80. package/src/read.ts +47 -0
  81. package/src/read_projection_namespace.ts +7 -0
  82. package/src/shape_compat.ts +38 -39
  83. package/src/stable_ids.ts +37 -2
  84. package/src/stable_ids_for_module.ts +64 -4
  85. package/src/test_call_usda.ts +83 -0
  86. package/src/wire.ts +36 -2
  87. package/src/wire_encode.ts +45 -1
  88. package/src/workspace_sharing.ts +27 -10
  89. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbjson.dart +0 -6096
  90. package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbserver.dart +0 -50
  91. package/dart_types/lib/src/proto/nomos/kernel/v1/progress.pbjson.dart +0 -178
  92. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pb.dart +0 -828
  93. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbenum.dart +0 -465
  94. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbjson.dart +0 -573
  95. package/dart_types/lib/src/proto/nomos/runtime/v1/runtime.pbserver.dart +0 -50
package/src/authoring.ts CHANGED
@@ -36,6 +36,7 @@ import type { PrincipalEvidence } from "./principal_evidence.js";
36
36
  import type { Ports } from "./ctx.js";
37
37
  import { __qualifyAggregateType, writeTuple } from "./framework/relations.js";
38
38
  import { __registerEnsure } from "./attested_core.js";
39
+ import { OWNED_CUSTODY_PROBE, type OwnedCustody } from "./framework/owned_custody_value.js";
39
40
 
40
41
  // ── the per-dispatch authoring sink — library state the engine never sees (NOT a side channel out of
41
42
  // the sandbox; it is internal to the directive runtime, drained synchronously by `executeDirectiveToIntent`). ──
@@ -45,7 +46,7 @@ let authoringContext: {
45
46
  principalRaw: string;
46
47
  stamp: string;
47
48
  ownedKeySubject: string;
48
- ownedCustody?: string;
49
+ ownedCustody?: OwnedCustody;
49
50
  preMintedRecords: { type: string; id: string }[];
50
51
  } | undefined;
51
52
  /** Clear the sink before a plan runs (called by `executeDirectiveToIntent`). */
@@ -53,7 +54,7 @@ export function __resetAuthoring(
53
54
  ctx?: Partial<Pick<Ports, "principal">>,
54
55
  stamp = "0",
55
56
  ownedKeySubject = `key:${"0".repeat(64)}`,
56
- ownedCustody: string | null = "{\"nomosProbe\":true}",
57
+ ownedCustody: OwnedCustody | null = OWNED_CUSTODY_PROBE,
57
58
  preMintedRecords: readonly { type: string; id: string }[] = [],
58
59
  ): void {
59
60
  sink = [];
package/src/births.ts CHANGED
@@ -33,6 +33,20 @@ export interface BirthRecipe {
33
33
  readonly workspace: string;
34
34
  /** The genesis chain: the ordered steps the child runs through its OWN gate to validate itself from intent 0. */
35
35
  readonly genesisChain: unknown;
36
+ /** Target-owned roles granted at genesis to the cryptographically verified immediate parent workspace.
37
+ * Values are law constants; the kernel supplies the parent workspace id after verifying the birth. */
38
+ readonly parentWorkspaceRoles?: readonly WorkspaceRole[];
39
+ }
40
+
41
+ declare const WORKSPACE_ROLE: unique symbol;
42
+ export type WorkspaceRole = string & { readonly [WORKSPACE_ROLE]: true };
43
+
44
+ /** Name a target relation that a born workspace will grant to its verified immediate parent. */
45
+ export function workspaceRole<const Name extends string>(name: Name): Name & WorkspaceRole {
46
+ if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(name)) {
47
+ throw new Error(`workspaceRole: '${name}' is not a valid relation name`);
48
+ }
49
+ return name as Name & WorkspaceRole;
36
50
  }
37
51
 
38
52
  // ── the per-dispatch birth footprint — library state drained by `executeDirectiveToIntent` (mirrors the
@@ -89,6 +103,7 @@ export interface BusinessBirthDecl<
89
103
  readonly founderScope: string;
90
104
  /** Explicit policy inherited by the BORN workspace. Zero declares a leaf workspace. */
91
105
  readonly maxChildWorkspacesPerUser: number;
106
+ readonly parentWorkspaceRoles: readonly WorkspaceRole[];
92
107
  /** @internal Compiler-derived namespaces installed into the born workspace. The declaration owns
93
108
  * the value; this list only repeats that value wherever the composed law requires its own state. */
94
109
  __nomosBirthPolicyDomains?: readonly string[];
@@ -127,6 +142,10 @@ export interface BusinessBirthSpec<F extends Record<string, Field>> {
127
142
  readonly children: {
128
143
  readonly maxWorkspacesPerUser: number;
129
144
  };
145
+ /** Roles the born workspace grants to the verified immediate parent workspace at genesis. */
146
+ readonly parentWorkspace?: {
147
+ readonly roles: readonly WorkspaceRole[];
148
+ };
130
149
  /** Additional atomic business initialization which belongs to the same birth. */
131
150
  readonly initialise?: (
132
151
  root: AggregateRef<F>,
@@ -194,6 +213,7 @@ export function birth<F extends Record<string, Field>>(
194
213
  "zero declares a leaf workspace and Nomos has no compiled fallback",
195
214
  );
196
215
  }
216
+ const parentWorkspaceRoles = [...new Set(spec.parentWorkspace?.roles ?? [])].sort();
197
217
  type Payload = BusinessBirthPayload<F>;
198
218
  const aggregateNoun = aggregate.id
199
219
  .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
@@ -221,6 +241,7 @@ export function birth<F extends Record<string, Field>>(
221
241
  founderRoles,
222
242
  founderScope,
223
243
  maxChildWorkspacesPerUser,
244
+ parentWorkspaceRoles,
224
245
  ...(spec.namespace !== undefined ? { namespace: spec.namespace } : {}),
225
246
  };
226
247
  const inDomain = (domain: string): BusinessBirthDecl<Payload, F> => {
@@ -574,6 +574,36 @@ export function composeDomainModule(spec: DomainModuleSpec): DomainModule {
574
574
  const queryById = new Map<string, QueryDecl>();
575
575
  for (const query of spec.queries ?? []) queryById.set(query.id, query);
576
576
  const queries = [...queryById.values()];
577
+ // A directive's `.reads(query)` retains the complete typed declaration. It is
578
+ // executable law, even when the query is intentionally absent from the
579
+ // tenant's presentation exports. Keep the named composer equivalent to the
580
+ // package compiler: seat each captured read once and mark compiler-carried
581
+ // declarations private rather than making test/client code invent a second
582
+ // query list.
583
+ for (const directive of directives) {
584
+ for (const declared of directive.declaredQueryReads ?? []) {
585
+ const existing = queryById.get(declared.id);
586
+ if (existing !== undefined) {
587
+ if (
588
+ existing.returns !== declared.returns ||
589
+ JSON.stringify(existing.key) !== JSON.stringify(declared.key)
590
+ ) {
591
+ throw new Error(
592
+ `domain '${domain}': captured read '${declared.id}' has conflicting declarations ` +
593
+ `(exported ${existing.returns}[${existing.key.join(",")}], directive ` +
594
+ `${directive.id} ${declared.returns}[${declared.key.join(",")}])`,
595
+ );
596
+ }
597
+ continue;
598
+ }
599
+ const internal = {
600
+ ...declared,
601
+ businessBirthInternal: true as const,
602
+ } as QueryDecl;
603
+ queries.push(internal);
604
+ queryById.set(internal.id, internal);
605
+ }
606
+ }
577
607
  for (const policy of applicationLanguage?.workspaceSharing ?? []) {
578
608
  if (!queries.some((candidate) => candidate.id === policy.invitationLaw.pendingByRecipient.id)) {
579
609
  queries.push(policy.invitationLaw.pendingByRecipient);
@@ -1,7 +1,14 @@
1
1
  // NOMOS — one business birth at the tenant surface; compute-science mechanics lower here.
2
2
 
3
3
  import { z } from "zod";
4
- import { BUSINESS_BIRTH_SEED_PAYLOAD_FIELD, OWNED_READ_RELATION } from "./aggregate.js";
4
+ import {
5
+ BUSINESS_BIRTH_SEED_PAYLOAD_FIELD,
6
+ OWNED_CUSTODY_PAYLOAD_FIELD,
7
+ OWNED_KEY_PAYLOAD_FIELD,
8
+ OWNED_PREMINTED_RECORDS_PAYLOAD_FIELD,
9
+ OWNED_READ_RELATION,
10
+ } from "./aggregate.js";
11
+ import { OwnedCustodyValue } from "./framework/owned_custody_value.js";
5
12
  import { ensure } from "./authoring.js";
6
13
  import { directive, type Directive } from "./directive.js";
7
14
  import {
@@ -11,12 +18,14 @@ import {
11
18
  type BusinessBirthDecl,
12
19
  type ParentAttestedBirthMarker,
13
20
  } from "./births.js";
14
- import { readFrameworkDeclared } from "./read.js";
15
21
  import type { Field } from "./fields.js";
16
22
  import {
17
23
  AuthProvider,
18
24
  authProvider,
25
+ authProviderCertificates,
26
+ authProviderKeys,
19
27
  authProviderSeedBeforeWarrant,
28
+ readAuthProviderVerifyingConfiguration,
20
29
  seedAuthProvider,
21
30
  setAuthProvider,
22
31
  } from "./framework/auth_provider_law.js";
@@ -90,6 +99,7 @@ export interface BusinessBirthMetadata {
90
99
  /** Private proof/lowering policy; omitted from every generated tenant payload. */
91
100
  readonly founderRoles: readonly string[];
92
101
  readonly founderScope: string;
102
+ readonly parentWorkspaceRoles: readonly import("./births.js").WorkspaceRole[];
93
103
  }
94
104
 
95
105
  export interface BusinessBirthDirective
@@ -179,8 +189,15 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
179
189
  principal: z.string().min(1),
180
190
  bornAt: z.string().min(1),
181
191
  });
192
+ const seedCarrierSchema = seedSchema.extend({
193
+ [OWNED_KEY_PAYLOAD_FIELD]: z.string().min(1).optional(),
194
+ [OWNED_CUSTODY_PAYLOAD_FIELD]: OwnedCustodyValue.zod.optional(),
195
+ [OWNED_PREMINTED_RECORDS_PAYLOAD_FIELD]: z
196
+ .array(z.object({ type: z.string().min(1), id: z.string().min(1) }))
197
+ .optional(),
198
+ });
182
199
  const parentSchema = seedSchema.extend({
183
- ...(encryptedBirth ? { [BUSINESS_BIRTH_SEED_PAYLOAD_FIELD]: z.string().min(1) } : {}),
200
+ ...(encryptedBirth ? { [BUSINESS_BIRTH_SEED_PAYLOAD_FIELD]: seedCarrierSchema } : {}),
184
201
  });
185
202
 
186
203
  const seedBase = directive(seedId)
@@ -240,22 +257,13 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
240
257
  const child = workspaceNameForKey(namespace, String(decl.key(p as P)));
241
258
  const childPayload = { ...(p as Record<string, unknown>) };
242
259
  if (encryptedBirth) {
243
- const rawSeed = childPayload[BUSINESS_BIRTH_SEED_PAYLOAD_FIELD];
244
- if (typeof rawSeed !== "string") {
260
+ const sealedSeed = childPayload[BUSINESS_BIRTH_SEED_PAYLOAD_FIELD];
261
+ if (sealedSeed === null || typeof sealedSeed !== "object" || Array.isArray(sealedSeed)) {
245
262
  throw new Error(
246
263
  `birth(${decl.aggregate.id}): Nomos did not carry the internally sealed genesis facts`,
247
264
  );
248
265
  }
249
- let sealed: unknown;
250
- try {
251
- sealed = JSON.parse(rawSeed);
252
- } catch {
253
- throw new Error(`birth(${decl.aggregate.id}): the internally sealed genesis facts are malformed`);
254
- }
255
- if (sealed === null || typeof sealed !== "object" || Array.isArray(sealed)) {
256
- throw new Error(`birth(${decl.aggregate.id}): the internally sealed genesis facts are malformed`);
257
- }
258
- Object.assign(childPayload, sealed as Record<string, unknown>);
266
+ Object.assign(childPayload, sealedSeed as Record<string, unknown>);
259
267
  }
260
268
  delete childPayload[BUSINESS_BIRTH_SEED_PAYLOAD_FIELD];
261
269
  const chain: Array<Record<string, unknown>> = [
@@ -287,39 +295,32 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
287
295
  },
288
296
  ];
289
297
 
290
- const apRows = readFrameworkDeclared<Array<Record<string, unknown>>>("authProvider", { scope: "platform" });
291
- const apRaw = Array.isArray(apRows) && apRows.length > 0 ? apRows[0] : undefined;
292
- const ap = (apRaw && typeof apRaw === "object" && typeof (apRaw as { data?: unknown }).data === "object"
293
- ? (apRaw as { data: Record<string, unknown> }).data
294
- : apRaw) as Record<string, unknown> | undefined;
295
- const apStr = (k: string): string | undefined => {
296
- const v = ap?.[k];
297
- return typeof v === "string" && v.length > 0 ? v : undefined;
298
- };
299
- if (apStr("issuer")) {
298
+ const inheritedProvider = readAuthProviderVerifyingConfiguration();
299
+ if (inheritedProvider !== undefined) {
300
300
  chain.push({
301
301
  domain,
302
302
  directiveId: "seedAuthProvider",
303
303
  actor: founder,
304
304
  payload: {
305
- issuer: apStr("issuer"),
306
- jwksUrl: apStr("jwksUrl") ?? apStr("issuer"),
307
- ...(apStr("keys") ? { keys: apStr("keys") } : {}),
308
- ...(apStr("audience") ? { audience: apStr("audience") } : {}),
309
- ...(apStr("principalClaim") ? { principalClaim: apStr("principalClaim") } : {}),
310
- ...(apStr("rootCert") ? { rootCert: apStr("rootCert") } : {}),
311
- ...(apStr("deviceBindingClaim") ? { deviceBindingClaim: apStr("deviceBindingClaim") } : {}),
312
- ...(apStr("requireDeviceBinding") ? { requireDeviceBinding: apStr("requireDeviceBinding") } : {}),
313
- label: apStr("label") ?? "inherited-from-parent",
305
+ ...inheritedProvider,
306
+ label: "inherited-from-parent",
314
307
  setBy: founder,
315
308
  setAt: 1,
316
309
  },
317
310
  });
318
311
  }
319
- birth({ workspace: child, genesisChain: chain });
312
+ birth({
313
+ workspace: child,
314
+ genesisChain: chain,
315
+ ...(decl.parentWorkspaceRoles.length > 0
316
+ ? { parentWorkspaceRoles: decl.parentWorkspaceRoles }
317
+ : {}),
318
+ });
320
319
  return [];
321
320
  })
322
321
  .reads(authProvider)
322
+ .reads(authProviderKeys)
323
+ .reads(authProviderCertificates)
323
324
  .births();
324
325
 
325
326
  const metadata: BusinessBirthMetadata = {
@@ -340,6 +341,7 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
340
341
  ],
341
342
  founderRoles: decl.founderRoles,
342
343
  founderScope: decl.founderScope,
344
+ parentWorkspaceRoles: decl.parentWorkspaceRoles,
343
345
  };
344
346
  const parent = {
345
347
  ...birthBase,
@@ -376,6 +378,8 @@ function lowerOne<P extends Record<string, unknown>, F extends Record<string, Fi
376
378
  __nomos_authProviderSeedBeforeWarrant: internalSurface(authProviderSeedBeforeWarrant),
377
379
  __nomos_setAuthProvider: internalDirective(setAuthProvider),
378
380
  __nomos_authProvider: internalSurface(authProvider),
381
+ __nomos_authProviderKeys: internalSurface(authProviderKeys),
382
+ __nomos_authProviderCertificates: internalSurface(authProviderCertificates),
379
383
  // Obscure framework export keys minimize accidental tenant collisions. Stable law ids remain the real
380
384
  // identity; the generic composition seam rejects a tenant-owned declaration with any of those ids.
381
385
  __nomos_NomosBirthRecord: internalSurface(NomosBirthRecord),