@feltdb/core 0.13.0 → 0.16.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/dist/agent-runtime.d.ts +64 -2
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +121 -11
- package/dist/agent-state.d.ts +68 -0
- package/dist/agent-state.d.ts.map +1 -1
- package/dist/agent-state.js +210 -12
- package/dist/agent.d.ts +10 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +10 -1
- package/dist/build-identity.json +12 -4
- package/dist/cli/commands.js +214 -10
- package/dist/cli/publish-engine.js +116 -16
- package/dist/collection.d.ts +3 -1
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +33 -8
- package/dist/create/build-identity.json +12 -4
- package/dist/create/cli.js +1 -1
- package/dist/create/create.js +4 -6
- package/dist/create/managed-account.js +93 -35
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/Cargo.lock +8 -511
- package/dist/create/server-source/Cargo.toml +2 -13
- package/dist/create/server-source/crates/feltdb-client/Cargo.toml +1 -1
- package/dist/create/server-source/crates/feltdb-server/Cargo.toml +1 -1
- package/dist/create/server-source/crates/feltdb-server/README.md +6 -1
- package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +9 -1
- package/dist/create/server-source/crates/feltdb-server/src/auth.rs +85 -25
- package/dist/create/server-source/crates/feltdb-server/src/backup.rs +4 -0
- package/dist/create/server-source/crates/feltdb-server/src/console_accounts.rs +1009 -0
- package/dist/create/server-source/crates/feltdb-server/src/control_authorization.rs +441 -0
- package/dist/create/server-source/crates/feltdb-server/src/identity.rs +68 -6
- package/dist/create/server-source/crates/feltdb-server/src/key_management.rs +355 -23
- package/dist/create/server-source/crates/feltdb-server/src/lib.rs +3 -0
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +1134 -96
- package/dist/create/server-source/crates/feltdb-server/src/redaction.rs +208 -0
- package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +198 -19
- package/dist/create/server-source/crates/feltdb-server/tests/transaction_precondition_contract.rs +403 -0
- package/dist/create/server-source/crates/feltdb-wasm/Cargo.toml +1 -1
- package/dist/db.d.ts +75 -10
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +168 -29
- package/dist/deployment.d.ts +19 -0
- package/dist/deployment.d.ts.map +1 -1
- package/dist/deployment.js +38 -2
- package/dist/embedded-query.d.ts.map +1 -1
- package/dist/embedded-query.js +5 -4
- package/dist/embedded-transaction.d.ts +8 -4
- package/dist/embedded-transaction.d.ts.map +1 -1
- package/dist/embedded-transaction.js +55 -19
- package/dist/error-codes.d.ts +36 -2
- package/dist/error-codes.d.ts.map +1 -1
- package/dist/error-codes.js +50 -3
- package/dist/feltdb.d.ts +7 -0
- package/dist/feltdb.d.ts.map +1 -1
- package/dist/file-db.d.ts +27 -0
- package/dist/file-db.d.ts.map +1 -1
- package/dist/file-db.js +145 -7
- package/dist/http-client.d.ts +11 -3
- package/dist/http-client.d.ts.map +1 -1
- package/dist/http-client.js +27 -14
- package/dist/http-db.d.ts +43 -1
- package/dist/http-db.d.ts.map +1 -1
- package/dist/http-db.js +287 -59
- package/dist/index.js +1 -1
- package/dist/local-state-lock.d.ts +34 -0
- package/dist/local-state-lock.d.ts.map +1 -0
- package/dist/local-state-lock.js +225 -0
- package/dist/managed-recovery.d.ts +6 -0
- package/dist/managed-recovery.d.ts.map +1 -1
- package/dist/managed-recovery.js +9 -0
- package/dist/reactive-graph.d.ts +0 -3
- package/dist/reactive-graph.d.ts.map +1 -1
- package/dist/reactive-graph.js +11 -1
- package/dist/runtime-registry.d.ts +7 -2
- package/dist/runtime-registry.d.ts.map +1 -1
- package/dist/runtime-registry.js +2 -2
- package/dist/studio/components/index.js +1 -1
- package/dist/studio/{components-BSGmHfif.js → components-CJmzntBi.js} +2 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio-app/assets/{feltdb_wasm-3hDngl1h.js → feltdb_wasm-DtybUY0q.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-DsgIUwaB.wasm +0 -0
- package/dist/studio-app/assets/index-C4OffsZl.js +37 -0
- package/dist/studio-app/index.html +1 -1
- package/dist/transaction.d.ts +27 -11
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +20 -14
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/wasm/package.json +1 -1
- package/dist/workload.d.ts +86 -6
- package/dist/workload.d.ts.map +1 -1
- package/dist/workload.js +51 -3
- package/dist/workspace/workspace-connection.d.ts.map +1 -1
- package/dist/workspace/workspace-connection.js +14 -3
- package/package.json +1 -1
- package/dist/create/server-source/crates/feltdb/Cargo.lock +0 -175
- package/dist/create/server-source/crates/feltdb/Cargo.toml +0 -102
- package/dist/create/server-source/crates/feltdb/LICENSE +0 -21
- package/dist/create/server-source/crates/feltdb/README.md +0 -75
- package/dist/create/server-source/crates/feltdb/benches/baselines/gate-13-redux.json +0 -370
- package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +0 -589
- package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +0 -247
- package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +0 -440
- package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +0 -275
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +0 -381
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +0 -467
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +0 -489
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +0 -281
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +0 -606
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +0 -531
- package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +0 -462
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +0 -505
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +0 -484
- package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +0 -758
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +0 -421
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +0 -329
- package/dist/create/server-source/crates/feltdb/src/acceptance_tests.rs +0 -1705
- package/dist/create/server-source/crates/feltdb/src/acquisition.rs +0 -286
- package/dist/create/server-source/crates/feltdb/src/admission.rs +0 -185
- package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +0 -507
- package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +0 -539
- package/dist/create/server-source/crates/feltdb/src/agent_state.rs +0 -320
- package/dist/create/server-source/crates/feltdb/src/agent_transition_contract.rs +0 -1545
- package/dist/create/server-source/crates/feltdb/src/analytics.rs +0 -521
- package/dist/create/server-source/crates/feltdb/src/application.rs +0 -2674
- package/dist/create/server-source/crates/feltdb/src/application_runtime.rs +0 -1070
- package/dist/create/server-source/crates/feltdb/src/authority.rs +0 -479
- package/dist/create/server-source/crates/feltdb/src/authority_failover.rs +0 -847
- package/dist/create/server-source/crates/feltdb/src/authorization.rs +0 -1030
- package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +0 -1122
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority-client.rs +0 -32
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb-authority.rs +0 -19
- package/dist/create/server-source/crates/feltdb/src/bin/feltdb_node.rs +0 -1474
- package/dist/create/server-source/crates/feltdb/src/capabilities/mod.rs +0 -8
- package/dist/create/server-source/crates/feltdb/src/capabilities/search.rs +0 -418
- package/dist/create/server-source/crates/feltdb/src/capabilities/vector.rs +0 -482
- package/dist/create/server-source/crates/feltdb/src/capability.rs +0 -903
- package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +0 -263
- package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -77
- package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +0 -496
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +0 -2574
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +0 -212
- package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +0 -422
- package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +0 -445
- package/dist/create/server-source/crates/feltdb/src/content_distribution.rs +0 -465
- package/dist/create/server-source/crates/feltdb/src/convergence.rs +0 -634
- package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +0 -427
- package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +0 -376
- package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +0 -365
- package/dist/create/server-source/crates/feltdb/src/cron.rs +0 -294
- package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +0 -483
- package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +0 -477
- package/dist/create/server-source/crates/feltdb/src/distributed_tests.rs +0 -1003
- package/dist/create/server-source/crates/feltdb/src/distributed_transactions.rs +0 -1334
- package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +0 -368
- package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +0 -231
- package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +0 -482
- package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +0 -203
- package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +0 -317
- package/dist/create/server-source/crates/feltdb/src/equality_index.rs +0 -595
- package/dist/create/server-source/crates/feltdb/src/execution.rs +0 -426
- package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +0 -214
- package/dist/create/server-source/crates/feltdb/src/indexing.rs +0 -776
- package/dist/create/server-source/crates/feltdb/src/lib.rs +0 -7274
- package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +0 -234
- package/dist/create/server-source/crates/feltdb/src/materialization.rs +0 -184
- package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -266
- package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +0 -310
- package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +0 -736
- package/dist/create/server-source/crates/feltdb/src/observability.rs +0 -379
- package/dist/create/server-source/crates/feltdb/src/operation.rs +0 -290
- package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +0 -439
- package/dist/create/server-source/crates/feltdb/src/operation_log.rs +0 -349
- package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +0 -332
- package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +0 -718
- package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +0 -487
- package/dist/create/server-source/crates/feltdb/src/peer_registry.rs +0 -166
- package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +0 -289
- package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +0 -566
- package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +0 -3391
- package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +0 -203
- package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +0 -261
- package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +0 -502
- package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +0 -216
- package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +0 -303
- package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +0 -323
- package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +0 -531
- package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +0 -406
- package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +0 -436
- package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +0 -387
- package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +0 -378
- package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +0 -359
- package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +0 -372
- package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +0 -404
- package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +0 -376
- package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +0 -461
- package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +0 -2125
- package/dist/create/server-source/crates/feltdb/src/production_api.rs +0 -418
- package/dist/create/server-source/crates/feltdb/src/provenance.rs +0 -207
- package/dist/create/server-source/crates/feltdb/src/query_execution_diagnostics.rs +0 -126
- package/dist/create/server-source/crates/feltdb/src/query_performance.rs +0 -218
- package/dist/create/server-source/crates/feltdb/src/read_basis.rs +0 -257
- package/dist/create/server-source/crates/feltdb/src/references.rs +0 -404
- package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +0 -401
- package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +0 -501
- package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +0 -680
- package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +0 -163
- package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +0 -133
- package/dist/create/server-source/crates/feltdb/src/routing.rs +0 -409
- package/dist/create/server-source/crates/feltdb/src/semantic_decision.rs +0 -2029
- package/dist/create/server-source/crates/feltdb/src/semantic_query.rs +0 -599
- package/dist/create/server-source/crates/feltdb/src/sharding.rs +0 -549
- package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +0 -516
- package/dist/create/server-source/crates/feltdb/src/state_contract.rs +0 -5894
- package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +0 -222
- package/dist/create/server-source/crates/feltdb/src/state_facade.rs +0 -320
- package/dist/create/server-source/crates/feltdb/src/state_hash.rs +0 -291
- package/dist/create/server-source/crates/feltdb/src/state_model.rs +0 -4158
- package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +0 -379
- package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +0 -673
- package/dist/create/server-source/crates/feltdb/src/storage.rs +0 -273
- package/dist/create/server-source/crates/feltdb/src/submission.rs +0 -471
- package/dist/create/server-source/crates/feltdb/src/sync.rs +0 -495
- package/dist/create/server-source/crates/feltdb/src/sync_contract.rs +0 -822
- package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +0 -433
- package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +0 -462
- package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +0 -965
- package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +0 -1120
- package/dist/create/server-source/crates/feltdb/src/transactions.rs +0 -643
- package/dist/create/server-source/crates/feltdb/src/trigger.rs +0 -390
- package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +0 -749
- package/dist/create/server-source/crates/feltdb/src/versioned_object_substrate.rs +0 -708
- package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +0 -1133
- package/dist/create/server-source/crates/feltdb/src/workflow.rs +0 -713
- package/dist/create/server-source/crates/feltdb/src/workflow_acceptance_tests.rs +0 -510
- package/dist/create/server-source/crates/feltdb/src/workflow_integration.rs +0 -354
- package/dist/create/server-source/crates/feltdb/src/workflow_runtime.rs +0 -594
- package/dist/create/server-source/crates/feltdb/src/workload.rs +0 -2886
- package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +0 -456
- package/dist/create/server-source/crates/feltdb/tests/agent_state_native.rs +0 -1188
- package/dist/create/server-source/crates/feltdb/tests/agent_transition_contract_conformance.rs +0 -2884
- package/dist/create/server-source/crates/feltdb/tests/authority_process.rs +0 -297
- package/dist/create/server-source/crates/feltdb/tests/authority_transaction_identity.rs +0 -534
- package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +0 -132
- package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +0 -299
- package/dist/create/server-source/crates/feltdb/tests/common/mod.rs +0 -96
- package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +0 -272
- package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +0 -467
- package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +0 -309
- package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +0 -445
- package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +0 -518
- package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +0 -392
- package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +0 -850
- package/dist/create/server-source/crates/feltdb/tests/fixtures/agent_transition_corpus.json +0 -23340
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +0 -1916
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +0 -1878
- package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +0 -1862
- package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_evidence.rs +0 -123
- package/dist/create/server-source/crates/feltdb/tests/generalized_version_control_substrate_completion.rs +0 -299
- package/dist/create/server-source/crates/feltdb/tests/local_process_ownership.rs +0 -69
- package/dist/create/server-source/crates/feltdb/tests/managed_incident_regression.rs +0 -191
- package/dist/create/server-source/crates/feltdb/tests/operational_health_contract.rs +0 -278
- package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +0 -234
- package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +0 -947
- package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +0 -404
- package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +0 -916
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +0 -1045
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +0 -347
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +0 -361
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +0 -330
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +0 -93
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +0 -622
- package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +0 -517
- package/dist/create/server-source/crates/feltdb/tests/production_certification.rs +0 -1153
- package/dist/create/server-source/crates/feltdb/tests/production_contract.rs +0 -771
- package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +0 -1383
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +0 -868
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +0 -221
- package/dist/create/server-source/crates/feltdb/tests/replicated_history_contract.rs +0 -417
- package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +0 -338
- package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +0 -1039
- package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +0 -739
- package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +0 -452
- package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +0 -81
- package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +0 -438
- package/dist/create/server-source/crates/feltdb/tests/semantic_decision.rs +0 -1165
- package/dist/create/server-source/crates/feltdb/tests/semantic_query.rs +0 -767
- package/dist/create/server-source/crates/feltdb/tests/semantic_query_contract.rs +0 -363
- package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +0 -1799
- package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +0 -1316
- package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +0 -358
- package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +0 -365
- package/dist/create/server-source/crates/feltdb/tests/state_ref_authority.rs +0 -918
- package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +0 -299
- package/dist/create/server-source/crates/feltdb/tests/storage_independent_versioned_object_substrate.rs +0 -328
- package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +0 -255
- package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +0 -249
- package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +0 -994
- package/dist/create/server-source/crates/feltdb/tests/workload_envelope_contract.rs +0 -484
- package/dist/studio-app/assets/feltdb_wasm_bg-CFQT4gCy.wasm +0 -0
- package/dist/studio-app/assets/index-Dql1hS5m.js +0 -30
|
@@ -95,6 +95,10 @@ export function recordKey(collection, id) {
|
|
|
95
95
|
return `${collection}:${id}`;
|
|
96
96
|
}
|
|
97
97
|
const SEGMENT = /^[A-Za-z0-9._-]{1,128}$/;
|
|
98
|
+
/** The version a guard fences on, whichever spelling supplied it. */
|
|
99
|
+
function fencedVersion(guard) {
|
|
100
|
+
return guard.expectedVersion ?? guard.ifVersion;
|
|
101
|
+
}
|
|
98
102
|
/**
|
|
99
103
|
* Whether the request is well-formed, judged without any stored state.
|
|
100
104
|
*
|
|
@@ -109,6 +113,11 @@ function structuralRefusal(request) {
|
|
|
109
113
|
if (request.operations.length === 0)
|
|
110
114
|
return invalid('a transaction requires at least one operation');
|
|
111
115
|
const seen = new Set();
|
|
116
|
+
for (const guarded of [...request.operations, ...(request.preconditions ?? [])]) {
|
|
117
|
+
if (guarded.ifVersion !== undefined && guarded.expectedVersion !== undefined && guarded.ifVersion !== guarded.expectedVersion) {
|
|
118
|
+
return invalid(`${guarded.collection}:${guarded.id} supplies ifVersion ${guarded.ifVersion} and expectedVersion ${guarded.expectedVersion}; they are the same predicate`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
112
121
|
for (const operation of request.operations) {
|
|
113
122
|
if (!SEGMENT.test(operation.collection) || !SEGMENT.test(operation.id)) {
|
|
114
123
|
return invalid(`invalid collection or id: ${operation.collection}:${operation.id}`);
|
|
@@ -195,16 +204,24 @@ export function decideTransaction(request, state, digest) {
|
|
|
195
204
|
}
|
|
196
205
|
// Preconditions first, before any operation is staged, so a failure cannot
|
|
197
206
|
// leave a prefix of the transaction decided.
|
|
207
|
+
//
|
|
208
|
+
// `ifVersion` is the public spelling of `expectedVersion` and reaches this
|
|
209
|
+
// boundary unnormalised from callers below `db.transaction` (collections,
|
|
210
|
+
// agent state, composition). It is the same predicate, so it is evaluated
|
|
211
|
+
// here rather than counted as "constrains something" and then skipped.
|
|
198
212
|
const guards = [
|
|
199
|
-
...(request.preconditions ?? []).map(condition => ({
|
|
213
|
+
...(request.preconditions ?? []).map(condition => ({
|
|
214
|
+
...condition,
|
|
215
|
+
expectedVersion: fencedVersion(condition),
|
|
216
|
+
})),
|
|
200
217
|
...request.operations
|
|
201
|
-
.filter(operation => operation
|
|
218
|
+
.filter(operation => fencedVersion(operation) !== undefined
|
|
202
219
|
|| operation.expectedEpoch !== undefined
|
|
203
220
|
|| operation.expectedLeaseId !== undefined)
|
|
204
221
|
.map(operation => ({
|
|
205
222
|
collection: operation.collection,
|
|
206
223
|
id: operation.id,
|
|
207
|
-
expectedVersion: operation
|
|
224
|
+
expectedVersion: fencedVersion(operation),
|
|
208
225
|
expectedEpoch: operation.expectedEpoch,
|
|
209
226
|
expectedLeaseId: operation.expectedLeaseId,
|
|
210
227
|
})),
|
|
@@ -214,11 +231,12 @@ export function decideTransaction(request, state, digest) {
|
|
|
214
231
|
kind: 'reject',
|
|
215
232
|
reason: 'this runtime cannot evaluate transaction preconditions, so it refuses the '
|
|
216
233
|
+ 'transaction rather than committing it unconditionally',
|
|
234
|
+
code: 'CONTRACT_UNSUPPORTED',
|
|
217
235
|
};
|
|
218
236
|
}
|
|
219
237
|
for (const guard of guards) {
|
|
220
238
|
if (!SEGMENT.test(guard.collection) || !SEGMENT.test(String(guard.id))) {
|
|
221
|
-
return { kind: 'reject', reason: `invalid collection or id: ${guard.collection}:${guard.id}
|
|
239
|
+
return { kind: 'reject', reason: `invalid collection or id: ${guard.collection}:${guard.id}`, code: 'INVALID_REQUEST' };
|
|
222
240
|
}
|
|
223
241
|
const constrains = guard.requireAbsent === true
|
|
224
242
|
|| guard.expectedVersion !== undefined
|
|
@@ -228,6 +246,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
228
246
|
return {
|
|
229
247
|
kind: 'reject',
|
|
230
248
|
reason: `precondition on ${guard.collection}:${guard.id} constrains nothing`,
|
|
249
|
+
code: 'INVALID_REQUEST',
|
|
231
250
|
};
|
|
232
251
|
}
|
|
233
252
|
const key = recordKey(guard.collection, String(guard.id));
|
|
@@ -237,7 +256,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
237
256
|
return {
|
|
238
257
|
kind: 'reject',
|
|
239
258
|
reason: `PRECONDITION_FAILED:${key}:record already exists`,
|
|
240
|
-
failure: { predicate: 'present', collection: guard.collection, key },
|
|
259
|
+
failure: { predicate: 'present', collection: guard.collection, id: String(guard.id), key },
|
|
241
260
|
};
|
|
242
261
|
}
|
|
243
262
|
continue;
|
|
@@ -246,7 +265,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
246
265
|
return {
|
|
247
266
|
kind: 'reject',
|
|
248
267
|
reason: `PRECONDITION_FAILED:${key}:record does not exist`,
|
|
249
|
-
failure: { predicate: 'missing', collection: guard.collection, key },
|
|
268
|
+
failure: { predicate: 'missing', collection: guard.collection, id: String(guard.id), key },
|
|
250
269
|
};
|
|
251
270
|
}
|
|
252
271
|
if (guard.expectedVersion !== undefined) {
|
|
@@ -258,6 +277,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
258
277
|
failure: {
|
|
259
278
|
predicate: 'version',
|
|
260
279
|
collection: guard.collection,
|
|
280
|
+
id: String(guard.id),
|
|
261
281
|
key,
|
|
262
282
|
expected: guard.expectedVersion,
|
|
263
283
|
actual,
|
|
@@ -275,6 +295,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
275
295
|
failure: {
|
|
276
296
|
predicate: 'epoch',
|
|
277
297
|
collection: guard.collection,
|
|
298
|
+
id: String(guard.id),
|
|
278
299
|
key,
|
|
279
300
|
expected: guard.expectedEpoch,
|
|
280
301
|
actual,
|
|
@@ -293,6 +314,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
293
314
|
failure: {
|
|
294
315
|
predicate: 'lease',
|
|
295
316
|
collection: guard.collection,
|
|
317
|
+
id: String(guard.id),
|
|
296
318
|
key,
|
|
297
319
|
expected: guard.expectedLeaseId,
|
|
298
320
|
actual: held ?? null,
|
|
@@ -310,18 +332,19 @@ export function decideTransaction(request, state, digest) {
|
|
|
310
332
|
kind: 'reject',
|
|
311
333
|
reason: 'this runtime cannot evaluate read-basis fences inside its commit boundary, so it refuses the '
|
|
312
334
|
+ 'transaction rather than committing it unfenced',
|
|
335
|
+
code: 'CONTRACT_UNSUPPORTED',
|
|
313
336
|
};
|
|
314
337
|
}
|
|
315
338
|
for (const fence of fences) {
|
|
316
339
|
if (typeof fence?.token !== 'string' || !fence.token.startsWith(EMBEDDED_READ_BASIS_PREFIX)) {
|
|
317
|
-
return { kind: 'reject', reason: 'a read basis was not issued by this authority' };
|
|
340
|
+
return { kind: 'reject', reason: 'a read basis was not issued by this authority', code: 'INVALID_REQUEST' };
|
|
318
341
|
}
|
|
319
342
|
let actual;
|
|
320
343
|
try {
|
|
321
344
|
actual = readBasisToken(fence.reads, { read: state.read, scan: state.scan });
|
|
322
345
|
}
|
|
323
346
|
catch (error) {
|
|
324
|
-
return { kind: 'reject', reason: `invalid read basis: ${error instanceof Error ? error.message : String(error)}
|
|
347
|
+
return { kind: 'reject', reason: `invalid read basis: ${error instanceof Error ? error.message : String(error)}`, code: 'INVALID_REQUEST' };
|
|
325
348
|
}
|
|
326
349
|
if (actual !== fence.token) {
|
|
327
350
|
const first = normaliseReadSet(fence.reads);
|
|
@@ -345,6 +368,7 @@ export function decideTransaction(request, state, digest) {
|
|
|
345
368
|
return {
|
|
346
369
|
kind: 'reject',
|
|
347
370
|
reason: `invalid collection or id: ${operation.collection}:${operation.id}`,
|
|
371
|
+
code: 'INVALID_REQUEST',
|
|
348
372
|
};
|
|
349
373
|
}
|
|
350
374
|
const key = recordKey(operation.collection, operation.id);
|
|
@@ -352,30 +376,38 @@ export function decideTransaction(request, state, digest) {
|
|
|
352
376
|
return {
|
|
353
377
|
kind: 'reject',
|
|
354
378
|
reason: `PRECONDITION_FAILED:${key}:record already exists`,
|
|
355
|
-
failure: { predicate: 'present', collection: operation.collection, key },
|
|
379
|
+
failure: { predicate: 'present', collection: operation.collection, id: operation.id, key },
|
|
356
380
|
};
|
|
357
381
|
}
|
|
358
382
|
// A requireAbsent create begins the authority-owned version lifecycle at
|
|
359
|
-
// 1. A write fenced by expectedVersion
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
//
|
|
383
|
+
// 1. A write fenced by expectedVersion -- on the operation itself or by a
|
|
384
|
+
// transaction-level precondition on the same record -- is validated at N
|
|
385
|
+
// and written at N + 1. Both are resolved in the same decision the runtime
|
|
386
|
+
// applies atomically. An unconditional write remains verbatim, and a
|
|
387
|
+
// delete has no record left to carry a version.
|
|
388
|
+
//
|
|
389
|
+
// Where the fence is declared does not matter, and must not: a guard
|
|
390
|
+
// `preconditions: [{ A, ifVersion: N }]` beside a write of A that left the
|
|
391
|
+
// version alone would let a second transaction guarded on N commit after
|
|
392
|
+
// the first, which is the exclusive progression the guard exists to
|
|
393
|
+
// provide. The Rust authority applies the same rule.
|
|
363
394
|
//
|
|
364
395
|
// The value the caller supplied for __version is replaced rather than
|
|
365
396
|
// honoured, because a caller that computes a different next version must
|
|
366
397
|
// not be able to install it.
|
|
367
398
|
// See docs/architecture/transaction-version-contract.md.
|
|
399
|
+
const sameRecord = (guard) => guard.collection === operation.collection
|
|
400
|
+
&& String(guard.id) === operation.id;
|
|
368
401
|
const guardedCreate = operation.requireAbsent === true
|
|
369
|
-
|| guards.some(guard => guard.requireAbsent === true
|
|
370
|
-
|
|
371
|
-
&& String(guard.id) === operation.id);
|
|
402
|
+
|| guards.some(guard => guard.requireAbsent === true && sameRecord(guard));
|
|
403
|
+
const fencedAt = guards.find(guard => guard.expectedVersion !== undefined && sameRecord(guard))?.expectedVersion;
|
|
372
404
|
const value = operation.value === undefined
|
|
373
405
|
? undefined
|
|
374
406
|
: guardedCreate
|
|
375
407
|
? { ...operation.value, id: operation.id, __version: 1 }
|
|
376
|
-
:
|
|
408
|
+
: fencedAt === undefined
|
|
377
409
|
? { ...operation.value, id: operation.id }
|
|
378
|
-
: { ...operation.value, id: operation.id, __version:
|
|
410
|
+
: { ...operation.value, id: operation.id, __version: fencedAt + 1 };
|
|
379
411
|
mutations.push({
|
|
380
412
|
key,
|
|
381
413
|
collection: operation.collection,
|
|
@@ -437,7 +469,11 @@ export function embeddedDuplicate(request, plan) {
|
|
|
437
469
|
export class EmbeddedTransactionRejected extends Error {
|
|
438
470
|
feltdbCode;
|
|
439
471
|
feltdbConflict;
|
|
440
|
-
/**
|
|
472
|
+
/**
|
|
473
|
+
* Set when the request itself was malformed (`INVALID_REQUEST`) or asks for
|
|
474
|
+
* something this runtime cannot evaluate (`CONTRACT_UNSUPPORTED`), as
|
|
475
|
+
* opposed to refused by state.
|
|
476
|
+
*/
|
|
441
477
|
code;
|
|
442
478
|
constructor(reason, failure, code) {
|
|
443
479
|
super(reason);
|
package/dist/error-codes.d.ts
CHANGED
|
@@ -53,13 +53,47 @@ export declare enum FeltDBErrorCode {
|
|
|
53
53
|
SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",
|
|
54
54
|
AUTHORITY_SCOPE_REQUIRED = "AUTHORITY_SCOPE_REQUIRED",
|
|
55
55
|
AUTHORITY_SCOPE_INVALID = "AUTHORITY_SCOPE_INVALID",
|
|
56
|
-
AUTHORITY_SCOPE_MISMATCH = "AUTHORITY_SCOPE_MISMATCH"
|
|
56
|
+
AUTHORITY_SCOPE_MISMATCH = "AUTHORITY_SCOPE_MISMATCH",
|
|
57
|
+
/** 409: The request named a revision that is not the one active in its environment (a
|
|
58
|
+
* promotion superseded it, or it was never promoted). Nothing was read or written; the
|
|
59
|
+
* client forgets the revision, so the next request runs under the active one. The client
|
|
60
|
+
* never resends the refused request: whether it still makes sense is the caller's decision. */
|
|
61
|
+
REVISION_NOT_ACTIVE = "REVISION_NOT_ACTIVE",
|
|
62
|
+
/** A local state directory is open exclusively by another live process. */
|
|
63
|
+
STATE_LOCKED = "STATE_LOCKED",
|
|
64
|
+
/** Stored content no longer hashes to its address. The bytes were not returned. */
|
|
65
|
+
CONTENT_INTEGRITY_FAILURE = "CONTENT_INTEGRITY_FAILURE"
|
|
57
66
|
}
|
|
58
67
|
export declare class FeltDBServiceError extends Error {
|
|
59
68
|
readonly code: FeltDBErrorCode | string;
|
|
60
69
|
readonly requestId?: string | undefined;
|
|
61
70
|
readonly status?: number | undefined;
|
|
62
|
-
|
|
71
|
+
/** The authority's structured error body, when it answered with one. */
|
|
72
|
+
readonly body?: Record<string, unknown>;
|
|
73
|
+
constructor(message: string, code: FeltDBErrorCode | string, requestId?: string | undefined, status?: number | undefined, body?: Record<string, unknown>);
|
|
74
|
+
/** The body's structured `details`, when it carried any (e.g. a reused idempotency key's reason). */
|
|
75
|
+
get details(): Record<string, unknown> | undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The local file runtime's state directory is held exclusively by another
|
|
79
|
+
* process. Nothing was opened, read, or modified.
|
|
80
|
+
*
|
|
81
|
+
* `owner` is what the lock file records about its holder. Close the other
|
|
82
|
+
* process, or, if it is gone and its lock could not be judged stale (another
|
|
83
|
+
* host, an unreadable lock), remove `lockPath` by hand.
|
|
84
|
+
*/
|
|
85
|
+
export declare class LocalStateLockedError extends FeltDBServiceError {
|
|
86
|
+
readonly lockPath: string;
|
|
87
|
+
readonly owner: {
|
|
88
|
+
pid?: number;
|
|
89
|
+
host?: string;
|
|
90
|
+
acquiredAt?: string;
|
|
91
|
+
};
|
|
92
|
+
constructor(lockPath: string, owner: {
|
|
93
|
+
pid?: number;
|
|
94
|
+
host?: string;
|
|
95
|
+
acquiredAt?: string;
|
|
96
|
+
}, detail?: string);
|
|
63
97
|
}
|
|
64
98
|
/**
|
|
65
99
|
* Error response structure that all FeltDB APIs must return
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;GAEG;AACH,oBAAY,eAAe;IACzB,eAAe,oBAAoB;IACnC,YAAY,iBAAiB;IAC7B,gBAAgB,qBAAqB;IACrC,eAAe,oBAAoB;IACnC,cAAc,mBAAmB;IACjC,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;IACzC,gBAAgB,qBAAqB;IACrC,oBAAoB,yBAAyB;IAC7C,6BAA6B;IAC7B,EAAE,OAAO;IAET,wEAAwE;IACxE,QAAQ,aAAa;IAErB,2DAA2D;IAC3D,mBAAmB,wBAAwB;IAE3C,gEAAgE;IAChE,QAAQ,aAAa;IAErB,6DAA6D;IAC7D,cAAc,mBAAmB;IACjC,uBAAuB,4BAA4B;IACnD,qBAAqB,0BAA0B;IAC/C,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,gBAAgB,qBAAqB;IACrC,oBAAoB,yBAAyB;IAC7C,gFAAgF;IAChF,wBAAwB,6BAA6B;IACrD;sEACkE;IAClE,sBAAsB,2BAA2B;IACjD,aAAa,kBAAkB;IAC/B,oBAAoB,yBAAyB;IAC7C,kBAAkB,uBAAuB;IACzC,eAAe,oBAAoB;IACnC,oBAAoB,yBAAyB;IAC7C,gBAAgB,qBAAqB;IACrC,mBAAmB,wBAAwB;IAC3C,wBAAwB,6BAA6B;IACrD,uBAAuB,4BAA4B;IACnD,wBAAwB,6BAA6B;
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"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"}
|
package/dist/error-codes.js
CHANGED
|
@@ -55,17 +55,58 @@ export var FeltDBErrorCode;
|
|
|
55
55
|
FeltDBErrorCode["AUTHORITY_SCOPE_REQUIRED"] = "AUTHORITY_SCOPE_REQUIRED";
|
|
56
56
|
FeltDBErrorCode["AUTHORITY_SCOPE_INVALID"] = "AUTHORITY_SCOPE_INVALID";
|
|
57
57
|
FeltDBErrorCode["AUTHORITY_SCOPE_MISMATCH"] = "AUTHORITY_SCOPE_MISMATCH";
|
|
58
|
+
/** 409: The request named a revision that is not the one active in its environment (a
|
|
59
|
+
* promotion superseded it, or it was never promoted). Nothing was read or written; the
|
|
60
|
+
* client forgets the revision, so the next request runs under the active one. The client
|
|
61
|
+
* never resends the refused request: whether it still makes sense is the caller's decision. */
|
|
62
|
+
FeltDBErrorCode["REVISION_NOT_ACTIVE"] = "REVISION_NOT_ACTIVE";
|
|
63
|
+
/** A local state directory is open exclusively by another live process. */
|
|
64
|
+
FeltDBErrorCode["STATE_LOCKED"] = "STATE_LOCKED";
|
|
65
|
+
/** Stored content no longer hashes to its address. The bytes were not returned. */
|
|
66
|
+
FeltDBErrorCode["CONTENT_INTEGRITY_FAILURE"] = "CONTENT_INTEGRITY_FAILURE";
|
|
58
67
|
})(FeltDBErrorCode || (FeltDBErrorCode = {}));
|
|
59
68
|
export class FeltDBServiceError extends Error {
|
|
60
69
|
code;
|
|
61
70
|
requestId;
|
|
62
71
|
status;
|
|
63
|
-
|
|
72
|
+
/** The authority's structured error body, when it answered with one. */
|
|
73
|
+
body;
|
|
74
|
+
constructor(message, code, requestId, status, body) {
|
|
64
75
|
super(message);
|
|
65
76
|
this.code = code;
|
|
66
77
|
this.requestId = requestId;
|
|
67
78
|
this.status = status;
|
|
68
79
|
this.name = 'FeltDBServiceError';
|
|
80
|
+
if (body !== undefined)
|
|
81
|
+
this.body = body;
|
|
82
|
+
}
|
|
83
|
+
/** The body's structured `details`, when it carried any (e.g. a reused idempotency key's reason). */
|
|
84
|
+
get details() {
|
|
85
|
+
const details = this.body?.details;
|
|
86
|
+
return details && typeof details === 'object' && !Array.isArray(details) ? details : undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The local file runtime's state directory is held exclusively by another
|
|
91
|
+
* process. Nothing was opened, read, or modified.
|
|
92
|
+
*
|
|
93
|
+
* `owner` is what the lock file records about its holder. Close the other
|
|
94
|
+
* process, or, if it is gone and its lock could not be judged stale (another
|
|
95
|
+
* host, an unreadable lock), remove `lockPath` by hand.
|
|
96
|
+
*/
|
|
97
|
+
export class LocalStateLockedError extends FeltDBServiceError {
|
|
98
|
+
lockPath;
|
|
99
|
+
owner;
|
|
100
|
+
constructor(lockPath, owner, detail) {
|
|
101
|
+
super(`STATE_LOCKED: ${lockPath.replace(/[\\/][^\\/]+$/, '')} is open exclusively by `
|
|
102
|
+
+ `${owner.pid === undefined ? 'another process' : `process ${owner.pid}`}`
|
|
103
|
+
+ `${owner.host ? ` on ${owner.host}` : ''}${owner.acquiredAt ? ` since ${owner.acquiredAt}` : ''}. `
|
|
104
|
+
+ (detail ? `${detail} ` : '')
|
|
105
|
+
+ 'Close that process first, or open with createFeltDB({ path, access: \'shared\' }) if several '
|
|
106
|
+
+ 'processes are meant to share this state.', FeltDBErrorCode.STATE_LOCKED);
|
|
107
|
+
this.lockPath = lockPath;
|
|
108
|
+
this.owner = owner;
|
|
109
|
+
this.name = 'LocalStateLockedError';
|
|
69
110
|
}
|
|
70
111
|
}
|
|
71
112
|
/**
|
|
@@ -81,7 +122,10 @@ export function classifyError(code) {
|
|
|
81
122
|
return 'retryable';
|
|
82
123
|
if (code === FeltDBErrorCode.CONFLICT || code === FeltDBErrorCode.VERSION_CONFLICT
|
|
83
124
|
|| code === FeltDBErrorCode.IDEMPOTENCY_CONFLICT
|
|
84
|
-
|| code === FeltDBErrorCode.COMMIT_OUTCOME_UNKNOWN
|
|
125
|
+
|| code === FeltDBErrorCode.COMMIT_OUTCOME_UNKNOWN
|
|
126
|
+
// A commit the authority could not make durable has an unknown outcome:
|
|
127
|
+
// reconcile by retrying with the same transaction id, never by assuming.
|
|
128
|
+
|| code === FeltDBErrorCode.DURABILITY_FAILURE)
|
|
85
129
|
return 'requires_reconciliation';
|
|
86
130
|
if (code === FeltDBErrorCode.PRECONDITION_FAILED
|
|
87
131
|
|| code === FeltDBErrorCode.VALIDATION_ERROR
|
|
@@ -91,7 +135,10 @@ export function classifyError(code) {
|
|
|
91
135
|
|| code === FeltDBErrorCode.SCOPE_VIOLATION
|
|
92
136
|
|| code === FeltDBErrorCode.INVALID_CURSOR
|
|
93
137
|
|| code === FeltDBErrorCode.CURSOR_SCOPE_VIOLATION
|
|
94
|
-
|| code === FeltDBErrorCode.INVALID_REQUEST
|
|
138
|
+
|| code === FeltDBErrorCode.INVALID_REQUEST
|
|
139
|
+
// Nothing was applied, but the request was built for a contract that is no longer active:
|
|
140
|
+
// only the caller knows whether it still makes sense under the new one.
|
|
141
|
+
|| code === FeltDBErrorCode.REVISION_NOT_ACTIVE)
|
|
95
142
|
return 'requires_caller_correction';
|
|
96
143
|
return 'non_retryable';
|
|
97
144
|
}
|
package/dist/feltdb.d.ts
CHANGED
|
@@ -67,6 +67,13 @@ export interface JsDb {
|
|
|
67
67
|
delete?(key: string): any | Promise<any>;
|
|
68
68
|
/** Subscribe to runtime-originated changes, including remote mutations. */
|
|
69
69
|
subscribe_changes?(callback: (collection: string) => void, collection?: string): () => void;
|
|
70
|
+
/** Content-addressed immutable bytes (server and local file runtimes). */
|
|
71
|
+
storeContent?(content: Uint8Array): Promise<{
|
|
72
|
+
hash: string;
|
|
73
|
+
bytes: number;
|
|
74
|
+
ref: string;
|
|
75
|
+
}>;
|
|
76
|
+
acquireContent?(hash: string): Promise<Uint8Array | null>;
|
|
70
77
|
close?(): void | Promise<void>;
|
|
71
78
|
/**
|
|
72
79
|
* Get capability records
|
package/dist/feltdb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feltdb.d.ts","sourceRoot":"","sources":["../src/feltdb.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feltdb.d.ts","sourceRoot":"","sources":["../src/feltdb.ts"],"names":[],"mappings":"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"}
|
package/dist/file-db.d.ts
CHANGED
|
@@ -57,6 +57,15 @@ export interface FileJsDbOptions {
|
|
|
57
57
|
};
|
|
58
58
|
/** Collect persistence timings. Also enabled by `FELTDB_PERSISTENCE_PROFILE=1`. */
|
|
59
59
|
profile?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* `shared` (the default for a directly constructed `FileJsDb`): any number
|
|
62
|
+
* of processes may open the directory; each commit is serialized by
|
|
63
|
+
* `state.lock`. `exclusive` (the default of `createFeltDB({ path })`): this
|
|
64
|
+
* process takes `owner.lock` at open and another process opening the same
|
|
65
|
+
* directory exclusively *or shared* is refused with `LocalStateLockedError`
|
|
66
|
+
* until `close()` or process exit. Handles in one process share the lock.
|
|
67
|
+
*/
|
|
68
|
+
access?: 'shared' | 'exclusive';
|
|
60
69
|
}
|
|
61
70
|
export interface PersistenceStatus {
|
|
62
71
|
format: 'none' | 'legacy-snapshot' | 'snapshot+journal';
|
|
@@ -91,7 +100,16 @@ export declare class FileJsDb implements JsDb {
|
|
|
91
100
|
private readonly profiler;
|
|
92
101
|
private readonly compaction;
|
|
93
102
|
private compactionScheduled;
|
|
103
|
+
private releaseOwnerLock;
|
|
104
|
+
/** How this handle opened its directory. */
|
|
105
|
+
readonly access: 'shared' | 'exclusive';
|
|
94
106
|
constructor(path: string, options?: FileJsDbOptions);
|
|
107
|
+
/**
|
|
108
|
+
* A shared open still respects an exclusive owner in another process: a
|
|
109
|
+
* process that asked for exclusive access must not find a second writer.
|
|
110
|
+
* Probing takes no lock of its own.
|
|
111
|
+
*/
|
|
112
|
+
private assertNotHeldExclusively;
|
|
95
113
|
private journalPath;
|
|
96
114
|
private snapshotKey;
|
|
97
115
|
private parseSnapshot;
|
|
@@ -283,6 +301,15 @@ export declare class FileJsDb implements JsDb {
|
|
|
283
301
|
conflictCode?: string;
|
|
284
302
|
item?: any;
|
|
285
303
|
}>;
|
|
304
|
+
private contentDirectory;
|
|
305
|
+
private static sha256;
|
|
306
|
+
storeContent(content: Uint8Array): Promise<{
|
|
307
|
+
hash: string;
|
|
308
|
+
bytes: number;
|
|
309
|
+
ref: string;
|
|
310
|
+
}>;
|
|
311
|
+
acquireContent(hash: string): Promise<Uint8Array | null>;
|
|
312
|
+
private fsyncDirectory;
|
|
286
313
|
close(): void;
|
|
287
314
|
}
|
|
288
315
|
//# sourceMappingURL=file-db.d.ts.map
|
package/dist/file-db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-db.d.ts","sourceRoot":"","sources":["../src/file-db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EAG1B,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"file-db.d.ts","sourceRoot":"","sources":["../src/file-db.ts"],"names":[],"mappings":"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"}
|
package/dist/file-db.js
CHANGED
|
@@ -2,9 +2,11 @@ import { validateOperationAdmissionInput, operationsConflict, generateOperationI
|
|
|
2
2
|
import { FeltDBErrorCode, FeltDBServiceError } from './error-codes.js';
|
|
3
3
|
import * as nodeFs from 'fs';
|
|
4
4
|
import * as nodePath from 'path';
|
|
5
|
+
import { createHash as nodeCreateHash } from 'crypto';
|
|
5
6
|
import { TransactionIdConflictError, TransactionIdUnverifiableError, normaliseReadSet } from './transaction.js';
|
|
6
7
|
import { decideTransaction, readBasisToken, scanRows, embeddedDuplicate, embeddedResult, prepareTransaction, refusalError, } from './embedded-transaction.js';
|
|
7
8
|
import { EmbeddedQueryEngine } from './embedded-query.js';
|
|
9
|
+
import { LOCAL_STATE_LOCK_FILE, acquireLocalStateLock } from './local-state-lock.js';
|
|
8
10
|
import { encodeRecord, scanJournal, JournalCorruptionError, PersistenceProfiler, } from './file-journal.js';
|
|
9
11
|
export { JournalCorruptionError } from './file-journal.js';
|
|
10
12
|
/** The newest local file snapshot format this build reads and writes. */
|
|
@@ -71,6 +73,9 @@ export class FileJsDb {
|
|
|
71
73
|
profiler;
|
|
72
74
|
compaction;
|
|
73
75
|
compactionScheduled = false;
|
|
76
|
+
releaseOwnerLock = null;
|
|
77
|
+
/** How this handle opened its directory. */
|
|
78
|
+
access;
|
|
74
79
|
constructor(path, options = {}) {
|
|
75
80
|
const nodePath = getPathSync();
|
|
76
81
|
const nodeFs = getFsSync();
|
|
@@ -96,13 +101,43 @@ export class FileJsDb {
|
|
|
96
101
|
}
|
|
97
102
|
// Generate stable instance ID based on path
|
|
98
103
|
this.origin = `file:${this.dataPath}`;
|
|
99
|
-
|
|
100
|
-
this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
this.access = options.access ?? 'shared';
|
|
105
|
+
if (this.access !== 'shared' && this.access !== 'exclusive') {
|
|
106
|
+
throw new Error(`access must be 'shared' or 'exclusive', not ${String(options.access)}`);
|
|
107
|
+
}
|
|
108
|
+
if (this.access === 'exclusive') {
|
|
109
|
+
this.releaseOwnerLock = acquireLocalStateLock(this.dataPath);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this.assertNotHeldExclusively(nodePath.join(this.dataPath, LOCAL_STATE_LOCK_FILE));
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
// Clean up any stale locks from previous crashes on startup
|
|
116
|
+
this.cleanupStaleLock();
|
|
117
|
+
// Load or initialize state
|
|
118
|
+
this.state = this.initializeState();
|
|
119
|
+
this.loadDurableState();
|
|
120
|
+
this.queryEngine = new EmbeddedQueryEngine(() => Object.entries(this.state.rows));
|
|
121
|
+
this.indexedSequence = this.state.sequence;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
this.releaseOwnerLock?.();
|
|
125
|
+
this.releaseOwnerLock = null;
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* A shared open still respects an exclusive owner in another process: a
|
|
131
|
+
* process that asked for exclusive access must not find a second writer.
|
|
132
|
+
* Probing takes no lock of its own.
|
|
133
|
+
*/
|
|
134
|
+
assertNotHeldExclusively(lockPath) {
|
|
135
|
+
const nodeFs = getFsSync();
|
|
136
|
+
if (!nodeFs.existsSync(lockPath))
|
|
137
|
+
return;
|
|
138
|
+
// acquire-then-release judges liveness and recovers a stale lock exactly
|
|
139
|
+
// as an exclusive open would; it refuses when a live process holds it.
|
|
140
|
+
acquireLocalStateLock(this.dataPath)();
|
|
106
141
|
}
|
|
107
142
|
/* ------------------------------------------------------------------------
|
|
108
143
|
* Durable layout
|
|
@@ -1442,8 +1477,111 @@ export class FileJsDb {
|
|
|
1442
1477
|
console.log(`[CAS-${casId}] lock released, EXIT`);
|
|
1443
1478
|
}
|
|
1444
1479
|
}
|
|
1480
|
+
/* ------------------------------------------------------------------------
|
|
1481
|
+
* Content store
|
|
1482
|
+
*
|
|
1483
|
+
* Immutable bytes addressed by SHA-256, under `<state dir>/content/<hash>`:
|
|
1484
|
+
* the same contract as the server's `PUT /content` / `GET /content/{hash}`.
|
|
1485
|
+
* A blob is written to a temporary file, fsynced, renamed into place, and
|
|
1486
|
+
* the directory fsynced, so it is durable before `storeContent` returns and
|
|
1487
|
+
* never visible half-written. Every read is re-hashed; bytes that no longer
|
|
1488
|
+
* match their address are refused, never returned. Content is not indexed
|
|
1489
|
+
* state and is never deleted by FeltDB.
|
|
1490
|
+
* ---------------------------------------------------------------------- */
|
|
1491
|
+
contentDirectory() {
|
|
1492
|
+
return getPathSync().join(this.dataPath, 'content');
|
|
1493
|
+
}
|
|
1494
|
+
static sha256(bytes) {
|
|
1495
|
+
return nodeCreateHash('sha256').update(bytes).digest('hex');
|
|
1496
|
+
}
|
|
1497
|
+
async storeContent(content) {
|
|
1498
|
+
if (!(content instanceof Uint8Array)) {
|
|
1499
|
+
throw new FeltDBServiceError('INVALID_REQUEST: content must be a Uint8Array', FeltDBErrorCode.INVALID_REQUEST);
|
|
1500
|
+
}
|
|
1501
|
+
if (content.byteLength === 0) {
|
|
1502
|
+
throw new FeltDBServiceError('INVALID_REQUEST: content body must not be empty', FeltDBErrorCode.INVALID_REQUEST);
|
|
1503
|
+
}
|
|
1504
|
+
const nodeFs = getFsSync();
|
|
1505
|
+
const nodePath = getPathSync();
|
|
1506
|
+
const bytes = Buffer.from(content.buffer, content.byteOffset, content.byteLength);
|
|
1507
|
+
const hash = FileJsDb.sha256(bytes);
|
|
1508
|
+
const directory = this.contentDirectory();
|
|
1509
|
+
const target = nodePath.join(directory, hash);
|
|
1510
|
+
if (!nodeFs.existsSync(directory)) {
|
|
1511
|
+
nodeFs.mkdirSync(directory, { recursive: true });
|
|
1512
|
+
this.fsyncDirectory(this.dataPath);
|
|
1513
|
+
}
|
|
1514
|
+
try {
|
|
1515
|
+
const existing = nodeFs.readFileSync(target);
|
|
1516
|
+
if (FileJsDb.sha256(existing) === hash)
|
|
1517
|
+
return { hash, bytes: bytes.length, ref: `sha256:${hash}` };
|
|
1518
|
+
// A damaged copy is replaced by the verified bytes now in hand.
|
|
1519
|
+
}
|
|
1520
|
+
catch (error) {
|
|
1521
|
+
if (!isMissing(error))
|
|
1522
|
+
throw error;
|
|
1523
|
+
}
|
|
1524
|
+
const temporary = nodePath.join(directory, `.${hash}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`);
|
|
1525
|
+
const fd = nodeFs.openSync(temporary, 'wx', 0o600);
|
|
1526
|
+
try {
|
|
1527
|
+
writeFully(fd, bytes, 0);
|
|
1528
|
+
nodeFs.fsyncSync(fd);
|
|
1529
|
+
}
|
|
1530
|
+
finally {
|
|
1531
|
+
nodeFs.closeSync(fd);
|
|
1532
|
+
}
|
|
1533
|
+
try {
|
|
1534
|
+
nodeFs.renameSync(temporary, target);
|
|
1535
|
+
}
|
|
1536
|
+
catch (error) {
|
|
1537
|
+
try {
|
|
1538
|
+
nodeFs.unlinkSync(temporary);
|
|
1539
|
+
}
|
|
1540
|
+
catch { /* best effort */ }
|
|
1541
|
+
throw error;
|
|
1542
|
+
}
|
|
1543
|
+
this.fsyncDirectory(directory);
|
|
1544
|
+
return { hash, bytes: bytes.length, ref: `sha256:${hash}` };
|
|
1545
|
+
}
|
|
1546
|
+
async acquireContent(hash) {
|
|
1547
|
+
// The bare lowercase hex digest, exactly as the server's GET /content/{hash} takes it.
|
|
1548
|
+
const address = hash;
|
|
1549
|
+
if (typeof address !== 'string' || !/^[0-9a-f]{64}$/.test(address)) {
|
|
1550
|
+
throw new FeltDBServiceError('INVALID_REQUEST: invalid sha256 content hash', FeltDBErrorCode.INVALID_REQUEST);
|
|
1551
|
+
}
|
|
1552
|
+
let bytes;
|
|
1553
|
+
try {
|
|
1554
|
+
bytes = getFsSync().readFileSync(getPathSync().join(this.contentDirectory(), address));
|
|
1555
|
+
}
|
|
1556
|
+
catch (error) {
|
|
1557
|
+
if (isMissing(error))
|
|
1558
|
+
return null;
|
|
1559
|
+
throw error;
|
|
1560
|
+
}
|
|
1561
|
+
if (FileJsDb.sha256(bytes) !== address) {
|
|
1562
|
+
throw new FeltDBServiceError(`CONTENT_INTEGRITY_FAILURE: stored content ${address} failed verification; it was not returned`, FeltDBErrorCode.CONTENT_INTEGRITY_FAILURE);
|
|
1563
|
+
}
|
|
1564
|
+
return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1565
|
+
}
|
|
1566
|
+
fsyncDirectory(directory) {
|
|
1567
|
+
const nodeFs = getFsSync();
|
|
1568
|
+
let fd;
|
|
1569
|
+
try {
|
|
1570
|
+
fd = nodeFs.openSync(directory, 'r');
|
|
1571
|
+
nodeFs.fsyncSync(fd);
|
|
1572
|
+
}
|
|
1573
|
+
catch {
|
|
1574
|
+
// Some platforms cannot fsync a directory; the rename is still atomic.
|
|
1575
|
+
}
|
|
1576
|
+
finally {
|
|
1577
|
+
if (fd !== undefined)
|
|
1578
|
+
nodeFs.closeSync(fd);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1445
1581
|
close() {
|
|
1446
1582
|
// Mutations are durable before they return. Closing a stale handle must
|
|
1447
1583
|
// never rewrite authority state produced by another process.
|
|
1584
|
+
this.releaseOwnerLock?.();
|
|
1585
|
+
this.releaseOwnerLock = null;
|
|
1448
1586
|
}
|
|
1449
1587
|
}
|