create-feltdb 0.11.2 → 0.11.3

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.
@@ -42,6 +42,7 @@ use feltdb::{
42
42
  Grant, GrantSigner, GrantStore, Subject as GrantSubject,
43
43
  },
44
44
  cardinality_endpoint::{CardinalityContext, CardinalityDiagnosticResponse},
45
+ execute_decision_transport,
45
46
  policy_evaluation::{
46
47
  Actor, AuthorizationState, PolicyContext, PolicyEvaluator, PolicySubject,
47
48
  RecordAuthorizationContext,
@@ -61,7 +62,8 @@ use feltdb::{
61
62
  WorkerRegistration,
62
63
  },
63
64
  workload::{CreateWorkload, WorkloadStore},
64
- AtomicMutation, DatabaseSnapshot, FeltDb, FlowError, JsonCasResult, Operation,
65
+ AtomicMutation, DatabaseSnapshot, DecisionError, DecisionPrincipal,
66
+ DecisionTransportExecutionRequest, FeltDb, FlowError, JsonCasResult, Operation,
65
67
  PeerAdvertisement, PeerId, RecordPrecondition, StateRevision, StateTriggerStore, StoredRow,
66
68
  };
67
69
  use feltdb_server::{
@@ -77,8 +79,8 @@ use feltdb_server::{
77
79
  server_artifacts, verify_bundle,
78
80
  },
79
81
  causal::{
80
- decode_cursor, decode_scoped_cursor, encode_cursor, encode_scoped_cursor, CausalEvent,
81
- CanonicalEventAuthority,
82
+ decode_cursor, decode_scoped_cursor, encode_cursor, encode_scoped_cursor,
83
+ CanonicalEventAuthority, CausalEvent,
82
84
  },
83
85
  certification::default_report,
84
86
  clock::LeaseClock,
@@ -159,14 +161,13 @@ fn api_error_body(status: StatusCode, message: String) -> Value {
159
161
  // that code. Other forbidden details retain the non-disclosing canonical
160
162
  // `FORBIDDEN` wire contract.
161
163
  let explicit_code = object.get("code").and_then(Value::as_str);
162
- let resolved_code = if status != StatusCode::FORBIDDEN
163
- || explicit_code == Some("CURSOR_SCOPE_VIOLATION")
164
- {
165
- explicit_code.unwrap_or(code)
166
- } else {
167
- code
168
- }
169
- .to_string();
164
+ let resolved_code =
165
+ if status != StatusCode::FORBIDDEN || explicit_code == Some("CURSOR_SCOPE_VIOLATION") {
166
+ explicit_code.unwrap_or(code)
167
+ } else {
168
+ code
169
+ }
170
+ .to_string();
170
171
  object.insert("error".into(), json!(resolved_code));
171
172
  object.insert("code".into(), json!(resolved_code));
172
173
  object.entry("message").or_insert_with(|| {
@@ -643,6 +644,42 @@ fn grant_subject(principal: &Principal) -> GrantSubject {
643
644
  _ => GrantSubject::Service(id),
644
645
  }
645
646
  }
647
+
648
+ fn decision_subject(principal: &Principal) -> GrantSubject {
649
+ let id = principal
650
+ .identity_id
651
+ .clone()
652
+ .unwrap_or_else(|| principal.key_id.clone());
653
+ match principal.subject_type.as_str() {
654
+ "human" | "user" => GrantSubject::Human(id),
655
+ "agent" => GrantSubject::Agent(id),
656
+ "workload" => GrantSubject::Workload(id),
657
+ "worker" => GrantSubject::Worker(id),
658
+ "connection" => GrantSubject::Connection(id),
659
+ _ => GrantSubject::Service(id),
660
+ }
661
+ }
662
+
663
+ fn bind_decision_authorization_principal(
664
+ principal: &Principal,
665
+ mut input: DecisionTransportExecutionRequest,
666
+ ) -> Result<DecisionTransportExecutionRequest, ApiError> {
667
+ if let Some(authorization) = input.authorization.as_mut() {
668
+ let requested = authorization.principal.as_ref().ok_or_else(|| {
669
+ semantic_decision_error(DecisionError::new(
670
+ "DECISION_INVALID_RESULT",
671
+ "authorization config requires a principal",
672
+ ))
673
+ })?;
674
+ authorization.principal = Some(DecisionPrincipal {
675
+ subject: decision_subject(principal),
676
+ tenant_id: requested.tenant_id.clone(),
677
+ application_id: requested.application_id.clone(),
678
+ capability: "state:read".into(),
679
+ });
680
+ }
681
+ Ok(input)
682
+ }
646
683
  fn authorization_error(error: feltdb::authorization::AuthorizationError) -> ApiError {
647
684
  let status = if error.code == "GRANT_INVALID" {
648
685
  StatusCode::BAD_REQUEST
@@ -1477,7 +1514,12 @@ fn worker_error(error: feltdb::worker_mesh::WorkerMeshError) -> ApiError {
1477
1514
  serde_json::to_string(&error).unwrap_or(error.message),
1478
1515
  )
1479
1516
  }
1480
- fn release_worker_claim_projection(state: &AppState, workload_id: &str, worker_id: &str, claim_id: &str) {
1517
+ fn release_worker_claim_projection(
1518
+ state: &AppState,
1519
+ workload_id: &str,
1520
+ worker_id: &str,
1521
+ claim_id: &str,
1522
+ ) {
1481
1523
  match state.mesh.lock() {
1482
1524
  Ok(mut mesh) => {
1483
1525
  if let Err(error) = mesh.release_claim(worker_id, claim_id) {
@@ -1793,12 +1835,7 @@ async fn complete_workload(
1793
1835
  unix_seconds_i64(),
1794
1836
  )
1795
1837
  .map_err(workload_error)?;
1796
- release_worker_claim_projection(
1797
- &state,
1798
- &id,
1799
- &input.fence.worker_id,
1800
- &input.fence.claim_id,
1801
- );
1838
+ release_worker_claim_projection(&state, &id, &input.fence.worker_id, &input.fence.claim_id);
1802
1839
  Ok(Json(json!(result)))
1803
1840
  }
1804
1841
  async fn fail_workload(
@@ -1822,12 +1859,7 @@ async fn fail_workload(
1822
1859
  unix_seconds_i64(),
1823
1860
  )
1824
1861
  .map_err(workload_error)?;
1825
- release_worker_claim_projection(
1826
- &state,
1827
- &id,
1828
- &input.fence.worker_id,
1829
- &input.fence.claim_id,
1830
- );
1862
+ release_worker_claim_projection(&state, &id, &input.fence.worker_id, &input.fence.claim_id);
1831
1863
  Ok(Json(json!({"state":status})))
1832
1864
  }
1833
1865
  async fn confirm_workload_cancelled(
@@ -3230,25 +3262,33 @@ async fn causal_chain(
3230
3262
  State(state): State<AppState>,
3231
3263
  Path(id): Path<String>,
3232
3264
  ) -> Result<Json<Value>, ApiError> {
3233
- Ok(Json(json!({"events":state.events.list(&id).map_err(control_error)?})))
3265
+ Ok(Json(
3266
+ json!({"events":state.events.list(&id).map_err(control_error)?}),
3267
+ ))
3234
3268
  }
3235
3269
  async fn workload_timeline(
3236
3270
  State(state): State<AppState>,
3237
3271
  Path(id): Path<String>,
3238
3272
  ) -> Result<Json<Value>, ApiError> {
3239
- Ok(Json(json!({"events":state.events.workload(&id).map_err(control_error)?})))
3273
+ Ok(Json(
3274
+ json!({"events":state.events.workload(&id).map_err(control_error)?}),
3275
+ ))
3240
3276
  }
3241
3277
  async fn execution_timeline(
3242
3278
  State(state): State<AppState>,
3243
3279
  Path(id): Path<String>,
3244
3280
  ) -> Result<Json<Value>, ApiError> {
3245
- Ok(Json(json!({"events":state.events.execution(&id).map_err(control_error)?})))
3281
+ Ok(Json(
3282
+ json!({"events":state.events.execution(&id).map_err(control_error)?}),
3283
+ ))
3246
3284
  }
3247
3285
  async fn revision_timeline(
3248
3286
  State(state): State<AppState>,
3249
3287
  Path(id): Path<String>,
3250
3288
  ) -> Result<Json<Value>, ApiError> {
3251
- Ok(Json(json!({"events":state.events.revision(&id).map_err(control_error)?})))
3289
+ Ok(Json(
3290
+ json!({"events":state.events.revision(&id).map_err(control_error)?}),
3291
+ ))
3252
3292
  }
3253
3293
  async fn export_bundle(
3254
3294
  State(state): State<AppState>,
@@ -7579,13 +7619,21 @@ async fn get_state_version(
7579
7619
  ))
7580
7620
  }
7581
7621
  fn require_bound_tenant(headers: &HeaderMap, tenant: &str) -> Result<(), ApiError> {
7582
- let Some(bound) = headers.get("feltdb-tenant-id") else { return Ok(()); };
7583
- if bound.to_str().ok() == Some(tenant) { return Ok(()); }
7584
- Err(ApiError(StatusCode::FORBIDDEN, json!({
7585
- "code":"AUTHORITY_SCOPE_MISMATCH",
7586
- "message":"request tenant does not match the authenticated application authority",
7587
- "http_status":403
7588
- }).to_string()))
7622
+ let Some(bound) = headers.get("feltdb-tenant-id") else {
7623
+ return Ok(());
7624
+ };
7625
+ if bound.to_str().ok() == Some(tenant) {
7626
+ return Ok(());
7627
+ }
7628
+ Err(ApiError(
7629
+ StatusCode::FORBIDDEN,
7630
+ json!({
7631
+ "code":"AUTHORITY_SCOPE_MISMATCH",
7632
+ "message":"request tenant does not match the authenticated application authority",
7633
+ "http_status":403
7634
+ })
7635
+ .to_string(),
7636
+ ))
7589
7637
  }
7590
7638
 
7591
7639
  async fn execute_canonical_query(
@@ -7643,6 +7691,49 @@ async fn execute_canonical_query(
7643
7691
  Ok(Json(json!(result)))
7644
7692
  }
7645
7693
 
7694
+ fn semantic_decision_error(error: feltdb::DecisionError) -> ApiError {
7695
+ let status = match error.code.as_str() {
7696
+ "DECISION_RECORD_NOT_FOUND" => StatusCode::NOT_FOUND,
7697
+ "DECISION_STORAGE_ERROR" => StatusCode::SERVICE_UNAVAILABLE,
7698
+ "DECISION_INVALID_RESULT"
7699
+ | "DECISION_INVALID_OPTION"
7700
+ | "DECISION_INVALID_DISTRIBUTION"
7701
+ | "DECISION_CONTEXT_EMPTY" => StatusCode::UNPROCESSABLE_ENTITY,
7702
+ _ => StatusCode::BAD_REQUEST,
7703
+ };
7704
+ ApiError::structured(
7705
+ status,
7706
+ json!({
7707
+ "code": error.code,
7708
+ "message": error.message,
7709
+ "http_status": status.as_u16(),
7710
+ }),
7711
+ )
7712
+ }
7713
+
7714
+ async fn execute_semantic_decision_transport(
7715
+ State(state): State<AppState>,
7716
+ Extension(principal): Extension<Principal>,
7717
+ Json(input): Json<DecisionTransportExecutionRequest>,
7718
+ ) -> Result<Json<Value>, ApiError> {
7719
+ let input = bind_decision_authorization_principal(&principal, input)?;
7720
+ let response =
7721
+ execute_decision_transport(&state.db, &input).map_err(semantic_decision_error)?;
7722
+ audit(
7723
+ &state,
7724
+ &principal.key_id,
7725
+ "semantic_decision.execute",
7726
+ &response.evaluation.provenance.cache_key,
7727
+ if response.evaluation.cached {
7728
+ "cache"
7729
+ } else {
7730
+ "runtime"
7731
+ },
7732
+ 200,
7733
+ );
7734
+ Ok(Json(json!(response)))
7735
+ }
7736
+
7646
7737
  #[derive(serde::Deserialize)]
7647
7738
  struct RevisionRecoveryRequest {
7648
7739
  #[serde(rename = "applicationId")]
@@ -7813,11 +7904,15 @@ async fn execute_canonical_transaction(
7813
7904
  &input.environment,
7814
7905
  )?;
7815
7906
  if !input.transaction.tenant_id.is_empty() && input.transaction.tenant_id != tenant {
7816
- return Err(ApiError(StatusCode::FORBIDDEN, json!({
7817
- "code":"AUTHORITY_SCOPE_MISMATCH",
7818
- "message":"transaction tenant does not match the bound authority",
7819
- "http_status":403
7820
- }).to_string()));
7907
+ return Err(ApiError(
7908
+ StatusCode::FORBIDDEN,
7909
+ json!({
7910
+ "code":"AUTHORITY_SCOPE_MISMATCH",
7911
+ "message":"transaction tenant does not match the bound authority",
7912
+ "http_status":403
7913
+ })
7914
+ .to_string(),
7915
+ ));
7821
7916
  }
7822
7917
  input.transaction.tenant_id = tenant.clone();
7823
7918
  input.transaction.application_id = input.application_id.clone();
@@ -7983,12 +8078,18 @@ fn catchup_status(
7983
8078
  authority_position: HashMap<String, u64>,
7984
8079
  retained_from: HashMap<String, u64>,
7985
8080
  ) -> CatchupStatus {
7986
- let lag = authority_position.iter().map(|(origin, sequence)| {
7987
- sequence.saturating_sub(peer_position.get(origin).copied().unwrap_or(0))
7988
- }).sum();
8081
+ let lag = authority_position
8082
+ .iter()
8083
+ .map(|(origin, sequence)| {
8084
+ sequence.saturating_sub(peer_position.get(origin).copied().unwrap_or(0))
8085
+ })
8086
+ .sum();
7989
8087
  let recovery_required = authority_position.iter().any(|(origin, through)| {
7990
8088
  let position = peer_position.get(origin).copied().unwrap_or(0);
7991
- let floor = retained_from.get(origin).copied().unwrap_or(through.saturating_add(1));
8089
+ let floor = retained_from
8090
+ .get(origin)
8091
+ .copied()
8092
+ .unwrap_or(through.saturating_add(1));
7992
8093
  position < *through && position.saturating_add(1) < floor
7993
8094
  });
7994
8095
  let catchup_mode = if recovery_required {
@@ -8005,7 +8106,12 @@ fn catchup_status(
8005
8106
  authority_position,
8006
8107
  retained_from,
8007
8108
  lag,
8008
- recoverability: if recovery_required { "rebootstrap_required" } else { "recoverable" }.into(),
8109
+ recoverability: if recovery_required {
8110
+ "rebootstrap_required"
8111
+ } else {
8112
+ "recoverable"
8113
+ }
8114
+ .into(),
8009
8115
  catchup_mode: catchup_mode.into(),
8010
8116
  recovery_required,
8011
8117
  }
@@ -8487,7 +8593,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
8487
8593
  let provider_store = ProviderStore::load(config.data.with_extension("providers.json"))?;
8488
8594
  let readiness_probe = config.data.with_extension("readiness");
8489
8595
  let tenancy_store = TenancyStore::load(config.data.with_extension("platform.json"))?;
8490
- let application_store = ApplicationStore::load(config.data.with_extension("applications.json"))?;
8596
+ let application_store =
8597
+ ApplicationStore::load(config.data.with_extension("applications.json"))?;
8491
8598
  let principal_authority =
8492
8599
  feltdb_server::canonical_principals::CanonicalPrincipalAuthority::new(db.clone());
8493
8600
  let legacy_principals = config.data.with_extension("principals.json");
@@ -8835,7 +8942,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
8835
8942
  get(control_plane_record_provenance),
8836
8943
  )
8837
8944
  .route("/v1/control-plane/agents", get(control_plane_agents))
8838
- .route("/v1/control-plane/agents/{agent_id}", get(control_plane_agent))
8945
+ .route(
8946
+ "/v1/control-plane/agents/{agent_id}",
8947
+ get(control_plane_agent),
8948
+ )
8839
8949
  .route("/v1/state/resources", get(state_resources))
8840
8950
  .route(
8841
8951
  "/v1/state/resources/{resource}/history",
@@ -8912,6 +9022,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
8912
9022
  )
8913
9023
  .route("/v1/state/version", get(get_state_version))
8914
9024
  .route("/v1/query", axum::routing::post(execute_canonical_query))
9025
+ .route(
9026
+ "/v1/experimental/semantic-decisions",
9027
+ axum::routing::post(execute_semantic_decision_transport),
9028
+ )
8915
9029
  .route(
8916
9030
  "/v1/transactions",
8917
9031
  axum::routing::post(execute_canonical_transaction),
@@ -9510,6 +9624,7 @@ async fn authenticate(
9510
9624
  } else if path == "/v1/state/diff"
9511
9625
  || path == "/v1/state/conflicts"
9512
9626
  || path == "/v1/state/reconciliation/plan"
9627
+ || path == "/v1/experimental/semantic-decisions"
9513
9628
  {
9514
9629
  // Describing state is reading it. These are POSTs because they take
9515
9630
  // three revision identities and a plan, not because they change
@@ -9647,8 +9762,7 @@ fn audit(
9647
9762
  // change that policy. What changed is that the failure is no longer
9648
9763
  // invisible — `AuditLog::record` has already counted it, timestamped it and
9649
9764
  // degraded the audit health state by the time this returns.
9650
- let _span =
9651
- feltdb::workload_diagnostics::span(feltdb::workload_diagnostics::Phase::AuditWrite);
9765
+ let _span = feltdb::workload_diagnostics::span(feltdb::workload_diagnostics::Phase::AuditWrite);
9652
9766
  if let Err(error) = state.audit.record(AuditEvent {
9653
9767
  timestamp_ms: 0,
9654
9768
  namespace: &state.namespace,
@@ -10447,14 +10561,21 @@ async fn sync_pull(
10447
10561
  let peer_position = request.versions;
10448
10562
  let authority_position = state.db.operation_versions()?;
10449
10563
  let retained_from = state.db.retained_operation_floors()?;
10450
- let catchup = catchup_status(request.requester, peer_position.clone(), authority_position.clone(), retained_from);
10564
+ let catchup = catchup_status(
10565
+ request.requester,
10566
+ peer_position.clone(),
10567
+ authority_position.clone(),
10568
+ retained_from,
10569
+ );
10451
10570
  if catchup.recovery_required {
10452
10571
  return Err(ApiError::structured(
10453
10572
  StatusCode::CONFLICT,
10454
- serde_json::to_value(&catchup).unwrap_or_else(|_| json!({
10455
- "catchup_mode": "snapshot_rebootstrap_required",
10456
- "recovery_required": true
10457
- })),
10573
+ serde_json::to_value(&catchup).unwrap_or_else(|_| {
10574
+ json!({
10575
+ "catchup_mode": "snapshot_rebootstrap_required",
10576
+ "recovery_required": true
10577
+ })
10578
+ }),
10458
10579
  ));
10459
10580
  }
10460
10581
  let operations = state.db.operations_since(&peer_position)?;
@@ -12786,7 +12907,11 @@ fn declare_configured_equality_indexes(db: &FeltDb) -> Result<Vec<String>, Strin
12786
12907
  return Ok(Vec::new());
12787
12908
  };
12788
12909
  let mut declared = Vec::new();
12789
- for entry in declaration.split(',').map(str::trim).filter(|entry| !entry.is_empty()) {
12910
+ for entry in declaration
12911
+ .split(',')
12912
+ .map(str::trim)
12913
+ .filter(|entry| !entry.is_empty())
12914
+ {
12790
12915
  let Some((collection, field)) = entry.split_once('.') else {
12791
12916
  return Err(format!(
12792
12917
  "FELTDB_EQUALITY_INDEXES entry {entry:?} must be written as collection.field"
@@ -12880,11 +13005,12 @@ fn bounded_query_records(
12880
13005
  ) -> Result<Vec<feltdb::StoredRow>, ApiError> {
12881
13006
  if execution != BoundedQueryExecution::Scan {
12882
13007
  let equalities = bounded_query_equalities(&request.conditions);
12883
- let indexed = state.db.query_collection_by_equality(
12884
- &request.collection,
12885
- &equalities,
12886
- |row| bounded_query_matches(row, &request.conditions),
12887
- )?;
13008
+ let indexed =
13009
+ state
13010
+ .db
13011
+ .query_collection_by_equality(&request.collection, &equalities, |row| {
13012
+ bounded_query_matches(row, &request.conditions)
13013
+ })?;
12888
13014
  if let Some(records) = indexed {
12889
13015
  return Ok(records);
12890
13016
  }
@@ -12897,15 +13023,18 @@ fn bounded_query_records(
12897
13023
  ));
12898
13024
  }
12899
13025
  }
12900
- Ok(state.db.query_collection(&request.collection, None, |row| {
12901
- bounded_query_matches(row, &request.conditions)
12902
- })?)
13026
+ Ok(state
13027
+ .db
13028
+ .query_collection(&request.collection, None, |row| {
13029
+ bounded_query_matches(row, &request.conditions)
13030
+ })?)
12903
13031
  }
12904
13032
 
12905
13033
  fn issue_bounded_cursor(
12906
13034
  state: &AppState,
12907
13035
  mut cursor: BoundedQueryCursor,
12908
- ) -> Result<String, ApiError> { let token = uuid::Uuid::new_v4().simple().to_string();
13036
+ ) -> Result<String, ApiError> {
13037
+ let token = uuid::Uuid::new_v4().simple().to_string();
12909
13038
  let now = unix_seconds_i64().max(0) as u64;
12910
13039
  cursor.created_at = now;
12911
13040
  let mut cursors = state.bounded_query_cursors.lock().map_err(|_| {
@@ -13356,9 +13485,10 @@ async fn commit_transaction(
13356
13485
  // mutations and retained across compaction.
13357
13486
  let payload_hash = format!(
13358
13487
  "sha256:{:x}",
13359
- Sha256::digest(serde_json::to_vec(&request).map_err(|error| {
13360
- ApiError(StatusCode::BAD_REQUEST, error.to_string())
13361
- })?)
13488
+ Sha256::digest(
13489
+ serde_json::to_vec(&request)
13490
+ .map_err(|error| { ApiError(StatusCode::BAD_REQUEST, error.to_string()) })?
13491
+ )
13362
13492
  );
13363
13493
 
13364
13494
  // Validate every operation before any of them is turned into a mutation, so
@@ -14276,7 +14406,9 @@ async fn control_plane_rebuild_index(
14276
14406
  "{}:{}",
14277
14407
  contract.environment.state_namespace, request.collection
14278
14408
  );
14279
- let created = state.db.create_equality_index(&capability, &request.field)?;
14409
+ let created = state
14410
+ .db
14411
+ .create_equality_index(&capability, &request.field)?;
14280
14412
  Ok(Json(json!({
14281
14413
  "collection": request.collection,
14282
14414
  "field": request.field,
@@ -14324,10 +14456,9 @@ async fn control_plane_operations(
14324
14456
  let matched = operations
14325
14457
  .iter()
14326
14458
  .filter(|operation| {
14327
- query
14328
- .collection
14329
- .as_deref()
14330
- .is_none_or(|collection| control_plane::collection_of(&operation.capability) == collection)
14459
+ query.collection.as_deref().is_none_or(|collection| {
14460
+ control_plane::collection_of(&operation.capability) == collection
14461
+ })
14331
14462
  })
14332
14463
  .filter(|operation| {
14333
14464
  query.kind.as_deref().is_none_or(|kind| {
@@ -14353,9 +14484,7 @@ async fn control_plane_operations(
14353
14484
  }
14354
14485
 
14355
14486
  /// Peers, causal position, and what replication still owes.
14356
- async fn control_plane_replication(
14357
- State(state): State<AppState>,
14358
- ) -> Result<Json<Value>, ApiError> {
14487
+ async fn control_plane_replication(State(state): State<AppState>) -> Result<Json<Value>, ApiError> {
14359
14488
  let db = state.db.clone();
14360
14489
  let namespace = state.namespace.to_string();
14361
14490
  let scan_namespace = namespace.clone();
@@ -14408,8 +14537,7 @@ async fn control_plane_applications(
14408
14537
  .iter()
14409
14538
  .map(|(environment, revision_id)| {
14410
14539
  let instance = instances.iter().find(|instance| {
14411
- instance.environment == *environment
14412
- && instance.revision_id == *revision_id
14540
+ instance.environment == *environment && instance.revision_id == *revision_id
14413
14541
  });
14414
14542
  json!({
14415
14543
  "environment": environment,
@@ -14722,10 +14850,7 @@ async fn control_plane_record_provenance(
14722
14850
  /// Computed from the two things that actually decide it: the capabilities the
14723
14851
  /// principal holds, and the actions and policies the contract declares. Nothing
14724
14852
  /// is inferred from the agent's name or history.
14725
- fn agent_access(
14726
- contract: &ApplicationRuntimeContract,
14727
- capabilities: &[String],
14728
- ) -> Vec<Value> {
14853
+ fn agent_access(contract: &ApplicationRuntimeContract, capabilities: &[String]) -> Vec<Value> {
14729
14854
  let holds = |required: &[String]| required.iter().all(|value| capabilities.contains(value));
14730
14855
  contract
14731
14856
  .state
@@ -15101,7 +15226,10 @@ async fn state_diff(
15101
15226
  object.insert("to".into(), control_plane::revision_summary_to_json(&to));
15102
15227
  object.insert(
15103
15228
  "relationship".into(),
15104
- json!(match (from.resource == to.resource, to.parent_id.as_ref() == Some(&from.id)) {
15229
+ json!(match (
15230
+ from.resource == to.resource,
15231
+ to.parent_id.as_ref() == Some(&from.id)
15232
+ ) {
15105
15233
  (true, true) => "parent",
15106
15234
  (true, false) => "same-resource",
15107
15235
  (false, _) => "cross-resource",
@@ -15146,7 +15274,15 @@ async fn state_conflicts(
15146
15274
  fn control_plane_reconciliation_inputs(
15147
15275
  store: &feltdb::StateStore,
15148
15276
  request: &control_plane::ReconciliationPlanRequest,
15149
- ) -> Result<(StateRevision, StateRevision, StateRevision, feltdb::ReconciliationPlan), ApiError> {
15277
+ ) -> Result<
15278
+ (
15279
+ StateRevision,
15280
+ StateRevision,
15281
+ StateRevision,
15282
+ feltdb::ReconciliationPlan,
15283
+ ),
15284
+ ApiError,
15285
+ > {
15150
15286
  let plan = request.to_plan().map_err(|message| {
15151
15287
  control_plane_error(StatusCode::UNPROCESSABLE_ENTITY, "invalid_plan", message)
15152
15288
  })?;
@@ -15169,11 +15305,10 @@ async fn state_reconciliation_plan(
15169
15305
  let store = control_plane_state_store(&state)?;
15170
15306
  let (base, left, right, plan) = control_plane_reconciliation_inputs(&store, &request)?;
15171
15307
  let classification = feltdb::ConflictClassification::classify(&base, &left, &right);
15172
- let preview = feltdb::apply_reconciliation_plan(&base, &left, &right, &plan).map_err(
15173
- |message| {
15308
+ let preview =
15309
+ feltdb::apply_reconciliation_plan(&base, &left, &right, &plan).map_err(|message| {
15174
15310
  control_plane_error(StatusCode::UNPROCESSABLE_ENTITY, "plan_refused", message)
15175
- },
15176
- )?;
15311
+ })?;
15177
15312
  let mut content = serde_json::from_str::<Value>(&preview).unwrap_or(Value::Null);
15178
15313
  redact_inspection_value(&mut content);
15179
15314
  Ok(Json(json!({
@@ -15221,11 +15356,7 @@ async fn state_reconciliation_execute(
15221
15356
  outcome.materialized_state.authority.clone(),
15222
15357
  )
15223
15358
  .map_err(|error| {
15224
- control_plane_error(
15225
- StatusCode::CONFLICT,
15226
- "revision_refused",
15227
- error.to_string(),
15228
- )
15359
+ control_plane_error(StatusCode::CONFLICT, "revision_refused", error.to_string())
15229
15360
  })?;
15230
15361
  // The two must agree. They are computed by the same constructor from the
15231
15362
  // same content, parent and authority, so a disagreement means the store and
@@ -15359,7 +15490,10 @@ mod worker_identity_tests {
15359
15490
 
15360
15491
  #[cfg(test)]
15361
15492
  mod authority_gate_tests {
15362
- use super::{api_error_body, authorize_transaction_collections, require_bound_tenant, state_authorization};
15493
+ use super::{
15494
+ api_error_body, authorize_transaction_collections, require_bound_tenant,
15495
+ state_authorization,
15496
+ };
15363
15497
  use axum::http::{HeaderMap, HeaderValue, StatusCode};
15364
15498
  use feltdb::{
15365
15499
  application::{
@@ -15476,7 +15610,10 @@ mod authority_gate_tests {
15476
15610
  let error = require_bound_tenant(&headers, "tenant-b").unwrap_err();
15477
15611
  assert_eq!(error.0, StatusCode::FORBIDDEN);
15478
15612
  let body: serde_json::Value = serde_json::from_str(&error.1).unwrap();
15479
- assert_eq!(body.get("code").and_then(serde_json::Value::as_str), Some("AUTHORITY_SCOPE_MISMATCH"));
15613
+ assert_eq!(
15614
+ body.get("code").and_then(serde_json::Value::as_str),
15615
+ Some("AUTHORITY_SCOPE_MISMATCH")
15616
+ );
15480
15617
  }
15481
15618
 
15482
15619
  #[test]