@githolon/dsl 0.101.6 → 0.102.0

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 (120) hide show
  1. package/dart/CHANGELOG.md +13 -0
  2. package/dart/lib/nomos_client.dart +3 -52
  3. package/dart/lib/src/dev_cloud.dart +5 -0
  4. package/dart/lib/src/home.dart +10 -15
  5. package/dart/lib/src/nms_conformance_runtime.dart +12 -0
  6. package/dart/lib/src/nms_generated_runtime.dart +29 -0
  7. package/dart/lib/src/nms_test_environment.dart +8 -0
  8. package/dart/lib/src/node_runner_transport.dart +56 -18
  9. package/dart/lib/src/provider.dart +5 -1
  10. package/dart/lib/src/record_origin.dart +55 -0
  11. package/dart/lib/src/runner/node-entry.mjs +9105 -0
  12. package/dart/lib/src/runner/offline-install.mjs +4729 -0
  13. package/dart/lib/src/session_bound.dart +23 -10
  14. package/dart/lib/src/source_trust.dart +51 -0
  15. package/dart/lib/src/test_harness.dart +490 -58
  16. package/dart/lib/src/webview_bridge.dart +167 -58
  17. package/dart/lib/src/workspace_name.dart +7 -1
  18. package/dart/pubspec.lock +3 -3
  19. package/dart/pubspec.yaml +4 -2
  20. package/dart/test/acquire_session_credentials_test.dart +34 -17
  21. package/dart/test/acquire_session_test.dart +109 -24
  22. package/dart/test/adv_realm_interference_test.dart +227 -99
  23. package/dart/test/bundle_version_pairing_test.dart +1 -1
  24. package/dart/test/cloud_bound_topology_test.dart +1 -1
  25. package/dart/test/cluster_attested_test.dart +52 -35
  26. package/dart/test/cluster_births_test.dart +5 -2
  27. package/dart/test/cluster_device_keyed_acceptance_test.dart +5 -2
  28. package/dart/test/cluster_local_autosync_test.dart +5 -2
  29. package/dart/test/cluster_scale_test.dart +5 -2
  30. package/dart/test/compat_test.dart +1 -1
  31. package/dart/test/dlq_session_surface_test.dart +2 -1
  32. package/dart/test/errors_test.dart +1 -1
  33. package/dart/test/first_app_gauntlet_test.dart +78 -51
  34. package/dart/test/four_layer_nested_topology_test.dart +1 -1
  35. package/dart/test/harness_phase_timeout_test.dart +1 -1
  36. package/dart/test/home_parity_test.dart +9 -5
  37. package/dart/test/local_sync_inert_test.dart +22 -14
  38. package/dart/test/node_runner_transport_test.dart +9 -5
  39. package/dart/test/null_slot_test.dart +1 -1
  40. package/dart/test/parent_signer_recovery_test.dart +5 -2
  41. package/dart/test/schema_validation_test.dart +1 -1
  42. package/dart/test/sealing_client_test.dart +2 -1
  43. package/dart/test/session_bound_test.dart +92 -119
  44. package/dart/test/stale_bundle_test.dart +1 -1
  45. package/dart/test/test_harness_test.dart +77 -22
  46. package/dart/test/vo_read_typing_test.dart +32 -14
  47. package/dart/test/watch_after_offer_stall_test.dart +2 -1
  48. package/dart/test/webview_bridge_test.dart +17 -4
  49. package/dart/test/wire_test.dart +1 -1
  50. package/dart_types/CHANGELOG.md +8 -0
  51. package/dart_types/lib/nomos_types.dart +7 -6
  52. package/dart_types/lib/src/activity.dart +23 -13
  53. package/dart_types/lib/src/foreign_ref.dart +61 -112
  54. package/dart_types/lib/src/invitation.dart +96 -0
  55. package/dart_types/lib/src/nomos_ref.dart +97 -59
  56. package/dart_types/pubspec.yaml +1 -1
  57. package/dart_types/test/surfaced_test.dart +125 -19
  58. package/package.json +7 -3
  59. package/runtime/generated-application-host.js +8851 -0
  60. package/src/activity.ts +2 -2
  61. package/src/aggregate.ts +24 -1
  62. package/src/application_composition.ts +282 -0
  63. package/src/application_topology.ts +151 -0
  64. package/src/attested_core.ts +2 -2
  65. package/src/authoring_context.ts +9 -0
  66. package/src/birth_meter_ensure.ts +1 -1
  67. package/src/births.ts +53 -5
  68. package/src/build_package.ts +79 -71
  69. package/src/business_birth.ts +93 -10
  70. package/src/clear_directive.ts +3 -1
  71. package/src/codegen_dart.ts +369 -420
  72. package/src/codegen_dart_application.ts +1508 -0
  73. package/src/codegen_dart_client.ts +156 -95
  74. package/src/codegen_dart_scenario.ts +299 -0
  75. package/src/codegen_openapi.ts +8 -3
  76. package/src/codegen_proof.ts +1113 -1137
  77. package/src/codegen_provider_dart.ts +12 -1
  78. package/src/codegen_ts.ts +1176 -496
  79. package/src/compat_package_main.ts +22 -10
  80. package/src/compile_package_main.ts +1536 -337
  81. package/src/contract.ts +10 -4
  82. package/src/dart_barrel_guard.ts +5 -1
  83. package/src/describe_model.ts +13 -5
  84. package/src/directive.ts +244 -5
  85. package/src/engine_entry.ts +56 -13
  86. package/src/engine_javascript.ts +31 -0
  87. package/src/evolve_preview.ts +3 -12
  88. package/src/framework/application_home.ts +24 -10
  89. package/src/framework/capability.ts +15 -1
  90. package/src/framework/domain_lifecycle.ts +8 -0
  91. package/src/framework/framework_aggregates.ts +2 -2
  92. package/src/framework/genesis.ts +11 -1
  93. package/src/framework/home.ts +178 -75
  94. package/src/framework/impure_capability.ts +24 -7
  95. package/src/framework/relations.ts +13 -5
  96. package/src/framework/workspaces.ts +13 -12
  97. package/src/generated_client_names.ts +42 -3
  98. package/src/idof_lint.ts +65 -13
  99. package/src/index.ts +46 -12
  100. package/src/intent.ts +587 -0
  101. package/src/law_check.ts +64 -16
  102. package/src/precondition.ts +16 -4
  103. package/src/read_projection_namespace.ts +2 -7
  104. package/src/recipient.ts +33 -0
  105. package/src/relation_schema.ts +93 -0
  106. package/src/secondary_ensure.ts +11 -2
  107. package/src/shape_compat.ts +11 -1
  108. package/src/usd.ts +30 -8
  109. package/src/usd_layers.ts +447 -246
  110. package/src/usd_state.ts +1 -1
  111. package/src/value_object.ts +49 -13
  112. package/src/wire_encode.ts +124 -26
  113. package/src/workspace_sharing.ts +269 -0
  114. package/src/zod_introspection.ts +84 -0
  115. package/dart/example/nomos_secure_key_store.dart +0 -82
  116. package/dart/example/nomos_webview_transport.dart +0 -63
  117. package/dart/lib/nomos_headless.dart +0 -50
  118. package/dart/lib/testing.dart +0 -14
  119. package/dart/test/co2_product_gauntlet_test.dart +0 -244
  120. package/src/framework/identity.ts +0 -537
package/dart/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.64.0
2
+
3
+ - Generate one self-documenting application object: intent-shaped business actions at the root, typed
4
+ aggregate collections for reads and navigation, aggregate-specific conflict decisions, and verified
5
+ activity. The generated application is the application state; raw runtime clients are private.
6
+ - Let one intent atomically create and ensure any number of aggregate consequences. Every created record and
7
+ reference-bearing query uses `NomosRef<T>`; secondary ensures keep their aggregate identity through
8
+ compilation and admission.
9
+ - Generate restart-safe offline scenarios and ownership-aware proofs while keeping keys, certificates,
10
+ signers, warrants, topology and retry machinery outside the tenant API.
11
+ - Mark the generator-only runtime library internal, so tenant imports receive an analyzer refusal while
12
+ compiler-generated application code retains the sole intentional implementation bridge.
13
+
1
14
  ## 0.63.1
2
15
 
3
16
  - Make automatic sync a truthful client-owned lifecycle: local acceptance is durable, offline/restored
@@ -1,54 +1,5 @@
1
- // NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
2
- // remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
3
- // wasm32-wasip1 artifact {kernel · projection · embedded
4
- // QuickJS engine} on V8 + WASI-shim, byte-identical everywhere. V8 = portability; the one
5
- // wasm = determinism. No native, no wasmtime, no 2nd artifact, no domain-JS on bare V8.
6
- // If a file isn't this / hosting this / authoring for this / proving this — it's gone.
7
-
8
- /// Nomos 2 Dart frontend types.
1
+ /// Nomos runtime implementation package.
9
2
  ///
10
- /// - The hand-written kernel WIRE types (`Value`, `Field`/`WireField`, `Hlc`,
11
- /// `Op`, `FieldOp`, `Event`, `Schema`/`WireDriver`) — byte-compatible with
12
- /// serde_json. See `src/wire.dart`, `src/driver.dart`.
13
- /// - The ONE effectful write verb `offer(intent)` (`src/offer.dart`) + the typed
14
- /// reactive read engine `NomosReads` (`src/subscriptions.dart`).
15
- /// - The framework PRIMITIVES ONLY. The CODE-GENERATED per-domain types
16
- /// (aggregates + public intent payloads + enums + `watch…` read accessors) NO LONGER
17
- /// live here — they were extracted into the co-located TENANT package
18
- /// `co2_nomos_domains` (`ts_packages/co2-nomos-domains/dart/`), emitted there by
19
- /// `ts_packages/co2-nomos-domains/src/emit_dart.ts`. Tenant domains squatting in
20
- /// the framework package was the wrong topology; this barrel now exports ONLY the
21
- /// hand-written framework wire/offer/read/provider primitives. App code that
22
- /// wants the typed domain surface imports `package:co2_nomos_domains/co2_nomos_domains.dart`,
23
- /// which re-exports this framework barrel PLUS every generated domain.
3
+ /// Tenant applications import their generated `<Domain>Application` package. No generic runtime surface is
4
+ /// exported here; generated code uses a private implementation import under `src/`.
24
5
  library;
25
-
26
- // THE PURE-DATA CORE — the hand-written kernel wire types, the `offer(intent)` codec,
27
- // the tri-state `NomosSlot<T>`, `NomosReads`, schema validation, runtime aggregate
28
- // metadata, the data-only error/trace types, and the typed diagnostics moved to the
29
- // standalone `nomos_types` package (so generated per-domain TYPES files resolve against
30
- // it alone). Re-exported here so this barrel's public API is unchanged for consumers.
31
- export 'package:nomos_types/nomos_types.dart';
32
- // homeNameOf(subject) — the canonical home-workspace name (parity with @githolon/client + the law side).
33
- export 'src/home.dart';
34
- export 'src/workspace_name.dart';
35
- // THE WEBVIEW BRIDGE (app-binding boundary) — the async Dart runtime that drives the REAL githolon running
36
- // in a WebView, so the generated typed client never needs a `MemoryPersistence` fake.
37
- export 'src/webview_bridge.dart';
38
- // SESSION-BOUND CLIENTS (architecture/session_bound_clients.md) — the typed session/client
39
- // contract: NomosClientInterface (`XClient.interface`), session.assertCompatible(...), and the two
40
- // typed mismatch errors (DomainClientSessionMismatch / DomainNotInstalledForSession).
41
- export 'src/session_bound.dart';
42
- // The PROVIDER boundary (server-side capability-provider SDK runtime: TaskOutcome /
43
- // TaskSuccess / TaskFailure / TaskResult / TaskProvider / HostClock). The symmetric twin
44
- // of `offer.dart`; the generated per-task provider classes build on it.
45
- export 'src/provider.dart';
46
-
47
- // ── NO generated domains here ──────────────────────────────────────────────
48
- // The per-domain generated types moved to the tenant `co2_nomos_domains` package
49
- // (`ts_packages/co2-nomos-domains/dart/lib/src/generated/`). The tenant barrel
50
- // (`package:co2_nomos_domains/co2_nomos_domains.dart`) re-exports THIS framework
51
- // barrel plus every generated domain — so importing it gives the whole typed
52
- // surface (framework primitives + tenant domains) through one import. The colliding
53
- // positional enums (`StatusEnum`/`KindEnum`/…) and their `hide` clauses now live on
54
- // the tenant barrel's exports, not here.
@@ -14,6 +14,11 @@
14
14
  // final remote = await cloud.remoteHead('estate'); // inspect remote head + commit count
15
15
  // await cloud.stop();
16
16
  // ```
17
+ @internal
18
+ library;
19
+
20
+ import 'package:meta/meta.dart' show internal;
21
+
17
22
  import 'dart:async';
18
23
  import 'dart:convert';
19
24
  import 'dart:io';
@@ -1,20 +1,15 @@
1
+ @internal
2
+ library;
3
+
4
+ import 'package:meta/meta.dart' show internal;
5
+
1
6
  import 'dart:convert';
2
7
 
3
8
  import 'package:crypto/crypto.dart';
4
9
 
5
- /// The canonical home-workspace name for an identity SUBJECT (e.g. `user:<firebaseUid>`).
6
- ///
7
- /// BYTE-IDENTICAL to `@githolon/client`'s `homeNameOf` and the law side
8
- /// (`dsl/src/framework/home.ts` `HOME_NAME_PREFIX`). A home holon is named by its SUBJECT — never the raw
9
- /// uid and never an app-chosen workspace name — so the same principal always resolves the same home, on
10
- /// every peer and on the cloud. Use it directly as the `workspace`:
11
- ///
12
- /// ```dart
13
- /// NomosScope.home(application: 'my-app', authToken: idToken, ...)
14
- /// ```
15
- ///
16
- /// Formula: `home-` + the first 40 hex chars of `sha256(utf8(subject))`.
17
- String homeNameOf(String subject) {
18
- final hex = sha256.convert(utf8.encode(subject)).toString(); // lowercase hex
19
- return 'home-${hex.substring(0, 40)}';
10
+ /// Compiler/runtime-only receiving-group address. Generated application hosts call this; tenant code does
11
+ /// not choose or persist framework workspace names.
12
+ String nmsInternalReceivingGroupNameOf(String principal) {
13
+ final hex = sha256.convert(utf8.encode(principal)).toString();
14
+ return 'nomos-rg-${hex.substring(0, 40)}';
20
15
  }
@@ -0,0 +1,12 @@
1
+ // Framework conformance surface. Nomos' own tests use this to exercise transport and lifecycle machinery.
2
+ // Generated tenant tests use nms_test_environment.dart instead.
3
+ @internal
4
+ library;
5
+
6
+ import 'package:meta/meta.dart' show internal;
7
+
8
+ export 'dev_cloud.dart';
9
+ export 'node_runner_transport.dart';
10
+ export 'session_bound.dart';
11
+ export 'test_harness.dart';
12
+ export 'webview_bridge.dart';
@@ -0,0 +1,29 @@
1
+ /// Generator and framework-host implementation surface.
2
+ ///
3
+ /// Deliberately lives under `src/`: tenant code imports its generated application package instead.
4
+ @internal
5
+ library;
6
+
7
+ import 'package:meta/meta.dart' show internal;
8
+
9
+ export 'package:nomos_types/nomos_types.dart';
10
+ export 'package:nomos_types/src/nomos_ref.dart' show NmsInternalNomosRefs;
11
+ export 'package:nomos_types/src/invitation.dart'
12
+ show NmsInternalInvitations, NmsInternalRecipients, NmsInternalUsers;
13
+ export 'package:nomos_types/src/foreign_ref.dart'
14
+ show
15
+ NmsInternalForeignRefs,
16
+ NomosForeignReader,
17
+ NomosForeignWorkspaceReader,
18
+ ForeignResolveResult,
19
+ ForeignFound,
20
+ ForeignNotFound,
21
+ ForeignDenied,
22
+ ForeignUnreachable;
23
+ export 'home.dart';
24
+ export 'workspace_name.dart';
25
+ export 'webview_bridge.dart';
26
+ export 'session_bound.dart';
27
+ export 'provider.dart';
28
+ export 'record_origin.dart';
29
+ export 'source_trust.dart';
@@ -0,0 +1,8 @@
1
+ // Framework implementation for generated business scenarios. Not a tenant entrypoint.
2
+ @internal
3
+ library;
4
+
5
+ import 'package:meta/meta.dart' show internal;
6
+
7
+ export 'dev_cloud.dart' show NomosTestCloud;
8
+ export 'test_harness.dart' show NomosTestHarness;
@@ -7,10 +7,17 @@
7
7
  //
8
8
  // This file is a PURE RELAY: no orchestration, no op knowledge — the protocol implementation lives in
9
9
  // createWebviewRunner (shared with the WebView path) and the orchestration in index.mjs, same as every peer.
10
+ @internal
11
+ library;
12
+
13
+ import 'package:meta/meta.dart' show internal;
14
+
10
15
  import 'dart:async';
11
16
  import 'dart:convert';
12
17
  import 'dart:io';
13
18
 
19
+ import 'package:package_config/package_config.dart' show loadPackageConfigUri;
20
+
14
21
  import 'webview_bridge.dart' show BridgeTransport;
15
22
 
16
23
  class NodeRunnerTransport implements BridgeTransport {
@@ -21,10 +28,8 @@ class NodeRunnerTransport implements BridgeTransport {
21
28
  bool _disposed = false;
22
29
 
23
30
  NodeRunnerTransport._(this._proc, this._onDiagnostic) {
24
- _proc.stdout
25
- .transform(utf8.decoder)
26
- .transform(const LineSplitter())
27
- .listen((line) {
31
+ _proc.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen(
32
+ (line) {
28
33
  final s = line.trim();
29
34
  if (s.isEmpty) return;
30
35
  Object? decoded;
@@ -39,8 +44,8 @@ class NodeRunnerTransport implements BridgeTransport {
39
44
  }
40
45
  }, onDone: () {
41
46
  if (!_disposed && !_incoming.isClosed) {
42
- _incoming.addError(
43
- StateError('the nomos node runner exited unexpectedly'));
47
+ _incoming
48
+ .addError(StateError('the nomos node runner exited unexpectedly'));
44
49
  }
45
50
  });
46
51
  _proc.stderr
@@ -79,24 +84,57 @@ class NodeRunnerTransport implements BridgeTransport {
79
84
  node,
80
85
  [entryPath],
81
86
  environment: environment,
82
- workingDirectory: resolveFrom,
87
+ // [resolveFrom] locates a packaged runner when [entry] is omitted; it is not a runtime dependency of
88
+ // an explicit, self-contained entry. Reusing it as cwd made copied release tests fail with ENOENT even
89
+ // though the selected runner existed and was executable.
90
+ workingDirectory: entry == null ? resolveFrom : null,
83
91
  );
84
92
  return NodeRunnerTransport._(proc, onDiagnostic);
85
93
  }
86
94
 
87
95
  static Future<String> _resolveEntry(String node, String from) async {
88
- final r = await Process.run(
89
- node,
90
- ['-p', "require.resolve('@githolon/client/runner/node-entry.ts')"],
91
- workingDirectory: from,
92
- );
93
- final out = (r.stdout as String).trim();
94
- if (r.exitCode != 0 || out.isEmpty) {
95
- throw StateError(
96
- 'cannot resolve @githolon/client/runner/node-entry.ts from $from — '
97
- 'is @githolon/client installed (npm install)? stderr: ${r.stderr}');
96
+ String? packageConfigPath = Platform.packageConfig;
97
+ if (packageConfigPath == null) {
98
+ var directory = Directory(from).absolute;
99
+ while (true) {
100
+ final candidate = File(
101
+ '${directory.path}${Platform.pathSeparator}.dart_tool${Platform.pathSeparator}package_config.json',
102
+ );
103
+ if (candidate.existsSync()) {
104
+ packageConfigPath = candidate.uri.toString();
105
+ break;
106
+ }
107
+ final parent = directory.parent;
108
+ if (parent.path == directory.path) break;
109
+ directory = parent;
110
+ }
111
+ }
112
+ if (packageConfigPath != null) {
113
+ final packages = await loadPackageConfigUri(
114
+ Uri.base.resolve(packageConfigPath),
115
+ );
116
+ final bundled = packages.resolve(
117
+ Uri.parse('package:nomos_client/src/runner/node-entry.mjs'),
118
+ );
119
+ if (bundled != null && bundled.scheme == 'file') {
120
+ final path = bundled.toFilePath();
121
+ if (File(path).existsSync()) return path;
122
+ }
123
+ }
124
+ for (final entry in const [
125
+ '@githolon/client/runner/node-entry.mjs',
126
+ '@githolon/client/runner/node-entry.ts',
127
+ ]) {
128
+ final r = await Process.run(
129
+ node,
130
+ ['-p', "require.resolve('$entry')"],
131
+ workingDirectory: from,
132
+ );
133
+ final out = (r.stdout as String).trim();
134
+ if (r.exitCode == 0 && out.isNotEmpty) return out;
98
135
  }
99
- return out;
136
+ throw StateError('the Nomos release contains no bundled node runner and no '
137
+ '@githolon/client runner is installed; reinstall nomos_client');
100
138
  }
101
139
 
102
140
  @override
@@ -27,8 +27,11 @@
27
27
  /// This file is HAND-WRITTEN and domain-AGNOSTIC (declared ONCE, here): the generated
28
28
  /// per-task provider classes build on these interfaces, so the round-trip mechanism is
29
29
  /// proven once and reused for every capability.
30
+ @internal
30
31
  library;
31
32
 
33
+ import 'package:meta/meta.dart' show internal;
34
+
32
35
  import 'dart:convert';
33
36
 
34
37
  import 'package:nomos_types/nomos_types.dart' show NomosIntent;
@@ -122,7 +125,8 @@ abstract interface class TaskProvider<O, R> {
122
125
  /// [NomosIntent] ready for the ONE write path (`offer`). `now` stamps the
123
126
  /// terminal time. Decoding raw JSON happens HERE and only here; the handler the dev
124
127
  /// writes sees ONLY the typed [O] and returns ONLY a typed [TaskOutcome].
125
- NomosIntent handleObligation(String obligationPayloadJson, {required HostClock now});
128
+ NomosIntent handleObligation(String obligationPayloadJson,
129
+ {required HostClock now});
126
130
 
127
131
  /// Convenience: decode an Obligation payload from an already-parsed map (the host may have
128
132
  /// the row's `data` map in hand from a read). Same path as [handleObligation].
@@ -0,0 +1,55 @@
1
+ /// Private generated-client state tying a decoded business object to the
2
+ /// workspace record it came from.
3
+ ///
4
+ /// This deliberately lives under `src/` and is never exported by a tenant
5
+ /// application package. Generated navigation and write facades use it so a
6
+ /// business record can be passed to another business action without exposing
7
+ /// workspace coordinates to tenant code.
8
+ @internal
9
+ library;
10
+
11
+ import 'package:meta/meta.dart' show internal;
12
+
13
+ final class NmsInternalRecordOrigin {
14
+ const NmsInternalRecordOrigin({
15
+ required this.workspace,
16
+ required this.type,
17
+ required this.id,
18
+ });
19
+
20
+ final String workspace;
21
+ final String type;
22
+ final String id;
23
+ }
24
+
25
+ final class NmsInternalRecordOrigins {
26
+ NmsInternalRecordOrigins._();
27
+
28
+ static final Expando<NmsInternalRecordOrigin> _origins =
29
+ Expando<NmsInternalRecordOrigin>('nms-record-origin');
30
+
31
+ static T remember<T>(
32
+ T record, {
33
+ required String workspace,
34
+ required String type,
35
+ required String id,
36
+ }) {
37
+ _origins[record as Object] = NmsInternalRecordOrigin(
38
+ workspace: workspace,
39
+ type: type,
40
+ id: id,
41
+ );
42
+ return record;
43
+ }
44
+
45
+ static NmsInternalRecordOrigin require(Object record) {
46
+ final origin = _origins[record];
47
+ if (origin == null) {
48
+ throw StateError(
49
+ 'This business record was not read through its generated application. '
50
+ 'Read or follow the record first, then pass that returned record to the action.',
51
+ );
52
+ }
53
+ return origin;
54
+ }
55
+ }