@feltdb/core 0.8.4 → 0.8.6
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/create/package-versions.js +1 -1
- package/dist/create/server-source/Cargo.lock +165 -0
- package/dist/create/server-source/Cargo.toml +9 -0
- package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
- package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
- package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
- package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
- package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
- package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
- package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
- package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
- package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
- package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
- package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
- package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
- package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
- package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
- package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
- package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
- package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
- package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
- package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
- package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
- package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
- package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
- package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
- package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
- package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
- package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
- package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
- package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
- package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
- package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
- package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
- package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
- package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
- package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
- package/dist/create/server-source/crates/feltdb/src/lib.rs +1648 -46
- package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
- package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
- package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
- package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
- package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
- package/dist/create/server-source/crates/feltdb/src/operation.rs +39 -0
- package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
- package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
- package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
- package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
- package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
- package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
- package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
- package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
- package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
- package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
- package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +79 -70
- package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
- package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
- package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
- package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
- package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
- package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
- package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
- package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
- package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
- package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
- package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
- package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
- package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
- package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
- package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
- package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
- package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
- package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
- package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
- package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
- package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
- package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
- package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
- package/dist/create/server-source/crates/feltdb/src/state_contract.rs +13 -4
- package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
- package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
- package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
- package/dist/create/server-source/crates/feltdb/src/state_model.rs +1565 -536
- package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
- package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
- package/dist/create/server-source/crates/feltdb/src/storage.rs +9 -3
- package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
- package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
- package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
- package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
- package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
- package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
- package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
- package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
- package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
- package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +3 -4
- package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +132 -0
- package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
- package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +272 -0
- package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +467 -0
- package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +309 -0
- package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +445 -0
- package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +518 -0
- package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
- package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
- package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
- package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
- package/dist/create/server-source/crates/feltdb/tests/operational_health_contract.rs +278 -0
- package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +2 -1
- package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +80 -25
- package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
- package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
- package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
- package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
- package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1365 -0
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
- package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
- package/dist/create/server-source/crates/feltdb/tests/replicated_history_contract.rs +417 -0
- package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
- package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
- package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
- package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
- package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
- package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
- package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
- package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
- package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
- package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
- package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
- package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
- package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
- package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
- package/dist/create/server-source/crates/feltdb/tests/workload_envelope_contract.rs +442 -0
- package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +16 -1
- package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +695 -47
- package/dist/create/server-source/crates/feltdb-server/src/metrics.rs +21 -0
- package/dist/studio-app/assets/{feltdb_wasm-CVQWgXO-.js → feltdb_wasm-C1VhI-U5.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-C8HXbAXb.wasm +0 -0
- package/dist/studio-app/assets/{index-DwgNAIIX.js → index-Bbos1m2U.js} +1 -1
- package/dist/studio-app/index.html +1 -1
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/workload.d.ts +2 -1
- package/dist/workload.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-CNVpvaZV.wasm +0 -0
|
@@ -40,6 +40,17 @@ pub struct ApiKeyRecord {
|
|
|
40
40
|
pub namespaces: Vec<String>,
|
|
41
41
|
#[serde(default)]
|
|
42
42
|
pub revoked: bool,
|
|
43
|
+
/// The worker this credential *is*, when it is a worker credential.
|
|
44
|
+
///
|
|
45
|
+
/// A key without one authenticates as a service, which is what every key
|
|
46
|
+
/// did before this field existed and what every key without it still does.
|
|
47
|
+
/// A key with one authenticates as `Subject::Worker(worker_id)` and is
|
|
48
|
+
/// thereby **narrower**, not wider: the worker lifecycle routes compare the
|
|
49
|
+
/// authenticated subject against the `worker_id` in the request body, so
|
|
50
|
+
/// such a credential can act as exactly one worker and no other, and cannot
|
|
51
|
+
/// satisfy a check that requires a human or service subject.
|
|
52
|
+
#[serde(default)]
|
|
53
|
+
pub worker_id: Option<String>,
|
|
43
54
|
}
|
|
44
55
|
|
|
45
56
|
#[derive(Debug, Clone, Serialize)]
|
|
@@ -104,6 +115,9 @@ impl KeyStore {
|
|
|
104
115
|
scopes: token.scopes,
|
|
105
116
|
namespaces: vec![token.namespace],
|
|
106
117
|
revoked: false,
|
|
118
|
+
// Legacy credentials predate worker identity and
|
|
119
|
+
// stay services, which is what they already were.
|
|
120
|
+
worker_id: None,
|
|
107
121
|
});
|
|
108
122
|
}
|
|
109
123
|
(records, true)
|
|
@@ -141,12 +155,25 @@ impl KeyStore {
|
|
|
141
155
|
.iter()
|
|
142
156
|
.any(|allowed| allowed == "*" || allowed == namespace);
|
|
143
157
|
if namespace_allowed && verify_api_key(token, &record.hash) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
// The credential decides the subject type. A worker
|
|
159
|
+
// credential can never present as a service and a service
|
|
160
|
+
// credential can never present as a worker, because neither
|
|
161
|
+
// the request nor any header participates in this choice.
|
|
162
|
+
Some(match &record.worker_id {
|
|
163
|
+
Some(worker) => Principal {
|
|
164
|
+
key_id: record.id.clone(),
|
|
165
|
+
scopes: record.scopes.clone(),
|
|
166
|
+
subject_type: "worker".into(),
|
|
167
|
+
identity_id: Some(worker.clone()),
|
|
168
|
+
session_id: None,
|
|
169
|
+
},
|
|
170
|
+
None => Principal {
|
|
171
|
+
key_id: record.id.clone(),
|
|
172
|
+
scopes: record.scopes.clone(),
|
|
173
|
+
subject_type: "service".into(),
|
|
174
|
+
identity_id: None,
|
|
175
|
+
session_id: None,
|
|
176
|
+
},
|
|
150
177
|
})
|
|
151
178
|
} else {
|
|
152
179
|
None
|
|
@@ -159,6 +186,21 @@ impl KeyStore {
|
|
|
159
186
|
name: String,
|
|
160
187
|
scopes: Vec<String>,
|
|
161
188
|
namespaces: Vec<String>,
|
|
189
|
+
) -> Result<CreatedApiKey, String> {
|
|
190
|
+
self.create_for_worker(name, scopes, namespaces, None)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/// Issue a credential that authenticates as one specific worker.
|
|
194
|
+
///
|
|
195
|
+
/// `worker_id` of `None` produces an ordinary service credential, so this
|
|
196
|
+
/// is the one construction path and [`KeyStore::create`] is the common case
|
|
197
|
+
/// spelled out.
|
|
198
|
+
pub fn create_for_worker(
|
|
199
|
+
&self,
|
|
200
|
+
name: String,
|
|
201
|
+
scopes: Vec<String>,
|
|
202
|
+
namespaces: Vec<String>,
|
|
203
|
+
worker_id: Option<String>,
|
|
162
204
|
) -> Result<CreatedApiKey, String> {
|
|
163
205
|
let secret: String = rand::thread_rng()
|
|
164
206
|
.sample_iter(&Alphanumeric)
|
|
@@ -185,6 +227,7 @@ impl KeyStore {
|
|
|
185
227
|
scopes,
|
|
186
228
|
namespaces,
|
|
187
229
|
revoked: false,
|
|
230
|
+
worker_id,
|
|
188
231
|
});
|
|
189
232
|
self.persist()?;
|
|
190
233
|
Ok(CreatedApiKey { id, secret: token })
|
|
@@ -266,13 +309,11 @@ fn verify_api_key(token: &str, stored_hash: &str) -> bool {
|
|
|
266
309
|
.is_ok();
|
|
267
310
|
}
|
|
268
311
|
|
|
269
|
-
PasswordHash::new(stored_hash)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
.is_ok()
|
|
275
|
-
})
|
|
312
|
+
PasswordHash::new(stored_hash).ok().is_some_and(|parsed| {
|
|
313
|
+
Argon2::default()
|
|
314
|
+
.verify_password(token.as_bytes(), &parsed)
|
|
315
|
+
.is_ok()
|
|
316
|
+
})
|
|
276
317
|
}
|
|
277
318
|
|
|
278
319
|
#[cfg(test)]
|
|
@@ -341,4 +382,114 @@ mod tests {
|
|
|
341
382
|
assert!(migrated.contains("managed-instance"));
|
|
342
383
|
let _ = fs::remove_file(path);
|
|
343
384
|
}
|
|
385
|
+
|
|
386
|
+
// ------------------------------------------------------------------
|
|
387
|
+
// Worker identity.
|
|
388
|
+
//
|
|
389
|
+
// The whole worker security boundary rests on one thing: which subject a
|
|
390
|
+
// credential authenticates as. That is decided here, by the stored
|
|
391
|
+
// credential alone — no request field, header or body participates — so
|
|
392
|
+
// these tests are the root of the boundary the workload lifecycle routes
|
|
393
|
+
// enforce further up.
|
|
394
|
+
// ------------------------------------------------------------------
|
|
395
|
+
|
|
396
|
+
fn key_store(name: &str) -> (PathBuf, KeyStore) {
|
|
397
|
+
let path = std::env::temp_dir().join(format!(
|
|
398
|
+
"feltdb-worker-identity-{name}-{}-{}.json",
|
|
399
|
+
std::process::id(),
|
|
400
|
+
rand::random::<u64>()
|
|
401
|
+
));
|
|
402
|
+
let _ = fs::remove_file(&path);
|
|
403
|
+
let store = KeyStore::load(&path).unwrap();
|
|
404
|
+
(path, store)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
#[test]
|
|
408
|
+
fn a_worker_credential_authenticates_as_that_one_worker() {
|
|
409
|
+
let (path, store) = key_store("worker");
|
|
410
|
+
let key = store
|
|
411
|
+
.create_for_worker(
|
|
412
|
+
"extractor".into(),
|
|
413
|
+
vec!["state:read".into()],
|
|
414
|
+
vec!["default".into()],
|
|
415
|
+
Some("worker-x".into()),
|
|
416
|
+
)
|
|
417
|
+
.unwrap();
|
|
418
|
+
|
|
419
|
+
let principal = store
|
|
420
|
+
.authenticate(&key.secret, "default")
|
|
421
|
+
.expect("authenticates");
|
|
422
|
+
assert_eq!(principal.subject_type, "worker");
|
|
423
|
+
assert_eq!(
|
|
424
|
+
principal.identity_id.as_deref(),
|
|
425
|
+
Some("worker-x"),
|
|
426
|
+
"the worker it is, not the key it uses, is the identity"
|
|
427
|
+
);
|
|
428
|
+
let _ = fs::remove_file(path);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
#[test]
|
|
432
|
+
fn a_service_credential_cannot_present_as_a_worker() {
|
|
433
|
+
let (path, store) = key_store("service");
|
|
434
|
+
let key = store
|
|
435
|
+
.create(
|
|
436
|
+
"control-plane".into(),
|
|
437
|
+
vec!["state:read".into()],
|
|
438
|
+
vec!["default".into()],
|
|
439
|
+
)
|
|
440
|
+
.unwrap();
|
|
441
|
+
|
|
442
|
+
let principal = store
|
|
443
|
+
.authenticate(&key.secret, "default")
|
|
444
|
+
.expect("authenticates");
|
|
445
|
+
assert_eq!(
|
|
446
|
+
principal.subject_type, "service",
|
|
447
|
+
"a key issued without a worker is a service, exactly as before this field existed"
|
|
448
|
+
);
|
|
449
|
+
assert_eq!(principal.identity_id, None);
|
|
450
|
+
let _ = fs::remove_file(path);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
#[test]
|
|
454
|
+
fn worker_identity_survives_a_restart_of_the_credential_store() {
|
|
455
|
+
let (path, store) = key_store("reload");
|
|
456
|
+
let key = store
|
|
457
|
+
.create_for_worker(
|
|
458
|
+
"extractor".into(),
|
|
459
|
+
vec!["state:read".into()],
|
|
460
|
+
vec!["default".into()],
|
|
461
|
+
Some("worker-x".into()),
|
|
462
|
+
)
|
|
463
|
+
.unwrap();
|
|
464
|
+
drop(store);
|
|
465
|
+
|
|
466
|
+
// A credential that forgot which worker it was on restart would silently
|
|
467
|
+
// downgrade to a service and start failing the identity check.
|
|
468
|
+
let reopened = KeyStore::load(&path).unwrap();
|
|
469
|
+
let principal = reopened
|
|
470
|
+
.authenticate(&key.secret, "default")
|
|
471
|
+
.expect("authenticates");
|
|
472
|
+
assert_eq!(principal.subject_type, "worker");
|
|
473
|
+
assert_eq!(principal.identity_id.as_deref(), Some("worker-x"));
|
|
474
|
+
let _ = fs::remove_file(path);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
#[test]
|
|
478
|
+
fn a_revoked_worker_credential_authenticates_as_nothing() {
|
|
479
|
+
let (path, store) = key_store("revoked");
|
|
480
|
+
let key = store
|
|
481
|
+
.create_for_worker(
|
|
482
|
+
"extractor".into(),
|
|
483
|
+
vec!["state:read".into()],
|
|
484
|
+
vec!["default".into()],
|
|
485
|
+
Some("worker-x".into()),
|
|
486
|
+
)
|
|
487
|
+
.unwrap();
|
|
488
|
+
assert!(store.revoke(&key.id).unwrap());
|
|
489
|
+
assert!(
|
|
490
|
+
store.authenticate(&key.secret, "default").is_none(),
|
|
491
|
+
"revocation is not weakened by carrying a worker identity"
|
|
492
|
+
);
|
|
493
|
+
let _ = fs::remove_file(path);
|
|
494
|
+
}
|
|
344
495
|
}
|