@githolon/dsl 0.108.7 → 0.110.1
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 +80 -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 +214 -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 +268 -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 +23950 -15776
- 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 +550 -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_event_desk_close_test.dart +16 -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 +1276 -0
- package/src/codegen_call_usda.ts +49 -6
- package/src/codegen_dart.ts +83 -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 +2017 -1195
- 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
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/** Authentication declared by one exact law member (identity target model, D7 and D22).
|
|
2
|
+
*
|
|
3
|
+
* `authenticatesWith(member, provider)` is per directive (and per read): it names the one provider
|
|
4
|
+
* whose principals may author that member. The kernel is the authentication (D22): an intent is
|
|
5
|
+
* admitted as principal P iff it is signed by a key K with `identity:P#signer@key:<sha256(K)>` active in
|
|
6
|
+
* parent state, and P's scope is the scope the member's provider declares. A principal is spelled
|
|
7
|
+
* `<scope>:<subject>` — exactly its Zanzibar subject, so `.requires` checks it verbatim. A provider is
|
|
8
|
+
* one of two kinds, and the kind is law; law declares nothing else about it (no issuer, no key, no
|
|
9
|
+
* token):
|
|
10
|
+
*
|
|
11
|
+
* - **enrolled** — a tenant with a login provider. The first key of a principal is written by a
|
|
12
|
+
* principal holding `principalScope:<scope>#enroller` (`enrollDevice`,
|
|
13
|
+
* `framework/principal_enrollment.ts`), after it verified the provider's token off the ledger.
|
|
14
|
+
* - **sovereign** — no login provider. The principal is `<scope>:<sha256(root public key)>`; the root
|
|
15
|
+
* key certifies its own first signer tuple (`sovereignSelfCertification`). Losing the root is losing
|
|
16
|
+
* the identity.
|
|
17
|
+
*
|
|
18
|
+
* Every further device of either kind is enrolled by proof of possession (`enrollSigner`).
|
|
19
|
+
*
|
|
20
|
+
* A legacy form — `{ scope, identitySha256 }` — pins a workspace-local provider row by digest. It is the
|
|
21
|
+
* provider-token machinery the target model deletes (`auth_provider_law.ts`, build-order step 4); it
|
|
22
|
+
* stays only until that deletion, and new law must not use it.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const authenticationProviderBrand: unique symbol = Symbol(
|
|
26
|
+
"nomos.authentication-provider",
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export type AuthenticationProviderKind = "enrolled" | "sovereign";
|
|
30
|
+
|
|
31
|
+
interface ProviderBase {
|
|
32
|
+
readonly [authenticationProviderBrand]: true;
|
|
33
|
+
/** The provider scope: the principal namespace, and the Zanzibar subject type of its principals. */
|
|
34
|
+
readonly scope: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface EnrolledProviderRef extends ProviderBase {
|
|
38
|
+
readonly kind: "enrolled";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SovereignProviderRef extends ProviderBase {
|
|
42
|
+
readonly kind: "sovereign";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @deprecated The provider-row-by-digest form; deleted with `auth_provider_law.ts` (step 4). */
|
|
46
|
+
export interface LegacySelectedProviderRef extends ProviderBase {
|
|
47
|
+
readonly kind: "legacySelected";
|
|
48
|
+
/** Immutable provider identity, independent of issuer URL and verification-key rotation. */
|
|
49
|
+
readonly identitySha256: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type AuthenticationProviderRef =
|
|
53
|
+
| EnrolledProviderRef
|
|
54
|
+
| SovereignProviderRef
|
|
55
|
+
| LegacySelectedProviderRef;
|
|
56
|
+
|
|
57
|
+
export enum MemberAuthenticationKind {
|
|
58
|
+
SelectedProvider = "selectedProvider",
|
|
59
|
+
EnrolledDevice = "enrolledDevice",
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type MemberAuthentication =
|
|
63
|
+
| Readonly<{
|
|
64
|
+
kind: MemberAuthenticationKind.SelectedProvider;
|
|
65
|
+
provider: AuthenticationProviderRef;
|
|
66
|
+
}>
|
|
67
|
+
| Readonly<{
|
|
68
|
+
kind: MemberAuthenticationKind.EnrolledDevice;
|
|
69
|
+
}>;
|
|
70
|
+
|
|
71
|
+
export interface AuthenticatedMember {
|
|
72
|
+
readonly authentication?: MemberAuthentication;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const scopePattern = /^[A-Za-z][A-Za-z0-9._-]{0,127}$/;
|
|
76
|
+
const digestPattern = /^[0-9a-f]{64}$/;
|
|
77
|
+
/** A principal's subject within its scope: a bounded token that can never re-open the `type:id` split. */
|
|
78
|
+
const principalSubjectPattern = /^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,255}$/;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Subject types the kernel or framework already owns. A provider's principals are Zanzibar subjects
|
|
82
|
+
* of type `<scope>`, so a scope named after one of these would let a provider's principals pose as
|
|
83
|
+
* framework subjects (`user:…`, `key:…`) in every relation that allows them. `principalScope` is the
|
|
84
|
+
* object type of the enroller relation (D22), reserved for the same reason.
|
|
85
|
+
*/
|
|
86
|
+
export const RESERVED_PROVIDER_SCOPES: readonly string[] = Object.freeze([
|
|
87
|
+
"key",
|
|
88
|
+
"identity",
|
|
89
|
+
"workspace",
|
|
90
|
+
"principalScope",
|
|
91
|
+
]);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The scope of the principals console.nomos.cafe enrolls: operators who install law, and hosted
|
|
95
|
+
* enrollers acting for tenants who do not run their own backend (D18, D22). Framework vocabulary: the
|
|
96
|
+
* framework's own governance relations (`workspace:self#operator`, `principalScope:<s>#enroller`) allow
|
|
97
|
+
* these principals, so a law that names this scope must declare it `enrolled` — a sovereign `console`
|
|
98
|
+
* scope would let anyone mint a principal the framework treats as a console principal.
|
|
99
|
+
*/
|
|
100
|
+
export const CONSOLE_PRINCIPAL_SCOPE = "console";
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The scope of custodian principals: the sovereign identities that found a universe's root (identity
|
|
104
|
+
* target model D22, token-free genesis). A custodian principal is `custodian:<sha256hex(root key)>` and
|
|
105
|
+
* certifies itself — nobody verified a login at root, and root must not depend on the console of its own
|
|
106
|
+
* descendant nomos.cafe, so a sovereign key is the one honest identity a root's founding admin can have.
|
|
107
|
+
* Framework vocabulary like {@link CONSOLE_PRINCIPAL_SCOPE}, and its mirror: a law naming this scope must
|
|
108
|
+
* declare it `sovereign`. Being a custodian principal grants nothing by itself; anyone can self-certify
|
|
109
|
+
* one, and authority is only ever an admin/operator/enroller tuple naming it.
|
|
110
|
+
*/
|
|
111
|
+
export const CUSTODIAN_PRINCIPAL_SCOPE = "custodian";
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The scope of an application's signed-in users: `user:<login provider subject>` (for CO2, the Firebase
|
|
115
|
+
* uid). Framework-owned like {@link CONSOLE_PRINCIPAL_SCOPE}: the principal spelling is the framework's
|
|
116
|
+
* existing `user:` Zanzibar subject, so every relation that already allows `user()` holds these
|
|
117
|
+
* principals unchanged. It is enrolled — an enroller holding `principalScope:user#enroller` (the console's
|
|
118
|
+
* hosted enroller) writes each user's first key after verifying the login token off the ledger — and only
|
|
119
|
+
* framework law declares it ({@link userPrincipals}); a tenant naming the scope itself is refused, so no
|
|
120
|
+
* tenant can declare `user` sovereign or re-spell who a user is.
|
|
121
|
+
*/
|
|
122
|
+
export const USER_PRINCIPAL_SCOPE = "user";
|
|
123
|
+
|
|
124
|
+
function requireScope(scope: string): string {
|
|
125
|
+
if (typeof scope !== "string" || !scopePattern.test(scope)) {
|
|
126
|
+
throw new Error("authentication provider scope must be a bounded identifier");
|
|
127
|
+
}
|
|
128
|
+
return scope;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function requireKindScope(scope: string): string {
|
|
132
|
+
requireScope(scope);
|
|
133
|
+
if (RESERVED_PROVIDER_SCOPES.includes(scope)) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`authentication provider scope '${scope}' is reserved: its principals would pose as framework '${scope}:' subjects`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
return scope;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Declare an enrolled provider: an enroller of this scope writes each principal's first key. */
|
|
142
|
+
export function authenticationProvider(input: {
|
|
143
|
+
readonly kind: "enrolled";
|
|
144
|
+
readonly scope: string;
|
|
145
|
+
}): EnrolledProviderRef;
|
|
146
|
+
/** Declare a sovereign provider: principals are their own root keys. */
|
|
147
|
+
export function authenticationProvider(input: {
|
|
148
|
+
readonly kind: "sovereign";
|
|
149
|
+
readonly scope: string;
|
|
150
|
+
}): SovereignProviderRef;
|
|
151
|
+
/** @deprecated Pins a workspace provider row by digest; deleted in build-order step 4. */
|
|
152
|
+
export function authenticationProvider(input: {
|
|
153
|
+
readonly scope: string;
|
|
154
|
+
readonly identitySha256: string;
|
|
155
|
+
}): LegacySelectedProviderRef;
|
|
156
|
+
export function authenticationProvider(input: {
|
|
157
|
+
readonly kind?: AuthenticationProviderKind;
|
|
158
|
+
readonly scope: string;
|
|
159
|
+
readonly identitySha256?: string;
|
|
160
|
+
}): AuthenticationProviderRef {
|
|
161
|
+
if (input.kind === undefined) {
|
|
162
|
+
requireScope(input.scope);
|
|
163
|
+
if (typeof input.identitySha256 !== "string" || !digestPattern.test(input.identitySha256)) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
"authentication provider identitySha256 must be 64 lowercase hexadecimal characters",
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
return Object.freeze({
|
|
169
|
+
[authenticationProviderBrand]: true as const,
|
|
170
|
+
kind: "legacySelected" as const,
|
|
171
|
+
scope: input.scope,
|
|
172
|
+
identitySha256: input.identitySha256,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (input.kind !== "enrolled" && input.kind !== "sovereign") {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`unknown authentication provider kind '${String(input.kind)}': a provider is "enrolled" or "sovereign" (D22)`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
for (const option of Object.keys(input)) {
|
|
181
|
+
if (option !== "kind" && option !== "scope") {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`a ${input.kind} provider declares only its kind and scope; '${option}' is not law (D22: no token, issuer or key reaches a ledger)`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const scope = requireKindScope(input.scope);
|
|
188
|
+
if (scope === USER_PRINCIPAL_SCOPE) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`scope '${USER_PRINCIPAL_SCOPE}' is the framework's enrolled user principals; use userPrincipals, never declare it`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
if (scope === CONSOLE_PRINCIPAL_SCOPE && input.kind !== "enrolled") {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`scope '${CONSOLE_PRINCIPAL_SCOPE}' is the console's enrolled principals; it cannot be ${input.kind}`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (scope === CUSTODIAN_PRINCIPAL_SCOPE && input.kind !== "sovereign") {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`scope '${CUSTODIAN_PRINCIPAL_SCOPE}' is the framework's sovereign custodian principals; it cannot be ${input.kind}`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return Object.freeze({
|
|
204
|
+
[authenticationProviderBrand]: true as const,
|
|
205
|
+
kind: input.kind,
|
|
206
|
+
scope,
|
|
207
|
+
}) as EnrolledProviderRef | SovereignProviderRef;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** The console's principals (`console:<subject>`), enrolled by console.nomos.cafe. */
|
|
211
|
+
export const consolePrincipals: EnrolledProviderRef = authenticationProvider({
|
|
212
|
+
kind: "enrolled",
|
|
213
|
+
scope: CONSOLE_PRINCIPAL_SCOPE,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
/** The framework's enrolled user principals (`user:<subject>`): see {@link USER_PRINCIPAL_SCOPE}. The one
|
|
217
|
+
* declaration of the scope; built here because the public constructor refuses it to tenant law. */
|
|
218
|
+
export const userPrincipals: EnrolledProviderRef = Object.freeze({
|
|
219
|
+
[authenticationProviderBrand]: true as const,
|
|
220
|
+
kind: "enrolled" as const,
|
|
221
|
+
scope: USER_PRINCIPAL_SCOPE,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
/** Custodian principals (`custodian:<sha256hex(root key)>`), sovereign: see {@link CUSTODIAN_PRINCIPAL_SCOPE}. */
|
|
225
|
+
export const custodianPrincipals: SovereignProviderRef = authenticationProvider({
|
|
226
|
+
kind: "sovereign",
|
|
227
|
+
scope: CUSTODIAN_PRINCIPAL_SCOPE,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
/** Is `principal` a well-formed `<scope>:<subject>` principal of a non-reserved scope? Returns its scope. */
|
|
231
|
+
export function principalScopeOf(principal: string): string | undefined {
|
|
232
|
+
if (typeof principal !== "string") return undefined;
|
|
233
|
+
const colon = principal.indexOf(":");
|
|
234
|
+
if (colon <= 0) return undefined;
|
|
235
|
+
const scope = principal.slice(0, colon);
|
|
236
|
+
const subject = principal.slice(colon + 1);
|
|
237
|
+
if (!scopePattern.test(scope) || RESERVED_PROVIDER_SCOPES.includes(scope)) return undefined;
|
|
238
|
+
if (!principalSubjectPattern.test(subject)) return undefined;
|
|
239
|
+
return scope;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** The principal a sovereign scope assigns to a root key: `<scope>:<sha256hex(root public key)>`. */
|
|
243
|
+
export function sovereignPrincipal(provider: SovereignProviderRef, rootKeyHash: string): string {
|
|
244
|
+
if (provider?.[authenticationProviderBrand] !== true || provider.kind !== "sovereign") {
|
|
245
|
+
throw new Error("sovereignPrincipal takes a sovereign provider declared with authenticationProvider");
|
|
246
|
+
}
|
|
247
|
+
if (!digestPattern.test(rootKeyHash)) {
|
|
248
|
+
throw new Error("a sovereign principal's subject is the lowercase sha256 hex of its root public key");
|
|
249
|
+
}
|
|
250
|
+
return `${provider.scope}:${rootKeyHash}`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Brand check shared by the framework's provider-taking helpers. */
|
|
254
|
+
export function isAuthenticationProvider(value: unknown): value is AuthenticationProviderRef {
|
|
255
|
+
return (value as { [authenticationProviderBrand]?: unknown } | undefined)?.[authenticationProviderBrand] === true;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* The principals a provider authenticates, as the subject class a relation may store: every
|
|
260
|
+
* `<scope>:<subject>` principal. Sugar for `object(provider.scope)`, so `allow: [principalsOf(members)]`
|
|
261
|
+
* lets the relation hold exactly that provider's principals and no one else's.
|
|
262
|
+
*/
|
|
263
|
+
export function principalsOf(provider: EnrolledProviderRef | SovereignProviderRef): {
|
|
264
|
+
readonly kind: "direct";
|
|
265
|
+
readonly type: string;
|
|
266
|
+
} {
|
|
267
|
+
if (provider?.[authenticationProviderBrand] !== true) {
|
|
268
|
+
throw new Error("principalsOf takes a provider declared with authenticationProvider");
|
|
269
|
+
}
|
|
270
|
+
if (provider.kind !== "enrolled" && provider.kind !== "sovereign") {
|
|
271
|
+
throw new Error("principalsOf takes an enrolled or sovereign provider, not a legacy provider row");
|
|
272
|
+
}
|
|
273
|
+
return Object.freeze({ kind: "direct" as const, type: provider.scope });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** Bind a finished read or directive to one exact provider dependency. */
|
|
277
|
+
export function authenticatesWith<
|
|
278
|
+
T extends object & AuthenticatedMember,
|
|
279
|
+
>(member: T, provider: AuthenticationProviderRef): T & {
|
|
280
|
+
readonly authentication: Readonly<{
|
|
281
|
+
kind: MemberAuthenticationKind.SelectedProvider;
|
|
282
|
+
provider: AuthenticationProviderRef;
|
|
283
|
+
}>;
|
|
284
|
+
} {
|
|
285
|
+
if (member.authentication !== undefined) {
|
|
286
|
+
throw new Error("law member already has an authentication selection");
|
|
287
|
+
}
|
|
288
|
+
if (provider?.[authenticationProviderBrand] !== true) {
|
|
289
|
+
throw new Error("authenticatesWith takes a provider declared with authenticationProvider");
|
|
290
|
+
}
|
|
291
|
+
return Object.freeze({
|
|
292
|
+
...member,
|
|
293
|
+
authentication: Object.freeze({
|
|
294
|
+
kind: MemberAuthenticationKind.SelectedProvider,
|
|
295
|
+
provider,
|
|
296
|
+
}),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export function enrolledDeviceAuthentication(): MemberAuthentication {
|
|
301
|
+
return Object.freeze({ kind: MemberAuthenticationKind.EnrolledDevice });
|
|
302
|
+
}
|
package/src/null_meta.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* `nullSemantic` (`"forbid"` default · `"explicit-empty"` · `"nullable"`), the required
|
|
11
11
|
* `nullReason` documentation for the null-admitting semantics, and `isClearable` for the
|
|
12
12
|
* explicit-clear lane. This module is the ONE reader of those props for the 5 codegen surfaces
|
|
13
|
-
* (TS/Dart clients, the Dart
|
|
13
|
+
* (TS/Dart clients, the Dart session client, proof synthesis, openapi) — so a shape change lands
|
|
14
14
|
* in one place, and the read is a structural cast (the props are additive/optional on `Field`,
|
|
15
15
|
* so a field carrying none is byte-identical to a pre-feature field).
|
|
16
16
|
*/
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
|
|
8
|
+
export interface OpenUsdFlattenRequest {
|
|
9
|
+
readonly usdcat: string;
|
|
10
|
+
readonly sourcePath: string;
|
|
11
|
+
readonly populationMask?: readonly string[];
|
|
12
|
+
readonly description: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface OpenUsdEncodeRequest {
|
|
16
|
+
readonly usdcat: string;
|
|
17
|
+
readonly usda: string;
|
|
18
|
+
readonly temporaryDirectory: string;
|
|
19
|
+
readonly temporaryStem: string;
|
|
20
|
+
readonly description: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function stderrOf(error: unknown): string {
|
|
24
|
+
if (typeof error !== "object" || error === null || !("stderr" in error))
|
|
25
|
+
return "";
|
|
26
|
+
return String((error as { readonly stderr?: unknown }).stderr ?? "").trim();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Ask stock OpenUSD to compose one source stage into canonical, inspectable USDA. */
|
|
30
|
+
export async function flattenOpenUsdToUsda(
|
|
31
|
+
request: OpenUsdFlattenRequest
|
|
32
|
+
): Promise<string> {
|
|
33
|
+
const args = ["--flatten", "--skipSourceFileComment"];
|
|
34
|
+
const populationMask =
|
|
35
|
+
request.populationMask === undefined
|
|
36
|
+
? undefined
|
|
37
|
+
: [...new Set(request.populationMask)]
|
|
38
|
+
.sort((left, right) =>
|
|
39
|
+
left.length === right.length
|
|
40
|
+
? left.localeCompare(right)
|
|
41
|
+
: left.length - right.length
|
|
42
|
+
)
|
|
43
|
+
.filter(
|
|
44
|
+
(candidate, index, paths) =>
|
|
45
|
+
!paths
|
|
46
|
+
.slice(0, index)
|
|
47
|
+
.some(
|
|
48
|
+
(ancestor) =>
|
|
49
|
+
candidate === ancestor || candidate.startsWith(`${ancestor}/`)
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
.sort();
|
|
53
|
+
if (
|
|
54
|
+
populationMask !== undefined &&
|
|
55
|
+
populationMask.length > 0
|
|
56
|
+
) {
|
|
57
|
+
args.push("--mask", populationMask.join(","));
|
|
58
|
+
}
|
|
59
|
+
args.push(request.sourcePath);
|
|
60
|
+
try {
|
|
61
|
+
const { stdout: usda } = await execFileAsync(request.usdcat, args, {
|
|
62
|
+
encoding: "utf8",
|
|
63
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
64
|
+
});
|
|
65
|
+
if (!usda.startsWith("#usda 1.0")) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`stock OpenUSD returned a non-USDA ${request.description}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
// `--skipSourceFileComment` drops usdcat's leading comment, but the flattened layer's `doc`
|
|
71
|
+
// still records the ABSOLUTE root-layer path ("Generated from Composed Stage of root layer
|
|
72
|
+
// /Users/…/build/bootstrap/…"). That is the checkout location, not law: identical sources
|
|
73
|
+
// hashed differently on every machine (four checkouts, four stage-zero law hashes on
|
|
74
|
+
// 2026-09-07) and the kernel release could never reproduce the reviewed candidate. Keep the
|
|
75
|
+
// sentence and the layer's file name; drop the directory.
|
|
76
|
+
return usda.replace(
|
|
77
|
+
/(Generated from Composed Stage of root layer )(?:[^"\n]*\/)?([^"\n/]+)/g,
|
|
78
|
+
"$1$2"
|
|
79
|
+
);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const stderr = stderrOf(error);
|
|
82
|
+
const maskDetail =
|
|
83
|
+
populationMask === undefined
|
|
84
|
+
? ""
|
|
85
|
+
: ` (population mask: ${populationMask.length} irredundant paths, ${populationMask.join(",").length} characters)`;
|
|
86
|
+
throw new Error(
|
|
87
|
+
`stock OpenUSD refused the canonical typed USDA closure while compiling ${request.description}${maskDetail}` +
|
|
88
|
+
(stderr.length === 0 ? "" : `: ${stderr}`),
|
|
89
|
+
{ cause: error }
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Encode already-composed USDA as OpenUSD's reversible binary crate representation. */
|
|
95
|
+
export async function encodeOpenUsdUsdc(
|
|
96
|
+
request: OpenUsdEncodeRequest
|
|
97
|
+
): Promise<Uint8Array> {
|
|
98
|
+
const sourcePath = path.join(
|
|
99
|
+
request.temporaryDirectory,
|
|
100
|
+
`.${request.temporaryStem}.tmp.usda`
|
|
101
|
+
);
|
|
102
|
+
const destinationPath = path.join(
|
|
103
|
+
request.temporaryDirectory,
|
|
104
|
+
`.${request.temporaryStem}.tmp.usdc`
|
|
105
|
+
);
|
|
106
|
+
try {
|
|
107
|
+
writeFileSync(sourcePath, request.usda);
|
|
108
|
+
await execFileAsync(request.usdcat, ["-o", destinationPath, sourcePath], {
|
|
109
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
110
|
+
});
|
|
111
|
+
const usdc = readFileSync(destinationPath);
|
|
112
|
+
if (
|
|
113
|
+
usdc.length < 8 ||
|
|
114
|
+
new TextDecoder().decode(usdc.subarray(0, 8)) !== "PXR-USDC"
|
|
115
|
+
) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`stock OpenUSD returned a non-USDC ${request.description}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return usdc;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
const stderr = stderrOf(error);
|
|
123
|
+
throw new Error(
|
|
124
|
+
`stock OpenUSD could not encode ${request.description} as USDC` +
|
|
125
|
+
(stderr.length === 0 ? "" : `: ${stderr}`),
|
|
126
|
+
{ cause: error }
|
|
127
|
+
);
|
|
128
|
+
} finally {
|
|
129
|
+
rmSync(sourcePath, { force: true });
|
|
130
|
+
rmSync(destinationPath, { force: true });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
/** Validate the emitted law, not a second in-memory interpretation of the DSL.
|
|
7
|
+
* Cached results accelerate compilation only; they never enter custody or stand
|
|
8
|
+
* in for the kernel's admission decision. A changed checker invalidates hits.
|
|
9
|
+
*/
|
|
10
|
+
export function checkOperationContracts(lawPath: string, descriptorPath: string, compilerRoot: string, cacheRoot: string): void {
|
|
11
|
+
const checker = path.join(compilerRoot, 'operation_contract_check.mjs');
|
|
12
|
+
const artifact = path.join(compilerRoot, 'assets', 'operation-contract.wasm');
|
|
13
|
+
if (!existsSync(artifact)) throw new Error('Nomos compiler is missing its bundled operation contract checker; rebuild/reinstall the compiler package');
|
|
14
|
+
const key = createHash('sha256').update('nomos.operation-contract-check.v1\0')
|
|
15
|
+
.update(readFileSync(artifact)).update(readFileSync(checker)).update(readFileSync(lawPath))
|
|
16
|
+
.update(readFileSync(descriptorPath)).digest('hex');
|
|
17
|
+
const cache = path.join(cacheRoot, 'node_modules', '.cache', 'nomos', 'operation-contracts');
|
|
18
|
+
const receipt = path.join(cache, `${key}.ok`);
|
|
19
|
+
if (existsSync(receipt)) return;
|
|
20
|
+
try {
|
|
21
|
+
execFileSync(process.execPath, [checker, path.resolve(lawPath), path.resolve(descriptorPath)], {
|
|
22
|
+
encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 8 * 1024 * 1024,
|
|
23
|
+
});
|
|
24
|
+
} catch (error) {
|
|
25
|
+
const detail = error instanceof Error && 'stderr' in error && error.stderr
|
|
26
|
+
? String(error.stderr) : String(error);
|
|
27
|
+
throw new Error(`Operation contract validation failed:\n${detail}`);
|
|
28
|
+
}
|
|
29
|
+
mkdirSync(cache, { recursive: true });
|
|
30
|
+
writeFileSync(receipt, 'validated by the bundled kernel contract checker\n');
|
|
31
|
+
}
|
package/src/ordered_read.ts
CHANGED
|
@@ -217,7 +217,8 @@ export function first(id: string): TypelessFirst {
|
|
|
217
217
|
* `n` MUST be ≥ 1. `n = 1` is equivalent to `first` but a distinct declaration id.
|
|
218
218
|
*/
|
|
219
219
|
export function take(id: string, n: number): TypelessTake {
|
|
220
|
-
if (n < 1
|
|
220
|
+
if (!Number.isInteger(n) || n < 1 || n > 0xffff_ffff)
|
|
221
|
+
throw new Error(`take(${id}, ${n}): n must be an integer from 1 through 4294967295`);
|
|
221
222
|
return {
|
|
222
223
|
id,
|
|
223
224
|
limit: n,
|
package/src/package_config.ts
CHANGED
|
@@ -8,7 +8,10 @@ import {
|
|
|
8
8
|
isApplicationHomeGenesis,
|
|
9
9
|
type ApplicationHomeGenesis,
|
|
10
10
|
} from "./application_home_genesis.js";
|
|
11
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
RECEIVING_GROUP_RECOVERY_POLICIES,
|
|
13
|
+
type ReceivingGroupRecoveryPolicy,
|
|
14
|
+
} from "./framework/receiving_group.js";
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
17
|
* One cohesive, vertically sliced business capability inside a domain.
|
|
@@ -74,12 +77,17 @@ export interface NomosPackageConfig {
|
|
|
74
77
|
* Required for a published application: Nomos never invents a child-workspace allowance. */
|
|
75
78
|
readonly application?: {
|
|
76
79
|
readonly maxChildWorkspacesPerUser: number;
|
|
77
|
-
/** Target-owned roles granted at genesis to the cryptographically verified platform workspace.
|
|
78
|
-
* These are law constants, not caller or host input. */
|
|
79
|
-
readonly parentWorkspaceRoles?: readonly WorkspaceRole[];
|
|
80
80
|
/** Tenant law which must hold from the application's first usable home state. Every entry is
|
|
81
81
|
* an ordinary offer executed through the child's gate; omission declares no tenant ceremony. */
|
|
82
82
|
readonly homeGenesis?: ApplicationHomeGenesis;
|
|
83
|
+
/** THE RECEIVING-GROUP DECLARATION. A verified person's receiving group is the framework's identity
|
|
84
|
+
* anchor; the application declares how that anchor behaves as DATA, never by authoring lifecycle law.
|
|
85
|
+
* `recovery` is the posture the anchor is BORN with (`"guardian-quorum"` is the framework default;
|
|
86
|
+
* `"platform-identity-provider"` lets the attested parent platform re-seat a replacement device).
|
|
87
|
+
* Era rule: an application that declares nothing is byte-identical to one compiled before this key. */
|
|
88
|
+
readonly receivingGroup?: {
|
|
89
|
+
readonly recovery?: ReceivingGroupRecoveryPolicy;
|
|
90
|
+
};
|
|
83
91
|
};
|
|
84
92
|
/** Separately installed law required at runtime; USDA composition arcs do not belong here. */
|
|
85
93
|
readonly dependencies?: readonly RuntimePackageDependency[];
|
|
@@ -228,15 +236,28 @@ export function validateNomosPackageConfig(value: unknown): {
|
|
|
228
236
|
"Nomos will not reinterpret an untyped genesis recipe",
|
|
229
237
|
);
|
|
230
238
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
const receivingGroup = config.application.receivingGroup;
|
|
240
|
+
if (receivingGroup !== undefined) {
|
|
241
|
+
if (receivingGroup === null || typeof receivingGroup !== "object" || Array.isArray(receivingGroup)) {
|
|
242
|
+
throw new Error("application.receivingGroup must be an object declaration");
|
|
243
|
+
}
|
|
244
|
+
if (
|
|
245
|
+
receivingGroup.recovery !== undefined &&
|
|
246
|
+
!(RECEIVING_GROUP_RECOVERY_POLICIES as readonly string[]).includes(receivingGroup.recovery as string)
|
|
247
|
+
) {
|
|
248
|
+
throw new Error(
|
|
249
|
+
`application.receivingGroup.recovery must be one of ${RECEIVING_GROUP_RECOVERY_POLICIES.join(", ")}; ` +
|
|
250
|
+
"Nomos will not reinterpret an unknown recovery posture",
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// RETIRED 2026-09-11 (receiving_group_lifecycle.md, cut 1 item 4): the role a receiving group grants
|
|
255
|
+
// its birthing platform is the framework's own `authProviderAuthority`, seated by construction. A tenant
|
|
256
|
+
// restating (or extending) it is refused loudly rather than silently ignored.
|
|
257
|
+
if ("parentWorkspaceRoles" in config.application) {
|
|
238
258
|
throw new Error(
|
|
239
|
-
"application.parentWorkspaceRoles
|
|
259
|
+
"application.parentWorkspaceRoles is retired: the framework seats authProviderAuthority for the " +
|
|
260
|
+
"verified platform on every receiving group it births; delete the key",
|
|
240
261
|
);
|
|
241
262
|
}
|
|
242
263
|
}
|
|
@@ -81,6 +81,7 @@ export function packageContractUsda(input: {
|
|
|
81
81
|
' def NomosPackage "Package"',
|
|
82
82
|
" {",
|
|
83
83
|
` custom uniform string nomos:name = ${usdaString(input.packageName)}`,
|
|
84
|
+
' custom uniform token nomos:operationContract = "nomos.protobuf.v1"',
|
|
84
85
|
` custom uniform string[] nomos:domains = ${usdaStringArray([...input.exportedDomains].sort())}`,
|
|
85
86
|
...(targets.length > 0
|
|
86
87
|
? [
|
package/src/plan_source_slice.ts
CHANGED
|
@@ -53,7 +53,33 @@ export class PlanSourceSliceProgram {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
// The slicer only ever retains declarations inside the slice roots, so the program needs
|
|
57
|
+
// exactly those files: no lib.d.ts, no @types, and no descent into dependency packages.
|
|
58
|
+
// Resolving `@githolon/dsl`/`zod` from a tenant module otherwise parses the whole dependency
|
|
59
|
+
// type graph (hundreds of files, ~0.4s) for symbols that are discarded on sight.
|
|
60
|
+
options = { ...options, noLib: true, types: [] };
|
|
61
|
+
const host = ts.createCompilerHost(options, true);
|
|
62
|
+
const normalizedRoots = this.#sliceRoots;
|
|
63
|
+
const insideSliceRoots = (file: string): boolean => {
|
|
64
|
+
const absolute = normalized(file);
|
|
65
|
+
return normalizedRoots.some((root) => absolute.startsWith(root)) &&
|
|
66
|
+
!absolute.includes(`${path.sep}node_modules${path.sep}`);
|
|
67
|
+
};
|
|
68
|
+
host.resolveModuleNameLiterals = (literals, containingFile, redirected, compilerOptions) => {
|
|
69
|
+
const containerInside = insideSliceRoots(containingFile);
|
|
70
|
+
return literals.map((literal) => {
|
|
71
|
+
if (!containerInside) return { resolvedModule: undefined };
|
|
72
|
+
const resolution = ts.resolveModuleName(
|
|
73
|
+
literal.text, containingFile, compilerOptions, host, undefined, redirected,
|
|
74
|
+
);
|
|
75
|
+
const resolved = resolution.resolvedModule;
|
|
76
|
+
if (resolved === undefined || !insideSliceRoots(resolved.resolvedFileName)) {
|
|
77
|
+
return { resolvedModule: undefined };
|
|
78
|
+
}
|
|
79
|
+
return resolution;
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
this.#program = ts.createProgram({ rootNames: rootNames.map(normalized), options, host });
|
|
57
83
|
this.#checker = this.#program.getTypeChecker();
|
|
58
84
|
}
|
|
59
85
|
|
|
@@ -155,6 +181,9 @@ export class PlanSourceSliceProgram {
|
|
|
155
181
|
};
|
|
156
182
|
const markSymbol = (symbol: ts.Symbol | undefined): void => {
|
|
157
183
|
if (symbol === undefined || retainedSymbols.has(symbol)) return;
|
|
184
|
+
// An unresolved external import aliases the checker's one shared `unknown` symbol; retaining
|
|
185
|
+
// it would make every other unresolved binding look retained.
|
|
186
|
+
if (symbol.declarations === undefined || symbol.declarations.length === 0) return;
|
|
158
187
|
retainedSymbols.add(symbol);
|
|
159
188
|
if ((symbol.flags & ts.SymbolFlags.Alias) !== 0) {
|
|
160
189
|
try {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE DERIVATION of a Protobuf field identity from a stable law identity.
|
|
3
|
+
*
|
|
4
|
+
* The kernel builds every operation descriptor from installed law with this exact function
|
|
5
|
+
* (`kernel/src/operation_contract/descriptor.rs` `protobuf_field_number`), and the compiler emits
|
|
6
|
+
* every generated facade with it too. It is a pure function of the stable identity: nothing is
|
|
7
|
+
* looked up, there is no registry, and declaration order is deliberately not an input — adding a
|
|
8
|
+
* field cannot renumber an existing one.
|
|
9
|
+
*
|
|
10
|
+
* It lives in its own leaf module, importing nothing, because BOTH sides need it: the compiler
|
|
11
|
+
* (`codegen_call_proto.ts` re-exports it) and the Peer Office's law-derived encoder
|
|
12
|
+
* (`peer-office/src/runtime/law_directive_call.ts`), which must derive a call's wire layout from
|
|
13
|
+
* a workspace's own installed law. `@githolon/dsl` already depends on `@githolon/runtime`, so
|
|
14
|
+
* the office cannot be the home without a package cycle; and the office reaches this file the way
|
|
15
|
+
* it already reaches `adapter/proto` — by repository path, inlined by its own bundler. Keeping the
|
|
16
|
+
* module dependency-free is what makes that safe.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fnv64 = (value: string): bigint => {
|
|
20
|
+
let hash = 0xcbf29ce484222325n;
|
|
21
|
+
for (const point of new TextEncoder().encode(value)) {
|
|
22
|
+
hash ^= BigInt(point);
|
|
23
|
+
hash = BigInt.asUintN(64, hash * 0x100000001b3n);
|
|
24
|
+
}
|
|
25
|
+
return hash;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function protobufFieldNumber(stableIdentity: string): number {
|
|
29
|
+
const identity = /^[0-9a-f]{16}$/i.test(stableIdentity)
|
|
30
|
+
? BigInt(`0x${stableIdentity}`)
|
|
31
|
+
: fnv64(stableIdentity);
|
|
32
|
+
const ordinarySlots = 536_869_911n; // 2^29-1, less the 1,000 reserved numbers.
|
|
33
|
+
let field = Number(identity % ordinarySlots) + 1;
|
|
34
|
+
if (field >= 19_000) field += 1_000;
|
|
35
|
+
return field;
|
|
36
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Transport-only identities derived from existing attributed law. No new durable state.
|
|
2
|
+
// Mirrored by kernel/src/call_authoring/provenance.rs and checked by the descriptor gate.
|
|
3
|
+
export const provenanceRowIdentity = (aggregate: string): string => `${aggregate}:result:provenance`;
|
|
4
|
+
export const provenanceFieldIdentity = (field: string): string => `${field}:result:provenance`;
|
|
5
|
+
export const provenanceAuthorIdentity = "nomos:provenance:author";
|
|
6
|
+
export const provenanceContestedIdentity = "nomos:provenance:wasContested";
|
package/src/query.ts
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import type { AggregateHandle } from "./aggregate.js";
|
|
31
31
|
import type { Field } from "./fields.js";
|
|
32
|
+
import type { AuthenticatedMember } from "./member_authentication.js";
|
|
32
33
|
import { pathString, type PathRef } from "./path.js";
|
|
33
34
|
|
|
34
35
|
/** A key argument accepted by `.key(...)`: a plain (dotted) string OR a typed {@link PathRef}
|
|
@@ -67,7 +68,7 @@ type QueryKeyCompatibility<
|
|
|
67
68
|
* sorted), and the aggregate TYPE id it `returns`. Minimal by design: params /
|
|
68
69
|
* where / scope are later steps.
|
|
69
70
|
*/
|
|
70
|
-
export interface QueryDecl {
|
|
71
|
+
export interface QueryDecl extends AuthenticatedMember {
|
|
71
72
|
readonly id: string;
|
|
72
73
|
/** Index key fields, in DECLARED order (= index column order). */
|
|
73
74
|
readonly key: string[];
|