@githolon/dsl 0.108.6 → 0.110.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.
- package/assets/operation-contract.wasm +0 -0
- package/check_package.mjs +12 -15
- package/compile_package.mjs +17 -18
- package/compile_proof.mjs +16 -1
- package/dart/CHANGELOG.md +76 -1
- package/dart/README.md +25 -2
- package/dart/lib/src/admission_decision.dart +41 -0
- package/dart/lib/src/application_framework_calls.dart +52 -2
- package/dart/lib/src/application_model_adoption.dart +187 -0
- package/dart/lib/src/application_status.dart +73 -0
- package/dart/lib/src/console_enrolment.dart +271 -0
- package/dart/lib/src/console_http_io.dart +26 -0
- package/dart/lib/src/console_http_stub.dart +7 -0
- package/dart/lib/src/dev_cloud.dart +69 -22
- package/dart/lib/src/generated_call.dart +83 -23
- package/dart/lib/src/kernel_primitives.dart +119 -0
- package/dart/lib/src/nms_conformance_runtime.dart +1 -1
- package/dart/lib/src/nms_generated_runtime.dart +32 -10
- package/dart/lib/src/nms_test_environment.dart +1 -1
- package/dart/lib/src/node_runner_transport.dart +41 -46
- package/dart/lib/src/observed_session_directory.dart +70 -0
- package/dart/lib/src/operation_receipts.dart +112 -0
- package/dart/lib/src/peer_application_streams.dart +103 -0
- package/dart/lib/src/reception/dart_reception.dart +4280 -0
- package/dart/lib/src/reception/event_desk.dart +211 -0
- package/dart/lib/src/reception/extremum_read.dart +46 -0
- package/dart/lib/src/reception/local_copies.dart +371 -0
- package/dart/lib/src/reception/peer_office_connection.dart +11 -0
- package/dart/lib/src/reception/progress_desk.dart +267 -0
- package/dart/lib/src/reception/reception_contract.dart +11 -0
- package/dart/lib/src/reception/reception_session.dart +284 -0
- package/dart/lib/src/reception/sync_diagnostics.dart +26 -0
- package/dart/lib/src/reception/workspace_preparation_report.dart +126 -0
- package/dart/lib/src/replica_readiness.dart +123 -0
- package/dart/lib/src/runner/node-entry.mjs +23905 -15774
- package/dart/lib/src/runtime_v2_gateway.dart +56 -3
- package/dart/lib/src/runtime_v2_transport.dart +544 -3
- package/dart/lib/src/session_bound.dart +200 -311
- package/dart/lib/src/signing_identity_kernel.dart +84 -0
- package/dart/lib/src/sync_status_projection.dart +548 -0
- package/dart/lib/src/sync_status_reducer.dart +170 -0
- package/dart/lib/src/test_harness.dart +809 -1153
- package/dart/lib/src/testing/test_custody.dart +66 -0
- package/dart/lib/src/testing/test_peer.dart +328 -0
- package/dart/lib/src/typed_watch_registry.dart +169 -0
- package/dart/lib/src/workspace_open_progress.dart +27 -0
- package/dart/pubspec.lock +24 -1
- package/dart/pubspec.yaml +7 -2
- package/dart/pubspec_overrides.yaml +2 -0
- package/dart/test/admission_decision_test.dart +48 -0
- package/dart/test/background_model_adoption_test.dart +228 -0
- package/dart/test/bundle_version_pairing_test.dart +4 -4
- package/dart/test/child_authentication_repair_test.dart +359 -0
- package/dart/test/cloud_bound_local_shell_test.dart +119 -0
- package/dart/test/console_enrolment_refusal_test.dart +52 -0
- package/dart/test/console_enrolment_test.dart +227 -0
- package/dart/test/errors_test.dart +5 -5
- package/dart/test/event_plane_seam_test.dart +50 -164
- package/dart/test/extremum_read_test.dart +58 -0
- package/dart/test/fixtures/wedge/wedge-entry.mjs +3 -21
- package/dart/test/generated_query_test.dart +32 -0
- package/dart/test/harness_phase_timeout_test.dart +18 -23
- package/dart/test/kernel_author_after_read_test.dart +242 -0
- package/dart/test/kernel_fence_test.dart +137 -0
- package/dart/test/local_copies_test.dart +222 -0
- package/dart/test/model_adoption_test.dart +198 -0
- package/dart/test/node_peer_local_custody_test.dart +153 -0
- package/dart/test/offer_authentication_proof_test.dart +352 -52
- package/dart/test/operation_compatibility_test.dart +151 -0
- package/dart/test/platform_credential_effect_test.dart +386 -0
- package/dart/test/receiving_group_open_test.dart +213 -0
- package/dart/test/reception/workspace_preparation_report_test.dart +103 -0
- package/dart/test/reception_span_trace_test.dart +23 -0
- package/dart/test/replica_readiness_test.dart +156 -0
- package/dart/test/runtime_projections_test.dart +92 -0
- package/dart/test/runtime_v2_gateway_test.dart +131 -0
- package/dart/test/signing_identity_kernel_test.dart +75 -0
- package/dart/test/sync_status_preparation_report_test.dart +29 -0
- package/dart/test/sync_status_reducer_test.dart +419 -0
- package/dart/test/test_harness_test.dart +71 -95
- package/dart/test/typed_query_watch_test.dart +170 -0
- package/dart/test/typed_watch_registry_test.dart +249 -0
- package/dart_lints/README.md +18 -0
- package/dart_lints/lib/nomos_lints.dart +70 -0
- package/dart_lints/pubspec.lock +580 -0
- package/dart_lints/pubspec.yaml +12 -0
- package/dart_lints/test/reference_identity_test.dart +75 -0
- package/dart_types/CHANGELOG.md +18 -0
- package/dart_types/lib/nomos_kernel_protocol.dart +21 -1
- package/dart_types/lib/nomos_types.dart +9 -1
- package/dart_types/lib/src/admission_decision.dart +37 -0
- package/dart_types/lib/src/aggregate_meta.dart +1 -1
- package/dart_types/lib/src/approved_model.dart +65 -0
- package/dart_types/lib/src/custody.dart +10 -18
- package/dart_types/lib/src/error_info.dart +4 -4
- package/dart_types/lib/src/errors.dart +29 -29
- package/dart_types/lib/src/foreign_ref.dart +62 -33
- package/dart_types/lib/src/local_work_rejected.dart +3 -3
- package/dart_types/lib/src/nomos_ref.dart +3 -1
- package/dart_types/lib/src/principal.dart +2 -2
- package/dart_types/lib/src/proto/google/protobuf/any.pb.dart +163 -0
- package/dart_types/lib/src/proto/google/protobuf/any.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pb.dart +137 -0
- package/dart_types/lib/src/proto/nomos/discovery/v1/workspace_placement.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pb.dart +20721 -10433
- package/dart_types/lib/src/proto/nomos/kernel/v1/kernel.pbenum.dart +555 -27
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pb.dart +387 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_desk.pbenum.dart +46 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pb.dart +295 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/application_readiness_desk.pbenum.dart +139 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pb.dart +269 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/authentication_desk.pbenum.dart +103 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pb.dart +417 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/compatibility_desk.pbenum.dart +62 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pb.dart +9968 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/correspondence_desk.pbenum.dart +133 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pb.dart +204 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/credentials_desk.pbenum.dart +54 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pb.dart +1550 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/custody_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pb.dart +710 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/framework.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pb.dart +845 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/identity_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pb.dart +198 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/interaction_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pb.dart +369 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/law_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pb.dart +609 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/maintenance_desk.pbenum.dart +65 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pb.dart +358 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/model_adoption_desk.pbenum.dart +100 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pb.dart +2231 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/observability_desk.pbenum.dart +271 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pb.dart +1286 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/placement_desk.pbenum.dart +11 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pb.dart +636 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/receiving_group_desk.pbenum.dart +116 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pb.dart +1637 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/records_desk.pbenum.dart +175 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pb.dart +1269 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/recovery_desk.pbenum.dart +129 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pb.dart +2782 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/residency_desk.pbenum.dart +97 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pb.dart +2232 -8627
- package/dart_types/lib/src/proto/nomos/runtime/v2/runtime.pbenum.dart +0 -358
- package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pb.dart +1639 -0
- package/dart_types/lib/src/proto/nomos/runtime/v2/sealing_desk.pbenum.dart +46 -0
- package/dart_types/lib/src/runtime_outcome.dart +133 -0
- package/dart_types/lib/src/subscriptions.dart +116 -23
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/extremum_subscriptions_test.dart +40 -0
- package/dart_types/test/foreign_ref_resolution_test.dart +75 -0
- package/dart_types/test/nomos_ref_address_test.dart +25 -0
- package/dart_types/test/ordered_subscriptions_test.dart +34 -0
- package/operation_contract_check.mjs +24 -0
- package/package.json +11 -6
- package/src/aggregate.ts +70 -10
- package/src/application_topology.ts +18 -11
- package/src/attested.ts +3 -0
- package/src/attested_core.ts +46 -3
- package/src/birth_meter_ensure.ts +19 -7
- package/src/births.ts +29 -4
- package/src/build_package.ts +140 -13
- package/src/business_birth.ts +181 -4
- package/src/codegen_call_proto.ts +1274 -0
- package/src/codegen_call_usda.ts +49 -6
- package/src/codegen_dart.ts +79 -44
- package/src/codegen_dart_client.ts +458 -800
- package/src/{codegen_dart_application.ts → codegen_dart_facade.ts} +331 -582
- package/src/codegen_dart_framework_calls.ts +320 -37
- package/src/codegen_dart_indexed_variant.ts +159 -0
- package/src/codegen_dart_scenario.ts +42 -13
- package/src/codegen_proof.ts +3 -3
- package/src/codegen_provider_dart.ts +5 -0
- package/src/codegen_query_proto.ts +158 -0
- package/src/codegen_refusal.ts +189 -0
- package/src/codegen_result_proto.ts +931 -0
- package/src/codegen_result_usda.ts +4 -0
- package/src/codegen_ts.ts +464 -616
- package/src/codegen_workspace_access.ts +105 -0
- package/src/compatibility_graph.ts +759 -0
- package/src/compatibility_usda.ts +264 -0
- package/src/compile_package_main.ts +2083 -1248
- package/src/custody_placement.ts +156 -0
- package/src/custody_placement_usda.ts +91 -0
- package/src/decl_shapes.ts +21 -2
- package/src/describe_model.ts +1 -0
- package/src/directive.ts +59 -2
- package/src/drivers.ts +51 -0
- package/src/engine_entry.ts +52 -8
- package/src/evolve_preview.ts +11 -4
- package/src/exists.ts +2 -0
- package/src/fields.ts +75 -11
- package/src/flow_gate.ts +2 -1
- package/src/framework/application_home.ts +170 -18
- package/src/framework/attested_receipts.ts +8 -3
- package/src/framework/auth_provider_law.ts +169 -9
- package/src/framework/birth_certificate_law.ts +4 -0
- package/src/framework/capability.ts +34 -3
- package/src/framework/child_authentication.ts +346 -0
- package/src/framework/console_governance.ts +295 -0
- package/src/framework/delegated_roles.ts +301 -0
- package/src/framework/domain_lifecycle.ts +26 -13
- package/src/framework/founding_genesis.ts +193 -0
- package/src/framework/framework_aggregates.ts +1 -1
- package/src/framework/genesis.ts +6 -1
- package/src/framework/governance_relations.ts +19 -0
- package/src/framework/home.ts +5 -734
- package/src/framework/legacy/child_auth_provider_epoch.ts +73 -0
- package/src/framework/model_authority_repair.ts +116 -0
- package/src/framework/model_authority_seed.ts +185 -0
- package/src/framework/model_transition.ts +211 -0
- package/src/framework/owned_custody.ts +1 -1
- package/src/framework/principal_enrollment.ts +302 -0
- package/src/framework/receiving_group.ts +857 -0
- package/src/framework/receiving_group_recovery.ts +314 -0
- package/src/framework/relations.ts +4 -8
- package/src/framework/signing_identity.ts +242 -95
- package/src/framework/source_roster.ts +11 -5
- package/src/framework/workspace_access.ts +149 -0
- package/src/framework/workspace_invariant.ts +73 -52
- package/src/framework/workspaces.ts +407 -40
- package/src/framework_call_definitions.ts +32 -3
- package/src/generated_client_bundle_boundary.ts +97 -0
- package/src/generated_client_names.ts +1 -0
- package/src/identity_usda.ts +27 -0
- package/src/index.ts +183 -12
- package/src/indexed_variant.ts +83 -0
- package/src/intent.ts +173 -45
- package/src/law_check.ts +8 -5
- package/src/law_dependency_index.ts +231 -0
- package/src/law_graph.ts +508 -71
- package/src/law_graph_usda.ts +170 -24
- package/src/law_identity.ts +119 -81
- package/src/law_source_map.ts +4 -1
- package/src/law_units.ts +498 -0
- package/src/law_value_type.ts +7 -3
- package/src/member_authentication.ts +302 -0
- package/src/null_meta.ts +1 -1
- package/src/openusd_compiled_layer.ts +132 -0
- package/src/operation_contract_check.ts +31 -0
- package/src/ordered_read.ts +2 -1
- package/src/package_config.ts +33 -12
- package/src/package_dependencies.ts +1 -0
- package/src/plan_source_slice.ts +30 -1
- package/src/protobuf_field_number.ts +36 -0
- package/src/provenance_wire.ts +6 -0
- package/src/query.ts +2 -1
- package/src/read.ts +50 -0
- package/src/relation.ts +4 -1
- package/src/relation_schema.ts +15 -2
- package/src/report.ts +2 -2
- package/src/sqlite_computation_bundle.ts +78 -0
- package/src/sqlite_computed.ts +102 -0
- package/src/sqlite_counts.ts +154 -0
- package/src/sqlite_layout.ts +823 -0
- package/src/sqlite_reads.ts +275 -0
- package/src/sqlite_samples.ts +185 -0
- package/src/stable_id_identity_bridge.ts +1 -1
- package/src/stable_ids_for_module.ts +16 -4
- package/src/test_call_usda.ts +6 -6
- package/src/usda_relationship_integrity.ts +20 -3
- package/src/usda_text.ts +21 -1
- package/src/value_object.ts +81 -11
- package/src/wire.ts +22 -0
- package/src/wire_encode.ts +227 -20
- package/src/workspace_sharding.ts +15 -6
- package/src/workspace_sharing.ts +51 -49
- package/src/zod_introspection.ts +2 -0
- package/compat_package.mjs +0 -46
- package/dart/lib/src/home.dart +0 -15
- package/dart/lib/src/runner/offline-install.mjs +0 -15367
- package/dart/lib/src/source_trust.dart +0 -51
- package/dart/lib/src/webview_bridge.dart +0 -6540
- package/dart/lib/src/workspace_name.dart +0 -30
- package/dart/test/acquire_session_credentials_test.dart +0 -150
- package/dart/test/acquire_session_test.dart +0 -534
- package/dart/test/adv_realm_interference_test.dart +0 -600
- package/dart/test/cloud_bound_topology_test.dart +0 -168
- package/dart/test/cluster_births_test.dart +0 -202
- package/dart/test/cluster_device_keyed_acceptance_test.dart +0 -105
- package/dart/test/cluster_local_autosync_test.dart +0 -123
- package/dart/test/cluster_scale_test.dart +0 -122
- package/dart/test/compat_test.dart +0 -61
- package/dart/test/dlq_session_surface_test.dart +0 -222
- package/dart/test/first_app_gauntlet_test.dart +0 -386
- package/dart/test/fixtures/wedge/fake-install.mjs +0 -11
- package/dart/test/four_layer_nested_topology_test.dart +0 -290
- package/dart/test/home_parity_test.dart +0 -13
- package/dart/test/local_sync_inert_test.dart +0 -107
- package/dart/test/node_runner_transport_test.dart +0 -78
- package/dart/test/parent_signer_recovery_test.dart +0 -155
- package/dart/test/residency_refusal_test.dart +0 -49
- package/dart/test/sealing_client_test.dart +0 -181
- package/dart/test/session_bound_test.dart +0 -285
- package/dart/test/stale_bundle_test.dart +0 -80
- package/dart/test/vo_read_typing_test.dart +0 -131
- package/dart/test/watch_after_offer_stall_test.dart +0 -100
- package/dart/test/webview_bridge_test.dart +0 -1930
- package/dart/test/workspace_name_test.dart +0 -24
- package/runtime/generated-application-host.js +0 -22860
- package/src/codegen_query_usda.ts +0 -214
- package/src/compat_manifest.ts +0 -26
- package/src/compat_package_main.ts +0 -224
- package/src/shape_compat.ts +0 -352
- package/src/usd_state.ts +0 -505
package/src/intent.ts
CHANGED
|
@@ -20,6 +20,11 @@ import type { PlannedOp } from "./ops.js";
|
|
|
20
20
|
import type { Field } from "./fields.js";
|
|
21
21
|
import type { AggregateHandle } from "./aggregate.js";
|
|
22
22
|
import type { QueryDecl } from "./query.js";
|
|
23
|
+
import {
|
|
24
|
+
enrolledDeviceAuthentication,
|
|
25
|
+
MemberAuthenticationKind,
|
|
26
|
+
type MemberAuthentication,
|
|
27
|
+
} from "./member_authentication.js";
|
|
23
28
|
import type {
|
|
24
29
|
InvariantReadBinding,
|
|
25
30
|
InvariantReadId,
|
|
@@ -53,12 +58,47 @@ export interface IntentStep<I = unknown, P = unknown> {
|
|
|
53
58
|
* the target workspace address; the nominal target directive and payload type remain sealed by the
|
|
54
59
|
* compiled source graph and its generated USDA encoder. */
|
|
55
60
|
export interface WorkspaceEffectStep<I = unknown, P = unknown> {
|
|
61
|
+
/** A source-local name for an effect that later consequences depend on. */
|
|
62
|
+
readonly key?: string;
|
|
63
|
+
/** Named predecessors from this same atomic consequence set, in declaration order. */
|
|
64
|
+
readonly after?: readonly string[];
|
|
56
65
|
readonly target: Directive<P>;
|
|
57
66
|
readonly destination:
|
|
58
|
-
| { readonly kind: "workspace"; readonly address: (facts: I) => string }
|
|
67
|
+
| { readonly kind: "workspace"; readonly address: (facts: I, ctx: Ports) => string }
|
|
59
68
|
| { readonly kind: "verifiedParent" }
|
|
60
69
|
| { readonly kind: "verifiedSource" };
|
|
61
|
-
readonly payload: (facts: I) => P;
|
|
70
|
+
readonly payload: (facts: I, ctx: Ports) => P;
|
|
71
|
+
/** Conditional correspondence is still captured source law, not host routing. */
|
|
72
|
+
readonly when?: (facts: I, ctx: Ports) => boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Validate the source-local dependency graph independently of payloads and host state. */
|
|
76
|
+
export function validateWorkspaceEffectDependencies(
|
|
77
|
+
effects: readonly Pick<WorkspaceEffectStep, "key" | "after">[],
|
|
78
|
+
): void {
|
|
79
|
+
const preceding = new Set<string>();
|
|
80
|
+
for (const effect of effects) {
|
|
81
|
+
if (effect.after !== undefined && !Array.isArray(effect.after)) {
|
|
82
|
+
throw new Error("Workspace effect dependencies must be an array of earlier effect names");
|
|
83
|
+
}
|
|
84
|
+
if (effect.key !== undefined && (
|
|
85
|
+
typeof effect.key !== "string" || effect.key.trim().length === 0 ||
|
|
86
|
+
effect.key !== effect.key.trim() || preceding.has(effect.key)
|
|
87
|
+
)) {
|
|
88
|
+
throw new Error("Workspace effect keys must be non-empty, unique names without surrounding whitespace");
|
|
89
|
+
}
|
|
90
|
+
const seen = new Set<string>();
|
|
91
|
+
for (const key of effect.after ?? []) {
|
|
92
|
+
if (!preceding.has(key)) {
|
|
93
|
+
throw new Error(`Workspace effect dependency '${key}' must name an earlier effect in the same atomic intent`);
|
|
94
|
+
}
|
|
95
|
+
if (seen.has(key)) {
|
|
96
|
+
throw new Error(`Workspace effect dependency '${key}' is repeated`);
|
|
97
|
+
}
|
|
98
|
+
seen.add(key);
|
|
99
|
+
}
|
|
100
|
+
if (effect.key !== undefined) preceding.add(effect.key);
|
|
101
|
+
}
|
|
62
102
|
}
|
|
63
103
|
|
|
64
104
|
const PAYLOAD_TRACE_PATH = Symbol("nomos.intent.payload-trace-path");
|
|
@@ -210,9 +250,6 @@ export interface BusinessIntent<I = unknown> extends Directive<I> {
|
|
|
210
250
|
) => void;
|
|
211
251
|
readonly steps: readonly IntentStep<I, any>[];
|
|
212
252
|
readonly workspaceEffects: readonly WorkspaceEffectStep<I, any>[];
|
|
213
|
-
/** Law-selected proof for this exact public offer. Omitted means the ordinary session proof
|
|
214
|
-
* posture. Tenant callers never choose this at invocation time. */
|
|
215
|
-
readonly offerAuthenticationProof?: "enrolledDevice";
|
|
216
253
|
/** Compiler-visible application lifecycle declaration. When opening a child of this aggregate
|
|
217
254
|
* type proves that its verifier/signer posture is stale, the generated parent application may
|
|
218
255
|
* invoke this exact nominal action on the already-authenticated parent. The action itself remains
|
|
@@ -234,7 +271,7 @@ export function authenticatesWithEnrolledDevice<I>(
|
|
|
234
271
|
): BusinessIntent<I> {
|
|
235
272
|
return Object.freeze({
|
|
236
273
|
...action,
|
|
237
|
-
|
|
274
|
+
authentication: enrolledDeviceAuthentication(),
|
|
238
275
|
});
|
|
239
276
|
}
|
|
240
277
|
|
|
@@ -248,14 +285,30 @@ export function repairsChildAuthenticationFor<I>(
|
|
|
248
285
|
child: AggregateHandle,
|
|
249
286
|
action: BusinessIntent<I>
|
|
250
287
|
): BusinessIntent<I> {
|
|
251
|
-
|
|
288
|
+
assertRepairsChildAuthentication(action, `repairsChildAuthenticationFor(${child.id})`);
|
|
289
|
+
return Object.freeze({
|
|
290
|
+
...action,
|
|
291
|
+
[CHILD_AUTHENTICATION_RECOVERY]: child.id,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** THE CHILD-AUTHENTICATION REPAIR GATE — the shape every repair must have, whether a tenant marks its
|
|
296
|
+
* own action per child kind ({@link repairsChildAuthenticationFor}) or the framework composes the one
|
|
297
|
+
* workspace-parameterised repair (`framework/child_authentication.ts`): the parent's enrolled device
|
|
298
|
+
* proves the author, the action writes nothing locally, and every effect addresses the exact child
|
|
299
|
+
* workspace named by its typed input. */
|
|
300
|
+
export function assertRepairsChildAuthentication<I>(
|
|
301
|
+
action: BusinessIntent<I>,
|
|
302
|
+
gate: string
|
|
303
|
+
): void {
|
|
304
|
+
if (action.authentication?.kind !== MemberAuthenticationKind.EnrolledDevice) {
|
|
252
305
|
throw new Error(
|
|
253
|
-
|
|
306
|
+
`${gate}: '${action.id}' must authenticate with the parent's enrolled device`
|
|
254
307
|
);
|
|
255
308
|
}
|
|
256
309
|
if (action.steps.length !== 0 || action.workspaceEffects.length === 0) {
|
|
257
310
|
throw new Error(
|
|
258
|
-
|
|
311
|
+
`${gate}: '${action.id}' must emit at least one child effect and make no parent-local write`
|
|
259
312
|
);
|
|
260
313
|
}
|
|
261
314
|
if (
|
|
@@ -264,13 +317,9 @@ export function repairsChildAuthenticationFor<I>(
|
|
|
264
317
|
)
|
|
265
318
|
) {
|
|
266
319
|
throw new Error(
|
|
267
|
-
|
|
320
|
+
`${gate}: '${action.id}' must address the exact child workspace from its typed input`
|
|
268
321
|
);
|
|
269
322
|
}
|
|
270
|
-
return Object.freeze({
|
|
271
|
-
...action,
|
|
272
|
-
[CHILD_AUTHENTICATION_RECOVERY]: child.id,
|
|
273
|
-
});
|
|
274
323
|
}
|
|
275
324
|
|
|
276
325
|
/** Internal compiler projection of {@link repairsChildAuthenticationFor}. */
|
|
@@ -339,6 +388,47 @@ function oneStaticRelationGate<I>(
|
|
|
339
388
|
return gates[0];
|
|
340
389
|
}
|
|
341
390
|
|
|
391
|
+
const authenticationIdentity = (authentication: MemberAuthentication): string =>
|
|
392
|
+
authentication.kind === MemberAuthenticationKind.SelectedProvider
|
|
393
|
+
? stable({
|
|
394
|
+
kind: authentication.kind,
|
|
395
|
+
providerKind: authentication.provider.kind,
|
|
396
|
+
scope: authentication.provider.scope,
|
|
397
|
+
identitySha256:
|
|
398
|
+
authentication.provider.kind === "legacySelected"
|
|
399
|
+
? authentication.provider.identitySha256
|
|
400
|
+
: undefined,
|
|
401
|
+
})
|
|
402
|
+
: stable({ kind: authentication.kind });
|
|
403
|
+
|
|
404
|
+
/** The one authentication a business intent carries: its own, or the single one its steps declare. */
|
|
405
|
+
function oneAuthentication<I>(
|
|
406
|
+
id: string,
|
|
407
|
+
own: MemberAuthentication | undefined,
|
|
408
|
+
steps: readonly IntentStep<I, any>[]
|
|
409
|
+
): MemberAuthentication | undefined {
|
|
410
|
+
// Only a provider selection (D7/D22) is inherited. An enrolled-device proof stays an explicit
|
|
411
|
+
// intent-level choice (`authenticatesWithEnrolledDevice`), exactly as before, so no existing law's
|
|
412
|
+
// published members change.
|
|
413
|
+
const declared = steps
|
|
414
|
+
.map((step) => (step.directive as { authentication?: MemberAuthentication }).authentication)
|
|
415
|
+
.filter((authentication): authentication is MemberAuthentication =>
|
|
416
|
+
authentication?.kind === MemberAuthenticationKind.SelectedProvider);
|
|
417
|
+
const identities = new Set(declared.map(authenticationIdentity));
|
|
418
|
+
if (identities.size > 1) {
|
|
419
|
+
throw new Error(
|
|
420
|
+
`intent('${id}') composes directives that authenticate with different providers — one member has one provider`
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
if (own !== undefined && declared.length > 0 && !identities.has(authenticationIdentity(own))) {
|
|
424
|
+
// e.g. an enrolled-device intent over a provider-selected directive: two different proofs.
|
|
425
|
+
throw new Error(
|
|
426
|
+
`intent('${id}') declares an authentication that differs from its directives'`
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
return own ?? declared[0];
|
|
430
|
+
}
|
|
431
|
+
|
|
342
432
|
function unsupportedKernelGate(directive: Directive<any>): string | undefined {
|
|
343
433
|
if (directive.attestationAuthorizedGate !== undefined)
|
|
344
434
|
return "attestation authorization";
|
|
@@ -428,7 +518,10 @@ function composePrimaryConsequenceOp(
|
|
|
428
518
|
...(directive.marker === "ensures" && op.aggregateType === undefined
|
|
429
519
|
? { aggregateType: directive.aggregateId }
|
|
430
520
|
: {}),
|
|
431
|
-
marker: directive
|
|
521
|
+
// An op the plan marked explicitly (`withMarker`) keeps its marker: a `.creates` directive that also
|
|
522
|
+
// supersedes an existing row of its own type (declared `.alsoMutates`) must lower that row as a Mutate,
|
|
523
|
+
// or the referential gate refuses it as a create of an id that already exists.
|
|
524
|
+
marker: op.marker ?? directive.marker,
|
|
432
525
|
};
|
|
433
526
|
}
|
|
434
527
|
|
|
@@ -446,7 +539,7 @@ class IntentBuilder<I> {
|
|
|
446
539
|
private readonly intentRelationGate?: NonNullable<
|
|
447
540
|
Directive["requiresRelationGate"]
|
|
448
541
|
>,
|
|
449
|
-
private readonly
|
|
542
|
+
private readonly authentication?: MemberAuthentication,
|
|
450
543
|
private readonly acceptsVerifiedBirthParentRecovery = false
|
|
451
544
|
) {}
|
|
452
545
|
|
|
@@ -473,7 +566,7 @@ class IntentBuilder<I> {
|
|
|
473
566
|
this.intentReads,
|
|
474
567
|
this.acceptsWorkspaceEffects,
|
|
475
568
|
this.intentRelationGate,
|
|
476
|
-
this.
|
|
569
|
+
this.authentication,
|
|
477
570
|
this.acceptsVerifiedBirthParentRecovery
|
|
478
571
|
);
|
|
479
572
|
}
|
|
@@ -484,10 +577,13 @@ class IntentBuilder<I> {
|
|
|
484
577
|
directsWorkspace<P>(
|
|
485
578
|
target: Directive<P>,
|
|
486
579
|
effect: {
|
|
580
|
+
readonly key?: string;
|
|
581
|
+
readonly after?: readonly string[];
|
|
487
582
|
readonly workspace: (facts: I) => string;
|
|
488
583
|
readonly payload: (facts: I) => P;
|
|
489
584
|
}
|
|
490
585
|
): IntentBuilder<I> {
|
|
586
|
+
validateWorkspaceEffectDependencies([...this.workspaceEffects, effect]);
|
|
491
587
|
if (
|
|
492
588
|
isBusinessIntent(target) &&
|
|
493
589
|
target.acceptsWorkspaceEffectGate !== true
|
|
@@ -506,12 +602,14 @@ class IntentBuilder<I> {
|
|
|
506
602
|
target,
|
|
507
603
|
destination: { kind: "workspace", address: effect.workspace },
|
|
508
604
|
payload: effect.payload,
|
|
605
|
+
...(effect.key !== undefined ? { key: effect.key } : {}),
|
|
606
|
+
...(effect.after !== undefined ? { after: [...effect.after] } : {}),
|
|
509
607
|
},
|
|
510
608
|
],
|
|
511
609
|
this.intentReads,
|
|
512
610
|
this.acceptsWorkspaceEffects,
|
|
513
611
|
this.intentRelationGate,
|
|
514
|
-
this.
|
|
612
|
+
this.authentication,
|
|
515
613
|
this.acceptsVerifiedBirthParentRecovery
|
|
516
614
|
);
|
|
517
615
|
}
|
|
@@ -546,7 +644,7 @@ class IntentBuilder<I> {
|
|
|
546
644
|
this.intentReads,
|
|
547
645
|
this.acceptsWorkspaceEffects,
|
|
548
646
|
this.intentRelationGate,
|
|
549
|
-
this.
|
|
647
|
+
this.authentication,
|
|
550
648
|
this.acceptsVerifiedBirthParentRecovery
|
|
551
649
|
);
|
|
552
650
|
}
|
|
@@ -582,7 +680,7 @@ class IntentBuilder<I> {
|
|
|
582
680
|
this.intentReads,
|
|
583
681
|
this.acceptsWorkspaceEffects,
|
|
584
682
|
this.intentRelationGate,
|
|
585
|
-
this.
|
|
683
|
+
this.authentication,
|
|
586
684
|
this.acceptsVerifiedBirthParentRecovery
|
|
587
685
|
);
|
|
588
686
|
}
|
|
@@ -598,7 +696,7 @@ class IntentBuilder<I> {
|
|
|
598
696
|
this.intentReads,
|
|
599
697
|
true,
|
|
600
698
|
this.intentRelationGate,
|
|
601
|
-
this.
|
|
699
|
+
this.authentication,
|
|
602
700
|
this.acceptsVerifiedBirthParentRecovery
|
|
603
701
|
);
|
|
604
702
|
}
|
|
@@ -615,7 +713,7 @@ class IntentBuilder<I> {
|
|
|
615
713
|
this.intentReads,
|
|
616
714
|
true,
|
|
617
715
|
this.intentRelationGate,
|
|
618
|
-
this.
|
|
716
|
+
this.authentication,
|
|
619
717
|
true
|
|
620
718
|
);
|
|
621
719
|
}
|
|
@@ -632,7 +730,7 @@ class IntentBuilder<I> {
|
|
|
632
730
|
this.intentReads,
|
|
633
731
|
this.acceptsWorkspaceEffects,
|
|
634
732
|
this.intentRelationGate,
|
|
635
|
-
|
|
733
|
+
enrolledDeviceAuthentication(),
|
|
636
734
|
this.acceptsVerifiedBirthParentRecovery
|
|
637
735
|
);
|
|
638
736
|
}
|
|
@@ -664,7 +762,7 @@ class IntentBuilder<I> {
|
|
|
664
762
|
this.intentReads,
|
|
665
763
|
this.acceptsWorkspaceEffects,
|
|
666
764
|
gate,
|
|
667
|
-
this.
|
|
765
|
+
this.authentication,
|
|
668
766
|
this.acceptsVerifiedBirthParentRecovery
|
|
669
767
|
);
|
|
670
768
|
}
|
|
@@ -688,7 +786,7 @@ class IntentBuilder<I> {
|
|
|
688
786
|
[...byKey.values()],
|
|
689
787
|
this.acceptsWorkspaceEffects,
|
|
690
788
|
this.intentRelationGate,
|
|
691
|
-
this.
|
|
789
|
+
this.authentication,
|
|
692
790
|
this.acceptsVerifiedBirthParentRecovery
|
|
693
791
|
);
|
|
694
792
|
}
|
|
@@ -707,13 +805,14 @@ class IntentBuilder<I> {
|
|
|
707
805
|
this.intentReads,
|
|
708
806
|
this.acceptsWorkspaceEffects,
|
|
709
807
|
this.intentRelationGate,
|
|
710
|
-
this.
|
|
808
|
+
this.authentication,
|
|
711
809
|
this.acceptsVerifiedBirthParentRecovery
|
|
712
810
|
);
|
|
713
811
|
}
|
|
714
812
|
|
|
715
813
|
/** Finish the intent and lower its directive graph to one atomic offer. */
|
|
716
814
|
atomically(): BusinessIntent<I> {
|
|
815
|
+
validateWorkspaceEffectDependencies(this.workspaceEffects);
|
|
717
816
|
if (this.steps.length === 0 && this.workspaceEffects.length === 0) {
|
|
718
817
|
throw new Error(
|
|
719
818
|
`intent('${this.id}') needs at least one directed consequence`
|
|
@@ -897,6 +996,18 @@ class IntentBuilder<I> {
|
|
|
897
996
|
}
|
|
898
997
|
}
|
|
899
998
|
const inheritedRelationGate = oneStaticRelationGate(this.steps);
|
|
999
|
+
// D7/D22 — authentication is declared per directive; the business intent that publishes a
|
|
1000
|
+
// directive IS the routable member the kernel judges, so it carries its steps' one provider (and
|
|
1001
|
+
// a sovereign self-certification marker) rather than silently dropping them.
|
|
1002
|
+
const authentication = oneAuthentication(this.id, this.authentication, this.steps);
|
|
1003
|
+
const selfCertifying = this.steps.some(
|
|
1004
|
+
(step) => step.directive.selfCertifyingPrincipalGate === true
|
|
1005
|
+
);
|
|
1006
|
+
if (selfCertifying && (this.steps.length !== 1 || this.workspaceEffects.length > 0)) {
|
|
1007
|
+
throw new Error(
|
|
1008
|
+
`intent('${this.id}') composes a sovereign self-certification; it must be the intent's only effect`
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
900
1011
|
if (
|
|
901
1012
|
this.intentRelationGate !== undefined &&
|
|
902
1013
|
inheritedRelationGate !== undefined &&
|
|
@@ -968,10 +1079,10 @@ class IntentBuilder<I> {
|
|
|
968
1079
|
},
|
|
969
1080
|
marker: primary.marker as ReferentialMarker,
|
|
970
1081
|
aggregateId: primary.aggregateId,
|
|
971
|
-
// Keep the typed
|
|
972
|
-
//
|
|
973
|
-
//
|
|
974
|
-
//
|
|
1082
|
+
// Keep the typed target on the executable intent. A narrow runtime plan
|
|
1083
|
+
// may retain only this intent export and needs the handle to register the
|
|
1084
|
+
// route. Package composition separately excludes a pure workspace
|
|
1085
|
+
// effect's remote target from the source domain's generated record types.
|
|
975
1086
|
...(primary.aggregate === undefined
|
|
976
1087
|
? {}
|
|
977
1088
|
: { aggregate: primary.aggregate }),
|
|
@@ -986,9 +1097,8 @@ class IntentBuilder<I> {
|
|
|
986
1097
|
plan,
|
|
987
1098
|
steps,
|
|
988
1099
|
workspaceEffects: this.workspaceEffects,
|
|
989
|
-
...(
|
|
990
|
-
|
|
991
|
-
: { offerAuthenticationProof: this.offerAuthenticationProof }),
|
|
1100
|
+
...(authentication === undefined ? {} : { authentication }),
|
|
1101
|
+
...(selfCertifying ? { selfCertifyingPrincipalGate: true as const } : {}),
|
|
992
1102
|
...(this.acceptsWorkspaceEffects
|
|
993
1103
|
? { acceptsWorkspaceEffectGate: true as const }
|
|
994
1104
|
: {}),
|
|
@@ -1044,7 +1154,10 @@ class IntentBuilder<I> {
|
|
|
1044
1154
|
}
|
|
1045
1155
|
|
|
1046
1156
|
class IntentContractStep {
|
|
1047
|
-
|
|
1157
|
+
private readonly id: string;
|
|
1158
|
+
constructor(id: string) {
|
|
1159
|
+
this.id = id;
|
|
1160
|
+
}
|
|
1048
1161
|
|
|
1049
1162
|
/**
|
|
1050
1163
|
* Publish one existing effect as a business intent without repeating its
|
|
@@ -1254,7 +1367,7 @@ export function executableDirectivesForLanguage(
|
|
|
1254
1367
|
`domain '${domain}' intent '${candidate.id}' collides with a different directive — rename one of them`
|
|
1255
1368
|
);
|
|
1256
1369
|
}
|
|
1257
|
-
if (isBusinessIntent(candidate) && published === undefined) {
|
|
1370
|
+
if (isBusinessIntent(candidate) && published === undefined && candidate.businessBirthInternal !== true) {
|
|
1258
1371
|
throw new Error(
|
|
1259
1372
|
`domain '${domain}' exports intent '${candidate.id}' outside its declared language — add it to language('${domain}', [...]) or remove it`
|
|
1260
1373
|
);
|
|
@@ -1262,11 +1375,34 @@ export function executableDirectivesForLanguage(
|
|
|
1262
1375
|
}
|
|
1263
1376
|
|
|
1264
1377
|
const remaining = discovered.filter(
|
|
1265
|
-
(candidate) => !privateIds.has(candidate.id) && !
|
|
1378
|
+
(candidate) => !privateIds.has(candidate.id) && !publicById.has(candidate.id)
|
|
1379
|
+
&& (!isBusinessIntent(candidate) || candidate.businessBirthInternal === true)
|
|
1266
1380
|
);
|
|
1267
1381
|
return [...remaining, ...language.intents];
|
|
1268
1382
|
}
|
|
1269
1383
|
|
|
1384
|
+
/**
|
|
1385
|
+
* The command name admitted at the public offer boundary.
|
|
1386
|
+
*
|
|
1387
|
+
* Most executable declarations keep their authored id. A bare `birth(A)` is
|
|
1388
|
+
* lowered to a private, aggregate-specific directive so replay can retain the
|
|
1389
|
+
* exact implementation, while every generated application exposes the single
|
|
1390
|
+
* stable verb `birth`. A wider authored business intent keeps its own name even
|
|
1391
|
+
* when one of its private consequences is a birth.
|
|
1392
|
+
*
|
|
1393
|
+
* Law description, generated clients and the executable registry must all call
|
|
1394
|
+
* this function. Re-deriving the rule at those boundaries creates a route that
|
|
1395
|
+
* type-checks but cannot dispatch.
|
|
1396
|
+
*/
|
|
1397
|
+
export function publicOfferRoute(directive: Directive<any>): string {
|
|
1398
|
+
const businessBirth = (
|
|
1399
|
+
directive as Directive<any> & { readonly businessBirth?: unknown }
|
|
1400
|
+
).businessBirth;
|
|
1401
|
+
return businessBirth === undefined || isBusinessIntent(directive)
|
|
1402
|
+
? directive.id
|
|
1403
|
+
: "birth";
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1270
1406
|
/**
|
|
1271
1407
|
* Refuse a half-migrated source module. Once a domain declares its language,
|
|
1272
1408
|
* every authored directive export must either be a published intent or one of
|
|
@@ -1284,20 +1420,12 @@ export function assertApplicationLanguageCoversAuthoredDirectives(
|
|
|
1284
1420
|
candidate.steps.map((step) => step.directive.id)
|
|
1285
1421
|
)
|
|
1286
1422
|
);
|
|
1287
|
-
const sharingReceiptIds = new Set(
|
|
1288
|
-
language.workspaceSharing.flatMap((policy) =>
|
|
1289
|
-
[...policy.delivered, ...policy.refused].map(
|
|
1290
|
-
(receipt) => receipt.records.id
|
|
1291
|
-
)
|
|
1292
|
-
)
|
|
1293
|
-
);
|
|
1294
1423
|
const uncovered = authored
|
|
1295
1424
|
.filter(
|
|
1296
1425
|
(directive) =>
|
|
1297
1426
|
directive.businessBirthInternal !== true &&
|
|
1298
1427
|
!publicIds.has(directive.id) &&
|
|
1299
|
-
!privateIds.has(directive.id)
|
|
1300
|
-
!sharingReceiptIds.has(directive.id)
|
|
1428
|
+
!privateIds.has(directive.id)
|
|
1301
1429
|
)
|
|
1302
1430
|
.map((directive) => directive.id)
|
|
1303
1431
|
.sort();
|
package/src/law_check.ts
CHANGED
|
@@ -142,7 +142,7 @@ function probeDirective(dir: Directive<unknown>, where: string): ProbeResult | u
|
|
|
142
142
|
returned = dir.plan(tracked as never, deterministicPorts({ physical: 1, replica: 1, principal: "principal:probe" }));
|
|
143
143
|
const drained: PlannedOp[] = [...__drainAuthoring(), ...(Array.isArray(returned) ? returned : [])];
|
|
144
144
|
ops = drained.filter((o): o is FieldOp => (o as { kind?: string }).kind !== "strike");
|
|
145
|
-
if (
|
|
145
|
+
if (dir.workspaceEffects) {
|
|
146
146
|
for (const effect of dir.workspaceEffects) {
|
|
147
147
|
// These two mappers are source law just as surely as the local plan. Run them against
|
|
148
148
|
// the same tracking payload so route/payload fields are not falsely diagnosed as dead.
|
|
@@ -150,10 +150,11 @@ function probeDirective(dir: Directive<unknown>, where: string): ProbeResult | u
|
|
|
150
150
|
// turn a successful local plan into a plan-return warning, but reads reached before the
|
|
151
151
|
// refusal are still drained and checked below.
|
|
152
152
|
try {
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
const ports = deterministicPorts({ physical: 1, replica: 1, principal: "principal:probe" });
|
|
154
|
+
if (effect.when?.(tracked as never, ports) ?? true) {
|
|
155
|
+
if (effect.destination.kind === "workspace") effect.destination.address(tracked as never, ports);
|
|
156
|
+
effect.payload(tracked as never, ports);
|
|
155
157
|
}
|
|
156
|
-
effect.payload(tracked as never);
|
|
157
158
|
} catch {
|
|
158
159
|
// Inconclusive mapper branch on the synthesized fixture; runtime/generator proof remains.
|
|
159
160
|
}
|
|
@@ -1029,7 +1030,7 @@ function invariantFindings(mod: DomainModule, aggById: ReadonlyMap<string, Aggre
|
|
|
1029
1030
|
const snap = synthesizeSnapshot(agg, `${domain}/${agg.id}#invariant`);
|
|
1030
1031
|
if (snap === undefined) continue; // unsynthesizable — proven by hand, not by check
|
|
1031
1032
|
try {
|
|
1032
|
-
withBirthProbeGlobals(() => agg.invariant!(snap));
|
|
1033
|
+
withBirthProbeGlobals(() => agg.invariant!(snap, null));
|
|
1033
1034
|
} catch (e) {
|
|
1034
1035
|
out.push({
|
|
1035
1036
|
domain,
|
|
@@ -1232,6 +1233,8 @@ function attestedReadFindings(mod: DomainModule): Finding[] {
|
|
|
1232
1233
|
// (b) unpopulatable trust set — a policy allow-list no directive writes.
|
|
1233
1234
|
const writtenTypes = new Set(directives.map((d) => (d as { aggregateId?: string }).aggregateId).filter(Boolean) as string[]);
|
|
1234
1235
|
for (const pol of mod.trustPolicies ?? []) {
|
|
1236
|
+
if (pol.authorizationOnly === true) continue;
|
|
1237
|
+
if (pol.allowListType === undefined) continue;
|
|
1235
1238
|
if (!writtenTypes.has(pol.allowListType)) {
|
|
1236
1239
|
findings.push({
|
|
1237
1240
|
domain,
|