From 98e550cb75c98c4c77b32e8c80f5a3d591a65611 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 03:24:48 +0100 Subject: [PATCH 01/52] fix(external-grants): own atomic profile admission and append agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 68 ++++++++++++++++++- .../external-grant-admission-atomicity.json | 1 + 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 release-notes/external-grant-admission-atomicity.json diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index 1b0378cd726..f0b9ecbea6b 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -51,6 +51,10 @@ impl Profile { } fn assistant_profile(source: &Value) -> Result<(), ApiError> { + #[cfg(test)] + if tests::SERVICE_PROFILE.get() && Profile::stored(source)? == Profile::Service { + return Ok(()); + } Profile::stored(source)?.issuable() } @@ -65,7 +69,7 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { } // Issuance-only scan: authentication retains its existing indexed lookup and reads. -// TRANSITIONS serializes completion; several grants of the same profile are allowed. +// append owns the admission lock; several grants of the same profile are allowed. fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { let profile = Profile::stored(source)?; let principal = principal(source)?; @@ -111,6 +115,10 @@ pub const SCOPES: &[&str] = &[ // against concurrent writers in the authoritative store. pub static TRANSITIONS: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(()); +// Synchronous because append never awaits. Callers may already hold TRANSITIONS: +// always acquire that outer lifecycle lock first, never from inside admission. +static ADMISSIONS: std::sync::Mutex<()> = std::sync::Mutex::new(()); + pub fn owning_person(state: &AppState) -> Result<&str, ApiError> { state.owning_person.as_deref() .filter(|person| person.starts_with("person/") && person.matches('/').count() == 1 && person.len() > 7) @@ -140,6 +148,13 @@ pub fn latest(state: &AppState, subject: &str, kind: &str) -> Result) -> Result { + // Subject fences do not serialize grants on independent subjects for one + // principal. Keep the cross-subject scan and authoritative append indivisible. + let _admission = if kind == GRANTED { + Some(ADMISSIONS.lock().map_err(|_| ApiError::internal("external grant admission lock poisoned"))?) + } else { + None + }; if matches!(kind, BEGUN | GRANTED | POLICY | REVOKED) { assistant_profile(&value)?; digest_only(&value)?; @@ -277,6 +292,57 @@ pub fn authorize_route(session: &ClientSession, request: &Request) -> Resu mod tests { use super::*; + // Only the current fixture thread can exercise the reserved profile through + // the real mutation/session boundary. Production issuable() stays closed. + thread_local! { + pub(super) static SERVICE_PROFILE: std::cell::Cell = const { std::cell::Cell::new(false) }; + } + + fn concurrent_grants(profiles: [&str; 2]) -> (usize, usize) { + let root = tempfile::tempdir().unwrap(); + let mut state = crate::api::tests_shared::state(root.path()); + state.owning_person = Some("person/owner".into()); + let barrier = std::sync::Barrier::new(2); + let results = std::thread::scope(|scope| { + let handles = profiles.into_iter().enumerate().map(|(index, profile)| { + let state = &state; + let barrier = &barrier; + scope.spawn(move || { + SERVICE_PROFILE.set(true); + let id = if index == 0 { "111111111111111111111111" } else { "222222222222222222222222" }; + let source = json!({"profile":profile,"grant_id":id,"principal":PRINCIPAL, + "issuer":"person/owner","session_actor":format!("{PRINCIPAL}/session/{id}"), + "expires_at_unix_ms":u64::MAX,"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":["read.assistant.summary"], + "credential_hash":credential_digest(id)}); + let subject = subject(id).unwrap(); + let begun = append(state, subject.clone(), BEGUN, "person/owner", source.clone(), None).unwrap(); + barrier.wait(); + append(state, subject, GRANTED, "person/owner", source, Some(&begun)) + }) + }).collect::>(); + handles.into_iter().map(|handle| handle.join().unwrap()).collect::>() + }); + let admitted = results.iter().filter(|result| result.is_ok()).count(); + let usable = std::thread::spawn(move || { + SERVICE_PROFILE.set(true); + results.iter().filter_map(|result| result.as_ref().ok()) + .filter(|grant| session(&state, grant, "http").is_ok()).count() + }).join().unwrap(); + (admitted, usable) + } + + #[test] + fn concurrent_opposite_profiles_have_exactly_one_usable_grant() { + assert_eq!(concurrent_grants(["assistant", "service"]), (1, 1)); + } + + #[test] + fn concurrent_same_profile_grants_remain_usable() { + assert_eq!(concurrent_grants(["assistant", "assistant"]), (2, 2)); + assert_eq!(concurrent_grants(["service", "service"]), (2, 2)); + } + #[test] fn persisted_active_profiles_are_checked_at_grant_admission() { let root = tempfile::tempdir().unwrap(); diff --git a/release-notes/external-grant-admission-atomicity.json b/release-notes/external-grant-admission-atomicity.json new file mode 100644 index 00000000000..d2ec8c4255d --- /dev/null +++ b/release-notes/external-grant-admission-atomicity.json @@ -0,0 +1 @@ +{"version":1,"summary":"Make external-grant profile admission and append one owned critical section","replay":{"status":"none","detail":"Existing grant claims retain their meanings; no migration or replay change."},"schema":{"status":"none","detail":"No schema or registry change."},"rules":{"status":"none","detail":"The existing cross-profile admission rule is now atomic across independent grant subjects. Multiple same-profile grants remain allowed; service issuance stays disabled."},"compatibility":{"status":"none","detail":"Existing lifecycle and approval-once TRANSITIONS critical sections remain unchanged. Admission uses an inner synchronous lock and never awaits or acquires the outer lifecycle lock."},"downtime":{"status":"none","detail":"No deployment or activation change."},"manual":{"status":"none","detail":"No operator action required."},"recovery":{"status":"none","detail":"Existing expiry and append-only revocation remain unchanged; no recovery action required."},"commits":[]} From 5ec504caa58d7dc20738e0d4167490005e4a8d84 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 06:20:02 +0100 Subject: [PATCH 02/52] perf(external-grants): index and prefilter principal admission history agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 81 +++- crates/fractal-store/src/store.rs | 5 +- crates/fractal-store/src/store/runtime.rs | 128 ++++++ crates/fractal/tests/daemon_cost.rs | 2 + .../tests/daemon_cost/assistant_admission.rs | 395 ++++++++++++++++++ docs/st3/compatibility.md | 33 ++ docs/st3/large-value-sites.json | 272 ++++++------ docs/st3/large-values.md | 20 + .../external-grant-admission-index.json | 12 + 9 files changed, 807 insertions(+), 141 deletions(-) create mode 100644 crates/fractal/tests/daemon_cost/assistant_admission.rs create mode 100644 release-notes/external-grant-admission-index.json diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index f0b9ecbea6b..f9c4bb13d62 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -70,15 +70,30 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { // Issuance-only scan: authentication retains its existing indexed lookup and reads. // append owns the admission lock; several grants of the same profile are allowed. +// Filter revoked/expired history before loading claim bodies into Rust. Expiry +// uses the latest policy, not the original grant. Keep malformed missing fields +// in the result so the existing validation below still reports them. +const ADMISSION_QUERY: &str = + "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) + AND (?5 IS NULL OR COALESCE( + (SELECT CASE WHEN json_type(policy.body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(policy.body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5,0) END + FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 ORDER BY policy.store_index DESC LIMIT 1), + CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { let profile = Profile::stored(source)?; let principal = principal(source)?; + // Without a valid owner the old scan must still surface its configuration + // error before examining expiry; do not prefilter those rows. + let expiry_cut = owning_person(state).ok().map(|_| client_now_ms() as u64); let ids = { let connection = state.store.readers.get(); - let mut query = connection.prepare( - "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2" - ).map_err(ApiError::internal)?; - query.query_map(rusqlite::params![GRANTED, principal], |row| row.get::<_, String>(0)) + let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-h99f1a302c7b1 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ ADMISSION_QUERY).map_err(ApiError::internal)?; + query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut], |row| row.get::<_, String>(0)) .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? }; for id in ids { @@ -332,6 +347,54 @@ mod tests { (admitted, usable) } + #[test] + fn admission_sql_filters_only_inactive_effective_policies() { + let connection = rusqlite::Connection::open_in_memory().unwrap(); + connection.execute_batch( + "CREATE TABLE claims(id TEXT,subject TEXT,kind TEXT,body TEXT,store_index INTEGER PRIMARY KEY); + CREATE INDEX principal_scan ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); + CREATE INDEX subject_kind ON claims(subject,kind,store_index);" + ).unwrap(); + let fixtures = [ + ("expired", json!({"fields":{"expires_at_unix_ms":99}}), None, false), + ("live", json!({"fields":{"expires_at_unix_ms":101}}), None, true), + ("boundary", json!({"fields":{"expires_at_unix_ms":100}}), None, false), + ("max", json!({"fields":{"expires_at_unix_ms":u64::MAX}}), None, true), + ("negative", json!({"fields":{"expires_at_unix_ms":-1}}), None, false), + ("string", json!({"fields":{"expires_at_unix_ms":"101"}}), None, false), + ("float", json!({"fields":{"expires_at_unix_ms":101.0}}), None, false), + ("absent-expiry", json!({"fields":{}}), None, false), + // Missing fields must still reach fields() and its existing error. + ("absent-fields", json!({}), None, true), + ("renewed", json!({"fields":{"expires_at_unix_ms":99}}), + Some(json!({"fields":{"expires_at_unix_ms":101}})), true), + ("shortened", json!({"fields":{"expires_at_unix_ms":101}}), + Some(json!({"fields":{"expires_at_unix_ms":99}})), false), + ("invalid-policy", json!({"fields":{"expires_at_unix_ms":99}}), + Some(json!({})), true), + ]; + let mut expected = Vec::new(); + for (id, grant, policy, included) in fixtures { + connection.execute("INSERT INTO claims(id,subject,kind,body) VALUES(?1,?1,?2,?3)", + rusqlite::params![id, GRANTED, grant.to_string()]).unwrap(); + if let Some(policy) = policy { + connection.execute("INSERT INTO claims(id,subject,kind,body) VALUES(?1,?2,?3,?4)", + rusqlite::params![format!("{id}-policy"), id, POLICY, policy.to_string()]).unwrap(); + } + if included { expected.push(id.to_owned()); } + } + let mut found = connection.prepare(ADMISSION_QUERY).unwrap() + .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, 100_u64], + |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); + found.sort(); + expected.sort(); + assert_eq!(found, expected); + let unfiltered = connection.prepare(ADMISSION_QUERY).unwrap() + .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, Option::::None], + |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); + assert_eq!(unfiltered.len(), 12, "invalid owner configuration must not hide validation errors"); + } + #[test] fn concurrent_opposite_profiles_have_exactly_one_usable_grant() { assert_eq!(concurrent_grants(["assistant", "service"]), (1, 1)); @@ -368,8 +431,16 @@ mod tests { state.store.append_claim(&ClaimInput { subject: service_subject, kind: REVOKED.into(), actor: Some("person/owner".into()), fields: BTreeMap::new(), evidence: vec![grant.id.clone()], - expected_subject: Some(Some(grant.id)), idempotency_key: None, + expected_subject: Some(Some(grant.id.clone())), idempotency_key: None, }).unwrap(); + let candidates = { + let connection = state.store.readers.get(); + connection.prepare(ADMISSION_QUERY).unwrap() + .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, client_now_ms() as u64], |row| row.get::<_, String>(0)) + .unwrap().collect::, _>>().unwrap() + }; + assert_eq!(candidates.len(), 2); + assert!(!candidates.contains(&grant.id), "revoked history must not reach the admission loop"); assert!(append(&state, next, GRANTED, "person/owner", source, None).is_ok()); } diff --git a/crates/fractal-store/src/store.rs b/crates/fractal-store/src/store.rs index 17b56ee1577..221793024b0 100644 --- a/crates/fractal-store/src/store.rs +++ b/crates/fractal-store/src/store.rs @@ -780,7 +780,7 @@ pub struct AgentWorkQueue { /// Fractal's projection tables, and the indexes its folds read the claim log through. The /// graph creates its own tables first; see `smallclaims::store::SCHEMA`. -const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-h22c8c670811c owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" +const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-hb9696ca837f7 owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL; @@ -930,6 +930,9 @@ WHERE kind='custom.client.pairing-completed'; CREATE INDEX IF NOT EXISTS claims_assistant_v1_credential_index ON claims(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'; +-- Match parameterized admission by kind and effective principal, including legacy ChatGPT grants. +CREATE INDEX IF NOT EXISTS claims_assistant_v1_principal_index +ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); -- A runtime incarnation's claims about a subject by acceptance time, so when a session began -- and last changed are two seeks instead of a read of every claim the subject has. The -- expression is INCARNATION_OF_CLAIM, which queries repeat so the planner uses this index. diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index c25edbe01f1..95bfe580810 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -830,6 +830,134 @@ impl FractalRuntime { mod schema_install_tests { use super::*; + #[test] + fn assistant_principal_index_installs_on_existing_claims_and_reopens_without_ddl() { + const GRANTED: &str = "custom.client.assistant.v1.granted"; + const REVOKED: &str = "custom.client.assistant.v1.revoked"; + const POLICY: &str = "custom.client.assistant.v1.policy"; + const INDEX: &str = "claims_assistant_v1_principal_index"; + const SELECT: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; + const ACTIVE: &str = + "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) + AND (?5 IS NULL OR COALESCE( + (SELECT CASE WHEN json_type(policy.body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(policy.body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5,0) END + FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 ORDER BY policy.store_index DESC LIMIT 1), + CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; + + fn snapshot(connection: &Connection) -> Vec> { + connection + .prepare("SELECT * FROM claims ORDER BY store_index") + .unwrap() + .query_map([], |row| { + (0..row.as_ref().column_count()).map(|column| row.get(column)).collect() + }) + .unwrap() + .collect::>() + .unwrap() + } + + fn plan(connection: &Connection, sql: &str, active: bool) -> Vec { + let parameters: Vec<&dyn rusqlite::ToSql> = if active { + vec![&GRANTED, &"assistant/chatgpt", &REVOKED, &POLICY, &100_u64] + } else { + vec![&GRANTED, &"assistant/chatgpt"] + }; + connection + .prepare(&format!("EXPLAIN QUERY PLAN {sql}")) + .unwrap() + .query_map(parameters.as_slice(), |row| row.get(3)) + .unwrap() + .collect::>() + .unwrap() + } + + // These supported stores need additive DDL, not a data or version conversion. + for version in [18, 19, fractal_schema::STORAGE_VERSION] { + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("claims.sqlite"); + let connection = Connection::open(&path).unwrap(); + connection.execute_batch(smallclaims::store::SCHEMA).unwrap(); + install_initial_schema(&connection, true).unwrap(); + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index;").unwrap(); + connection.pragma_update(None, "user_version", version).unwrap(); + connection.execute( + "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES('batch','node',1,'hash','1')", + [], + ).unwrap(); + for (id, subject, kind, body) in [ + ("legacy", "custom/client/legacy", GRANTED, r#"{"fields":{"expires_at_unix_ms":200}}"#), + ("chatgpt", "custom/client/chatgpt", GRANTED, r#"{"fields":{"principal":"assistant/chatgpt","expires_at_unix_ms":50}}"#), + ("mcp", "custom/client/mcp", GRANTED, r#"{"fields":{"principal":"assistant/mcp","expires_at_unix_ms":200}}"#), + ("policy", "custom/client/chatgpt", POLICY, r#"{"fields":{"expires_at_unix_ms":200}}"#), + ("revoked", "custom/client/legacy", REVOKED, r#"{"fields":{}}"#), + ("unrelated", "custom/test/unrelated", "custom.test.recorded", r#"{"fields":{}}"#), + ] { + connection.execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,body,predecessors,accepted_at_unix_ms) VALUES(?1,'batch',?2,?3,'node',?4,'[]','1')", + params![id, subject, kind, body], + ).unwrap(); + } + let before = snapshot(&connection); + let plans_before = [plan(&connection, SELECT, false), plan(&connection, ACTIVE, true)]; + assert!(plans_before.iter().flatten().all(|detail| !detail.contains(INDEX))); + drop(connection); + + let connection = Connection::open(&path).unwrap(); + migrate_schema(&connection).unwrap(); + install_initial_schema(&connection, false).unwrap(); + assert_eq!(snapshot(&connection), before, "version {version}: claim bytes"); + assert_eq!( + connection.pragma_query_value(None, "user_version", |row| row.get::<_, u32>(0)).unwrap(), + version, + ); + for (sql, active, previous) in [(SELECT, false, &plans_before[0]), (ACTIVE, true, &plans_before[1])] { + let current = plan(&connection, sql, active); + eprintln!("assistant admission version={version} active={active} before={previous:?} after={current:?}"); + assert!( + current.iter().any(|detail| detail.contains("SEARCH") && detail.contains(INDEX) + && detail.contains("kind=?") && detail.contains("=?")), + "version {version}: before={previous:?}; after={current:?}", + ); + } + for (principal, mut expected) in [ + ("assistant/chatgpt", vec!["chatgpt".to_owned(), "legacy".to_owned()]), + ("assistant/mcp", vec!["mcp".to_owned()]), + ] { + let mut found = connection.prepare(SELECT).unwrap() + .query_map(params![GRANTED, principal], |row| row.get::<_, String>(0)) + .unwrap().collect::>>().unwrap(); + found.sort(); + expected.sort(); + assert_eq!(found, expected); + } + let active = connection.prepare(ACTIVE).unwrap() + .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, 100_u64], |row| row.get::<_, String>(0)) + .unwrap().collect::>>().unwrap(); + assert_eq!(active, vec!["chatgpt"]); + let unfiltered = connection.prepare(ACTIVE).unwrap() + .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, Option::::None], |row| row.get::<_, String>(0)) + .unwrap().collect::>>().unwrap(); + assert_eq!(unfiltered.len(), 2, "no cutoff preserves unfiltered validation candidates"); + let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); + drop(connection); + + let connection = Connection::open(&path).unwrap(); + migrate_schema(&connection).unwrap(); + install_initial_schema(&connection, false).unwrap(); + assert_eq!(snapshot(&connection), before); + assert_eq!( + connection.pragma_query_value(None, "schema_version", |row| row.get::<_, u32>(0)).unwrap(), + cookie, + "an unchanged reopen must not rebuild the index", + ); + } + } + #[test] fn complete_runtime_schema_does_not_take_a_held_writer_lock() { let directory = tempfile::tempdir().unwrap(); diff --git a/crates/fractal/tests/daemon_cost.rs b/crates/fractal/tests/daemon_cost.rs index 84715be0dd1..c96558399d2 100644 --- a/crates/fractal/tests/daemon_cost.rs +++ b/crates/fractal/tests/daemon_cost.rs @@ -45,6 +45,8 @@ //! - `ST_BENCH_DIR` keeps generated stores for the next run, as for `daemon_bench`. //! - `ST_COST_REPORT` writes the measurements as JSON to that path. +mod assistant_admission; + use fractal_daemon::ConversationReadsStore; use fractal_daemon::CustomStore; use fractal_daemon::AdhocWorkStore; diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs new file mode 100644 index 00000000000..5fb7dcfbef2 --- /dev/null +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -0,0 +1,395 @@ +//! Opt-in, real HTTP/Unix daemon measurement (not a router oneshot or mocked daemon). +//! Run this same test source on 98e550cb and on PR3-B, sequentially on dev5: +//! ```sh +//! ST_ADMISSION_VARIANT=baseline cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 +//! ST_ADMISSION_VARIANT=indexed cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 +//! ``` +//! Copy only this file and its `mod assistant_admission;` registration to the A worktree. +//! The baseline must actually be built from 98e550cb: dropping an index on PR3-B does not +//! restore A's admission query. Use distinct CARGO_TARGET_DIR paths for the two worktrees: +//! Cargo freshness can otherwise reuse the baseline's artifacts for the indexed checkout. +//! ST_ADMISSION_HISTORY (default 10000) is expired grants PER principal; ST_ADMISSION_SAMPLES +//! (default 200) is measured GET/completion pairs PER read mode. Setup and proof creation are +//! outside timing. Each pair starts behind a barrier, with no sleeps, polling, retries or timers. +//! ST_ADMISSION_REPORT optionally saves the complete JSON report. Run on dev5; hardware is +//! observed from uname/lscpu in the report, not inferred from an environment label. +//! The index DDL timing is a synthetic startup migration probe on the populated disposable +//! real store, not total daemon startup or cold-disk startup. Latencies use the real daemon's +//! bound sockets, bearer middleware, grant lookup, projection and durable approval consumption. + +use std::{collections::BTreeMap, path::PathBuf, sync::Arc, time::{Instant, SystemTime, UNIX_EPOCH}}; + +use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD}; +use fractal_daemon::{api::{self, AppState}, client::Client, model::ClaimInput, store::Store}; +use fractal_daemon::{AttentionListStore as _, EvidenceStore as _, SeatsStore as _}; +use fractal_daemon::api::client_v0::assistant::authorization::{ReadPayload, request_digest, signing_bytes, HEADER}; +use ring::{rand::SystemRandom, signature::{Ed25519KeyPair, KeyPair as _}}; +use serde_json::{Value, json}; +use tokio::sync::Barrier; + +const OWNER: &str = "person/admission-bench"; +const NODE: &str = "admission-bench"; +const GRANTED: &str = "custom.client.assistant.v1.granted"; +const INDEX: &str = "claims_assistant_v1_principal_index"; +const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))"; +const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; +const INDEXED_QUERY: &str = + "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) + AND (?5 IS NULL OR COALESCE( + (SELECT CASE WHEN json_type(policy.body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(policy.body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5,0) END + FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 ORDER BY policy.store_index DESC LIMIT 1), + CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; +const PATH: &str = "/v1/client/assistant/summary"; + +fn number(name: &str, default: usize) -> usize { + let value = std::env::var(name).map_or(default, |s| s.parse().expect("positive integer setting")); + assert!(value > 0, "{name} must be positive"); + value +} + +fn value(response: Value) -> Value { + response.get("value").cloned().unwrap_or(response) +} + +fn key() -> Ed25519KeyPair { + let encoded = Ed25519KeyPair::generate_pkcs8(&SystemRandom::new()).unwrap(); + Ed25519KeyPair::from_pkcs8(encoded.as_ref()).unwrap() +} + +async fn begin(owner: &Client, mode: &str) -> Value { + value(owner.post("/v1/client/pairings", &json!({ + "api_version":"st3.client.v0", "device_name":"Admission measurement", + "assistant_id":"assistant/chatgpt", "scopes":["read.assistant.summary","read.assistant.attention","read.assistant.missions","read.assistant.agents"], + "expires_in_seconds":3600, "disclosure_consent":true, + "consent_evidence":"Disposable synthetic benchmark owner consent", "minimal_read_mode":mode, + })).await.unwrap()) +} + +async fn complete(http: &reqwest::Client, base: &str, challenge: &Value) -> Value { + let id = challenge["pairing_id"].as_str().unwrap().trim_start_matches("pairing/"); + let response = http.post(format!("{base}/v1/client/pairings/{id}/complete")) + .json(&json!({"api_version":"st3.client.v0", "code":challenge["code"], + "device_public_key":"BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc", "key_storage":"software"})) + .send().await.unwrap(); + let status = response.status(); + let body: Value = response.json().await.unwrap(); + assert!(status.is_success(), "completion {status}: {body}"); + value(body) +} + +fn proof(paired: &Value, signer: &Ed25519KeyPair, sequence: usize) -> String { + let parameters = BTreeMap::new(); + let payload = ReadPayload { + issuer:"scg/admission-bench".into(), identity:"chatgpt".into(), assistant_id:"assistant/chatgpt".into(), + grant_id:paired["grant"]["id"].as_str().unwrap().into(), + policy_revision:paired["grant"]["policy_revision"].as_u64().unwrap(), key_id:"approval-key/admission-bench".into(), + approval_id:format!("approval/admission-{sequence}"), execution_id:format!("execution/admission-{sequence}"), + projection:"summary".into(), max_response_bytes:4096, + request_digest:request_digest(PATH, ¶meters).unwrap(), parameters, + expires_at_unix_ms:u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap() + 60_000, + nonce:uuid::Uuid::new_v4().to_string(), + }; + let signature = URL_SAFE_NO_PAD.encode(signer.sign(signing_bytes(&payload).unwrap().as_bytes()).as_ref()); + URL_SAFE_NO_PAD.encode(serde_json::to_vec(&json!({"payload":payload,"signature":signature})).unwrap()) +} + +fn explain(connection: &rusqlite::Connection, query: &str) -> Vec { + let mut statement = connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")).unwrap(); + let mut rows = if query == A_QUERY { + statement.query(rusqlite::params![GRANTED, "assistant/chatgpt"]).unwrap() + } else { + statement.query(rusqlite::params![GRANTED, "assistant/chatgpt", "custom.client.assistant.v1.revoked", + "custom.client.assistant.v1.policy", + u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap()]).unwrap() + }; + let mut plan = Vec::new(); + while let Some(row) = rows.next().unwrap() { plan.push(row.get::<_, String>(3).unwrap()); } + plan +} + +fn p95(samples: &mut [f64]) -> f64 { + samples.sort_by(f64::total_cmp); + samples[(samples.len() * 95).div_ceil(100) - 1] +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 8)] +async fn authenticated_get_during_pairing() { + let Ok(variant) = std::env::var("ST_ADMISSION_VARIANT") else { return }; + assert!(matches!(variant.as_str(), "baseline" | "indexed")); + assert!(fractal_daemon::test_support::optimized_build(), "use --release"); + let indexed = variant == "indexed"; + let history = number("ST_ADMISSION_HISTORY", 10_000); + let samples = number("ST_ADMISSION_SAMPLES", 200); + let root = tempfile::tempdir().unwrap(); + let database = root.path().join("admission.sqlite"); + let store = Arc::new(Store::open(&database, NODE).unwrap()); + store.bind_fleet(super::super::daemon_bench::FLEET).unwrap(); + store.set_node_key(Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0)).unwrap(); + let state = AppState { + seat_admission:Default::default(), owning_person:Some(OWNER.into()), store:store.clone(), + notify:Arc::new(tokio::sync::Notify::new()), event_notify:tokio::sync::watch::channel(0).0, + node:NODE.into(), state_dir:root.path().into(), pty_root:root.path().join("pty"), pty_binary:PathBuf::from("pty"), + fleet_id:None, configured_peers:vec![], client_relay:None, native_session_home:None, + planner_default:Default::default(), harness_question_sink:None, assistant_receipts:Default::default(), private_notes:Default::default(), + }; + api::start_operation_report(&state); + // Match run_up/daemon_load: the generic lists do not own the independent + // attention/summary and agent-roster publication workers. + let mut roster_publications = store.subscribe_agent_roster(); + let mut attention_publications = store.subscribe_attention_list(); + api::start_agent_roster(&state); + api::start_attention_list(&state); + api::start_published_lists(&state); + // Observe the workers' real publication watches, not an HTTP retry or a + // synchronous test-only fold. Subscribe before starting to avoid lost wakes. + roster_publications.wait_for(|_| store.published_agent_roster(u64::MAX, false).is_some()) + .await.expect("the daemon publishes its initial agent roster"); + attention_publications.wait_for(|_| store.published_attention_list().is_some()) + .await.expect("the daemon publishes its initial attention view"); + let socket = root.path().join("owner.sock"); + let reserved = api::reserve_unix_socket(&socket, None).await.unwrap(); + let (ready_tx, ready_rx) = tokio::sync::oneshot::channel(); + let local_app = api::router(state.clone()); + let local = tokio::spawn(async move { + api::serve_reserved_unix_with_ready(reserved, local_app, None, || { ready_tx.send(()).unwrap(); }).await.unwrap(); + }); + ready_rx.await.unwrap(); + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let base = format!("http://{}", listener.local_addr().unwrap()); + let fabric_app = api::fabric_router(state.clone()); + let fabric = tokio::spawn(async move { axum::serve(listener, fabric_app).await.unwrap(); }); + let owner = Client::unix_as(&socket, OWNER).unwrap(); + let http = reqwest::Client::builder().no_proxy().build().unwrap(); + let signer = key(); + let mut sessions = Vec::new(); + for mode in ["approval-once", "caller-bound-allow"] { + let mut paired = complete(&http, &base, &begin(&owner, mode).await).await; + if mode == "approval-once" { + let id = paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/"); + let trust = value(owner.post(&format!("/v1/client/assistant/grants/{id}/read-trust"), &json!({ + "api_version":"st3.client.v0", "issuer":"scg/admission-bench", "key_id":"approval-key/admission-bench", + "attestor_public_key":URL_SAFE_NO_PAD.encode(signer.public_key().as_ref()), + "shim_public_key":URL_SAFE_NO_PAD.encode(key().public_key().as_ref()), + "default_response_bytes":4096, "max_response_bytes":16_384, + })).await.unwrap()); + paired["grant"] = trust; + } + sessions.push((mode, paired)); + } + // Synthetic expired grants retain valid production field shapes, native Store envelopes, + // origin/actor and per-subject indexes. They are never service-profile fixtures and never + // authorize a request. Grant history is deliberately nonempty for BOTH principals. + let template_subject = format!("custom/client/assistant-v1-{}", sessions[0].1["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); + let template = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + let fixture_store = store.clone(); + tokio::task::spawn_blocking(move || { + for principal in ["assistant/chatgpt", "assistant/mcp"] { + for row in 0..history { + let id = format!("history-{}-{row}", principal.trim_start_matches("assistant/")); + let mut fields = template.body["fields"].clone(); + fields["principal"] = json!(principal); + fields["grant_id"] = json!(format!("assistant-grant/{id}")); + fields["session_actor"] = json!(format!("{principal}/session/assistant-grant/{id}")); + fields["expires_at_unix_ms"] = json!(1); + fields["credential_hash"] = json!(hex::encode(ring::digest::digest(&ring::digest::SHA256, id.as_bytes()).as_ref())); + fixture_store.append_claim(&ClaimInput { subject:format!("custom/client/assistant-v1-{id}"), kind:GRANTED.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); + } + } + }).await.unwrap(); + let connection = rusqlite::Connection::open(&database).unwrap(); + let query = if indexed { INDEXED_QUERY } else { A_QUERY }; + let index_exists: bool = connection.query_row("SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", [INDEX], |r| r.get(0)).unwrap(); + assert_eq!(index_exists, indexed, "build baseline on 98e550cb; indexed on PR3-B"); + let (before, after, build_ms) = if indexed { + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index").unwrap(); + let before = explain(&connection, query); + let started = Instant::now(); + connection.execute_batch(CREATE_INDEX).unwrap(); + let elapsed = started.elapsed().as_secs_f64() * 1000.0; + let after = explain(&connection, query); + assert!(after.iter().any(|line| line.contains(INDEX)), "{after:?}"); + (before, after, Some(elapsed)) + } else { (explain(&connection, query), Vec::new(), None) }; + let total_rows: u64 = connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); + let mut principal_rows = BTreeMap::new(); + for principal in ["assistant/chatgpt", "assistant/mcp"] { + let count: u64 = connection.query_row("SELECT count(*) FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2", rusqlite::params![GRANTED,principal], |r| r.get(0)).unwrap(); + principal_rows.insert(principal, count); + } + drop(connection); + api::wait_published_lists_at_least(&store, store.index().unwrap()).await.unwrap(); + let mut measurements = Vec::new(); + for (mode, paired) in sessions { + let credential = paired["credential"].as_str().unwrap(); + let mut get_ms = Vec::with_capacity(samples); + let mut completion_ms = Vec::with_capacity(samples); + // One unmeasured warm GET, with a distinct one-use proof. + let warm = http.get(format!("{base}{PATH}")).bearer_auth(credential); + let warm = if mode == "approval-once" { warm.header(HEADER, proof(&paired, &signer, samples + 1)) } else { warm }; + let response = warm.send().await.unwrap(); + assert!(response.status().is_success(), "warm GET: {}", response.text().await.unwrap()); + for sequence in 0..samples { + let challenge = begin(&owner, mode).await; + let get = http.get(format!("{base}{PATH}")).bearer_auth(credential); + let get = if mode == "approval-once" { get.header(HEADER, proof(&paired, &signer, sequence)) } else { get }; + let barrier = Barrier::new(2); + let read = async { + barrier.wait().await; + let started = Instant::now(); + let response = get.send().await.unwrap(); + let status = response.status(); + let body = response.bytes().await.unwrap(); + let elapsed = started.elapsed().as_secs_f64() * 1000.0; + assert!(status.is_success(), "GET {status}: {}", String::from_utf8_lossy(&body)); + elapsed + }; + let pairing = async { + barrier.wait().await; + let started = Instant::now(); + let completed = complete(&http, &base, &challenge).await; + (started.elapsed().as_secs_f64() * 1000.0, completed) + }; + let (read_ms, (pair_ms, completed)) = tokio::join!(read, pairing); + get_ms.push(read_ms); + completion_ms.push(pair_ms); + // Keep live-grant count stable; revocation is owner HTTP, outside both samples. + let id = completed["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/"); + let _: Value = owner.post(&format!("/v1/client/assistant/grants/{id}/revoke"), &json!({})).await.unwrap(); + } + state.assistant_receipts.flush().await.unwrap(); + let get_p95 = p95(&mut get_ms); + let completion_p95 = p95(&mut completion_ms); + measurements.push(json!({"mode":mode,"get_samples":get_ms.len(),"completion_samples":completion_ms.len(), + "get_p95_ms":get_p95,"completion_p95_ms":completion_p95,"q39_budget_ms":100,"q39_pass":get_p95 <= 100.0, + "get_ms":get_ms,"completion_ms":completion_ms})); + } + let hardware = |program: &str, args: &[&str]| { + let output = std::process::Command::new(program).args(args).output().unwrap(); + assert!(output.status.success()); + String::from_utf8(output.stdout).unwrap() + }; + let final_connection = rusqlite::Connection::open(&database).unwrap(); + let final_rows: u64 = final_connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); + let report = json!({"variant":variant,"baseline_revision":"98e550cb75", "hardware_uname":hardware("uname", &["-a"]), + "hardware_lscpu":hardware("lscpu", &["-J"]),"hardware_hostname":hardware("hostname", &[]), + "expected_host":"dev5, AMD Ryzen 9 9955HX, 16 cores / 32 threads (verify observed hardware)", + "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, + "final_total_claim_rows":final_rows,"admission_query":query, + "explain_without_index":before,"explain_with_index":after,"synthetic_startup_index_build_ms":build_ms, + "measurements":measurements}); + println!("ADMISSION_MEASUREMENT {}", serde_json::to_string_pretty(&report).unwrap()); + if let Some(path) = std::env::var_os("ST_ADMISSION_REPORT") { std::fs::write(path, serde_json::to_vec_pretty(&report).unwrap()).unwrap(); } + local.abort(); + fabric.abort(); + if indexed { + assert!(report["measurements"].as_array().unwrap().iter().all(|row| row["q39_pass"] == true), "q39: authenticated GET p95 must be <=100ms; see report"); + } +} + +/// Synthetic large-store index build, independent of the HTTP latency fixture: +/// ```sh +/// ST_ADMISSION_INDEX_BUILD=1 cargo test --release -p fractal --test integration daemon_cost::assistant_admission::synthetic_large_store_index_build -- --exact --nocapture --test-threads=1 +/// ``` +/// ST_ADMISSION_INDEX_ROWS defaults to 1,000,000 total claims. ST_ADMISSION_INDEX_REPORT +/// optionally saves JSON. Run on the indexed branch. This measures the exact startup index +/// CREATE DDL, not full Store::open, cold-disk startup, admission, or signature verification. +#[test] +fn synthetic_large_store_index_build() { + if std::env::var_os("ST_ADMISSION_INDEX_BUILD").is_none() { return; } + assert!(fractal_daemon::test_support::optimized_build(), "use --release"); + let rows = number("ST_ADMISSION_INDEX_ROWS", 1_000_000); + let root = tempfile::tempdir().unwrap(); + let database = root.path().join("synthetic-index.sqlite"); + let store = Store::open(&database, NODE).unwrap(); + // Obtain a real Store-authored envelope and the real migrated schema. The SQL copies + // below are intentionally synthetic, not independently signed or admission-authoritative. + // Never reopen this fixture as a source of replicated/authenticated claims. + let template = store.append_claim(&ClaimInput { + subject:"custom/admission-index/template".into(), + kind:"custom.admission-index.fixture".into(), actor:Some(OWNER.into()), + fields:serde_json::from_value(json!({"principal":"assistant/chatgpt", + "expires_at_unix_ms":1,"fixture_payload":"synthetic large-store index build only"})).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + drop(store); + let mut connection = rusqlite::Connection::open(&database).unwrap(); + // Native claims triggers retain their real digest implementation during the + // synthetic population, just as on production/checkpoint writer connections. + smallclaims::store::configure_projection_writer(&connection).unwrap(); + let installed: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", + [INDEX], |row| row.get(0), + ).unwrap(); + assert!(installed, "run the large-store index probe on the indexed branch"); + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index").unwrap(); + // Copy every native required column rather than depending on a second claims schema. + // The native autoincrement store_index, claim ID and subject must remain unique. + let columns = { + let mut statement = connection.prepare("PRAGMA table_info(claims)").unwrap(); + statement.query_map([], |row| row.get::<_, String>(1)).unwrap() + .collect::, _>>().unwrap() + }; + let quote = |name: &str| format!("\"{}\"", name.replace('"', "\"\"")); + let copied = columns.iter().filter(|name| name.as_str() != "store_index").collect::>(); + let destinations = copied.iter().map(|name| quote(name)).collect::>().join(","); + let expressions = copied.iter().map(|name| match name.as_str() { + "id" => "'synthetic-index-claim/' || sequence.n".to_owned(), + "subject" => "'custom/admission-index/row-' || sequence.n".to_owned(), + "kind" => format!("'{GRANTED}'"), + "body" => "json_set(template.body,'$.subject','custom/admission-index/row-' || sequence.n,\ + '$.kind','custom.client.assistant.v1.granted','$.fields.principal',\ + CASE WHEN sequence.n % 2=0 THEN 'assistant/chatgpt' ELSE 'assistant/mcp' END)".to_owned(), + _ => format!("template.{}", quote(name)), + }).collect::>().join(","); + let transaction = connection.transaction().unwrap(); + if rows > 1 { + transaction.execute(&format!( + "WITH RECURSIVE sequence(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM sequence WHERE n= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, - {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, + {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_id_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "({RUNTIME_ID_FIELD}, subject, store_index) WHERE {ACTUAL_STATE_CLAIM} AND typeof({RUNTIME_ID_FIELD})='text'", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actual_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE {ACTUAL_STATE_CLAIM}", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_origin_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, origin, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='runtime.observed'", "value_size_proven": false}, @@ -923,6 +924,7 @@ {"id": "lv-h1b6e1f9abd79", "path": "crates/fractal-api-core/src/api/client_push/tests.rs", "kind": "sql-template", "fingerprint": "fdcbfdd1abff3814f2b09fa3cce20d1b963541f1badd2f887675afe9896c0250", "owner": "fractal_api_core::api::client_push::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 349, "excerpt": "DROP TABLE local_push_registrations"}, {"id": "lv-h1bf70a74e357", "path": "crates/fractal-api-core/src/api/client_push/tests.rs", "kind": "sql-template", "fingerprint": "0a87b6ca1c3206e8e53b141ed709386caa959f2c69d6f181138e4850400b77ea", "owner": "fractal_api_core::api::client_push::tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 219, "excerpt": "UPDATE claims SET origin='foreign-member' WHERE subject=?1"}, {"id": "lv-h2ac955b61469", "path": "crates/fractal-api-core/src/api/client_push/tests.rs", "kind": "sql-template", "fingerprint": "affb99d1b03c4f420bd38607d6e066885296c940ee119b70002f8d6c5b933049", "owner": "fractal_api_core::api::client_push::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 399, "excerpt": "CREATE TRIGGER push_failure BEFORE INSERT ON local_push_registrations BEGIN SELECT RAISE(ABORT,'{TOKEN}'); END;"}, + {"id": "lv-h99f1a302c7b1", "path": "crates/fractal-api-core/src/api/client_v0/external_grants.rs", "kind": "unresolved-sql-sink", "fingerprint": "e43321ad215ad6548370e6aa528d88374c2734277a245c0589a162c3666a7909", "owner": "fractal_api_core::api::client_v0::external_grants", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 95, "excerpt": "ADMISSION_QUERY"}, {"id": "lv-he7d3ed99394d", "path": "crates/fractal-api-core/src/api/client_v0/raw_terminal/lease.rs", "kind": "unresolved-sql-sink", "fingerprint": "8c5bb4cddd6b8d6685308f20bf7367d763a4a9e5cb44eb0b0f7c687994135151", "owner": "fractal_api_core::api::client_v0::raw_terminal::lease", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 75, "excerpt": "& query , params ! [ subject , kind ] , | row | { Ok ( ( row . get ( 0 ) ? , row . get ( 1 ) ? ) ) }"}, {"id": "lv-h314a3080bc73", "path": "crates/fractal-api-core/src/api/client_v0/related_runs.rs", "kind": "unresolved-sql-sink", "fingerprint": "47622b87da9e8d2f6d3972c9459402094f347c5d8e58e7fee498393d6c3f2b4b", "owner": "fractal_api_core::api::client_v0::related_runs", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 33, "excerpt": "RELATED"}, {"id": "lv-h5747b91e24d9", "path": "crates/fractal-api-core/src/api/client_v0/summary.rs", "kind": "unresolved-sql-sink", "fingerprint": "aba95403b0b732c2a12e7b98379d7a878c4c576d5ea990774ea22738f001ddcc", "owner": "fractal_api_core::api::client_v0::summary", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 71, "excerpt": "state , session , & internal"}, @@ -1951,7 +1953,6 @@ {"id": "lv-h20950ed4b5dc", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "5d869aba23919ebabbf18885e6d7deebf69a7298969b72ec41ca59a8ecc6015c", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 20254, "excerpt": "& work_wake_history_query ( complete )"}, {"id": "lv-h20ede67dacaa", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "6d5b306c813337790dcc59d3ea0244058138d994c293b1d1b62b4d21f61d94ca", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1608, "excerpt": "params ! [ subject , store_index ] , | row | row . get : : < _ , u64 > ( 0 )"}, {"id": "lv-h518e0bfb7ccb", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "cb1e349434ed46ec91aff46ff49e260a10ee9290d17983beff6d16108dcda3c4", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 11867, "excerpt": "& format ! ( \"SELECT claims.id, claims.origin, claims.kind FROM claims INDEXED BY claims_actual_accepted_index JOIN batches ON batches.id=claims.batch_id WHERE claims.subject=?1 AND +claims.store_inde"}, - {"id": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "9630d07c20f6a6d1e638ea3b963e3b7d598498adadaf17e78ad3b0a2df790033", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 754, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, {"id": "lv-h26214094cec7", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "a07b2af24ca5ab021fe4b21e8353c58beb343552ea83e0a6b54c50510d16194e", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 10422, "excerpt": "UPDATE step_runs SET updated_at_unix_ms=?2, activated_at_unix_ms=CASE WHEN ?3='ready' THEN ?2 ELSE activated_at_unix_ms END WHERE subject=?1"}, {"id": "lv-h26512c176d95", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "c40c825e3f560b060d1f8d9c67e790832cd2ec75806dde3bb03626c07da15aee", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 17987, "excerpt": "UPDATE step_runs SET assignee=?2, available_to='[]', status='ready', lease_owner=NULL, lease_incarnation=NULL, lease_expires_at_unix_ms=NULL, readiness_epoch=?3, updated_at_unix_ms=?4 WHERE subject=?1"}, {"id": "lv-h27486c82727c", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "9bbb118568a2871f011bcf539a4d106bd062dd77ec81e1f6bfd7b03c780f2b8d", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 10121, "excerpt": "UPDATE run_generations SET created_at_unix_ms=?2,updated_at_unix_ms=?2 WHERE id=?1"}, @@ -2112,6 +2113,7 @@ {"id": "lv-hb73bd4f2f38c", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "700d14798fd37c5da5b5389e3903a51a34c8c957866a0dd94482dfcc246b196b", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 8862, "excerpt": "& canonical_sql ( \"SELECT json_extract(body, '$.fields.session_id') FROM claims WHERE subject=?1 AND kind='harness.session-file' AND json_extract(body, '$.fields.incarnation_id')=?2 AND json_extract(b"}, {"id": "lv-hb7b64cc10c51", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "7a41ee06927a48e907a8b303d67368f1f76113a73b7efcaf20c658e641deaac8", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1838, "excerpt": "params ! [ subject , at_index . unwrap_or ( i64 : : MAX as u64 ) ] , | row | row . get : : < _ , String > ( 0 ) ,"}, {"id": "lv-hb922e5825674", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "a521c5dad40bb69aa774c45feb4115e928e9636649863fd2f9284a6b6dd95c5c", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 15155, "excerpt": "DELETE FROM mission_runs WHERE id=?1"}, + {"id": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "0be5ad06badeb1870cc630ed6799adfebd3bffbdf2b2e4a85fb44b0a04b15ad6", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 783, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, {"id": "lv-hba4b0d735af8", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "68c5253450e4ab064ffddaaa91ab3fd123bd25dce5fca8c4f4b63ed02e14e26d", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 11818, "excerpt": "params ! [ subject , at_index ] , | row | { row . get : : < _ , String > ( 0 ) }"}, {"id": "lv-hba707764f720", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "746038271c3a30a5efca3979d788db5d87a588acb47362b3cb27a9a3d4c1d0ce", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 18333, "excerpt": "& canonical_sql ( \"SELECT kind, body, accepted_at_unix_ms FROM claims WHERE subject=?1 AND kind IN ('work.progress','work.submitted','step-run.carried') ORDER BY CANONICAL_DESC(claims)\" , )"}, {"id": "lv-hba80f02be5e7", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "f0cf159db9d7e30d00dd58f281267eb75687e6eaea2c416eddf5df095accc440", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 8212, "excerpt": "& canonical_sql ( \"SELECT body FROM claims WHERE subject=?1 AND kind='resource.observed' ORDER BY CANONICAL_DESC(claims)\" ) ,"}, diff --git a/docs/st3/large-values.md b/docs/st3/large-values.md index 1d40a495128..e9dc44959dc 100644 --- a/docs/st3/large-values.md +++ b/docs/st3/large-values.md @@ -475,3 +475,23 @@ current publication rejects for-each syntax. The UPDATE binds body, mission-ID and revision TEXT values; no production writer changes. The maintainer must preserve this historical regression through referenced storage/reclamation work. Inline storage here proves neither encoded size nor execution-cost bounds. + +## Assistant principal admission index review + +`fractal_store::store` owns schema site `lv-hb9696ca837f7`, replacing +`lv-h22c8c670811c`. The added principal admission index retains claim-kind TEXT +and the effective principal JSON field inline; absent principals use the fixed +`assistant/chatgpt` key. The composite seek changes neither claim bodies nor +admission semantics. These keys remain variable-size, and SQLite maintains them +on insertion and deletion; indexed lookup is not a byte-size or startup-cost +proof. The producer maintainer retains `chunk-or-reference-variable-columns` +responsibility while preserving effective-principal matching and claim authority. + +`fractal_api_core::api::client_v0::external_grants` owns the conservative +read-only sink `lv-h99f1a302c7b1`. Its prepared admission query binds fixed claim +kinds, an assistant principal and an optional expiry cutoff, then returns claim +IDs after revocation and latest-policy filtering. It adds no writer or body copy; +principal, subject and claim-ID TEXT keys remain variable-size. The producer +maintainer retains `trace-statement-and-value-representation` responsibility for +these bindings and returned identifiers; fewer candidates and indexed seeks do +not establish encoded-size or execution-cost bounds. diff --git a/release-notes/external-grant-admission-index.json b/release-notes/external-grant-admission-index.json new file mode 100644 index 00000000000..79b4bd3f2c3 --- /dev/null +++ b/release-notes/external-grant-admission-index.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "summary": "Index external-grant admission by principal and exclude revoked or effectively expired history before claim hydration", + "replay": {"status": "none", "detail": "No claim rewrite, projection replay or history removal. The SQL expiry filter uses the latest policy, retains missing-fields validation candidates, and preserves legacy absent-principal ChatGPT grants."}, + "schema": {"status": "changed", "detail": "Schema-on-open adds claims_assistant_v1_principal_index on claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')). This additive derived access path changes neither STORAGE_VERSION (20), RULES_VERSION (26), the registry nor shared projection digests. Existing supported stores install the index automatically; subsequent opens reuse it."}, + "rules": {"status": "none", "detail": "Profile admission, grant lifecycle, approval-once consumption, issuer checks and retention semantics are unchanged. Multiple same-profile grants remain allowed; service issuance remains disabled."}, + "compatibility": {"status": "none", "detail": "On dev5 (AMD Ryzen 9 9955HX, 16 cores/32 threads, Linux x86_64), real bound daemon APIs with bearer authentication and one concurrent pairing completion per GET were measured against exact baseline 98e550cb75. With 10000 expired grants per principal and 200 samples per mode, approval-once GET p95 improved from 965.184401 ms to 54.153648 ms; caller-bound-allow improved from 933.049170 ms to 46.173346 ms. Both indexed modes pass q39 <=100 ms. These are in-process production routers over Unix/TCP sockets, not an external daemon-process startup benchmark. SQL work still scales with matching principal history; the index avoids unrelated principals and inactive records no longer hydrate into Rust."}, + "downtime": {"status": "changed", "detail": "The first store open missing the index waits synchronously for its construction. Exact index CREATE DDL on a synthetic 1000000-claim real Store schema took 1524.850241 ms (about 1.525 s) on dev5, AMD Ryzen 9 9955HX, 16 cores/32 threads, Linux 6.18.51 x86_64. Main database size grew from 1421651968 to 1481170944 bytes. This measures index-build startup work only, not complete restart-to-API time or cold-disk startup; allow additional first-open delay according to local history and hardware. Later opens do not rebuild the index."}, + "manual": {"status": "none", "detail": "No operator SQL, data conversion, credential reissue or manual migration is required. Allow the first open to finish index construction."}, + "recovery": {"status": "none", "detail": "Claims and signed bodies are unchanged. Previous binaries can ignore the additional index, which SQLite continues maintaining. An interrupted first-open index build can be completed by normal subsequent schema-on-open installation; no history deletion or repair SQL is needed."}, + "commits": [] +} From c1365c450e836c02e5fc92ee7af0973b225adb33 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 06:53:41 +0100 Subject: [PATCH 03/52] test(external-grants): prove prefilter admission equivalence agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 116 +++++++++++++++++- .../tests/daemon_cost/assistant_admission.rs | 2 +- docs/st3/compatibility.md | 6 +- .../external-grant-admission-index.json | 6 +- 4 files changed, 121 insertions(+), 9 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index f9c4bb13d62..a4e43670642 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -84,12 +84,20 @@ const ADMISSION_QUERY: &str = CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; +fn admission_now_ms() -> u128 { + #[cfg(test)] + if let Some(now) = tests::ADMISSION_NOW.get() { + return now; + } + client_now_ms() +} + fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { let profile = Profile::stored(source)?; let principal = principal(source)?; // Without a valid owner the old scan must still surface its configuration // error before examining expiry; do not prefilter those rows. - let expiry_cut = owning_person(state).ok().map(|_| client_now_ms() as u64); + let expiry_cut = owning_person(state).ok().map(|_| admission_now_ms() as u64); let ids = { let connection = state.store.readers.get(); let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-h99f1a302c7b1 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ ADMISSION_QUERY).map_err(ApiError::internal)?; @@ -105,7 +113,7 @@ fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { } let policy = effective(state, &grant)?; let active = fields(&policy)?; - if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > client_now_ms() { + if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > admission_now_ms() { profile.compatible(Profile::stored(fields(&grant)?)?)?; profile.compatible(Profile::stored(active)?)?; } @@ -311,6 +319,7 @@ mod tests { // the real mutation/session boundary. Production issuable() stays closed. thread_local! { pub(super) static SERVICE_PROFILE: std::cell::Cell = const { std::cell::Cell::new(false) }; + pub(super) static ADMISSION_NOW: std::cell::Cell> = const { std::cell::Cell::new(None) }; } fn concurrent_grants(profiles: [&str; 2]) -> (usize, usize) { @@ -347,6 +356,109 @@ mod tests { (admitted, usable) } + // 98e550cb's Rust-only admission, retained independently as the differential + // oracle. Only its wall clock is substituted so expiry == now is exact. + fn rust_only_admission(state: &AppState, source: &Value) -> Result<(), ApiError> { + let profile = Profile::stored(source)?; + let principal = principal(source)?; + let ids = { + let connection = state.store.readers.get(); + let mut query = connection.prepare( + "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2" + ).map_err(ApiError::internal)?; + query.query_map(rusqlite::params![GRANTED, principal], |row| row.get::<_, String>(0)) + .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? + }; + for id in ids { + let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? + .ok_or_else(|| forbidden("external grant is absent"))?; + if grant.origin != state.store.origin() || grant.actor.as_deref() != Some(owning_person(state)?) + || latest(state, &grant.subject, REVOKED)?.is_some() { + continue; + } + let policy = effective(state, &grant)?; + let active = fields(&policy)?; + if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > admission_now_ms() { + profile.compatible(Profile::stored(fields(&grant)?)?)?; + profile.compatible(Profile::stored(active)?)?; + } + } + Ok(()) + } + + #[test] + fn prefiltered_admission_matches_rust_only_reference() { + struct Clock; + impl Drop for Clock { + fn drop(&mut self) { ADMISSION_NOW.set(None); } + } + ADMISSION_NOW.set(Some(100)); + let _clock = Clock; + let cases = [ + ("live", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ("expired", json!({"expires_at_unix_ms":99}), vec![], 0, false, false), + ("equal-boundary", json!({"expires_at_unix_ms":100}), vec![], 0, false, false), + ("null-expiry", json!({"expires_at_unix_ms":null}), vec![], 0, false, false), + ("missing-expiry", json!({}), vec![], 0, false, false), + ("replicated-revoke", json!({"expires_at_unix_ms":101}), vec![], 1, true, false), + ("revoke-of-revoke", json!({"expires_at_unix_ms":101}), vec![], 2, false, false), + ("several-policies-live", json!({"expires_at_unix_ms":99}), vec![102, 98, 101], 0, false, true), + ("several-policies-expired", json!({"expires_at_unix_ms":101}), vec![99, 102, 100], 0, false, false), + ("unrelated-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, false), + ("legacy-default-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ]; + for (name, mut source, policies, revokes, replicated, denied) in cases { + let root = tempfile::tempdir().unwrap(); + let mut state = crate::api::tests_shared::state(root.path()); + state.owning_person = Some("person/owner".into()); + source["profile"] = json!("service"); + if name != "legacy-default-principal" { + source["principal"] = json!(if name == "unrelated-principal" { MCP_PRINCIPAL } else { PRINCIPAL }); + } + let subject = format!("custom/client/differential-{name}"); + let append_fixture = |store: &Store, kind: &str, value: Value, previous: Option<&ClaimRecord>| { + store.append_claim(&ClaimInput { + subject:subject.clone(), kind:kind.into(), actor:Some("person/owner".into()), + fields:serde_json::from_value(value).unwrap(), + evidence:previous.map(|claim| vec![claim.id.clone()]).unwrap_or_default(), + expected_subject:None, idempotency_key:None, + }).unwrap() + }; + let mut previous = append_fixture(&state.store, GRANTED, source.clone(), None); + for expiry in policies { + let mut policy = source.clone(); + policy["expires_at_unix_ms"] = json!(expiry); + previous = append_fixture(&state.store, POLICY, policy, Some(&previous)); + } + if replicated { + let peer = Store::open_memory("peer").unwrap(); + let revoke = append_fixture(&peer, REVOKED, source.clone(), None); + state.store.import_replication("peer", &peer.export_replication(0).unwrap()).unwrap(); + let imported = latest(&state, &subject, REVOKED).unwrap().unwrap(); + assert_eq!(imported.id, revoke.id); + assert_eq!(imported.origin, "peer"); + } else { + for _ in 0..revokes { + // The second revoke cites the first revoke, not the grant: + // neither reader may interpret that as restoring authority. + previous = append_fixture(&state.store, REVOKED, source.clone(), Some(&previous)); + } + } + for owner in [Some("person/owner"), None] { + state.owning_person = owner.map(str::to_owned); + for profile in ["assistant", "service"] { + let candidate = json!({"profile":profile,"principal":PRINCIPAL}); + let old = rust_only_admission(&state, &candidate).map_err(|error| error.code); + let new = admit_profile(&state, &candidate).map_err(|error| error.code); + assert_eq!(new, old, "{name}: owner={owner:?}, profile={profile}"); + if owner.is_some() { + assert_eq!(new.is_err(), denied && profile == "assistant", "{name}: expected decision"); + } + } + } + } + } + #[test] fn admission_sql_filters_only_inactive_effective_policies() { let connection = rusqlite::Connection::open_in_memory().unwrap(); diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 5fb7dcfbef2..f2c94c35cba 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -27,7 +27,7 @@ use ring::{rand::SystemRandom, signature::{Ed25519KeyPair, KeyPair as _}}; use serde_json::{Value, json}; use tokio::sync::Barrier; -const OWNER: &str = "person/admission-bench"; +const OWNER: &str = "person/bench-operator"; const NODE: &str = "admission-bench"; const GRANTED: &str = "custom.client.assistant.v1.granted"; const INDEX: &str = "claims_assistant_v1_principal_index"; diff --git a/docs/st3/compatibility.md b/docs/st3/compatibility.md index e3f513c4f5a..786b096374d 100644 --- a/docs/st3/compatibility.md +++ b/docs/st3/compatibility.md @@ -148,8 +148,8 @@ This derived access path does not change `STORAGE_VERSION` (20), replication digests: row formats, vocabulary, shared projections and retention semantics are unchanged. It follows the schema-on-open index installation used for the assistant mission-run collection indexes. The first open builds the -index synchronously over retained claims. On dev5 (AMD Ryzen 9 9955HX, -16 cores/32 threads, Linux x86_64), exact index creation on a synthetic +index synchronously over retained claims. On a 16-core x86_64 benchmark host +(AMD Ryzen 9 9955HX, 32 threads, Linux), exact index creation on a synthetic 1,000,000-claim real Store schema took 1.525 seconds and grew the main database by 59,518,976 bytes. This measures index-build work, not complete daemon startup or cold-disk restart time; local history and hardware determine first-open delay. @@ -160,7 +160,7 @@ Admission excludes revoked and effectively expired history in SQL while preserving the latest-policy and malformed-fields validation semantics. SQL work still scales with matching principal history, but inactive records no longer hydrate into Rust. With 10,000 expired grants per principal and concurrent pairing -completions, real authenticated summary GET p95 on dev5 was 54.154 ms +completions, real authenticated summary GET p95 on that benchmark host was 54.154 ms (approval-once) and 46.173 ms (caller-bound-allow), compared with 965.184 ms and 933.049 ms on baseline `98e550cb75` (200 samples per mode). Both indexed modes meet q39's 100 ms budget. The opt-in `daemon_cost::assistant_admission` tests use diff --git a/release-notes/external-grant-admission-index.json b/release-notes/external-grant-admission-index.json index 79b4bd3f2c3..ff04823e236 100644 --- a/release-notes/external-grant-admission-index.json +++ b/release-notes/external-grant-admission-index.json @@ -4,9 +4,9 @@ "replay": {"status": "none", "detail": "No claim rewrite, projection replay or history removal. The SQL expiry filter uses the latest policy, retains missing-fields validation candidates, and preserves legacy absent-principal ChatGPT grants."}, "schema": {"status": "changed", "detail": "Schema-on-open adds claims_assistant_v1_principal_index on claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')). This additive derived access path changes neither STORAGE_VERSION (20), RULES_VERSION (26), the registry nor shared projection digests. Existing supported stores install the index automatically; subsequent opens reuse it."}, "rules": {"status": "none", "detail": "Profile admission, grant lifecycle, approval-once consumption, issuer checks and retention semantics are unchanged. Multiple same-profile grants remain allowed; service issuance remains disabled."}, - "compatibility": {"status": "none", "detail": "On dev5 (AMD Ryzen 9 9955HX, 16 cores/32 threads, Linux x86_64), real bound daemon APIs with bearer authentication and one concurrent pairing completion per GET were measured against exact baseline 98e550cb75. With 10000 expired grants per principal and 200 samples per mode, approval-once GET p95 improved from 965.184401 ms to 54.153648 ms; caller-bound-allow improved from 933.049170 ms to 46.173346 ms. Both indexed modes pass q39 <=100 ms. These are in-process production routers over Unix/TCP sockets, not an external daemon-process startup benchmark. SQL work still scales with matching principal history; the index avoids unrelated principals and inactive records no longer hydrate into Rust."}, - "downtime": {"status": "changed", "detail": "The first store open missing the index waits synchronously for its construction. Exact index CREATE DDL on a synthetic 1000000-claim real Store schema took 1524.850241 ms (about 1.525 s) on dev5, AMD Ryzen 9 9955HX, 16 cores/32 threads, Linux 6.18.51 x86_64. Main database size grew from 1421651968 to 1481170944 bytes. This measures index-build startup work only, not complete restart-to-API time or cold-disk startup; allow additional first-open delay according to local history and hardware. Later opens do not rebuild the index."}, + "compatibility": {"status": "none", "detail": "On a 16-core x86_64 benchmark host (AMD Ryzen 9 9955HX, 32 threads, Linux), real bound daemon APIs with bearer authentication and one concurrent pairing completion per GET were measured against exact baseline 98e550cb75. With 10000 expired grants per principal and 200 samples per mode, approval-once GET p95 improved from 965.184401 ms to 54.153648 ms; caller-bound-allow improved from 933.049170 ms to 46.173346 ms. Both indexed modes pass q39 <=100 ms. These are in-process production routers over Unix/TCP sockets, not an external daemon-process startup benchmark. SQL work still scales with matching principal history; the index avoids unrelated principals and inactive records no longer hydrate into Rust."}, + "downtime": {"status": "changed", "detail": "The first store open missing the index waits synchronously for its construction. Exact index CREATE DDL on a synthetic 1000000-claim real Store schema took 1524.850241 ms (about 1.525 s) on a 16-core x86_64 benchmark host (AMD Ryzen 9 9955HX, 32 threads, Linux 6.18.51). This is one measurement on that host, not a guaranteed rate of 1.5 seconds per million rows or a startup-time guarantee. Main database size grew from 1421651968 to 1481170944 bytes. This measures index-build startup work only, not complete restart-to-API time or cold-disk startup; allow additional first-open delay according to local history and hardware. Later opens do not rebuild the index."}, "manual": {"status": "none", "detail": "No operator SQL, data conversion, credential reissue or manual migration is required. Allow the first open to finish index construction."}, - "recovery": {"status": "none", "detail": "Claims and signed bodies are unchanged. Previous binaries can ignore the additional index, which SQLite continues maintaining. An interrupted first-open index build can be completed by normal subsequent schema-on-open installation; no history deletion or repair SQL is needed."}, + "recovery": {"status": "none", "detail": "Claims and signed bodies are unchanged. A binary rollback leaves the index in place: previous binaries can ignore it, and SQLite keeps maintaining it on writes. An interrupted first-open index build can be completed by normal subsequent schema-on-open installation; no history deletion or repair SQL is needed."}, "commits": [] } From 0f1f0ebb700025828d711ed1bdc30ba38bfebffb Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 08:24:44 +0100 Subject: [PATCH 04/52] fix(external-grants): suspend fleet-wide mixed-profile conflicts agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../Sources/FractalClient/Models.swift | 19 +- .../fractal-client/Models.generated.ts | 22 ++ .../fractal-client/ReadSchema.generated.ts | 1 + .../fractal-client/Schema.generated.ts | 59 +++- crates/fractal-api-core/src/api.rs | 2 + .../src/api/client_v0/external_grants.rs | 137 +++++++- .../external_grants/conflict_tests.rs | 302 ++++++++++++++++++ .../templates/Models.swift.in | 19 +- .../templates/generated.rs.in | 35 ++ .../templates/lib.rs.in | 1 + crates/fractal-client/src/generated.rs | 35 ++ crates/fractal-client/src/lib.rs | 1 + crates/smallclaims/src/store.rs | 49 +++ .../src/store/membership_query_tests.rs | 115 +++++++ .../client-v0/schemas/client-v0.schema.json | 32 ++ docs/st3/large-value-sites.json | 9 + docs/st3/principals-and-grants.md | 28 +- .../external-grant-profile-conflict.json | 33 ++ 18 files changed, 867 insertions(+), 32 deletions(-) create mode 100644 crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs create mode 100644 release-notes/external-grant-profile-conflict.json diff --git a/clients/swift/FractalClient/Sources/FractalClient/Models.swift b/clients/swift/FractalClient/Sources/FractalClient/Models.swift index ebde03f65ae..a874bcb628c 100644 --- a/clients/swift/FractalClient/Sources/FractalClient/Models.swift +++ b/clients/swift/FractalClient/Sources/FractalClient/Models.swift @@ -153,6 +153,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case peerTooOld case validationFailed case idempotencyConflict + case grantProfileConflict case agentsPublicationRowTooLarge case attentionMigrated case invalidAnswer, notAnswerable @@ -243,6 +244,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case "peer-too-old": .peerTooOld case "validation-failed": .validationFailed case "idempotency-conflict": .idempotencyConflict + case "grant-profile-conflict": .grantProfileConflict case "stale-fence": .staleFence case "issuer-required": .issuerRequired case "invalid-answer": .invalidAnswer; case "not-answerable": .notAnswerable @@ -333,6 +335,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case .peerTooOld: "peer-too-old" case .validationFailed: "validation-failed" case .idempotencyConflict: "idempotency-conflict" + case .grantProfileConflict: "grant-profile-conflict" case .staleFence: "stale-fence" case .issuerRequired: "issuer-required" case .invalidAnswer: "invalid-answer"; case .notAnswerable: "not-answerable" @@ -1485,7 +1488,21 @@ public struct AssistantGrant: Codable, Sendable { public let kind, id, sessionActor, deviceID, keyID, issuer, expiresAt, consentEvidence: String; public let principal: AssistantPrincipal; public let senderClass: AssistantSenderClass; public let scopes: [AssistantScope]; public let policyRevision: UInt64; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]; public let disclosureConsent, revoked: Bool /// Owner-provisioned SCG read pins; absent means every assistant read is denied. public let readTrust: AssistantReadTrust? - enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust" } + public let conflict: GrantProfileConflictWitness? + public let clearedConflicts: [ClearedGrantProfileConflictWitness]? + enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust", conflict, clearedConflicts = "cleared_conflicts" } +} +public enum ExternalGrantProfile: String, Codable, Sendable { case assistant, service } +public enum GrantProfileConflictCause: String, Codable, Sendable { case revoked, expired } +public struct GrantProfileWitness: Codable, Sendable { + public let grantID: String?; public let origin: String; public let profile: ExternalGrantProfile + enum CodingKeys: String, CodingKey { case grantID = "grant_id", origin, profile } +} +public struct GrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness] +} +public struct ClearedGrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness]; public let cause: GrantProfileConflictCause } public struct AssistantGrantPolicy: Codable, Sendable { public let apiVersion, consentEvidence: String; public let scopes: [AssistantScope]; public let expiresInSeconds: UInt64?; public let disclosureConsent: Bool; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]? diff --git a/clients/typescript/fractal-client/Models.generated.ts b/clients/typescript/fractal-client/Models.generated.ts index 0a60db76f32..61f1d0cee69 100644 --- a/clients/typescript/fractal-client/Models.generated.ts +++ b/clients/typescript/fractal-client/Models.generated.ts @@ -793,6 +793,8 @@ export type AssistantConversationTimelineRequest = { }; export type AssistantGrant = { + cleared_conflicts?: Array; + conflict?: (GrantProfileConflictWitness | null); consent_evidence: string; device_id: Id; disclosure_consent: boolean; @@ -1237,6 +1239,11 @@ export type Capability = { version: number; }; +export type ClearedGrantProfileConflictWitness = { + cause: GrantProfileConflictCause; + grants: Array; +}; + export type ClientConnection = { actor: string; client?: string | null; @@ -1852,6 +1859,7 @@ export type ErrorCode = ( | "peer-too-old" | "validation-failed" | "idempotency-conflict" + | "grant-profile-conflict" | "legacy-action-receipt-untrusted" | "issuer-required" | "suspend-authored-session-selection" @@ -1926,6 +1934,8 @@ export type ExchangeTransport = { fabric_route?: string; }; +export type ExternalGrantProfile = "assistant" | "service"; + export type FabricGrant = { detail?: string; peer?: string; @@ -1986,6 +1996,18 @@ export type GlassTab = { export type GoldenResourceSet = Array; +export type GrantProfileConflictCause = "revoked" | "expired"; + +export type GrantProfileConflictWitness = { + grants: Array; +}; + +export type GrantProfileWitness = { + grant_id: string | null; + origin: string; + profile: ExternalGrantProfile; +}; + export type HarnessAnswerInput = { positions: Array; }; diff --git a/clients/typescript/fractal-client/ReadSchema.generated.ts b/clients/typescript/fractal-client/ReadSchema.generated.ts index 82a4e23314b..f1ea7df9c79 100644 --- a/clients/typescript/fractal-client/ReadSchema.generated.ts +++ b/clients/typescript/fractal-client/ReadSchema.generated.ts @@ -1698,6 +1698,7 @@ export const ErrorCode = /*#__PURE__*/ (() => openEnum([ "peer-too-old", "validation-failed", "idempotency-conflict", + "grant-profile-conflict", "legacy-action-receipt-untrusted", "issuer-required", "suspend-authored-session-selection", diff --git a/clients/typescript/fractal-client/Schema.generated.ts b/clients/typescript/fractal-client/Schema.generated.ts index d0dc340e5f9..adca8cad969 100644 --- a/clients/typescript/fractal-client/Schema.generated.ts +++ b/clients/typescript/fractal-client/Schema.generated.ts @@ -494,7 +494,41 @@ export const AssistantScope = /*#__PURE__*/ (() => Schema.Literals([ export type AssistantScope = typeof AssistantScope.Type export type AssistantScopeEncoded = typeof AssistantScope.Encoded +export const GrantProfileConflictCause = /*#__PURE__*/ (() => Schema.Literals(["revoked","expired"]).annotate({ identifier: "GrantProfileConflictCause" }))() +export type GrantProfileConflictCause = typeof GrantProfileConflictCause.Type +export type GrantProfileConflictCauseEncoded = typeof GrantProfileConflictCause.Encoded + +export const ExternalGrantProfile = /*#__PURE__*/ (() => Schema.Literals(["assistant","service"]).annotate({ identifier: "ExternalGrantProfile" }))() +export type ExternalGrantProfile = typeof ExternalGrantProfile.Type +export type ExternalGrantProfileEncoded = typeof ExternalGrantProfile.Encoded + +export const GrantProfileWitness = /*#__PURE__*/ (() => Schema.Struct({ + /** Grant ID; null only for legacy local fixtures without an ID. */ + "grant_id": Schema.OptionFromNullOr(Schema.String).annotate({ description: "Grant ID; null only for legacy local fixtures without an ID." }), + "origin": Schema.String, + "profile": ExternalGrantProfile +}).annotate({ identifier: "GrantProfileWitness" }))() +export type GrantProfileWitness = typeof GrantProfileWitness.Type +export type GrantProfileWitnessEncoded = typeof GrantProfileWitness.Encoded + +export const ClearedGrantProfileConflictWitness = /*#__PURE__*/ (() => Schema.Struct({ + "cause": GrantProfileConflictCause, + "grants": Schema.Array(GrantProfileWitness) +}).annotate({ identifier: "ClearedGrantProfileConflictWitness" }))() +export type ClearedGrantProfileConflictWitness = typeof ClearedGrantProfileConflictWitness.Type +export type ClearedGrantProfileConflictWitnessEncoded = typeof ClearedGrantProfileConflictWitness.Encoded + +export const GrantProfileConflictWitness = /*#__PURE__*/ (() => Schema.Struct({ + "grants": Schema.Array(GrantProfileWitness) +}).annotate({ identifier: "GrantProfileConflictWitness" }))() +export type GrantProfileConflictWitness = typeof GrantProfileConflictWitness.Type +export type GrantProfileConflictWitnessEncoded = typeof GrantProfileConflictWitness.Encoded + export const AssistantGrant = /*#__PURE__*/ (() => Schema.Struct({ + /** Revoked or expired opposite-profile witnesses; emitted only when conflict is null. */ + "cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only when conflict is null." }), + /** Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers. */ + "conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, @@ -902,23 +936,25 @@ export const Envelope = /*#__PURE__*/ (() => Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "request_id": RequestId, "snapshot": Snapshot, - "value": Schema.Union([Schema.Struct({ "notes": Schema.Array(DirectiveNote), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "capabilities": Schema.Array(Capability), "event_cursor": Cursor, "grant_expires_at": optionalKey(Timestamp), "grant_id": optionalKey(Id), "grant_kind": optionalKey(Schema.Literals(["person","assistant"])), "kind": Schema.Literal("capabilities"), "limits": Schema.Struct({ "default_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(4096))), "max_arrangement_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_folders": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_key_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_name_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_operations": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_placements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_resource_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(16384))), "max_event_items": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "max_glass_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_depth": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_nodes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glasses": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), /** The longest message body in UTF-8 bytes this daemon takes; absent on older daemons, which take 4096. */ + "value": Schema.Union([Schema.Struct({ "notes": Schema.Array(DirectiveNote), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "capabilities": Schema.Array(Capability), "event_cursor": Cursor, "grant_expires_at": optionalKey(Timestamp), "grant_id": optionalKey(Id), "grant_kind": optionalKey(Schema.Literals(["person","assistant"])), "kind": Schema.Literal("capabilities"), "limits": Schema.Struct({ "default_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(4096))), "max_arrangement_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_folders": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_key_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_name_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_operations": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_placements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangement_resource_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_arrangements": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_assistant_response_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(16384))), "max_event_items": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "max_glass_body_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_depth": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glass_nodes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "max_glasses": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), /** The longest message body in UTF-8 bytes this daemon takes; absent on older daemons, which take 4096. */ "max_message_bytes": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))).annotate({ description: "The longest message body in UTF-8 bytes this daemon takes; absent on older daemons, which take 4096." }), "max_page_items": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "max_response_bytes": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1024)), "max_wait_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)) }), /** Compile-time build identity of the responding daemon; absent on older servers. */ -"machine_version": optionalKey(Schema.String).annotate({ description: "Compile-time build identity of the responding daemon; absent on older servers." }), "minimal_read_mode": optionalKey(AssistantMinimalReadMode), "oldest_event_cursor": Cursor, "policy_revision": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "principal": optionalKey(AssistantPrincipal), "schemas": Schema.Array(Schema.String.check(Schema.isPattern(URI_REFERENCE, { expected: "an RFC 3986 URI reference" }))).check(Schema.isMinLength(1)), "sender_class": optionalKey(AssistantSenderClass), "session_actor": Id, "transport": Schema.Literals(["unix","fabric-loopback"]), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "actions": Schema.Array(PrivateNotesAction).check(Schema.isMaxLength(1)), "data": PrivateNotesData, "family": Schema.Literal("private-notes"), "live": Schema.Null, "ref": PrivateNotesUri, "schema": Schema.Literal("fractal.private-notes@1"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "bytes": Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(255))), "changed_at_unix_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "latest": optionalKey(Schema.Boolean), "name": optionalKey(Schema.String), "owner": optionalKey(Schema.String), "reference": Schema.String, "size": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "version": optionalKey(Schema.String), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "history": Schema.Boolean, "items": Schema.Array(DocumentItem), "limit": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "next_cursor": Schema.OptionFromOptionalNullOr(Schema.String, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), SchedulesPage, Schema.Struct({ "complete": Schema.Boolean, "references": Schema.Array(DocumentReference), "subject": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "conflicts": Schema.Array(Schema.String), "desired": Schema.suspend(() => CanonicalNode), "desired_revision": Revision, "desired_token": Schema.String.check(Schema.isMinCodePoints(1)), "kdl": Schema.String, "kind": Schema.Literal("subject-definition"), "subject": Schema.String.check(Schema.isPattern(new RegExp("^agent/[^\\s]+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "declaration": Schema.Record(Schema.String, Schema.Unknown), "kind": Schema.Literal("publication-definition"), "revision": Revision, "subject": Schema.String.check(Schema.isPattern(new RegExp("^(agent|mission|schedule)/[^\\s]+$", "u"))), "token": Schema.String.check(Schema.isMinCodePoints(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Contains removed loop shapes that the current parser rejects. */ -"legacy": Schema.Boolean.annotate({ description: "Contains removed loop shapes that the current parser rejects." }), "mission": Schema.String.check(Schema.isPattern(new RegExp("^mission/[^\\s]+$", "u"))), "published_at": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "revision": Revision, "text": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": AgentId, /** Agent declaration supplying the workspace; reached through unambiguous stop predecessors. */ +"machine_version": optionalKey(Schema.String).annotate({ description: "Compile-time build identity of the responding daemon; absent on older servers." }), "minimal_read_mode": optionalKey(AssistantMinimalReadMode), "oldest_event_cursor": Cursor, "policy_revision": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), "principal": optionalKey(AssistantPrincipal), "schemas": Schema.Array(Schema.String.check(Schema.isPattern(URI_REFERENCE, { expected: "an RFC 3986 URI reference" }))).check(Schema.isMinLength(1)), "sender_class": optionalKey(AssistantSenderClass), "session_actor": Id, "transport": Schema.Literals(["unix","fabric-loopback"]), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "actions": Schema.Array(PrivateNotesAction).check(Schema.isMaxLength(1)), "data": PrivateNotesData, "family": Schema.Literal("private-notes"), "live": Schema.Null, "ref": PrivateNotesUri, "schema": Schema.Literal("fractal.private-notes@1"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "bytes": Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(255))), "changed_at_unix_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "latest": optionalKey(Schema.Boolean), "name": optionalKey(Schema.String), "owner": optionalKey(Schema.String), "reference": Schema.String, "size": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "version": optionalKey(Schema.String), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "history": Schema.Boolean, "items": Schema.Array(DocumentItem), "limit": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "next_cursor": Schema.OptionFromOptionalNullOr(Schema.String, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), SchedulesPage, Schema.Struct({ "complete": Schema.Boolean, "references": Schema.Array(DocumentReference), "subject": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "conflicts": Schema.Array(Schema.String), "desired": Schema.suspend(() => CanonicalNode), "desired_revision": Revision, "desired_token": Schema.String.check(Schema.isMinCodePoints(1)), "kdl": Schema.String, "kind": Schema.Literal("subject-definition"), "subject": Schema.String.check(Schema.isPattern(new RegExp("^agent/[^\\s]+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "declaration": Schema.Record(Schema.String, Schema.Unknown), "kind": Schema.Literal("publication-definition"), "revision": Revision, "subject": Schema.String.check(Schema.isPattern(new RegExp("^(agent|mission|schedule)/[^\\s]+$", "u"))), "token": Schema.String.check(Schema.isMinCodePoints(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Contains removed loop shapes that the current parser rejects. */ +"legacy": Schema.Boolean.annotate({ description: "Contains removed loop shapes that the current parser rejects." }), "mission": Schema.String.check(Schema.isPattern(new RegExp("^mission/[^\\s]+$", "u"))), "published_at": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "revision": Revision, "text": Schema.String, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": AgentId, /** Agent declaration supplying the workspace; reached through unambiguous stop predecessors. */ "declaration_token": Schema.String.annotate({ description: "Agent declaration supplying the workspace; reached through unambiguous stop predecessors." }), /** Selected desired claim, including a stop when the seat is retired. */ "desired_token": Schema.String.annotate({ description: "Selected desired claim, including a stop when the seat is retired." }), "host_id": HostId, "kind": Schema.Literal("agent-workspace"), /** Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory. */ -"workspace": Schema.String.annotate({ description: "Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory." }), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.String.check(Schema.makeFilter((value: string) => !new RegExp("^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$", "u").test(value), { expected: "a string not matching ^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$" })), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(Resource), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("ordered-memberships"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(OrderedMembership), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("resources"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(ResourceObservation), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Resource, Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ -"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry), "kind": Schema.Literal("timeline-page"), "page": PageInfo, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ -"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ +"workspace": Schema.String.annotate({ description: "Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory." }), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.String.check(Schema.makeFilter((value: string) => !new RegExp("^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$", "u").test(value), { expected: "a string not matching ^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$" })), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(Resource), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("ordered-memberships"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(OrderedMembership), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("resources"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(ResourceObservation), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Resource, Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ +"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry), "kind": Schema.Literal("timeline-page"), "page": PageInfo, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ +"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ /** Revoked or expired opposite-profile witnesses; emitted only when conflict is null. */ +"cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only when conflict is null." }), /** Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers. */ +"conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ "issuer": PersonId, /** SHA-256 of the canonical device public-key string; never a credential digest. */ "key_id": Schema.String.check(Schema.isPattern(new RegExp("^[0-9a-f]{64}$", "u"))).annotate({ description: "SHA-256 of the canonical device public-key string; never a credential digest." }), "kind": Schema.Literal("assistant-grant"), "minimal_read_mode": AssistantMinimalReadMode, "policy_revision": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "principal": AssistantPrincipal, /** Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied. */ "read_trust": optionalKey(AssistantReadTrust), /** Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person. */ -"recipient_allowlist": Schema.Array(Schema.String.check(Schema.isPattern(new RegExp("^agent/.+$", "u")))).annotate({ description: "Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person." }), "revoked": Schema.Boolean, "scopes": Schema.Array(AssistantScope).check(Schema.isMinLength(1)).check(Schema.isUnique()), "sender_class": AssistantSenderClass, "session_actor": Schema.String.check(Schema.isPattern(new RegExp("^assistant/(?:chatgpt|mcp)/session/.+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of": Timestamp, "counts": Schema.Struct({ "agent_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "attention": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "mission_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))) }), "kind": Schema.Literal("assistant-summary"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.attention"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAttentionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.missions"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantMissionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.agents"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAgentItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AssistantContentPage, Schema.Struct({ "columns": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "cursor": Schema.Struct({ "blinking": Schema.Boolean, "column": Schema.Int, "row": Schema.Int, "style": Schema.Literals(["block","underline","bar"]), "visible": Schema.Boolean }), "facts": optionalKey(TerminalFacts), "kind": Schema.Literal("terminal-screen"), "lines": Schema.Array(TerminalLine), "modes": TerminalModes, /** Fence for the next input or resize. */ +"recipient_allowlist": Schema.Array(Schema.String.check(Schema.isPattern(new RegExp("^agent/.+$", "u")))).annotate({ description: "Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person." }), "revoked": Schema.Boolean, "scopes": Schema.Array(AssistantScope).check(Schema.isMinLength(1)).check(Schema.isUnique()), "sender_class": AssistantSenderClass, "session_actor": Schema.String.check(Schema.isPattern(new RegExp("^assistant/(?:chatgpt|mcp)/session/.+$", "u"))), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of": Timestamp, "counts": Schema.Struct({ "agent_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))), "attention": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "mission_states": Schema.Record(Schema.String, Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))) }), "kind": Schema.Literal("assistant-summary"), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.attention"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAttentionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.missions"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantMissionItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("assistant.agents"), "filters": Schema.Record(Schema.String, Schema.Never), "items": Schema.Array(AssistantAgentItem), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AssistantContentPage, Schema.Struct({ "columns": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "cursor": Schema.Struct({ "blinking": Schema.Boolean, "column": Schema.Int, "row": Schema.Int, "style": Schema.Literals(["block","underline","bar"]), "visible": Schema.Boolean }), "facts": optionalKey(TerminalFacts), "kind": Schema.Literal("terminal-screen"), "lines": Schema.Array(TerminalLine), "modes": TerminalModes, /** Fence for the next input or resize. */ "next_sequence": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).annotate({ description: "Fence for the next input or resize." }), "relay": optionalKey(TerminalRelay), /** Digest of the rest of the screen: equal revisions mean equal screens. */ -"revision": Schema.String.check(Schema.isMinCodePoints(1)).pipe(Schema.brand("st3/ScreenRevision")).annotate({ description: "Digest of the rest of the screen: equal revisions mean equal screens." }), "rows": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "runtime_incarnation": Schema.String, "terminal_id": TerminalId, "title": Schema.String, "truncated": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "complete": Schema.Boolean, "items": Schema.Array(StatusTransition).check(Schema.isMaxLength(200)), "kind": Schema.Literal("status-history"), "retained_from": Timestamp, "seat": AgentId, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": Id, "current_work_ids": Schema.Array(Id), "kind": Schema.Literal("agent-queue"), "move_count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "moves": Schema.Array(AgentQueueMove), "next_work_id": Schema.OptionFromNullOr(Id), "runs": Schema.Array(AgentQueueRun), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AgentRelatedRuns, Schema.Struct({ /** Every declared account in name order, so each panel lists the same accounts. Absent on older servers. */ -"accounts": optionalKey(Schema.Array(UsageAccount)).annotate({ description: "Every declared account in name order, so each panel lists the same accounts. Absent on older servers." }), "agent_messages": optionalKey(AgentMessageEstimate), "limits": optionalKey(Schema.Array(UsageLimit)), "rows": Schema.Array(UsageRow), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "cleanup_command": Schema.String, "count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "threshold_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of_unix_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), /** Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured. */ -"otel_ui_url": optionalKey(Schema.String).annotate({ description: "Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured." }), "rows": Schema.Array(SloRow), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "id": Schema.String, "samples": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "steps": Schema.Array(Schema.NullOr(Schema.Number.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)))), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) })], { mode: "oneOf" }) +"revision": Schema.String.check(Schema.isMinCodePoints(1)).pipe(Schema.brand("st3/ScreenRevision")).annotate({ description: "Digest of the rest of the screen: equal revisions mean equal screens." }), "rows": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "runtime_incarnation": Schema.String, "terminal_id": TerminalId, "title": Schema.String, "truncated": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "complete": Schema.Boolean, "items": Schema.Array(StatusTransition).check(Schema.isMaxLength(200)), "kind": Schema.Literal("status-history"), "retained_from": Timestamp, "seat": AgentId, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "agent_id": Id, "current_work_ids": Schema.Array(Id), "kind": Schema.Literal("agent-queue"), "move_count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "moves": Schema.Array(AgentQueueMove), "next_work_id": Schema.OptionFromNullOr(Id), "runs": Schema.Array(AgentQueueRun), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), AgentRelatedRuns, Schema.Struct({ /** Every declared account in name order, so each panel lists the same accounts. Absent on older servers. */ +"accounts": optionalKey(Schema.Array(UsageAccount)).annotate({ description: "Every declared account in name order, so each panel lists the same accounts. Absent on older servers." }), "agent_messages": optionalKey(AgentMessageEstimate), "limits": optionalKey(Schema.Array(UsageLimit)), "rows": Schema.Array(UsageRow), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "cleanup_command": Schema.String, "count": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "threshold_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "as_of_unix_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), /** Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured. */ +"otel_ui_url": optionalKey(Schema.String).annotate({ description: "Where a person reads the exported observation history, from the daemon's [observations.otlp] ui_url. Absent when none is configured." }), "rows": Schema.Array(SloRow), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "id": Schema.String, "samples": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "since_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "steps": Schema.Array(Schema.NullOr(Schema.Number.check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)))), "until_ms": Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) })], { mode: "oneOf" }) }).annotate({ identifier: "Envelope" }))() export type Envelope = typeof Envelope.Type export type EnvelopeEncoded = typeof Envelope.Encoded @@ -1000,6 +1036,7 @@ export const ErrorEnvelope = /*#__PURE__*/ (() => Schema.Union([ Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("peer-too-old"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("validation-failed"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("idempotency-conflict"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("grant-profile-conflict"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("legacy-action-receipt-untrusted"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("issuer-required"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("suspend-authored-session-selection"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), @@ -1042,7 +1079,7 @@ export const ErrorEnvelope = /*#__PURE__*/ (() => Schema.Union([ Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("invalid-answer"), "details": HarnessInvalidAnswerDetails, "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("not-answerable"), "details": HarnessNotAnswerableDetails, "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("internal"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), - Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": unknownCase(["recipient-retired","agents-publication-row-too-large","identity-cycle","identity-occupied","identity-retired-source","identity-cross-kind","identity-unknown","lifecycle-unavailable","retirement-upgrade-required","retire-revision-mismatch","retire-incarnation-mismatch","invalid-custody-successor","custody-pending","attention-migrated","arrangement-exists","arrangement-folder-exists","arrangement-retired","arrangement-limit","arrangement-folder-deleted","arrangement-cycle","arrangement-body-too-large","arrangement-owner-forbidden","invalid-arrangement-subject","invalid-arrangement-action","invalid-arrangement-operations","invalid-arrangement-folder","invalid-arrangement-name","invalid-arrangement-key","invalid-arrangement-version","invalid-arrangement-body","unsupported-membership-container","membership-owner-forbidden","invalid-membership-member","invalid-membership-bucket","invalid-membership-key","invalid-membership-operations","membership-edit-too-large","invalid-subject-reference","not-found","forbidden","unsupported-capability","peer-too-old","validation-failed","idempotency-conflict","legacy-action-receipt-untrusted","issuer-required","suspend-authored-session-selection","stale-fence","cursor-gap","page-cursor-expired","agent-roster-not-ready","agent-roster-cut-not-ready","message-selectors-not-ready","rate-limited","runtime-not-local","runtime-authority-indeterminate","runtime-list-not-ready","runtime-list-ended","remote-unavailable","terminal-unavailable","inventory-unavailable","terminal-ended","timeline-history-incomplete","projection-detail-too-large","projection-detail-invalid-source","conversation-content-invalidated","transcript-unavailable","blob-too-large","unsupported-media-type","blob-content-mismatch","blob-quota-exceeded","blob-not-found","blob-expired","message-too-large","message-store-full","long-message-signature-unsupported","response-budget-exceeded","content-not-text","invalid-document-reference","document-not-synced","private-notes-unreachable","private-notes-carrier-conflict","private-notes-indeterminate","invalid-answer","not-answerable","internal"]), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }) + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": unknownCase(["recipient-retired","agents-publication-row-too-large","identity-cycle","identity-occupied","identity-retired-source","identity-cross-kind","identity-unknown","lifecycle-unavailable","retirement-upgrade-required","retire-revision-mismatch","retire-incarnation-mismatch","invalid-custody-successor","custody-pending","attention-migrated","arrangement-exists","arrangement-folder-exists","arrangement-retired","arrangement-limit","arrangement-folder-deleted","arrangement-cycle","arrangement-body-too-large","arrangement-owner-forbidden","invalid-arrangement-subject","invalid-arrangement-action","invalid-arrangement-operations","invalid-arrangement-folder","invalid-arrangement-name","invalid-arrangement-key","invalid-arrangement-version","invalid-arrangement-body","unsupported-membership-container","membership-owner-forbidden","invalid-membership-member","invalid-membership-bucket","invalid-membership-key","invalid-membership-operations","membership-edit-too-large","invalid-subject-reference","not-found","forbidden","unsupported-capability","peer-too-old","validation-failed","idempotency-conflict","grant-profile-conflict","legacy-action-receipt-untrusted","issuer-required","suspend-authored-session-selection","stale-fence","cursor-gap","page-cursor-expired","agent-roster-not-ready","agent-roster-cut-not-ready","message-selectors-not-ready","rate-limited","runtime-not-local","runtime-authority-indeterminate","runtime-list-not-ready","runtime-list-ended","remote-unavailable","terminal-unavailable","inventory-unavailable","terminal-ended","timeline-history-incomplete","projection-detail-too-large","projection-detail-invalid-source","conversation-content-invalidated","transcript-unavailable","blob-too-large","unsupported-media-type","blob-content-mismatch","blob-quota-exceeded","blob-not-found","blob-expired","message-too-large","message-store-full","long-message-signature-unsupported","response-budget-exceeded","content-not-text","invalid-document-reference","document-not-synced","private-notes-unreachable","private-notes-carrier-conflict","private-notes-indeterminate","invalid-answer","not-answerable","internal"]), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }) ], { mode: "oneOf" }).annotate({ identifier: "ErrorEnvelope" }))() export type ErrorEnvelope = typeof ErrorEnvelope.Type export type ErrorEnvelopeEncoded = typeof ErrorEnvelope.Encoded diff --git a/crates/fractal-api-core/src/api.rs b/crates/fractal-api-core/src/api.rs index e8991a938c8..853d4868794 100644 --- a/crates/fractal-api-core/src/api.rs +++ b/crates/fractal-api-core/src/api.rs @@ -474,6 +474,7 @@ impl ApiError { | "stale-subject" | "stale-fence" | "idempotency-conflict" + | "grant-profile-conflict" | "private-notes-carrier-conflict" | "owned-set-refused" | "set-managed-subject" @@ -1993,6 +1994,7 @@ pub fn client_error_code(code: Option<&str>) -> String { | "peer-too-old" | "validation-failed" | "idempotency-conflict" + | "grant-profile-conflict" | "invalid-answer" | "not-answerable" | "idempotency-key-expired" diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index f9c4bb13d62..e1140d4cbce 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -68,11 +68,10 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { Ok(()) } -// Issuance-only scan: authentication retains its existing indexed lookup and reads. +// Admission and authentication share the principal-indexed active-grant fold. // append owns the admission lock; several grants of the same profile are allowed. // Filter revoked/expired history before loading claim bodies into Rust. Expiry -// uses the latest policy, not the original grant. Keep malformed missing fields -// in the result so the existing validation below still reports them. +// uses the latest policy, not the original grant. const ADMISSION_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) @@ -84,30 +83,112 @@ const ADMISSION_QUERY: &str = CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; -fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { - let profile = Profile::stored(source)?; - let principal = principal(source)?; - // Without a valid owner the old scan must still surface its configuration - // error before examining expiry; do not prefilter those rows. - let expiry_cut = owning_person(state).ok().map(|_| client_now_ms() as u64); +fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) -> Result, ApiError> { + let owner = owning_person(state)?; let ids = { let connection = state.store.readers.get(); let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-h99f1a302c7b1 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ ADMISSION_QUERY).map_err(ApiError::internal)?; query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut], |row| row.get::<_, String>(0)) .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? }; + let mut active = Vec::new(); for id in ids { let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? .ok_or_else(|| forbidden("external grant is absent"))?; - if grant.origin != state.store.origin() || grant.actor.as_deref() != Some(owning_person(state)?) - || latest(state, &grant.subject, REVOKED)?.is_some() { + if grant.actor.as_deref() != Some(owner) + || (expiry_cut.is_some() && latest(state, &grant.subject, REVOKED)?.is_some()) { continue; } let policy = effective(state, &grant)?; - let active = fields(&policy)?; - if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > client_now_ms() { - profile.compatible(Profile::stored(fields(&grant)?)?)?; - profile.compatible(Profile::stored(active)?)?; + let foreign = grant.origin != state.store.origin(); + // Custom fields are open at replication admission. Actor/origin strings + // alone therefore confer no authority to suspend another credential. + // Only well-formed owner grants carried by a signed, admitted issuer + // count; policies must have the same provenance and immutable identity. + if foreign && (!valid_foreign_grant(state, &grant, &policy)? + || !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)? + || (policy.id != grant.id && !state.store.claim_has_authenticated_member_writer(&policy.id).map_err(ApiError::internal)?)) { + continue; + } + let source = fields(&policy)?; + if expiry_cut.is_none_or(|now| unexpired(source, now)) { + let profile = Profile::stored(fields(&grant)?)?; + profile.compatible(Profile::stored(source)?)?; + active.push((grant, profile)); + } + } + Ok(active) +} + +fn unexpired(source: &Value, now: u64) -> bool { + source["expires_at_unix_ms"].as_u64().is_some_and(|expires| expires > now) +} + +fn valid_foreign_grant(state: &AppState, grant: &ClaimRecord, policy: &ClaimRecord) -> Result { + let validate = || -> Result<(), ApiError> { + let original = fields(grant)?; + let source = fields(policy)?; + let principal = principal(original)?; + let id = original["grant_id"].as_str().ok_or_else(|| forbidden("grant ID absent"))?; + if subject(id)? != grant.subject || policy.origin != grant.origin + || policy.actor.as_deref() != Some(owning_person(state)?) + || self::principal(source)? != principal + || ["grant_id", "session_actor", "issuer", "profile"].iter().any(|key| source[*key] != original[*key]) + || source["issuer"] != owning_person(state)? + || source["session_actor"].as_str().and_then(|actor| actor.strip_prefix(principal)) + .and_then(|suffix| suffix.strip_prefix("/session/")) != Some(id) + || !matches!(source["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) + || source["disclosure_consent"] != true + || !original["credential_hash"].as_str().is_some_and(|digest| digest.len() == 64 + && digest.bytes().all(|byte| byte.is_ascii_hexdigit())) + || !source["scopes"].as_array().is_some_and(|scopes| + scopes.iter().all(|scope| scope.as_str().is_some_and(|scope| SCOPES.contains(&scope)))) { + return Err(forbidden("invalid foreign external grant")); + } + digest_only(original)?; + digest_only(source)?; + Profile::stored(original)?.compatible(Profile::stored(source)?)?; + Ok(()) + }; + Ok(validate().is_ok()) +} + +fn witness(grant: &ClaimRecord, profile: Profile) -> Value { + json!({"grant_id":fields(grant).ok().and_then(|source| source.get("grant_id")), + "origin":grant.origin,"profile":match profile { Profile::Assistant => "assistant", Profile::Service => "service" }}) +} + +fn conflict_error(witness: Value) -> ApiError { + ApiError { + status: StatusCode::CONFLICT, + code: "grant-profile-conflict".into(), + message: "principal has active grants of opposite profiles; revoke one to clear the conflict".into(), + details: Box::new(serde_json::Map::from_iter([("conflict".into(), witness)])), + } +} + +#[cfg(test)] +pub fn profile_conflict(state: &AppState, granted: &ClaimRecord) -> Result, ApiError> { + profile_conflict_at(state, granted, client_now_ms() as u64) +} + +fn profile_conflict_at(state: &AppState, granted: &ClaimRecord, now: u64) -> Result, ApiError> { + let active = candidate_grants(state, principal(fields(granted)?)?, Some(now))?; + let Some((grant, profile)) = active.iter().find(|(grant, _)| grant.id == granted.id) else { + return Ok(None); + }; + Ok(active.iter().find(|(_, other)| other != profile).map(|(other, other_profile)| + json!({"grants":[witness(grant, *profile),witness(other, *other_profile)]}))) +} + +fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { + let profile = Profile::stored(source)?; + for (grant, other) in candidate_grants(state, principal(source)?, Some(client_now_ms() as u64))? { + if profile != other { + return Err(conflict_error(json!({"grants":[ + {"grant_id":source["grant_id"],"origin":state.store.origin(), + "profile":match profile { Profile::Assistant => "assistant", Profile::Service => "service" }}, + witness(&grant, other)]}))); } } Ok(()) @@ -235,6 +316,23 @@ pub fn projection(state: &AppState, granted: &ClaimRecord) -> Result Result { + let now = client_now_ms() as u64; + if let Some(witness) = profile_conflict_at(state, granted, now)? { + return Err(conflict_error(witness)); + } let policy = effective(state, granted)?; let source = fields(&policy)?; let principal = principal(source)?; @@ -268,7 +370,7 @@ pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) return Err(forbidden("assistant requests require the authoritative grant issuer")); } if latest(state, &granted.subject, REVOKED)?.is_some() - || source["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) <= client_now_ms() + || !unexpired(source, now) || source["issuer"] != owning_person(state)? || !matches!(source["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) || source["disclosure_consent"] != true { return Err(forbidden("assistant grant was revoked, expired, or has invalid policy")); @@ -303,6 +405,9 @@ pub fn authorize_route(session: &ClientSession, request: &Request) -> Resu Ok(()) } +#[cfg(test)] +mod conflict_tests; + #[cfg(test)] mod tests { use super::*; diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs new file mode 100644 index 00000000000..3e262da596e --- /dev/null +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -0,0 +1,302 @@ +use super::*; +use fractal_client::ErrorCode; +use smallclaims::fleet::MemberKey; +use std::sync::Arc; + +const FLEET: &str = "86700000-0000-4000-8000-000000000001"; +const OWNER: &str = "person/owner"; +const ASSISTANT_ID: &str = "111111111111111111111111"; +const SERVICE_ID: &str = "222222222222222222222222"; + +// This override is thread-local: the reserved service profile remains closed in +// production, and another test thread cannot accidentally inherit the fixture. +struct ServiceFixture; +impl ServiceFixture { + fn enable() -> Self { + assert!(!tests::SERVICE_PROFILE.replace(true)); + Self + } +} +impl Drop for ServiceFixture { + fn drop(&mut self) { + tests::SERVICE_PROFILE.set(false); + } +} + +fn member(root: &std::path::Path, name: &str) -> AppState { + let mut state = crate::api::tests_shared::state(root); + state.store = Arc::new(Store::open_memory(name).unwrap()); + state.node = name.into(); + state.owning_person = Some(OWNER.into()); + state.fleet_id = Some(FLEET.into()); + state.store.bind_fleet(FLEET).unwrap(); + state +} + +fn replicate(from: &AppState, to: &AppState) { + let exchange = from.store.export_replication_exchange_answering( + FLEET, &to.store.replication_inventory().unwrap(), + &to.store.replication_signature_requests().unwrap(), + ).unwrap(); + to.store.receive_replication_exchange(from.store.origin(), FLEET, &exchange).unwrap(); + to.store.validate_replication_backlog().unwrap(); + to.store.project_replication_backlog().unwrap(); +} + +fn admitted_pair(root: &std::path::Path) -> (AppState, AppState) { + let a = member(root, "alder"); + let b = member(root, "birch"); + let anchor = Arc::new(MemberKey::generate().unwrap().0); + let peer = Arc::new(MemberKey::generate().unwrap().0); + for (state, key) in [(&a, &anchor), (&b, &peer)] { + state.store.pin_fleet_anchor(anchor.public()).unwrap(); + state.store.set_member_key(Some(key.clone())).unwrap(); + } + a.store.admit_fleet_anchor(FLEET, anchor.public(), "listening").unwrap(); + raw_claim(&a, "host/birch", "fleet.member-admitted", OWNER, json!({ + "fleet_id":FLEET,"member_key":peer.public(),"via":"invite","mode":"listening" + })); + replicate(&a, &b); + assert!(matches!(b.store.fleet_membership().unwrap().state("birch"), + smallclaims::fleet::MemberState::Current(_))); + (a, b) +} + +fn grant_fields(id: &str, profile: &str) -> Value { + json!({"profile":profile,"grant_id":id,"principal":PRINCIPAL, + "issuer":OWNER,"session_actor":format!("{PRINCIPAL}/session/{id}"), + "expires_at_unix_ms":u64::MAX,"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":["read.assistant.summary"], + "credential_hash":credential_digest(id)}) +} + +fn issue(state: &AppState, id: &str, profile: &str) -> Result { + let source = grant_fields(id, profile); + let subject = subject(id).unwrap(); + let begun = append(state, subject.clone(), BEGUN, OWNER, source.clone(), None)?; + append(state, subject, GRANTED, OWNER, source, Some(&begun)) +} + +fn raw_claim(state: &AppState, subject: &str, kind: &str, actor: &str, source: Value) -> ClaimRecord { + state.store.append_claim(&ClaimInput { + subject:subject.into(),kind:kind.into(),actor:Some(actor.into()), + fields:serde_json::from_value(source).unwrap(),evidence:Vec::new(), + expected_subject:None,idempotency_key:None, + }).unwrap() +} + +fn authenticate_id(state: &AppState, id: &str) -> Result, ApiError> { + authenticate(state, &credential_digest(id), "http") +} + +fn assert_conflict(error: &ApiError) { + let typed: ErrorCode = serde_json::from_value(json!(error.code)).unwrap(); + assert_eq!(typed, ErrorCode::GrantProfileConflict); + assert_eq!(error.status, StatusCode::CONFLICT); +} + +fn assert_witness(value: &Value) { + let rows = value["grants"].as_array().unwrap(); + assert_eq!(rows.len(), 2); + for (id, origin, profile) in [(ASSISTANT_ID, "alder", "assistant"), + (SERVICE_ID, "birch", "service")] { + assert!(rows.contains(&json!({"grant_id":id,"origin":origin,"profile":profile})), + "missing grant witness: {value}"); + } +} + +#[test] +fn disconnected_opposite_profiles_conflict_on_both_members_and_revocation_recovers() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let assistant = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + assert!(authenticate_id(&b, SERVICE_ID).unwrap().is_some()); + replicate(&a, &b); + replicate(&b, &a); + for state in [&a, &b] { + for grant in [&assistant, &service] { + assert!(state.store.claim_has_authenticated_member_writer(&grant.id).unwrap()); + let error = authenticate_id(state, fields(grant).unwrap()["grant_id"].as_str().unwrap()) + .err().expect("both credentials must be suspended on either member"); + assert_conflict(&error); + assert_witness(&Value::Object((*error.details).clone())["conflict"]); + assert_witness(&profile_conflict(state, grant).unwrap().unwrap()); + assert_witness(&projection(state, grant).unwrap()["conflict"]); + } + } + append(&b, service.subject.clone(), REVOKED, OWNER, + fields(&service).unwrap().clone(), Some(&service)).unwrap(); + replicate(&b, &a); + for state in [&a, &b] { + for grant in [&assistant, &service] { + assert!(profile_conflict(state, grant).unwrap().is_none()); + assert!(projection(state, grant).unwrap()["conflict"].is_null()); + } + assert!(authenticate_id(state, SERVICE_ID).is_err()); + let inspected = projection(state, &assistant).unwrap(); + let cleared = inspected["cleared_conflicts"].as_array().unwrap(); + assert_eq!(cleared.len(), 1); + assert_eq!(cleared[0]["cause"], "revoked"); + assert_witness(&cleared[0]); + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let foreign = authenticate_id(&b, ASSISTANT_ID).err().unwrap(); + assert_eq!(foreign.code, "forbidden"); + assert!(foreign.message.contains("authoritative grant issuer")); +} + +#[test] +fn expiry_boundary_clears_conflict_and_disconnected_reissue_recomputes_it() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let assistant = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + // Birch never receives Alder's assistant grant: it remains a disconnected + // issuer even as Alder receives its grants and policy transitions. + replicate(&b, &a); + assert_witness(&profile_conflict(&a, &assistant).unwrap().unwrap()); + + let mut policy = fields(&service).unwrap().clone(); + policy["expires_at_unix_ms"] = json!(100_u64); + append(&b, service.subject.clone(), POLICY, OWNER, policy, Some(&service)).unwrap(); + replicate(&b, &a); + for (now, expected_count, conflicted) in [(99_u64, 2, true), (100, 1, false), (101, 1, false)] { + let candidates = candidate_grants(&a, PRINCIPAL, Some(now)).unwrap(); + assert_eq!(candidates.len(), expected_count, "SQL/Rust expiry boundary at {now}"); + assert_eq!(candidates.iter().any(|(grant, _)| grant.id == service.id), conflicted); + assert_eq!(profile_conflict_at(&a, &assistant, now).unwrap().is_some(), conflicted); + assert_eq!(profile_conflict_at(&a, &service, now).unwrap().is_some(), conflicted); + assert_eq!(unexpired(fields(&effective(&a, &service).unwrap()).unwrap(), now), conflicted); + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let inspected = projection(&a, &assistant).unwrap(); + assert!(inspected["conflict"].is_null()); + let cleared = inspected["cleared_conflicts"].as_array().unwrap(); + assert_eq!(cleared.len(), 1); + assert_eq!(cleared[0]["cause"], "expired"); + assert_witness(&cleared[0]); + + let replacement_id = "333333333333333333333333"; + let replacement = issue(&b, replacement_id, "service").unwrap(); + replicate(&b, &a); + let witness = profile_conflict(&a, &assistant).unwrap().unwrap(); + let rows = witness["grants"].as_array().unwrap(); + assert_eq!(rows.len(), 2); + assert!(rows.contains(&json!({"grant_id":ASSISTANT_ID,"origin":"alder","profile":"assistant"}))); + assert!(rows.contains(&json!({"grant_id":replacement_id,"origin":"birch","profile":"service"}))); + assert!(!rows.iter().any(|row| row["grant_id"] == SERVICE_ID)); + assert!(profile_conflict(&a, &service).unwrap().is_none()); + assert!(profile_conflict(&a, &replacement).unwrap().is_some()); + for id in [ASSISTANT_ID, replacement_id] { + assert_conflict(&authenticate_id(&a, id).err().unwrap()); + } + let inspected = projection(&a, &assistant).unwrap(); + assert_eq!(inspected["conflict"], witness); + assert!(inspected["cleared_conflicts"].is_null()); +} + +#[test] +fn same_profile_foreign_grants_do_not_conflict_or_authenticate_on_the_wrong_member() { + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let first = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let second = issue(&b, SERVICE_ID, "assistant").unwrap(); + replicate(&a, &b); + replicate(&b, &a); + for state in [&a, &b] { + for grant in [&first, &second] { + assert!(profile_conflict(state, grant).unwrap().is_none()); + } + } + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + assert!(authenticate_id(&b, SERVICE_ID).unwrap().is_some()); + assert_eq!(authenticate_id(&a, SERVICE_ID).err().unwrap().code, "forbidden"); + assert_eq!(authenticate_id(&b, ASSISTANT_ID).err().unwrap().code, "forbidden"); +} + +#[test] +fn admission_refuses_a_known_authenticated_foreign_opposite_profile() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + issue(&b, SERVICE_ID, "service").unwrap(); + replicate(&b, &a); + let error = issue(&a, ASSISTANT_ID, "assistant").err().unwrap(); + assert_conflict(&error); + assert_witness(&Value::Object((*error.details).clone())["conflict"]); + assert!(latest(&a, &subject(ASSISTANT_ID).unwrap(), GRANTED).unwrap().is_none()); +} + +#[test] +fn malformed_authenticated_foreign_grants_cannot_suspend_a_local_credential() { + let root = tempfile::tempdir().unwrap(); + // Each case is independently a signed admitted writer's claim, rather than + // an unsigned claim rejected before it can exercise the conflict scanner. + for invalid in ["profile", "grant_id", "principal", "issuer", "session_actor", + "minimal_read_mode", "disclosure_consent", "scopes", "credential_hash", "actor"] { + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let mut source = grant_fields(SERVICE_ID, "service"); + if invalid != "actor" { + source[invalid] = Value::Null; + } + let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, + if invalid == "actor" { "person/attacker" } else { OWNER }, source); + replicate(&b, &a); + assert!(a.store.claim_by_id(&foreign.id).unwrap().is_some(), "{invalid}"); + assert!(a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap(), "{invalid}"); + assert!(profile_conflict(&a, &local).unwrap().is_none(), "{invalid}"); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some(), "{invalid}"); + } +} + +#[test] +fn foreign_policy_with_mismatched_identity_cannot_suspend_a_local_credential() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = issue(&b, SERVICE_ID, "service").unwrap(); + let mut policy = fields(&foreign).unwrap().clone(); + policy["session_actor"] = json!("assistant/chatgpt/session/333333333333333333333333"); + raw_claim(&b, &foreign.subject, POLICY, OWNER, policy); + replicate(&b, &a); + assert!(profile_conflict(&a, &local).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); +} + +#[test] +fn unverifiable_foreign_grant_cannot_suspend_a_local_credential() { + let root = tempfile::tempdir().unwrap(); + // Legacy replication projects unsigned envelopes. Mere visibility and an + // owner-shaped actor are not sufficient provenance for a conflict witness. + let a = member(root.path(), "alder"); + let b = member(root.path(), "birch"); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, OWNER, + grant_fields(SERVICE_ID, "service")); + replicate(&b, &a); + assert!(a.store.claim_by_id(&foreign.id).unwrap().is_some()); + assert!(!a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap()); + assert!(profile_conflict(&a, &local).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); +} + +#[test] +fn admission_scan_uses_the_real_principal_index() { + let root = tempfile::tempdir().unwrap(); + let state = member(root.path(), "alder"); + issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let connection = state.store.readers.get(); + let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-hf4201606586b owner=fractal_api_core::api::client_v0::external_grants::conflict_tests TODO=trace-statement-and-value-representation */ &format!("EXPLAIN QUERY PLAN {ADMISSION_QUERY}")).unwrap(); + let plan = query.query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, + Some(client_now_ms() as u64)], |row| row.get::<_, String>(3)).unwrap() + .collect::, _>>().unwrap(); + println!("external grant admission query plan:\n{}", plan.join("\n")); + assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_index")), + "principal admission must use its production index: {plan:?}"); +} diff --git a/crates/fractal-client-codegen/templates/Models.swift.in b/crates/fractal-client-codegen/templates/Models.swift.in index ddebf7a3d54..ac6f5cf5a62 100644 --- a/crates/fractal-client-codegen/templates/Models.swift.in +++ b/crates/fractal-client-codegen/templates/Models.swift.in @@ -153,6 +153,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case peerTooOld case validationFailed case idempotencyConflict + case grantProfileConflict case agentsPublicationRowTooLarge case attentionMigrated case invalidAnswer, notAnswerable @@ -243,6 +244,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case "peer-too-old": .peerTooOld case "validation-failed": .validationFailed case "idempotency-conflict": .idempotencyConflict + case "grant-profile-conflict": .grantProfileConflict case "stale-fence": .staleFence case "issuer-required": .issuerRequired case "invalid-answer": .invalidAnswer; case "not-answerable": .notAnswerable @@ -333,6 +335,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case .peerTooOld: "peer-too-old" case .validationFailed: "validation-failed" case .idempotencyConflict: "idempotency-conflict" + case .grantProfileConflict: "grant-profile-conflict" case .staleFence: "stale-fence" case .issuerRequired: "issuer-required" case .invalidAnswer: "invalid-answer"; case .notAnswerable: "not-answerable" @@ -1427,7 +1430,21 @@ public struct AssistantGrant: Codable, Sendable { public let kind, id, sessionActor, deviceID, keyID, issuer, expiresAt, consentEvidence: String; public let principal: AssistantPrincipal; public let senderClass: AssistantSenderClass; public let scopes: [AssistantScope]; public let policyRevision: UInt64; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]; public let disclosureConsent, revoked: Bool /// Owner-provisioned SCG read pins; absent means every assistant read is denied. public let readTrust: AssistantReadTrust? - enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust" } + public let conflict: GrantProfileConflictWitness? + public let clearedConflicts: [ClearedGrantProfileConflictWitness]? + enum CodingKeys: String, CodingKey { case kind, id, sessionActor = "session_actor", deviceID = "device_id", keyID = "key_id", issuer, expiresAt = "expires_at", consentEvidence = "consent_evidence", principal, senderClass = "sender_class", scopes, policyRevision = "policy_revision", minimalReadMode = "minimal_read_mode", recipientAllowlist = "recipient_allowlist", disclosureConsent = "disclosure_consent", revoked, readTrust = "read_trust", conflict, clearedConflicts = "cleared_conflicts" } +} +public enum ExternalGrantProfile: String, Codable, Sendable { case assistant, service } +public enum GrantProfileConflictCause: String, Codable, Sendable { case revoked, expired } +public struct GrantProfileWitness: Codable, Sendable { + public let grantID: String?; public let origin: String; public let profile: ExternalGrantProfile + enum CodingKeys: String, CodingKey { case grantID = "grant_id", origin, profile } +} +public struct GrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness] +} +public struct ClearedGrantProfileConflictWitness: Codable, Sendable { + public let grants: [GrantProfileWitness]; public let cause: GrantProfileConflictCause } public struct AssistantGrantPolicy: Codable, Sendable { public let apiVersion, consentEvidence: String; public let scopes: [AssistantScope]; public let expiresInSeconds: UInt64?; public let disclosureConsent: Bool; public let minimalReadMode: AssistantMinimalReadMode; public let recipientAllowlist: [String]? diff --git a/crates/fractal-client-codegen/templates/generated.rs.in b/crates/fractal-client-codegen/templates/generated.rs.in index b23666338e7..3df01ac2da0 100644 --- a/crates/fractal-client-codegen/templates/generated.rs.in +++ b/crates/fractal-client-codegen/templates/generated.rs.in @@ -134,6 +134,7 @@ pub enum ErrorCode { PeerTooOld, ValidationFailed, IdempotencyConflict, + GrantProfileConflict, LegacyActionReceiptUntrusted, IssuerRequired, SuspendAuthoredSessionSelection, @@ -4324,6 +4325,40 @@ pub struct AssistantGrant { pub revoked: bool, #[serde(default, skip_serializing_if = "Option::is_none")] pub read_trust: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub conflict: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cleared_conflicts: Option>, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum ExternalGrantProfile { + Assistant, + Service, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum GrantProfileConflictCause { + Revoked, + Expired, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileWitness { + pub grant_id: Option, + pub origin: String, + pub profile: ExternalGrantProfile, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileConflictWitness { + pub grants: Vec, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct ClearedGrantProfileConflictWitness { + pub grants: Vec, + pub cause: GrantProfileConflictCause, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(deny_unknown_fields)] diff --git a/crates/fractal-client-codegen/templates/lib.rs.in b/crates/fractal-client-codegen/templates/lib.rs.in index 0f0ca7259e4..a801826b95c 100644 --- a/crates/fractal-client-codegen/templates/lib.rs.in +++ b/crates/fractal-client-codegen/templates/lib.rs.in @@ -1192,6 +1192,7 @@ fn render_message(code: Option<&ErrorCode>, message: &str, human: bool) -> Strin | ErrorCode::LegacyActionReceiptUntrusted | ErrorCode::RuntimeNotLocal | ErrorCode::PrivateNotesCarrierConflict + | ErrorCode::GrantProfileConflict | ErrorCode::PrivateNotesUnreachable | ErrorCode::PrivateNotesIndeterminate | ErrorCode::ArrangementExists diff --git a/crates/fractal-client/src/generated.rs b/crates/fractal-client/src/generated.rs index cb8a786636d..068871294d3 100644 --- a/crates/fractal-client/src/generated.rs +++ b/crates/fractal-client/src/generated.rs @@ -134,6 +134,7 @@ pub enum ErrorCode { PeerTooOld, ValidationFailed, IdempotencyConflict, + GrantProfileConflict, LegacyActionReceiptUntrusted, IssuerRequired, SuspendAuthoredSessionSelection, @@ -5155,6 +5156,40 @@ pub struct AssistantGrant { pub revoked: bool, #[serde(default, skip_serializing_if = "Option::is_none")] pub read_trust: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub conflict: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cleared_conflicts: Option>, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum ExternalGrantProfile { + Assistant, + Service, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum GrantProfileConflictCause { + Revoked, + Expired, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileWitness { + pub grant_id: Option, + pub origin: String, + pub profile: ExternalGrantProfile, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct GrantProfileConflictWitness { + pub grants: Vec, +} +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct ClearedGrantProfileConflictWitness { + pub grants: Vec, + pub cause: GrantProfileConflictCause, } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[serde(deny_unknown_fields)] diff --git a/crates/fractal-client/src/lib.rs b/crates/fractal-client/src/lib.rs index e13b116fda1..4f1001ea92c 100644 --- a/crates/fractal-client/src/lib.rs +++ b/crates/fractal-client/src/lib.rs @@ -1278,6 +1278,7 @@ fn render_message(code: Option<&ErrorCode>, message: &str, human: bool) -> Strin | ErrorCode::LegacyActionReceiptUntrusted | ErrorCode::RuntimeNotLocal | ErrorCode::PrivateNotesCarrierConflict + | ErrorCode::GrantProfileConflict | ErrorCode::PrivateNotesUnreachable | ErrorCode::PrivateNotesIndeterminate | ErrorCode::ArrangementExists diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 0d5ecbf05fd..6aa7182a434 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -2935,6 +2935,55 @@ impl Store { Ok(false) } + /// Whether an accepted copy was signed by a keyed fleet member acting as its origin. + /// Requires a valid record in a validated envelope, a signature key authorized for that + /// writer's sequence, and a cryptographically valid signature in this store's fleet/shard + /// domain. Legacy and unkeyed writers do not authenticate provenance. Reads only sealed + /// membership; this query never seals local batches or scans the replication log. + pub fn claim_has_authenticated_member_writer(&self, claim_id: &str) -> Result { + self.read_snapshot(|_| { + let membership = self.fleet_membership_sealed()?; + let connection = self.readers.get(); + let Some(fleet_id) = self.signing_fleet_id(&connection)? else { + return Ok(false); + }; + let shard = fleet_meta(&connection, "shard_id")?; + let mut statement = connection.prepare_cached( + "SELECT records.writer, records.sequence, records.envelope_hash, + signatures.member_key, signatures.signature + FROM replica_records AS records + JOIN claims ON claims.id=records.claim_id AND claims.origin=records.writer + JOIN replica_envelopes AS envelopes + USING (writer, sequence, envelope_hash) + JOIN replica_envelope_signatures AS signatures + USING (writer, sequence, envelope_hash) + WHERE records.claim_id=?1 AND records.state='valid' + AND envelopes.receipt_state='validated'", + )?; + let rows = statement.query_map([claim_id], |row| { + Ok(( + row.get::<_, String>(0)?, + row.get::<_, u64>(1)?, + row.get::<_, String>(2)?, + row.get::<_, String>(3)?, + row.get::<_, String>(4)?, + )) + })?; + for row in rows { + let (writer, sequence, hash, key, signature) = row?; + if matches!( + membership.window(&writer, sequence), + crate::fleet::Window::Keyed(keys) if keys.contains(&key) + ) && VerifiedEnvelopeSignature::verify( + shard.as_deref(), &fleet_id, &writer, sequence, &hash, &key, &signature, + ).is_some() { + return Ok(true); + } + } + Ok(false) + }) + } + /// Envelopes this node admitted before it knew that their writer is keyed or that their /// incarnation had ended. Admission decisions are not revisited, so these stay admitted; diff --git a/crates/smallclaims/src/store/membership_query_tests.rs b/crates/smallclaims/src/store/membership_query_tests.rs index 8022ac07543..3ba1abe2dcf 100644 --- a/crates/smallclaims/src/store/membership_query_tests.rs +++ b/crates/smallclaims/src/store/membership_query_tests.rs @@ -356,3 +356,118 @@ fn sealed_fleet_cache_tracks_batch_signers_after_envelope_identity_changes() { ); } } + +fn cache_member_window(store: &Store, key: &str, start: u64) { + let mut anchor = admitted("anchor", "birch", key, "anchor", "birch", start.max(1)); + anchor.fields.insert("writer_floor".into(), serde_json::json!(start.saturating_sub(1))); + anchor.signers.insert(key.into()); + let membership = Membership::fold(Some(key), &[anchor]); + assert!(membership.counts("anchor"), "the synthetic keyed window must have a valid anchor"); + let generation = fleet_generation(&store.readers.get()).unwrap(); + *store.membership_cache.lock().unwrap() = Some((generation, membership)); +} + +fn authenticated_member_fixture() -> (Store, String, Arc) { + const FLEET: &str = "3e7a9c41-5d2b-4f86-b0c3-9a1e6d4f2b58"; + let source = Store::open_memory("birch", Arc::new(super::runtime::Plain)).unwrap(); + source.bind_fleet(FLEET).unwrap(); + let key = Arc::new(crate::fleet::MemberKey::generate().unwrap().0); + source.load_member_key(Some(key.clone())).unwrap(); + let claim = source.append_claim(&ClaimInput { + subject: "note/provenance".into(), + kind: "example.note".into(), + actor: None, + fields: BTreeMap::new(), + evidence: Vec::new(), + expected_subject: None, + idempotency_key: None, + }).unwrap(); + let target = Store::open_memory("cedar", Arc::new(super::runtime::Plain)).unwrap(); + target.bind_fleet(FLEET).unwrap(); + let exchange = source.export_replication_exchange( + FLEET, &target.replication_inventory().unwrap(), + ).unwrap(); + target.receive_replication_exchange("birch", FLEET, &exchange).unwrap(); + assert_eq!(target.validate_replication_backlog().unwrap().valid, 1); + target.project_replication_backlog().unwrap(); + assert!(target.claim_by_id(&claim.id).unwrap().is_some()); + // Membership folding is tested above. Pin a sealed keyed window so these controls + // exercise provenance itself, including its warm request-path cache. + cache_member_window(&target, key.public(), 0); + (target, claim.id, key) +} + +#[test] +fn authenticated_member_writer_accepts_a_foreign_origin_from_sealed_membership() { + let (store, claim, _) = authenticated_member_fixture(); + assert!(!store.claim_has_authenticated_self_writer(&claim).unwrap()); + for _ in 0..3 { + assert!(store.claim_has_authenticated_member_writer(&claim).unwrap()); + } + assert!(!store.claim_has_authenticated_member_writer("missing").unwrap()); +} + +#[test] +fn authenticated_member_writer_rejects_legacy_wrong_key_and_outside_window() { + let (store, claim, key) = authenticated_member_fixture(); + assert!(store.claim_has_authenticated_member_writer(&claim).unwrap()); + let generation = fleet_generation(&store.readers.get()).unwrap(); + *store.membership_cache.lock().unwrap() = Some((generation, Membership::default())); + assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); + let other = crate::fleet::MemberKey::generate().unwrap().0; + cache_member_window(&store, other.public(), 0); + assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); + cache_member_window(&store, key.public(), u64::MAX); + assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); +} + +#[test] +fn authenticated_member_writer_requires_origin_valid_record_validated_envelope_and_signature() { + for sql in [ + /* sqlite-large-value: allow-for-now lv-h908d794ad3e8 owner=smallclaims::store::membership_query_tests TODO=prepare-body-and-predecessor-values */ + "UPDATE claims SET origin='forged-origin'", + /* sqlite-large-value: allow-for-now lv-h6ff49ec4f026 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_records SET state='invalid'", + /* sqlite-large-value: allow-for-now lv-ha41272fe6b10 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelopes SET receipt_state='pending'", + /* sqlite-large-value: allow-for-now lv-hbea4b67b6a13 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "DELETE FROM replica_envelope_signatures", + /* sqlite-large-value: allow-for-now lv-h9e7e7a841384 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelope_signatures SET signature='invalid'", + /* sqlite-large-value: allow-for-now lv-hc8361ab9b858 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelope_signatures SET envelope_hash='other-envelope'", + ] { + let (store, claim, key) = authenticated_member_fixture(); + store.connection.write().execute_batch(/* sqlite-large-value: allow-for-now lv-h622f4fdd0f6d owner=smallclaims::store::membership_query_tests TODO=trace-statement-and-value-representation */ sql).unwrap(); + cache_member_window(&store, key.public(), 0); + assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap(), "{sql}"); + } +} + +#[test] +fn authenticated_member_writer_rejects_wrong_fleet_and_shard_signature_domains() { + for shard in [None, Some("another-shard")] { + let (store, claim, key) = authenticated_member_fixture(); + let connection = store.connection.write(); + let (sequence, hash): (u64, String) = connection.query_row( + "SELECT sequence, envelope_hash FROM replica_records WHERE claim_id=?1", + [&claim], |row| Ok((row.get(0)?, row.get(1)?)), + ).unwrap(); + let signature = key.sign(&crate::fleet::envelope_signature_message_in( + shard, + if shard.is_some() { + "3e7a9c41-5d2b-4f86-b0c3-9a1e6d4f2b58" + } else { + "another-fleet" + }, + "birch", sequence, &hash, + )); + connection.execute( + /* sqlite-large-value: allow-for-now lv-hf3e2d678372b owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelope_signatures SET signature=?1", [&signature], + ).unwrap(); + drop(connection); + cache_member_window(&store, key.public(), 0); + assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); + } +} diff --git a/docs/st3/client-v0/schemas/client-v0.schema.json b/docs/st3/client-v0/schemas/client-v0.schema.json index 53f3563731f..305de428cdb 100644 --- a/docs/st3/client-v0/schemas/client-v0.schema.json +++ b/docs/st3/client-v0/schemas/client-v0.schema.json @@ -592,6 +592,7 @@ "peer-too-old", "validation-failed", "idempotency-conflict", + "grant-profile-conflict", "legacy-action-receipt-untrusted", "issuer-required", "suspend-authored-session-selection", @@ -3816,6 +3817,35 @@ "write.assistant.answers" ] }, "AssistantMinimalReadMode": { "enum": ["approval-once", "caller-bound-allow"] }, + "ExternalGrantProfile": { "enum": ["assistant", "service"] }, + "GrantProfileConflictCause": { "enum": ["revoked", "expired"] }, + "GrantProfileWitness": { + "type": "object", + "additionalProperties": false, + "required": ["grant_id", "origin", "profile"], + "properties": { + "grant_id": { "type": ["string", "null"], "description": "Grant ID; null only for legacy local fixtures without an ID." }, + "origin": { "type": "string" }, + "profile": { "$ref": "#/$defs/ExternalGrantProfile" } + } + }, + "GrantProfileConflictWitness": { + "type": "object", + "additionalProperties": false, + "required": ["grants"], + "properties": { + "grants": { "type": "array", "items": { "$ref": "#/$defs/GrantProfileWitness" } } + } + }, + "ClearedGrantProfileConflictWitness": { + "type": "object", + "additionalProperties": false, + "required": ["grants", "cause"], + "properties": { + "grants": { "type": "array", "items": { "$ref": "#/$defs/GrantProfileWitness" } }, + "cause": { "$ref": "#/$defs/GrantProfileConflictCause" } + } + }, "AssistantGrant": { "type": "object", "additionalProperties": false, @@ -3837,6 +3867,8 @@ "disclosure_consent": { "type": "boolean" }, "consent_evidence": { "type": "string", "minLength": 1, "maxLength": 512 }, "revoked": { "type": "boolean" }, + "conflict": { "anyOf": [{ "$ref": "#/$defs/GrantProfileConflictWitness" }, { "type": "null" }], "description": "Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers." }, + "cleared_conflicts": { "type": "array", "items": { "$ref": "#/$defs/ClearedGrantProfileConflictWitness" }, "description": "Revoked or expired opposite-profile witnesses; emitted only when conflict is null." }, "read_trust": { "$ref": "#/$defs/AssistantReadTrust", "description": "Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied." } } }, diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index 380f9415f40..1bb7a6a3beb 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -798,6 +798,15 @@ {"id": "flow-h39d714b2bc13", "path": "crates/smallclaims/src/store/checkpoint_trim.rs", "function": "trim_checkpoint_from", "owner": "smallclaims::store::checkpoint_trim", "fingerprint": "344fc686f5b0778d9f534c322d46e20e2a21066b09d5acfc1c01c0cf88ad607a", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "description": "Exact-adoption/trim publication and durable cleanup must be separated without bypassing certification."} ], "sites": [ + {"id":"lv-hf4201606586b","path":"crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs","kind":"unresolved-sql-sink","fingerprint":"412c0c2f9ba50d78b84d6a1f379e285a435a7c6c05e777851130e01716e85c3c","owner":"fractal_api_core::api::client_v0::external_grants::conflict_tests","todo":"trace-statement-and-value-representation","disposition":"allow-for-now","line_hint":295,"excerpt":"& format ! ( \"EXPLAIN QUERY PLAN {ADMISSION_QUERY}\" )"}, + {"id":"lv-h622f4fdd0f6d","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"unresolved-sql-sink","fingerprint":"4ec7c53222c8a758c722e2111541035ce700d5ae7bd0898c5f1b1a743e6450fd","owner":"smallclaims::store::membership_query_tests","todo":"trace-statement-and-value-representation","disposition":"allow-for-now","line_hint":432,"excerpt":"sql"}, + {"id":"lv-h6ff49ec4f026","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"77379a14bb57c713620fd58bbdc380648a7d4228bbda0e58474916d971a24bad","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":425,"excerpt":"UPDATE replica_records SET state='invalid'"}, + {"id":"lv-h908d794ad3e8","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"5facd844161e6200be26cba65f6ea644e1238917f9a484d28577aa6deb8e905d","owner":"smallclaims::store::membership_query_tests","todo":"prepare-body-and-predecessor-values","disposition":"allow-for-now","line_hint":424,"excerpt":"UPDATE claims SET origin='forged-origin'"}, + {"id":"lv-h9e7e7a841384","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"701329c99c19076f8b477e2f84c40f1a2ece7974203ef799364c1f2382fd1875","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":428,"excerpt":"UPDATE replica_envelope_signatures SET signature='invalid'"}, + {"id":"lv-ha41272fe6b10","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"5427c45f190aa6981cd95fcddb43cdb335d88c69516ecb47c398627fc59c2f71","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":426,"excerpt":"UPDATE replica_envelopes SET receipt_state='pending'"}, + {"id":"lv-hbea4b67b6a13","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"309875e8abb2bc3a99eb38ecee4c711cb76b3289ec093bfbbc7fb20330b57bac","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":427,"excerpt":"DELETE FROM replica_envelope_signatures"}, + {"id":"lv-hc8361ab9b858","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"e55b2d5107f04e028d035bbb48904b58e786391c869a4b3a77d380d2543beb0c","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":429,"excerpt":"UPDATE replica_envelope_signatures SET envelope_hash='other-envelope'"}, + {"id":"lv-hf3e2d678372b","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"a650ee653ab427324395872e5e14688cc5d5b4a85d2c17aaafcdc2177d7f40c5","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":457,"excerpt":"UPDATE replica_envelope_signatures SET signature=?1"}, {"id": "lv-h2d6ca7ff29ef", "path": "crates/fractal-store/src/store/notice_authority.rs", "kind": "sql-template", "fingerprint": "bffb6dc7a37c0f4dc2b8f7d9c9f4330331b47cda2278c2dc99116326e0060fa7", "owner": "fractal_store::store::notice_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 86, "excerpt": "INSERT OR IGNORE INTO custom_dependencies VALUES(?1,?2,'[]','')"}, {"id": "lv-h6b344b76fae0", "path": "crates/fractal-store/src/store/notice_authority.rs", "kind": "sql-template", "fingerprint": "d413e887f4063a27a07b744cd1decd88fd76b81bcf87ca8bf4bd66434e18ef3b", "owner": "fractal_store::store::notice_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 61, "excerpt": "CREATE TRIGGER {name} BEFORE {action} ON {table} WHEN ({relevant}) AND ({changed}) BEGIN INSERT INTO local_custom_dirty SELECT subject FROM custom_sources WHERE subject LIKE 'custom/attention/%' ON CO"}, {"id": "lv-h80b0a7485e7e", "path": "crates/fractal-store/src/store/notice_authority.rs", "kind": "sql-template", "fingerprint": "8dc3b720253389a4c76f2c322c03a8f44a29cd7331786ca96608bdcbc12eb19d", "owner": "fractal_store::store::notice_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 135, "excerpt": "INSERT INTO local_custom_dirty SELECT subject FROM custom_sources WHERE subject LIKE 'custom/attention/%' ON CONFLICT(subject) DO NOTHING"}, diff --git a/docs/st3/principals-and-grants.md b/docs/st3/principals-and-grants.md index d5c4d70f00f..de4b43e9188 100644 --- a/docs/st3/principals-and-grants.md +++ b/docs/st3/principals-and-grants.md @@ -113,9 +113,31 @@ The claim-backed external-grant core is `crates/fractal-api-core/src/api/client_v0/external_grants.rs`. Its closed profiles keep `assistant/chatgpt` and `assistant/mcp` in the same assistant profile; service issuance is disabled and service has no assistant route or disclosure rights. -Several active grants of a principal's own profile are allowed, but a different -active profile is refused. Historical `custom.client.assistant.v1.*` claim kinds -and absent-principal legacy ChatGPT grants retain their existing meaning. +Several active grants of a principal's own profile are allowed. Admission refuses +a known opposite-profile grant, including one replicated from another issuer. +If disconnected issuers create opposite-profile grants, authentication suspends +every conflicting grant with `grant-profile-conflict`; there is no winner. +Inspect exposes a `conflict.grants` witness with both grant IDs, origins and +profiles. Once an owner's revoke replicates (or the opposite grant expires), +the remaining grant works again on its authoritative issuer; replication never +makes foreign credentials authenticate on another member. +While opposite-profile records remain visible, inspect also computes +`cleared_conflicts` witnesses naming the `revoked` or `expired` clearing cause. +Conflict state is never persisted. Admission and authentication use the same +millisecond clock and strict `expires_at_unix_ms > now` active boundary; a newly +issued opposite-profile grant reintroduces the conflict by computation. + +Only well-formed foreign grants attributed to the configured concrete owner +count as witnesses. Their grant and effective policy must have matching immutable +identity/profile, and each must have validated envelope provenance signed by a +key in its writer's admitted fleet membership window. Legacy unsigned, +unverifiable and malformed custom claims do not gain suspension authority merely +by naming an owner or origin. This intentionally favors verifiable issuer claims +over allowing arbitrary replicated custom fields to deny service. The fold uses +the principal expression index and removes expired/revoked history in SQL on +every admission/authentication/inspect read, including after replication catches +up. Historical `custom.client.assistant.v1.*` claim kinds and absent-principal +legacy ChatGPT grants retain their existing meaning. Claims persist credential/code digests, never bearer tokens or pairing codes; grant projections expose neither credential material nor its digests. diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json new file mode 100644 index 00000000000..884a071764a --- /dev/null +++ b/release-notes/external-grant-profile-conflict.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "summary": "Suspend external-grant authentication when replicated grants assign opposite profiles to one principal", + "replay": { + "status": "changed", + "detail": "Existing append-only grant and revocation claims are read without rewriting history. Active opposite-profile grants conflict regardless of replication arrival order; revoked and expired grants do not contribute to the conflict." + }, + "schema": { + "status": "changed", + "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409, plus optional AssistantGrant conflict and cleared_conflicts projection witnesses with typed assistant/service profiles and revoked/expired causes. No grant claim shape or storage migration changes." + }, + "rules": { + "status": "changed", + "detail": "If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view; service issuance remains disabled. Inspect computes active witnesses and cleared_conflicts witnesses with revoked or expired causes; no conflict state is persisted." + }, + "compatibility": { + "status": "changed", + "detail": "Conflict admission counts only well-formed foreign owner grants and matching effective policies with authenticated envelope provenance from a keyed, admitted fleet writer. Unverifiable or malformed replicated custom claims cannot acquire suspension authority by naming an owner. Tokens remain issuer-local. Older members do not enforce this suspension rule, so upgrade all serving members before relying on it." + }, + "downtime": { + "status": "changed", + "detail": "No migration downtime is required. Affected people cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend this interruption until revocations replicate. Unaffected people retain existing authentication behavior." + }, + "manual": { + "status": "changed", + "detail": "For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer; do not delete claims or replace tokens to resolve the conflict." + }, + "recovery": { + "status": "changed", + "detail": "After revocations replicate, remaining otherwise-valid grants in the intended profile can authenticate again without reissuance. Expiry of every remaining active opposite-profile grant also clears the conflict; expired and revoked grants remain unusable. If authentication is still suspended on an issuer after revocation, restore replication so it receives the revocations; restarting or changing claim arrival order does not resolve the conflict." + }, + "commits": [] +} From 0c5875e750e2a2b25cc4c7435a837a5982a7c211 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 08:28:51 +0100 Subject: [PATCH 05/52] test(external-grants): measure q39 with verified foreign grants agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../tests/daemon_cost/assistant_admission.rs | 74 +++++++++++++++++-- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 5fb7dcfbef2..3270fde11e8 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -1,5 +1,5 @@ //! Opt-in, real HTTP/Unix daemon measurement (not a router oneshot or mocked daemon). -//! Run this same test source on 98e550cb and on PR3-B, sequentially on dev5: +//! Run this same test source on the named revisions, sequentially on the same host: //! ```sh //! ST_ADMISSION_VARIANT=baseline cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 //! ST_ADMISSION_VARIANT=indexed cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 @@ -11,8 +11,9 @@ //! ST_ADMISSION_HISTORY (default 10000) is expired grants PER principal; ST_ADMISSION_SAMPLES //! (default 200) is measured GET/completion pairs PER read mode. Setup and proof creation are //! outside timing. Each pair starts behind a barrier, with no sleeps, polling, retries or timers. -//! ST_ADMISSION_REPORT optionally saves the complete JSON report. Run on dev5; hardware is -//! observed from uname/lscpu in the report, not inferred from an environment label. +//! ST_ADMISSION_FOREIGN_ACTIVE optionally adds verified same-profile active foreign grants +//! (default 0; use 3 for the provenance-check scenario). ST_ADMISSION_REPORT optionally +//! saves the complete JSON report. Hardware is observed from uname/lscpu, not inferred. //! The index DDL timing is a synthetic startup migration probe on the populated disposable //! real store, not total daemon startup or cold-disk startup. Latencies use the real daemon's //! bound sockets, bearer middleware, grant lookup, projection and durable approval consumption. @@ -27,8 +28,8 @@ use ring::{rand::SystemRandom, signature::{Ed25519KeyPair, KeyPair as _}}; use serde_json::{Value, json}; use tokio::sync::Barrier; -const OWNER: &str = "person/admission-bench"; -const NODE: &str = "admission-bench"; +const OWNER: &str = "person/bench-operator"; +const NODE: &str = "benchmark-member"; const GRANTED: &str = "custom.client.assistant.v1.granted"; const INDEX: &str = "claims_assistant_v1_principal_index"; const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))"; @@ -117,6 +118,55 @@ fn p95(samples: &mut [f64]) -> f64 { samples[(samples.len() * 95).div_ceil(100) - 1] } +// Real signed membership and replication, outside measured requests. Merely +// copying origin text would not exercise the authentication provenance check. +fn foreign_same_profile(store: &Store, anchor: Arc, template: &Value, count: usize) { + let fleet = super::super::daemon_bench::FLEET; + store.pin_fleet_anchor(anchor.public()).unwrap(); + store.set_member_key(Some(anchor.clone())).unwrap(); + store.admit_fleet_anchor(fleet, anchor.public(), "listening").unwrap(); + let peer = Store::open_memory("benchmark-peer").unwrap(); + peer.bind_fleet(fleet).unwrap(); + let key = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + peer.pin_fleet_anchor(anchor.public()).unwrap(); + peer.set_member_key(Some(key.clone())).unwrap(); + store.append_claim(&ClaimInput { + subject:"host/benchmark-peer".into(), kind:"fleet.member-admitted".into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(json!({ + "fleet_id":fleet,"member_key":key.public(),"via":"invite","mode":"listening" + })).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + let sync = |from: &Store, to: &Store| { + let exchange = from.export_replication_exchange_answering( + fleet, &to.replication_inventory().unwrap(), &to.replication_signature_requests().unwrap(), + ).unwrap(); + to.receive_replication_exchange(from.origin(), fleet, &exchange).unwrap(); + to.validate_replication_backlog().unwrap(); + to.project_replication_backlog().unwrap(); + }; + sync(store, &peer); + let mut ids = Vec::new(); + for row in 0..count { + let id = format!("{:024x}", row + 1); + let mut fields = template.clone(); + fields["grant_id"] = json!(id); + fields["session_actor"] = json!(format!("assistant/chatgpt/session/{id}")); + fields["expires_at_unix_ms"] = json!(u64::MAX); + fields["credential_hash"] = json!(hex::encode(ring::digest::digest(&ring::digest::SHA256, id.as_bytes()).as_ref())); + let grant = peer.append_claim(&ClaimInput { + subject:format!("custom/client/assistant-v1-{id}"), kind:GRANTED.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None, + }).unwrap(); + ids.push(grant.id); + } + sync(&peer, store); + for id in ids { + assert!(store.claim_has_authenticated_member_writer(&id).unwrap(), + "the foreign-grant scenario must exercise verified provenance"); + } +} + #[tokio::test(flavor = "multi_thread", worker_threads = 8)] async fn authenticated_get_during_pairing() { let Ok(variant) = std::env::var("ST_ADMISSION_VARIANT") else { return }; @@ -125,11 +175,14 @@ async fn authenticated_get_during_pairing() { let indexed = variant == "indexed"; let history = number("ST_ADMISSION_HISTORY", 10_000); let samples = number("ST_ADMISSION_SAMPLES", 200); + let foreign_active: usize = std::env::var("ST_ADMISSION_FOREIGN_ACTIVE") + .map_or(0, |value| value.parse().expect("nonnegative foreign grant count")); let root = tempfile::tempdir().unwrap(); let database = root.path().join("admission.sqlite"); let store = Arc::new(Store::open(&database, NODE).unwrap()); store.bind_fleet(super::super::daemon_bench::FLEET).unwrap(); - store.set_node_key(Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0)).unwrap(); + let node_key = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + store.set_node_key(node_key.clone()).unwrap(); let state = AppState { seat_admission:Default::default(), owning_person:Some(OWNER.into()), store:store.clone(), notify:Arc::new(tokio::sync::Notify::new()), event_notify:tokio::sync::watch::channel(0).0, @@ -186,6 +239,9 @@ async fn authenticated_get_during_pairing() { // authorize a request. Grant history is deliberately nonempty for BOTH principals. let template_subject = format!("custom/client/assistant-v1-{}", sessions[0].1["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); let template = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + if foreign_active > 0 { + foreign_same_profile(&store, node_key, &template.body["fields"], foreign_active); + } let fixture_store = store.clone(); tokio::task::spawn_blocking(move || { for principal in ["assistant/chatgpt", "assistant/mcp"] { @@ -278,7 +334,8 @@ async fn authenticated_get_during_pairing() { let final_rows: u64 = final_connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); let report = json!({"variant":variant,"baseline_revision":"98e550cb75", "hardware_uname":hardware("uname", &["-a"]), "hardware_lscpu":hardware("lscpu", &["-J"]),"hardware_hostname":hardware("hostname", &[]), - "expected_host":"dev5, AMD Ryzen 9 9955HX, 16 cores / 32 threads (verify observed hardware)", + "host_description":"Observed local benchmark host; no prescribed hardware identity", + "fixture_person_ids":[OWNER],"verified_foreign_same_profile_active_grants":foreign_active, "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, "final_total_claim_rows":final_rows,"admission_query":query, "explain_without_index":before,"explain_with_index":after,"synthetic_startup_index_build_ms":build_ms, @@ -386,7 +443,8 @@ fn synthetic_large_store_index_build() { "explain_without_index":before,"explain_with_index":after, "hardware_uname":hardware("uname", &["-a"]), "hardware_hostname":hardware("hostname", &[]),"hardware_lscpu":hardware("lscpu", &["-J"]), - "expected_host":"dev5, AMD Ryzen 9 9955HX, 16 cores / 32 threads (verify observed hardware)", + "host_description":"Observed local benchmark host; no prescribed hardware identity", + "fixture_person_ids":[OWNER], }); println!("ADMISSION_INDEX_BUILD {}", serde_json::to_string_pretty(&report).unwrap()); if let Some(path) = std::env::var_os("ST_ADMISSION_INDEX_REPORT") { From 7a9009d615eeee9ca0572958f78dbcace021a9df Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 08:35:55 +0100 Subject: [PATCH 06/52] fix(delivery): retain request-history seek after admission index agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 11 ++++++++--- crates/fractal-delivery/src/store/delivery.rs | 5 ++++- crates/fractal-delivery/src/store/tests.rs | 2 +- .../fractal/tests/daemon_cost/assistant_admission.rs | 10 +++++----- docs/st3/compatibility.md | 8 +++++++- release-notes/external-grant-admission-index.json | 4 ++-- 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index a4e43670642..ae44187565c 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -406,14 +406,18 @@ mod tests { ("several-policies-expired", json!({"expires_at_unix_ms":101}), vec![99, 102, 100], 0, false, false), ("unrelated-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, false), ("legacy-default-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ("null-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ("mcp-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), ]; for (name, mut source, policies, revokes, replicated, denied) in cases { let root = tempfile::tempdir().unwrap(); let mut state = crate::api::tests_shared::state(root.path()); state.owning_person = Some("person/owner".into()); source["profile"] = json!("service"); - if name != "legacy-default-principal" { - source["principal"] = json!(if name == "unrelated-principal" { MCP_PRINCIPAL } else { PRINCIPAL }); + if name == "null-principal" { + source["principal"] = Value::Null; + } else if name != "legacy-default-principal" { + source["principal"] = json!(if matches!(name, "unrelated-principal" | "mcp-principal") { MCP_PRINCIPAL } else { PRINCIPAL }); } let subject = format!("custom/client/differential-{name}"); let append_fixture = |store: &Store, kind: &str, value: Value, previous: Option<&ClaimRecord>| { @@ -447,7 +451,8 @@ mod tests { for owner in [Some("person/owner"), None] { state.owning_person = owner.map(str::to_owned); for profile in ["assistant", "service"] { - let candidate = json!({"profile":profile,"principal":PRINCIPAL}); + let principal = if name == "mcp-principal" { MCP_PRINCIPAL } else { PRINCIPAL }; + let candidate = json!({"profile":profile,"principal":principal}); let old = rust_only_admission(&state, &candidate).map_err(|error| error.code); let new = admit_profile(&state, &candidate).map_err(|error| error.code); assert_eq!(new, old, "{name}: owner={owner:?}, profile={profile}"); diff --git a/crates/fractal-delivery/src/store/delivery.rs b/crates/fractal-delivery/src/store/delivery.rs index 672e27e928b..7a9c20fe1dd 100644 --- a/crates/fractal-delivery/src/store/delivery.rs +++ b/crates/fractal-delivery/src/store/delivery.rs @@ -935,8 +935,11 @@ impl DeliveryStore for Store { if let Some((deadline, attempts)) = local { return Ok(Some((deadline as u128, attempts))); } + // Pin the request seek, like the other plan-sensitive history reads: + // without ANALYZE, adding a kind-leading index can make SQLite prefer + // a generic subject/kind scan that decodes every deferred request. let count: u32 = connection.query_row( - "SELECT COUNT(*) FROM claims + "SELECT COUNT(*) FROM claims INDEXED BY claims_subscription_deferred_request_index WHERE subject=?1 AND kind='subscription.mission-deferred' AND json_extract(body, '$.fields.request')=?2", params![subject, request], diff --git a/crates/fractal-delivery/src/store/tests.rs b/crates/fractal-delivery/src/store/tests.rs index 3c2ae535a28..3694eeef623 100644 --- a/crates/fractal-delivery/src/store/tests.rs +++ b/crates/fractal-delivery/src/store/tests.rs @@ -92,7 +92,7 @@ fn subscription_retry_queries_use_history_indexes() { let connection = store.readers.get(); let request_plan: String = connection .query_row( - "EXPLAIN QUERY PLAN SELECT COUNT(*) FROM claims + "EXPLAIN QUERY PLAN SELECT COUNT(*) FROM claims INDEXED BY claims_subscription_deferred_request_index WHERE subject=?1 AND kind='subscription.mission-deferred' AND json_extract(body, '$.fields.request')=?2", params![subject, "request-a"], diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index f2c94c35cba..bf589f829ca 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -1,5 +1,5 @@ //! Opt-in, real HTTP/Unix daemon measurement (not a router oneshot or mocked daemon). -//! Run this same test source on 98e550cb and on PR3-B, sequentially on dev5: +//! Run this same test source on 98e550cb and on PR3-B, sequentially on one host: //! ```sh //! ST_ADMISSION_VARIANT=baseline cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 //! ST_ADMISSION_VARIANT=indexed cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 @@ -11,8 +11,8 @@ //! ST_ADMISSION_HISTORY (default 10000) is expired grants PER principal; ST_ADMISSION_SAMPLES //! (default 200) is measured GET/completion pairs PER read mode. Setup and proof creation are //! outside timing. Each pair starts behind a barrier, with no sleeps, polling, retries or timers. -//! ST_ADMISSION_REPORT optionally saves the complete JSON report. Run on dev5; hardware is -//! observed from uname/lscpu in the report, not inferred from an environment label. +//! ST_ADMISSION_REPORT optionally saves the complete JSON report. Hardware is observed +//! from uname/lscpu in the report, not inferred from an environment label. //! The index DDL timing is a synthetic startup migration probe on the populated disposable //! real store, not total daemon startup or cold-disk startup. Latencies use the real daemon's //! bound sockets, bearer middleware, grant lookup, projection and durable approval consumption. @@ -278,7 +278,7 @@ async fn authenticated_get_during_pairing() { let final_rows: u64 = final_connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); let report = json!({"variant":variant,"baseline_revision":"98e550cb75", "hardware_uname":hardware("uname", &["-a"]), "hardware_lscpu":hardware("lscpu", &["-J"]),"hardware_hostname":hardware("hostname", &[]), - "expected_host":"dev5, AMD Ryzen 9 9955HX, 16 cores / 32 threads (verify observed hardware)", + "expected_host":"same otherwise-idle host for both variants (verify observed hardware)", "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, "final_total_claim_rows":final_rows,"admission_query":query, "explain_without_index":before,"explain_with_index":after,"synthetic_startup_index_build_ms":build_ms, @@ -386,7 +386,7 @@ fn synthetic_large_store_index_build() { "explain_without_index":before,"explain_with_index":after, "hardware_uname":hardware("uname", &["-a"]), "hardware_hostname":hardware("hostname", &[]),"hardware_lscpu":hardware("lscpu", &["-J"]), - "expected_host":"dev5, AMD Ryzen 9 9955HX, 16 cores / 32 threads (verify observed hardware)", + "expected_host":"same otherwise-idle host for both variants (verify observed hardware)", }); println!("ADMISSION_INDEX_BUILD {}", serde_json::to_string_pretty(&report).unwrap()); if let Some(path) = std::env::var_os("ST_ADMISSION_INDEX_REPORT") { diff --git a/docs/st3/compatibility.md b/docs/st3/compatibility.md index 786b096374d..903053bd11a 100644 --- a/docs/st3/compatibility.md +++ b/docs/st3/compatibility.md @@ -149,7 +149,7 @@ replication digests: row formats, vocabulary, shared projections and retention semantics are unchanged. It follows the schema-on-open index installation used for the assistant mission-run collection indexes. The first open builds the index synchronously over retained claims. On a 16-core x86_64 benchmark host -(AMD Ryzen 9 9955HX, 32 threads, Linux), exact index creation on a synthetic +(32 threads, Linux), exact index creation on a synthetic 1,000,000-claim real Store schema took 1.525 seconds and grew the main database by 59,518,976 bytes. This measures index-build work, not complete daemon startup or cold-disk restart time; local history and hardware determine first-open delay. @@ -167,6 +167,12 @@ meet q39's 100 ms budget. The opt-in `daemon_cost::assistant_admission` tests us production daemon routers over bound Unix/TCP sockets, real bearer middleware, and distinct build directories for the baseline and indexed worktrees. +Subscription deferral counts keep their request-history index explicitly selected, +following the existing plan-sensitive history-query convention. Without `ANALYZE`, +SQLite's default estimates can select a subject/kind history scan after an unrelated +kind-leading index is added; request filtering must remain an index seek rather +than decoding every deferral for that subscription. + Use CLI and the terminal UI from the same release source. Current client version scope is: | Client | Version/evidence boundary | diff --git a/release-notes/external-grant-admission-index.json b/release-notes/external-grant-admission-index.json index ff04823e236..ef545f40a58 100644 --- a/release-notes/external-grant-admission-index.json +++ b/release-notes/external-grant-admission-index.json @@ -4,8 +4,8 @@ "replay": {"status": "none", "detail": "No claim rewrite, projection replay or history removal. The SQL expiry filter uses the latest policy, retains missing-fields validation candidates, and preserves legacy absent-principal ChatGPT grants."}, "schema": {"status": "changed", "detail": "Schema-on-open adds claims_assistant_v1_principal_index on claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')). This additive derived access path changes neither STORAGE_VERSION (20), RULES_VERSION (26), the registry nor shared projection digests. Existing supported stores install the index automatically; subsequent opens reuse it."}, "rules": {"status": "none", "detail": "Profile admission, grant lifecycle, approval-once consumption, issuer checks and retention semantics are unchanged. Multiple same-profile grants remain allowed; service issuance remains disabled."}, - "compatibility": {"status": "none", "detail": "On a 16-core x86_64 benchmark host (AMD Ryzen 9 9955HX, 32 threads, Linux), real bound daemon APIs with bearer authentication and one concurrent pairing completion per GET were measured against exact baseline 98e550cb75. With 10000 expired grants per principal and 200 samples per mode, approval-once GET p95 improved from 965.184401 ms to 54.153648 ms; caller-bound-allow improved from 933.049170 ms to 46.173346 ms. Both indexed modes pass q39 <=100 ms. These are in-process production routers over Unix/TCP sockets, not an external daemon-process startup benchmark. SQL work still scales with matching principal history; the index avoids unrelated principals and inactive records no longer hydrate into Rust."}, - "downtime": {"status": "changed", "detail": "The first store open missing the index waits synchronously for its construction. Exact index CREATE DDL on a synthetic 1000000-claim real Store schema took 1524.850241 ms (about 1.525 s) on a 16-core x86_64 benchmark host (AMD Ryzen 9 9955HX, 32 threads, Linux 6.18.51). This is one measurement on that host, not a guaranteed rate of 1.5 seconds per million rows or a startup-time guarantee. Main database size grew from 1421651968 to 1481170944 bytes. This measures index-build startup work only, not complete restart-to-API time or cold-disk startup; allow additional first-open delay according to local history and hardware. Later opens do not rebuild the index."}, + "compatibility": {"status": "none", "detail": "On a 16-core x86_64 benchmark host (32 threads, Linux), real bound daemon APIs with bearer authentication and one concurrent pairing completion per GET were measured against exact baseline 98e550cb75. With 10000 expired grants per principal and 200 samples per mode, approval-once GET p95 improved from 965.184401 ms to 54.153648 ms; caller-bound-allow improved from 933.049170 ms to 46.173346 ms. Both indexed modes pass q39 <=100 ms. These are in-process production routers over Unix/TCP sockets, not an external daemon-process startup benchmark. SQL work still scales with matching principal history; the index avoids unrelated principals and inactive records no longer hydrate into Rust. Subscription deferral counts explicitly retain their request-history seek, avoiding a generic subject/kind history scan under SQLite's default estimates."}, + "downtime": {"status": "changed", "detail": "The first store open missing the index waits synchronously for its construction. Exact index CREATE DDL on a synthetic 1000000-claim real Store schema took 1524.850241 ms (about 1.525 s) on a 16-core x86_64 benchmark host (32 threads, Linux 6.18.51). This is one measurement on that host, not a guaranteed rate of 1.5 seconds per million rows or a startup-time guarantee. Main database size grew from 1421651968 to 1481170944 bytes. This measures index-build startup work only, not complete restart-to-API time or cold-disk startup; allow additional first-open delay according to local history and hardware. Later opens do not rebuild the index."}, "manual": {"status": "none", "detail": "No operator SQL, data conversion, credential reissue or manual migration is required. Allow the first open to finish index construction."}, "recovery": {"status": "none", "detail": "Claims and signed bodies are unchanged. A binary rollback leaves the index in place: previous binaries can ignore it, and SQLite keeps maintaining it on writes. An interrupted first-open index build can be completed by normal subsequent schema-on-open installation; no history deletion or repair SQL is needed."}, "commits": [] From d374cbecbeb146d77c6fb79b80f40894140fa15c Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 09:07:19 +0100 Subject: [PATCH 07/52] fix(external-grants): authenticate lifecycle overlays and opt in witnesses agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../Sources/FractalClient/Client.swift | 2 +- .../fractal-client/Client.generated.ts | 4 +- .../fractal-client/Schema.generated.ts | 14 +-- .../src/api/client_v0/assistant.rs | 91 ++++++++++++++- .../src/api/client_v0/external_grants.rs | 103 ++++++++++++----- .../external_grants/conflict_tests.rs | 107 ++++++++++++++++-- .../templates/Client.swift.in | 2 +- .../templates/Client.ts.in | 4 +- .../templates/lib.rs.in | 5 + crates/fractal-client/src/lib.rs | 13 +++ .../tests/daemon_cost/assistant_admission.rs | 42 +++++-- crates/smallclaims/src/store.rs | 38 ++++++- .../src/store/membership_query_tests.rs | 90 ++++++++++++++- .../client-v0/schemas/client-v0.schema.json | 4 +- docs/st3/client-v0/schemas/operations.json | 2 +- docs/st3/large-value-sites.json | 5 + docs/st3/principals-and-grants.md | 27 +++-- .../external-grant-profile-conflict.json | 4 +- 18 files changed, 470 insertions(+), 87 deletions(-) diff --git a/clients/swift/FractalClient/Sources/FractalClient/Client.swift b/clients/swift/FractalClient/Sources/FractalClient/Client.swift index 4ba33db7e92..ecfa16a4a92 100644 --- a/clients/swift/FractalClient/Sources/FractalClient/Client.swift +++ b/clients/swift/FractalClient/Sources/FractalClient/Client.swift @@ -437,7 +437,7 @@ public actor FractalClient { public func beginPairing(deviceName: String, personID: String) async throws -> Envelope { try await post("v1/client/pairings", PersonPairingBegin(apiVersion: fractalClientAPIVersion, deviceName: deviceName, personID: personID)) } public func beginPairing(_ request: PairingBegin) async throws -> Envelope { try await post("v1/client/pairings", request) } public func completePairing(pairingID: String, code: String, devicePublicKey: String) async throws -> Envelope { try await post("v1/client/pairings/\(pairingID.replacingOccurrences(of: "pairing/", with: ""))/complete", PairingComplete(apiVersion: fractalClientAPIVersion, code: code, devicePublicKey: devicePublicKey)) } - public func assistantGrant(_ id: String) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)") } + public func assistantGrant(_ id: String, witness: Bool = false) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)", query: witness ? [.init(name: "witness", value: "1")] : []) } public func assistantGrantRevoke(_ id: String) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/revoke", [String: String]()) } public func assistantGrantPolicy(_ id: String, _ policy: AssistantGrantPolicy) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/policy", policy) } public func assistantGrantReadTrust(_ id: String, _ trust: AssistantReadTrustRequest) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/read-trust", trust) } diff --git a/clients/typescript/fractal-client/Client.generated.ts b/clients/typescript/fractal-client/Client.generated.ts index 5e7eb2a1444..28a2f6808eb 100644 --- a/clients/typescript/fractal-client/Client.generated.ts +++ b/clients/typescript/fractal-client/Client.generated.ts @@ -482,8 +482,8 @@ export class FractalClient { return this.request('POST', `/v1/client/pairings/${encodeURIComponent(routedId(id))}/complete`, request, undefined, undefined, requestOptions); } - async assistantGrant(id: string): Promise> { - return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}`); + async assistantGrant(id: string, options: { witness?: boolean } = {}): Promise> { + return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}${query({ witness: options.witness ? 1 : undefined })}`); } async assistantGrantRevoke(id: string): Promise> { return this.request('POST', `/v1/client/assistant/grants/${encodeURIComponent(id)}/revoke`, {}); diff --git a/clients/typescript/fractal-client/Schema.generated.ts b/clients/typescript/fractal-client/Schema.generated.ts index adca8cad969..e9413268804 100644 --- a/clients/typescript/fractal-client/Schema.generated.ts +++ b/clients/typescript/fractal-client/Schema.generated.ts @@ -525,10 +525,10 @@ export type GrantProfileConflictWitness = typeof GrantProfileConflictWitness.Typ export type GrantProfileConflictWitnessEncoded = typeof GrantProfileConflictWitness.Encoded export const AssistantGrant = /*#__PURE__*/ (() => Schema.Struct({ - /** Revoked or expired opposite-profile witnesses; emitted only when conflict is null. */ - "cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only when conflict is null." }), - /** Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers. */ - "conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers." }), + /** Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null. */ + "cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null." }), + /** Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses. */ + "conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, @@ -944,9 +944,9 @@ export const Envelope = /*#__PURE__*/ (() => Schema.Struct({ "desired_token": Schema.String.annotate({ description: "Selected desired claim, including a stop when the seat is retired." }), "host_id": HostId, "kind": Schema.Literal("agent-workspace"), /** Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory. */ "workspace": Schema.String.annotate({ description: "Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory." }), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.String.check(Schema.makeFilter((value: string) => !new RegExp("^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$", "u").test(value), { expected: "a string not matching ^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$" })), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(Resource), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("ordered-memberships"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(OrderedMembership), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("resources"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(ResourceObservation), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Resource, Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ "header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry), "kind": Schema.Literal("timeline-page"), "page": PageInfo, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ -"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ /** Revoked or expired opposite-profile witnesses; emitted only when conflict is null. */ -"cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only when conflict is null." }), /** Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers. */ -"conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ +"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ /** Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null. */ +"cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null." }), /** Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses. */ +"conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ "issuer": PersonId, /** SHA-256 of the canonical device public-key string; never a credential digest. */ "key_id": Schema.String.check(Schema.isPattern(new RegExp("^[0-9a-f]{64}$", "u"))).annotate({ description: "SHA-256 of the canonical device public-key string; never a credential digest." }), "kind": Schema.Literal("assistant-grant"), "minimal_read_mode": AssistantMinimalReadMode, "policy_revision": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "principal": AssistantPrincipal, /** Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied. */ "read_trust": optionalKey(AssistantReadTrust), /** Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person. */ diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs index 7997c4adfce..659b65c08a0 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs @@ -6,6 +6,7 @@ pub use native::propose; pub use authorization::{ReadReceipt, finish as finish_read, pin as pin_read_trust, read as read_projection}; pub use fractal_api_core::api::client_v0::assistant::*; pub use fractal_api_core::api::client_v0::assistant::{PRINCIPAL, append, authenticate, authorize_route, device_resources, trusted_issuer}; +use fractal_api_core::api::client_v0::external_grants::{projection_with_witness, revoked}; pub mod authorization; pub mod native; pub mod reads; @@ -182,12 +183,22 @@ async fn complete_inner(state: &AppState, id: &str, request: &PairingComplete, "grant":projection})))) } +#[derive(Default, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct AssistantGrantQuery { + witness: Option, +} + pub async fn inspect(State(state): State, Extension(session): Extension, - AxumPath(id): AxumPath) -> Result, ApiError> { + AxumPath(id): AxumPath, Query(query): Query) -> Result, ApiError> { trusted_issuer(&state, &session)?; let granted = latest(&state, &subject(&id)?, GRANTED)? .ok_or_else(|| ApiError::not_found("assistant grant does not exist"))?; - Ok(Json(projection(&state, &granted)?)) + Ok(Json(if query.witness.as_deref() == Some("1") { + projection_with_witness(&state, &granted)? + } else { + projection(&state, &granted)? + })) } async fn revoke_inner(State(state): State, Extension(session): Extension, @@ -200,7 +211,7 @@ async fn revoke_inner(State(state): State, Extension(session): Extensi if granted.origin != state.store.origin() { return Err(forbidden("assistant revocation must run on its authoritative issuer")); } - if latest(&state, &subject, REVOKED)?.is_none() { + if !revoked(&state, &granted)? { let previous = effective(&state, &granted)?; append(&state, subject, REVOKED, issuer, json!({"version":1,"grant_id":fields(&granted)?["grant_id"], "principal":principal(fields(&granted)?)?,"issuer":issuer,"transport":session.transport, @@ -226,7 +237,7 @@ async fn update_policy_inner(State(state): State, Extension(session): if granted.origin != state.store.origin() { return Err(forbidden("assistant policy must change on its authoritative issuer")); } - if latest(&state, &subject, REVOKED)?.is_some() { return Err(forbidden("assistant grant was revoked")); } + if revoked(&state, &granted)? { return Err(forbidden("assistant grant was revoked")); } let previous = effective(&state, &granted)?; // Policy changes must not revive an expired grant: fail closed instead of extending it. if fields(&previous)?["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) <= client_now_ms() { @@ -280,6 +291,73 @@ mod tests { &request, "fabric-loopback").await.unwrap().unwrap().0 } + // Frozen pre-witness shape, independent of today's generated grant model. + #[derive(Deserialize)] + #[serde(deny_unknown_fields)] + #[allow(dead_code)] + struct LegacyAssistantGrant { + kind: String, + id: String, + principal: String, + sender_class: String, + session_actor: String, + device_id: String, + key_id: String, + issuer: String, + scopes: Vec, + expires_at: String, + policy_revision: u64, + minimal_read_mode: String, + recipient_allowlist: Vec, + disclosure_consent: bool, + consent_evidence: String, + revoked: bool, + read_trust: Option, + } + + #[tokio::test] + async fn grant_responses_preserve_strict_legacy_shape_unless_inspect_opts_in() { + use axum::{body::{Body, to_bytes}, http::Request}; + use tower::ServiceExt; + + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let paired = paired(&state).await; + serde_json::from_value::(paired["grant"].clone()).unwrap(); + let id = paired["grant"]["id"].as_str().unwrap(); + let app = super::super::super::router_for_transport(state.clone(), ClientTransportBoundary::Unix, &[crate::api::client_v0::routes]); + for query in ["", "?witness=0", "?witness=true", "?witness=1"] { + let mut request = Request::builder() + .uri(format!("/v1/client/assistant/grants/{}{query}", urlencoding::encode(id))) + .header(LOCAL_PERSON_HEADER, ISSUER).body(Body::empty()).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + let response = app.clone().oneshot(request).await.unwrap(); + assert_eq!(response.status(), StatusCode::OK); + let body: Value = serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap()).unwrap(); + let grant = body["value"].clone(); + if query == "?witness=1" { + assert_eq!(grant["conflict"], Value::Null); + assert!(grant["cleared_conflicts"].is_array()); + assert!(serde_json::from_value::(grant).is_err()); + } else { + serde_json::from_value::(grant).unwrap(); + } + } + let policy = serde_json::from_value(json!({ + "api_version": CLIENT_API_VERSION, "scopes": SCOPES[..4], + "disclosure_consent": true, "consent_evidence": "owner approved renewal", + "minimal_read_mode": "approval-once" + })).unwrap(); + let Json(changed) = update_policy(State(state.clone()), + Extension(ClientSession::local(Some(ISSUER)).unwrap()), + AxumPath(id.into()), Json(policy)).await.unwrap(); + serde_json::from_value::(changed).unwrap(); + let Json(revoked) = revoke(State(state), + Extension(ClientSession::local(Some(ISSUER)).unwrap()), + AxumPath(id.into())).await.unwrap(); + serde_json::from_value::(revoked).unwrap(); + } + #[tokio::test] async fn supported_principals_bind_grants_to_the_same_owner_and_origin() { for principal in [PRINCIPAL, MCP_PRINCIPAL] { @@ -368,7 +446,8 @@ mod tests { value["principal"] = json!(replacement); value["session_actor"] = json!(format!("{replacement}/session/{}", paired["grant"]["id"].as_str().unwrap())); append(&state, granted.subject.clone(), POLICY, ISSUER, value, Some(&granted)).unwrap(); - assert!(authenticate(&state, &credential_digest(paired["credential"].as_str().unwrap()), "fabric-loopback").is_err()); + let session = authenticate(&state, &credential_digest(paired["credential"].as_str().unwrap()), "fabric-loopback").unwrap().unwrap(); + assert_eq!(session.authority_actor, principal); } } } @@ -618,7 +697,7 @@ mod tests { assert_eq!(fs::metadata(&profile).unwrap().permissions().mode() & 0o777,0o600); assert!(!root.path().join("devices.json").exists()); let Json(grant)=inspect(State(state),Extension(ClientSession::local(Some(ISSUER)).unwrap()), - AxumPath(device.session.grant.id)).await.unwrap(); + AxumPath(device.session.grant.id), Query(AssistantGrantQuery::default())).await.unwrap(); assert_eq!(grant["principal"],PRINCIPAL); server.abort(); } diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index e1140d4cbce..cabce38fef0 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -70,25 +70,36 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { // Admission and authentication share the principal-indexed active-grant fold. // append owns the admission lock; several grants of the same profile are allowed. -// Filter revoked/expired history before loading claim bodies into Rust. Expiry -// uses the latest policy, not the original grant. +// Expired base grants without issuer policies are pruned in SQL. A policy +// candidate must reach the authenticated fold: SQL cannot verify its signature. +// Foreign revocations likewise reach Rust. Local revocations can be prefiltered +// only when their origin, owner and immutable grant identity match. const ADMISSION_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) - AND (?5 IS NULL OR COALESCE( - (SELECT CASE WHEN json_type(policy.body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(policy.body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5,0) END - FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 ORDER BY policy.store_index DESC LIMIT 1), - CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE + AND (?5 IS NULL OR origin<>?6 OR NOT EXISTS ( + SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3 + AND revoked.origin=claims.origin AND revoked.actor=claims.actor + AND (json_type(revoked.body,'$.fields.principal') IS NULL OR json_extract(revoked.body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) + AND (json_type(revoked.body,'$.fields.profile') IS NULL OR json_extract(revoked.body,'$.fields.profile') IN ('assistant','service')) + AND json_extract(revoked.body,'$.fields.issuer') IS json_extract(claims.body,'$.fields.issuer') + AND json_extract(revoked.body,'$.fields.grant_id') IS json_extract(claims.body,'$.fields.grant_id') + AND COALESCE(json_extract(revoked.body,'$.fields.principal'),'assistant/chatgpt')=COALESCE(json_extract(claims.body,'$.fields.principal'),'assistant/chatgpt') + AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant'))) + AND (?5 IS NULL OR EXISTS ( + SELECT 1 FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 AND policy.origin=claims.origin) + OR CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END)"; + +#[cfg(feature = "test-support")] +pub const fn admission_query_for_test() -> &'static str { ADMISSION_QUERY } + fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) -> Result, ApiError> { let owner = owning_person(state)?; let ids = { let connection = state.store.readers.get(); let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-h99f1a302c7b1 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ ADMISSION_QUERY).map_err(ApiError::internal)?; - query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut], |row| row.get::<_, String>(0)) + query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut, state.store.origin()], |row| row.get::<_, String>(0)) .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? }; let mut active = Vec::new(); @@ -96,7 +107,7 @@ fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? .ok_or_else(|| forbidden("external grant is absent"))?; if grant.actor.as_deref() != Some(owner) - || (expiry_cut.is_some() && latest(state, &grant.subject, REVOKED)?.is_some()) { + || (expiry_cut.is_some() && revoked(state, &grant)?) { continue; } let policy = effective(state, &grant)?; @@ -106,8 +117,7 @@ fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) // Only well-formed owner grants carried by a signed, admitted issuer // count; policies must have the same provenance and immutable identity. if foreign && (!valid_foreign_grant(state, &grant, &policy)? - || !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)? - || (policy.id != grant.id && !state.store.claim_has_authenticated_member_writer(&policy.id).map_err(ApiError::internal)?)) { + || !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)?) { continue; } let source = fields(&policy)?; @@ -299,8 +309,43 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, Ok(()) } +// Ignore unauthoritative overlays, including a newer malformed policy. Walk +// backwards to the last valid issuer transition rather than dropping the grant. +fn transition(state: &AppState, granted: &ClaimRecord, kind: &str) -> Result, ApiError> { + let mut before = None; + loop { + let page = state.store.claims_for_subject_kind_at(&granted.subject, kind, before, true, 32) + .map_err(ApiError::internal)?; + for candidate in page.claims { + if candidate.origin != granted.origin || candidate.actor.as_deref() != Some(owning_person(state)?) { + continue; + } + let (Ok(original), Ok(source)) = (fields(granted), fields(&candidate)) else { continue }; + let consistent = principal(source).ok().zip(principal(original).ok()).is_some_and(|(a, b)| a == b) + && Profile::stored(source).ok().zip(Profile::stored(original).ok()).is_some_and(|(a, b)| a == b) + && ["grant_id", "issuer"].iter().all(|key| source[*key] == original[*key]); + if !consistent || source["issuer"] != owning_person(state)? { continue; } + if kind == POLICY && (!valid_foreign_grant(state, granted, &candidate)? + || source["expires_at_unix_ms"].as_u64().is_none()) { + continue; + } + if granted.origin != state.store.origin() + && !state.store.claim_has_authenticated_member_writer(&candidate.id).map_err(ApiError::internal)? { + continue; + } + return Ok(Some(candidate)); + } + let Some(cursor) = page.next_cursor else { return Ok(None) }; + before = Some(cursor); + } +} + +pub fn revoked(state: &AppState, granted: &ClaimRecord) -> Result { + Ok(transition(state, granted, REVOKED)?.is_some()) +} + pub fn effective(state: &AppState, granted: &ClaimRecord) -> Result { - Ok(latest(state, &granted.subject, POLICY)?.unwrap_or_else(|| granted.clone())) + Ok(transition(state, granted, POLICY)?.unwrap_or_else(|| granted.clone())) } pub fn projection(state: &AppState, granted: &ClaimRecord) -> Result { let policy = effective(state, granted)?; @@ -308,7 +353,7 @@ pub fn projection(state: &AppState, granted: &ClaimRecord) -> Result Result Result { + let mut value = projection(state, granted)?; + let policy = effective(state, granted)?; + let source = fields(&policy)?; let now = client_now_ms() as u64; value["conflict"] = profile_conflict_at(state, granted, now)?.unwrap_or(Value::Null); if value["conflict"].is_null() { @@ -324,8 +376,7 @@ pub fn projection(state: &AppState, granted: &ClaimRecord) -> Result(0)).unwrap().collect::, _>>().unwrap(); found.sort(); expected.sort(); assert_eq!(found, expected); let unfiltered = connection.prepare(ADMISSION_QUERY).unwrap() - .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, Option::::None], + .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, Option::::None, "local"], |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); assert_eq!(unfiltered.len(), 12, "invalid owner configuration must not hide validation errors"); } @@ -535,13 +586,13 @@ mod tests { assert!(latest(&state, &next, GRANTED).unwrap().is_none()); state.store.append_claim(&ClaimInput { subject: service_subject, kind: REVOKED.into(), actor: Some("person/owner".into()), - fields: BTreeMap::new(), evidence: vec![grant.id.clone()], + fields: serde_json::from_value(fields(&grant).unwrap().clone()).unwrap(), evidence: vec![grant.id.clone()], expected_subject: Some(Some(grant.id.clone())), idempotency_key: None, }).unwrap(); let candidates = { let connection = state.store.readers.get(); connection.prepare(ADMISSION_QUERY).unwrap() - .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, client_now_ms() as u64], |row| row.get::<_, String>(0)) + .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, client_now_ms() as u64, state.store.origin()], |row| row.get::<_, String>(0)) .unwrap().collect::, _>>().unwrap() }; assert_eq!(candidates.len(), 2); diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 3e262da596e..3b894fca786 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -124,7 +124,7 @@ fn disconnected_opposite_profiles_conflict_on_both_members_and_revocation_recove assert_conflict(&error); assert_witness(&Value::Object((*error.details).clone())["conflict"]); assert_witness(&profile_conflict(state, grant).unwrap().unwrap()); - assert_witness(&projection(state, grant).unwrap()["conflict"]); + assert_witness(&projection_with_witness(state, grant).unwrap()["conflict"]); } } append(&b, service.subject.clone(), REVOKED, OWNER, @@ -133,10 +133,10 @@ fn disconnected_opposite_profiles_conflict_on_both_members_and_revocation_recove for state in [&a, &b] { for grant in [&assistant, &service] { assert!(profile_conflict(state, grant).unwrap().is_none()); - assert!(projection(state, grant).unwrap()["conflict"].is_null()); + assert!(projection_with_witness(state, grant).unwrap()["conflict"].is_null()); } assert!(authenticate_id(state, SERVICE_ID).is_err()); - let inspected = projection(state, &assistant).unwrap(); + let inspected = projection_with_witness(state, &assistant).unwrap(); let cleared = inspected["cleared_conflicts"].as_array().unwrap(); assert_eq!(cleared.len(), 1); assert_eq!(cleared[0]["cause"], "revoked"); @@ -173,7 +173,7 @@ fn expiry_boundary_clears_conflict_and_disconnected_reissue_recomputes_it() { assert_eq!(unexpired(fields(&effective(&a, &service).unwrap()).unwrap(), now), conflicted); } assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); - let inspected = projection(&a, &assistant).unwrap(); + let inspected = projection_with_witness(&a, &assistant).unwrap(); assert!(inspected["conflict"].is_null()); let cleared = inspected["cleared_conflicts"].as_array().unwrap(); assert_eq!(cleared.len(), 1); @@ -194,7 +194,7 @@ fn expiry_boundary_clears_conflict_and_disconnected_reissue_recomputes_it() { for id in [ASSISTANT_ID, replacement_id] { assert_conflict(&authenticate_id(&a, id).err().unwrap()); } - let inspected = projection(&a, &assistant).unwrap(); + let inspected = projection_with_witness(&a, &assistant).unwrap(); assert_eq!(inspected["conflict"], witness); assert!(inspected["cleared_conflicts"].is_null()); } @@ -245,7 +245,7 @@ fn malformed_authenticated_foreign_grants_cannot_suspend_a_local_credential() { source[invalid] = Value::Null; } let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, - if invalid == "actor" { "person/attacker" } else { OWNER }, source); + if invalid == "actor" { "person/intruder" } else { OWNER }, source); replicate(&b, &a); assert!(a.store.claim_by_id(&foreign.id).unwrap().is_some(), "{invalid}"); assert!(a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap(), "{invalid}"); @@ -255,7 +255,7 @@ fn malformed_authenticated_foreign_grants_cannot_suspend_a_local_credential() { } #[test] -fn foreign_policy_with_mismatched_identity_cannot_suspend_a_local_credential() { +fn foreign_policy_with_mismatched_identity_cannot_clear_a_conflict() { let _service = ServiceFixture::enable(); let root = tempfile::tempdir().unwrap(); let (a, b) = admitted_pair(root.path()); @@ -265,7 +265,96 @@ fn foreign_policy_with_mismatched_identity_cannot_suspend_a_local_credential() { policy["session_actor"] = json!("assistant/chatgpt/session/333333333333333333333333"); raw_claim(&b, &foreign.subject, POLICY, OWNER, policy); replicate(&b, &a); - assert!(profile_conflict(&a, &local).unwrap().is_none()); + assert!(profile_conflict(&a, &local).unwrap().is_some()); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).err().unwrap()); +} + +#[test] +fn wrong_origin_revocation_and_expired_policy_cannot_clear_conflict() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + for kind in [REVOKED, POLICY] { + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = issue(&b, SERVICE_ID, "service").unwrap(); + replicate(&a, &b); + replicate(&b, &a); + let mut overlay = fields(&foreign).unwrap().clone(); + if kind == POLICY { + overlay["expires_at_unix_ms"] = json!(1_u64); + } + // An admitted, signed writer with an owner-shaped actor still cannot + // mutate another member's grant lifecycle. + let malicious = raw_claim(&a, &foreign.subject, kind, OWNER, overlay); + replicate(&a, &b); + for state in [&a, &b] { + assert!(state.store.claim_has_authenticated_member_writer(&malicious.id).unwrap()); + assert_eq!(effective(state, &foreign).unwrap().id, foreign.id); + assert_witness(&profile_conflict(state, &local).unwrap().unwrap()); + for id in [ASSISTANT_ID, SERVICE_ID] { + assert_conflict(&authenticate_id(state, id).err().unwrap()); + } + let inspected = projection_with_witness(state, &local).unwrap(); + assert!(inspected["conflict"].is_object()); + assert!(inspected["cleared_conflicts"].is_null()); + } + } +} + +#[test] +fn malformed_same_origin_expired_policy_keeps_the_last_valid_live_policy() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let foreign = issue(&b, SERVICE_ID, "service").unwrap(); + let mut live = fields(&foreign).unwrap().clone(); + live["policy_revision"] = json!(2); + let live = append(&b, foreign.subject.clone(), POLICY, OWNER, live, Some(&foreign)).unwrap(); + let mut malformed = fields(&live).unwrap().clone(); + malformed["expires_at_unix_ms"] = json!(1_u64); + malformed["session_actor"] = json!("assistant/chatgpt/session/not-this-grant"); + raw_claim(&b, &foreign.subject, POLICY, OWNER, malformed); + replicate(&a, &b); + replicate(&b, &a); + for state in [&a, &b] { + assert_eq!(effective(state, &foreign).unwrap().id, live.id); + assert_witness(&profile_conflict(state, &local).unwrap().unwrap()); + assert_conflict(&authenticate_id(state, ASSISTANT_ID).err().unwrap()); + } +} + +#[test] +fn signed_revocation_arriving_before_its_grant_converges_without_conflict() { + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + replicate(&a, &b); + let source = grant_fields(SERVICE_ID, "service"); + let subject = subject(SERVICE_ID).unwrap(); + // Replicated custom lifecycle claims are open data. Import the authentic + // revocation first, while its grant is absent, then import that grant. + let revoked = raw_claim(&b, &subject, REVOKED, OWNER, source.clone()); + replicate(&b, &a); + assert!(latest(&a, &subject, GRANTED).unwrap().is_none()); + assert!(a.store.claim_by_id(&revoked.id).unwrap().is_some()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let granted = raw_claim(&b, &subject, GRANTED, OWNER, source); + replicate(&b, &a); + for state in [&a, &b] { + let revoked = state.store.claim_by_id(&revoked.id).unwrap().unwrap(); + let granted = state.store.claim_by_id(&granted.id).unwrap().unwrap(); + assert!(revoked.store_index < granted.store_index); + assert!(state.store.claim_has_authenticated_member_writer(&revoked.id).unwrap()); + assert!(state.store.claim_has_authenticated_member_writer(&granted.id).unwrap()); + assert!(profile_conflict(state, &local).unwrap().is_none()); + assert!(profile_conflict(state, &granted).unwrap().is_none()); + let inspected = projection_with_witness(state, &local).unwrap(); + let cleared = inspected["cleared_conflicts"].as_array().unwrap(); + assert_eq!(cleared.len(), 1); + assert_eq!(cleared[0]["cause"], "revoked"); + assert_witness(&cleared[0]); + } assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); } @@ -294,7 +383,7 @@ fn admission_scan_uses_the_real_principal_index() { let connection = state.store.readers.get(); let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-hf4201606586b owner=fractal_api_core::api::client_v0::external_grants::conflict_tests TODO=trace-statement-and-value-representation */ &format!("EXPLAIN QUERY PLAN {ADMISSION_QUERY}")).unwrap(); let plan = query.query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, - Some(client_now_ms() as u64)], |row| row.get::<_, String>(3)).unwrap() + Some(client_now_ms() as u64), state.store.origin()], |row| row.get::<_, String>(3)).unwrap() .collect::, _>>().unwrap(); println!("external grant admission query plan:\n{}", plan.join("\n")); assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_index")), diff --git a/crates/fractal-client-codegen/templates/Client.swift.in b/crates/fractal-client-codegen/templates/Client.swift.in index cf0251cacd9..dd2f94a1bf3 100644 --- a/crates/fractal-client-codegen/templates/Client.swift.in +++ b/crates/fractal-client-codegen/templates/Client.swift.in @@ -299,7 +299,7 @@ public actor FractalClient { public func beginPairing(deviceName: String, personID: String) async throws -> Envelope { try await post("v1/client/pairings", PersonPairingBegin(apiVersion: fractalClientAPIVersion, deviceName: deviceName, personID: personID)) } public func beginPairing(_ request: PairingBegin) async throws -> Envelope { try await post("v1/client/pairings", request) } public func completePairing(pairingID: String, code: String, devicePublicKey: String) async throws -> Envelope { try await post("v1/client/pairings/\(pairingID.replacingOccurrences(of: "pairing/", with: ""))/complete", PairingComplete(apiVersion: fractalClientAPIVersion, code: code, devicePublicKey: devicePublicKey)) } - public func assistantGrant(_ id: String) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)") } + public func assistantGrant(_ id: String, witness: Bool = false) async throws -> Envelope { try await get("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)", query: witness ? [.init(name: "witness", value: "1")] : []) } public func assistantGrantRevoke(_ id: String) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/revoke", [String: String]()) } public func assistantGrantPolicy(_ id: String, _ policy: AssistantGrantPolicy) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/policy", policy) } public func assistantGrantReadTrust(_ id: String, _ trust: AssistantReadTrustRequest) async throws -> Envelope { try await post("v1/client/assistant/grants/\(id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed.subtracting(CharacterSet(charactersIn: "/"))) ?? id)/read-trust", trust) } diff --git a/crates/fractal-client-codegen/templates/Client.ts.in b/crates/fractal-client-codegen/templates/Client.ts.in index 54253b63f42..f99b064142e 100644 --- a/crates/fractal-client-codegen/templates/Client.ts.in +++ b/crates/fractal-client-codegen/templates/Client.ts.in @@ -482,8 +482,8 @@ export class FractalClient { return this.request('POST', `/v1/client/pairings/${encodeURIComponent(routedId(id))}/complete`, request, undefined, undefined, requestOptions); } - async assistantGrant(id: string): Promise> { - return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}`); + async assistantGrant(id: string, options: { witness?: boolean } = {}): Promise> { + return this.request('GET', `/v1/client/assistant/grants/${encodeURIComponent(id)}${query({ witness: options.witness ? 1 : undefined })}`); } async assistantGrantRevoke(id: string): Promise> { return this.request('POST', `/v1/client/assistant/grants/${encodeURIComponent(id)}/revoke`, {}); diff --git a/crates/fractal-client-codegen/templates/lib.rs.in b/crates/fractal-client-codegen/templates/lib.rs.in index a801826b95c..87be4939449 100644 --- a/crates/fractal-client-codegen/templates/lib.rs.in +++ b/crates/fractal-client-codegen/templates/lib.rs.in @@ -2063,6 +2063,11 @@ impl Client { pub async fn assistant_grant(&self, id: &str) -> Result, ClientError> { self.get(&format!("/v1/client/assistant/grants/{}", percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id)))).await } + /// Inspect with optional conflict witnesses; the default method retains the legacy wire shape. + pub async fn assistant_grant_with_witness(&self, id: &str, witness: bool) -> Result, ClientError> { + let query = if witness { "?witness=1" } else { "" }; + self.get(&format!("/v1/client/assistant/grants/{}{query}", percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id)))).await + } pub async fn assistant_grant_revoke(&self, id: &str) -> Result, ClientError> { self.post(&format!("/v1/client/assistant/grants/{}/revoke", percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id))), &serde_json::json!({})).await } diff --git a/crates/fractal-client/src/lib.rs b/crates/fractal-client/src/lib.rs index 4f1001ea92c..5f66ff24e64 100644 --- a/crates/fractal-client/src/lib.rs +++ b/crates/fractal-client/src/lib.rs @@ -3706,6 +3706,19 @@ impl Client { )) .await } + /// Inspect with optional conflict witnesses; the default method retains the legacy wire shape. + pub async fn assistant_grant_with_witness( + &self, + id: &str, + witness: bool, + ) -> Result, ClientError> { + let query = if witness { "?witness=1" } else { "" }; + self.get(&format!( + "/v1/client/assistant/grants/{}{query}", + percent_encode_segment(id.strip_prefix("assistant-grant/").unwrap_or(id)) + )) + .await + } pub async fn assistant_grant_revoke( &self, id: &str, diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 3270fde11e8..4fb7b61b472 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -34,17 +34,7 @@ const GRANTED: &str = "custom.client.assistant.v1.granted"; const INDEX: &str = "claims_assistant_v1_principal_index"; const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))"; const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; -const INDEXED_QUERY: &str = - "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) - AND (?5 IS NULL OR COALESCE( - (SELECT CASE WHEN json_type(policy.body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(policy.body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5,0) END - FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 ORDER BY policy.store_index DESC LIMIT 1), - CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; +const INDEXED_QUERY: &str = api::client_v0::external_grants::admission_query_for_test(); const PATH: &str = "/v1/client/assistant/summary"; fn number(name: &str, default: usize) -> usize { @@ -106,7 +96,7 @@ fn explain(connection: &rusqlite::Connection, query: &str) -> Vec { } else { statement.query(rusqlite::params![GRANTED, "assistant/chatgpt", "custom.client.assistant.v1.revoked", "custom.client.assistant.v1.policy", - u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap()]).unwrap() + u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(), NODE]).unwrap() }; let mut plan = Vec::new(); while let Some(row) = rows.next().unwrap() { plan.push(row.get::<_, String>(3).unwrap()); } @@ -278,6 +268,32 @@ async fn authenticated_get_during_pairing() { let count: u64 = connection.query_row("SELECT count(*) FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2", rusqlite::params![GRANTED,principal], |r| r.get(0)).unwrap(); principal_rows.insert(principal, count); } + // Isolate indexed SQL from claim/policy loading, provenance and locks. + // Diagnostic work stays outside HTTP samples; no request-path cache. + let mut diagnostics = Vec::new(); + if indexed { for _ in 0..8 { + let started = Instant::now(); + let candidate_ids = connection.prepare(query).unwrap().query_map(rusqlite::params![ + GRANTED,"assistant/chatgpt","custom.client.assistant.v1.revoked","custom.client.assistant.v1.policy", + u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(),NODE + ], |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); + let candidate_sql_ms = started.elapsed().as_secs_f64() * 1000.0; + let credential = sessions[0].1["credential"].as_str().unwrap(); + let digest = hex::encode(ring::digest::digest(&ring::digest::SHA256, credential.as_bytes()).as_ref()); + let started = Instant::now(); + assert!(api::client_v0::external_grants::authenticate(&state, &digest, "http").unwrap().is_some()); + diagnostics.push(json!({"candidate_count":candidate_ids.len(),"candidate_sql_ms":candidate_sql_ms, + "direct_auth_ms":started.elapsed().as_secs_f64()*1000.0})); + }} + let inspected = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + let started = Instant::now(); + api::client_v0::external_grants::projection(&state, &inspected).unwrap(); + let legacy_projection_ms = started.elapsed().as_secs_f64()*1000.0; + let started = Instant::now(); + api::client_v0::external_grants::projection_with_witness(&state, &inspected).unwrap(); + let witness_projection_ms = started.elapsed().as_secs_f64()*1000.0; + println!("ADMISSION_DIAGNOSTICS {}", json!({"plan":explain(&connection, query),"samples":diagnostics, + "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms})); drop(connection); api::wait_published_lists_at_least(&store, store.index().unwrap()).await.unwrap(); let mut measurements = Vec::new(); @@ -338,6 +354,8 @@ async fn authenticated_get_during_pairing() { "fixture_person_ids":[OWNER],"verified_foreign_same_profile_active_grants":foreign_active, "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, "final_total_claim_rows":final_rows,"admission_query":query, + "conflict_fold_diagnostics":diagnostics, + "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms, "explain_without_index":before,"explain_with_index":after,"synthetic_startup_index_build_ms":build_ms, "measurements":measurements}); println!("ADMISSION_MEASUREMENT {}", serde_json::to_string_pretty(&report).unwrap()); diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 6aa7182a434..8b2a2e15a1a 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -878,6 +878,9 @@ pub struct Store { admission_schema_digest: std::sync::OnceLock, /// The membership last folded, and the `fleet_generation` it was folded at. pub membership_cache: Mutex>, + /// Request-only sealed folds, which may omit local batches not yet sealed. + /// Never used by the sealing path's `membership_cache` fast path. + sealed_membership_cache: Mutex>, /// Where the scan for signatures missing on admitted envelopes stands. signature_backfill: Mutex, /// Read-only sealed view; never populated with the client's local-signer fallback. @@ -1336,6 +1339,7 @@ impl Store { admission: Mutex::new(()), admission_schema_digest: std::sync::OnceLock::new(), membership_cache: Mutex::new(None), + sealed_membership_cache: Mutex::new(None), fleet_authority: std::sync::OnceLock::new(), admitted_fleet_generation: AtomicI64::new(i64::MIN), signature_backfill: Mutex::default(), @@ -2636,8 +2640,13 @@ impl Store { { return Ok(membership.clone()); } - // Do not populate the sealing path's cache with a fold that can omit local batches. - fleet_membership_tx(&connection) + // Keep cold request folds separate: they can omit unsealed local batches, + // so publishing them into membership_cache would bypass the sealing path. + sealed_membership_tx( + &connection, + &mut self.sealed_membership_cache.lock() + .unwrap_or_else(PoisonError::into_inner), + ) }) } @@ -2936,9 +2945,10 @@ impl Store { } /// Whether an accepted copy was signed by a keyed fleet member acting as its origin. - /// Requires a valid record in a validated envelope, a signature key authorized for that - /// writer's sequence, and a cryptographically valid signature in this store's fleet/shard - /// domain. Legacy and unkeyed writers do not authenticate provenance. Reads only sealed + /// Requires a valid record in a validated or degraded envelope, a signature key authorized + /// for that writer's sequence, and a cryptographically valid signature in this store's + /// fleet/shard domain. Invalid sibling records do not disqualify a valid record in a + /// degraded envelope. Legacy and unkeyed writers do not authenticate provenance. Reads only sealed /// membership; this query never seals local batches or scans the replication log. pub fn claim_has_authenticated_member_writer(&self, claim_id: &str) -> Result { self.read_snapshot(|_| { @@ -2958,7 +2968,7 @@ impl Store { JOIN replica_envelope_signatures AS signatures USING (writer, sequence, envelope_hash) WHERE records.claim_id=?1 AND records.state='valid' - AND envelopes.receipt_state='validated'", + AND envelopes.receipt_state IN ('validated', 'degraded')", )?; let rows = statement.query_map([claim_id], |row| { Ok(( @@ -3327,6 +3337,22 @@ fn fleet_generation(connection: &Connection) -> Result { .query_row(/* sqlite-large-value: allow-for-now lv-h339ecb1b2413 owner=smallclaims::store TODO=trace-statement-and-value-representation */ [], |row| row.get(0))?) } +// The caller holds one snapshot for both the generation read and membership fold. +fn sealed_membership_tx( + connection: &Connection, + cache: &mut Option<(i64, crate::fleet::Membership)>, +) -> Result { + let generation = fleet_generation(connection)?; + if let Some((cached_generation, membership)) = cache.as_ref() + && *cached_generation == generation + { + return Ok(membership.clone()); + } + let membership = fleet_membership_tx(connection)?; + *cache = Some((generation, membership.clone())); + Ok(membership) +} + // The caller holds a read snapshot. Unlike the client view this has no local signer; // Membership::fold and FleetView::from_membership use no clock or expiry state. fn sealed_fleet_view_tx( diff --git a/crates/smallclaims/src/store/membership_query_tests.rs b/crates/smallclaims/src/store/membership_query_tests.rs index 3ba1abe2dcf..da53fc5fb3b 100644 --- a/crates/smallclaims/src/store/membership_query_tests.rs +++ b/crates/smallclaims/src/store/membership_query_tests.rs @@ -357,6 +357,71 @@ fn sealed_fleet_cache_tracks_batch_signers_after_envelope_identity_changes() { } } +#[test] +fn sealed_membership_cache_reuses_cold_folds_and_recomputes_on_generation_changes() { + let mut connection = fixture(); + connection.execute_batch(/* sqlite-large-value: allow-for-now lv-hf348da4e378d owner=smallclaims::store::membership_query_tests TODO=trace-statement-and-value-representation */ &fleet_generation_schema()).unwrap(); + let anchor = admitted("anchor", "birch", "anchor-key", "anchor", "birch", 3); + insert_claim(&connection, &anchor); + let mut cache = None; + connection.trace(Some(|sql| { + if sql.starts_with("SELECT claims.id, claims.kind, claims.subject, claims.body,") { + STATEMENTS.with(|count| count.set(count.get() + 1)); + } + })); + STATEMENTS.with(|count| count.set(0)); + // Even an empty fold with local unsealed claims must be cached. + for _ in 0..8 { + assert!(!sealed_membership_tx(&connection, &mut cache).unwrap().counts("anchor")); + } + STATEMENTS.with(|count| assert_eq!(count.get(), 1)); + let unsealed_generation = cache.as_ref().unwrap().0; + envelope(&connection, &anchor, "sealed", &["anchor-key"]); + for _ in 0..8 { + assert!(sealed_membership_tx(&connection, &mut cache).unwrap().counts("anchor")); + } + assert!(cache.as_ref().unwrap().0 > unsealed_generation); + STATEMENTS.with(|count| assert_eq!(count.get(), 2)); + connection.execute(/* sqlite-large-value: allow-for-now lv-hbea4b67b6a13 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "DELETE FROM replica_envelope_signatures", []).unwrap(); + for _ in 0..8 { + assert!(!sealed_membership_tx(&connection, &mut cache).unwrap().counts("anchor")); + } + STATEMENTS.with(|count| assert_eq!(count.get(), 3)); + connection.trace(None); +} + +#[test] +fn sealed_membership_request_cache_does_not_bypass_local_batch_sealing() { + let store = Store::open_memory("birch", Arc::new(super::runtime::Plain)).unwrap(); + store.bind_fleet("3e7a9c41-5d2b-4f86-b0c3-9a1e6d4f2b58").unwrap(); + let key = Arc::new(crate::fleet::MemberKey::generate().unwrap().0); + store.load_member_key(Some(key.clone())).unwrap(); + store.pin_fleet_anchor(key.public()).unwrap(); + let mut anchor = admitted("anchor", "birch", key.public(), "anchor", "birch", 1); + anchor.fields.insert( + "fleet_id".into(), + serde_json::json!("3e7a9c41-5d2b-4f86-b0c3-9a1e6d4f2b58"), + ); + let claim = store.append_claim(&ClaimInput { + subject: anchor.subject, + kind: anchor.kind, + actor: None, + fields: anchor.fields, + evidence: Vec::new(), + expected_subject: None, + idempotency_key: None, + }).unwrap(); + assert!(store.membership_cache.lock().unwrap().is_none()); + assert!(store.sealed_membership_cache.lock().unwrap().is_none()); + for _ in 0..3 { + assert!(!store.fleet_membership_sealed().unwrap().counts(&claim.id)); + } + assert!(store.sealed_membership_cache.lock().unwrap().is_some()); + assert!(store.membership_cache.lock().unwrap().is_none()); + assert!(store.fleet_membership().unwrap().counts(&claim.id)); + assert!(store.fleet_membership_sealed().unwrap().counts(&claim.id)); +} + fn cache_member_window(store: &Store, key: &str, start: u64) { let mut anchor = admitted("anchor", "birch", key, "anchor", "birch", start.max(1)); anchor.fields.insert("writer_floor".into(), serde_json::json!(start.saturating_sub(1))); @@ -407,6 +472,23 @@ fn authenticated_member_writer_accepts_a_foreign_origin_from_sealed_membership() assert!(!store.claim_has_authenticated_member_writer("missing").unwrap()); } +#[test] +fn authenticated_member_writer_accepts_valid_records_in_a_degraded_envelope() { + let (store, claim, key) = authenticated_member_fixture(); + store.connection.write().execute( + /* sqlite-large-value: allow-for-now lv-h6d03218a7182 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelopes SET receipt_state='degraded'", [], + ).unwrap(); + cache_member_window(&store, key.public(), 0); + assert!(store.claim_has_authenticated_member_writer(&claim).unwrap()); + store.connection.write().execute( + /* sqlite-large-value: allow-for-now lv-h9e7e7a841384 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelope_signatures SET signature='invalid'", [], + ).unwrap(); + cache_member_window(&store, key.public(), 0); + assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); +} + #[test] fn authenticated_member_writer_rejects_legacy_wrong_key_and_outside_window() { let (store, claim, key) = authenticated_member_fixture(); @@ -422,17 +504,19 @@ fn authenticated_member_writer_rejects_legacy_wrong_key_and_outside_window() { } #[test] -fn authenticated_member_writer_requires_origin_valid_record_validated_envelope_and_signature() { +fn authenticated_member_writer_requires_origin_valid_record_admitted_envelope_and_signature() { for sql in [ /* sqlite-large-value: allow-for-now lv-h908d794ad3e8 owner=smallclaims::store::membership_query_tests TODO=prepare-body-and-predecessor-values */ "UPDATE claims SET origin='forged-origin'", /* sqlite-large-value: allow-for-now lv-h6ff49ec4f026 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "UPDATE replica_records SET state='invalid'", + /* sqlite-large-value: allow-for-now lv-h98f2eff88ab2 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_records SET state='pending'", /* sqlite-large-value: allow-for-now lv-ha41272fe6b10 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "UPDATE replica_envelopes SET receipt_state='pending'", - /* sqlite-large-value: allow-for-now lv-hbea4b67b6a13 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + /* sqlite-large-value: allow-for-now lv-h93f4bed1c2b4 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "DELETE FROM replica_envelope_signatures", - /* sqlite-large-value: allow-for-now lv-h9e7e7a841384 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + /* sqlite-large-value: allow-for-now lv-h1c91a0dec004 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "UPDATE replica_envelope_signatures SET signature='invalid'", /* sqlite-large-value: allow-for-now lv-hc8361ab9b858 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "UPDATE replica_envelope_signatures SET envelope_hash='other-envelope'", diff --git a/docs/st3/client-v0/schemas/client-v0.schema.json b/docs/st3/client-v0/schemas/client-v0.schema.json index 305de428cdb..61e3217de5d 100644 --- a/docs/st3/client-v0/schemas/client-v0.schema.json +++ b/docs/st3/client-v0/schemas/client-v0.schema.json @@ -3867,8 +3867,8 @@ "disclosure_consent": { "type": "boolean" }, "consent_evidence": { "type": "string", "minLength": 1, "maxLength": 512 }, "revoked": { "type": "boolean" }, - "conflict": { "anyOf": [{ "$ref": "#/$defs/GrantProfileConflictWitness" }, { "type": "null" }], "description": "Current opposite-profile conflict, or null when no active conflict exists. Absent on older servers." }, - "cleared_conflicts": { "type": "array", "items": { "$ref": "#/$defs/ClearedGrantProfileConflictWitness" }, "description": "Revoked or expired opposite-profile witnesses; emitted only when conflict is null." }, + "conflict": { "anyOf": [{ "$ref": "#/$defs/GrantProfileConflictWitness" }, { "type": "null" }], "description": "Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses." }, + "cleared_conflicts": { "type": "array", "items": { "$ref": "#/$defs/ClearedGrantProfileConflictWitness" }, "description": "Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null." }, "read_trust": { "$ref": "#/$defs/AssistantReadTrust", "description": "Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied." } } }, diff --git a/docs/st3/client-v0/schemas/operations.json b/docs/st3/client-v0/schemas/operations.json index 0c9fe829703..321ffab52e5 100644 --- a/docs/st3/client-v0/schemas/operations.json +++ b/docs/st3/client-v0/schemas/operations.json @@ -135,7 +135,7 @@ { "id": "action.submit", "method": "POST", "path": "/v1/client/actions", "request": "ActionRequest", "response": "ActionResult" }, { "id": "pairing.begin", "method": "POST", "path": "/v1/client/pairings", "request": "PairingBegin", "response": "PairingChallenge", "local_only": true }, { "id": "pairing.complete", "method": "POST", "path": "/v1/client/pairings/{id}/complete", "request": "PairingComplete", "response": "PairedSession" }, - { "id": "assistant.grant.get", "method": "GET", "path": "/v1/client/assistant/grants/{id}", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1" }, + { "id": "assistant.grant.get", "method": "GET", "path": "/v1/client/assistant/grants/{id}", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1", "query": { "witness": "optional; only 1 opts into conflict and cleared_conflicts fields. Omitted or any other value retains the pre-witness response shape. Opt-in applies only to inspection, never pairing or grant mutations; 409 errors may carry conflict witnesses independently." } }, { "id": "assistant.grant.revoke", "method": "POST", "path": "/v1/client/assistant/grants/{id}/revoke", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1" }, { "id": "assistant.grant.policy", "method": "POST", "path": "/v1/client/assistant/grants/{id}/policy", "request": "AssistantGrantPolicy", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1" }, { "id": "assistant.grant.read-trust", "method": "POST", "path": "/v1/client/assistant/grants/{id}/read-trust", "request": "AssistantReadTrustRequest", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1", "increments_policy_revision": true }, diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index 1bb7a6a3beb..ed399befe88 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -798,6 +798,11 @@ {"id": "flow-h39d714b2bc13", "path": "crates/smallclaims/src/store/checkpoint_trim.rs", "function": "trim_checkpoint_from", "owner": "smallclaims::store::checkpoint_trim", "fingerprint": "344fc686f5b0778d9f534c322d46e20e2a21066b09d5acfc1c01c0cf88ad607a", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "description": "Exact-adoption/trim publication and durable cleanup must be separated without bypassing certification."} ], "sites": [ + {"id":"lv-h1c91a0dec004","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"701329c99c19076f8b477e2f84c40f1a2ece7974203ef799364c1f2382fd1875","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":517,"excerpt":"UPDATE replica_envelope_signatures SET signature='invalid'"}, + {"id":"lv-h6d03218a7182","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"9832c5a9904e935c7d7a9c2554db48b6c0173e6a2776085f9b183724794ffa3e","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":479,"excerpt":"UPDATE replica_envelopes SET receipt_state='degraded'"}, + {"id":"lv-h93f4bed1c2b4","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"309875e8abb2bc3a99eb38ecee4c711cb76b3289ec093bfbbc7fb20330b57bac","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":515,"excerpt":"DELETE FROM replica_envelope_signatures"}, + {"id":"lv-h98f2eff88ab2","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"a425d1008a65ca301d0a04b451621d9b1641c6739d812d23fe0c37819f712672","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":511,"excerpt":"UPDATE replica_records SET state='pending'"}, + {"id":"lv-hf348da4e378d","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"unresolved-sql-sink","fingerprint":"275c4c4da97210df1e7bfe33129bee3db036859980da47101d33c19e6caa7b4a","owner":"smallclaims::store::membership_query_tests","todo":"trace-statement-and-value-representation","disposition":"allow-for-now","line_hint":363,"excerpt":"& fleet_generation_schema ( )"}, {"id":"lv-hf4201606586b","path":"crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs","kind":"unresolved-sql-sink","fingerprint":"412c0c2f9ba50d78b84d6a1f379e285a435a7c6c05e777851130e01716e85c3c","owner":"fractal_api_core::api::client_v0::external_grants::conflict_tests","todo":"trace-statement-and-value-representation","disposition":"allow-for-now","line_hint":295,"excerpt":"& format ! ( \"EXPLAIN QUERY PLAN {ADMISSION_QUERY}\" )"}, {"id":"lv-h622f4fdd0f6d","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"unresolved-sql-sink","fingerprint":"4ec7c53222c8a758c722e2111541035ce700d5ae7bd0898c5f1b1a743e6450fd","owner":"smallclaims::store::membership_query_tests","todo":"trace-statement-and-value-representation","disposition":"allow-for-now","line_hint":432,"excerpt":"sql"}, {"id":"lv-h6ff49ec4f026","path":"crates/smallclaims/src/store/membership_query_tests.rs","kind":"sql-template","fingerprint":"77379a14bb57c713620fd58bbdc380648a7d4228bbda0e58474916d971a24bad","owner":"smallclaims::store::membership_query_tests","todo":"chunk-or-reference-exact-wire-values","disposition":"allow-for-now","line_hint":425,"excerpt":"UPDATE replica_records SET state='invalid'"}, diff --git a/docs/st3/principals-and-grants.md b/docs/st3/principals-and-grants.md index de4b43e9188..aa31f6e55ab 100644 --- a/docs/st3/principals-and-grants.md +++ b/docs/st3/principals-and-grants.md @@ -117,7 +117,7 @@ Several active grants of a principal's own profile are allowed. Admission refuse a known opposite-profile grant, including one replicated from another issuer. If disconnected issuers create opposite-profile grants, authentication suspends every conflicting grant with `grant-profile-conflict`; there is no winner. -Inspect exposes a `conflict.grants` witness with both grant IDs, origins and +Inspect with `?witness=1` exposes a `conflict.grants` witness with both grant IDs, origins and profiles. Once an owner's revoke replicates (or the opposite grant expires), the remaining grant works again on its authoritative issuer; replication never makes foreign credentials authenticate on another member. @@ -129,15 +129,28 @@ issued opposite-profile grant reintroduces the conflict by computation. Only well-formed foreign grants attributed to the configured concrete owner count as witnesses. Their grant and effective policy must have matching immutable -identity/profile, and each must have validated envelope provenance signed by a +identity/profile, and each must have authenticated envelope provenance signed by a key in its writer's admitted fleet membership window. Legacy unsigned, unverifiable and malformed custom claims do not gain suspension authority merely by naming an owner or origin. This intentionally favors verifiable issuer claims -over allowing arbitrary replicated custom fields to deny service. The fold uses -the principal expression index and removes expired/revoked history in SQL on -every admission/authentication/inspect read, including after replication catches -up. Historical `custom.client.assistant.v1.*` claim kinds and absent-principal -legacy ChatGPT grants retain their existing meaning. +over allowing arbitrary replicated custom fields to deny service. A valid record +in a degraded envelope still counts when its signature and writer window verify; +an unrelated rejected record cannot hide the grant. + +Only transitions from the grant's own origin, by its owner, with consistent +immutable identity can revoke it or change its effective policy. Foreign +transitions additionally require authenticated provenance. Invalid overlays are +ignored; the last valid policy (or original grant) stays in force. This applies to +local grants too: an unauthorized newer overlay no longer replaces their policy. +The principal expression index prunes expired base grants without issuer policy +candidates, and matching local revocations, before the authenticated Rust fold. +Foreign revocations and policy candidates reach Rust because SQL cannot verify +signatures. The sealed membership fold has a separate generation-keyed cache: +request-side cold folds populate it without populating the sealing-path cache. +Every admission/authentication/witness read recomputes conflict, including after +replication catches up. Default grant responses preserve their pre-witness shape +for old strict clients. Historical `custom.client.assistant.v1.*` claim kinds and +absent-principal legacy ChatGPT grants retain their existing meaning. Claims persist credential/code digests, never bearer tokens or pairing codes; grant projections expose neither credential material nor its digests. diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 884a071764a..ecfa30f5fc5 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -7,7 +7,7 @@ }, "schema": { "status": "changed", - "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409, plus optional AssistantGrant conflict and cleared_conflicts projection witnesses with typed assistant/service profiles and revoked/expired causes. No grant claim shape or storage migration changes." + "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409, plus inspect-only ?witness=1 opt-in conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients. No grant claim shape or storage migration changes." }, "rules": { "status": "changed", @@ -15,7 +15,7 @@ }, "compatibility": { "status": "changed", - "detail": "Conflict admission counts only well-formed foreign owner grants and matching effective policies with authenticated envelope provenance from a keyed, admitted fleet writer. Unverifiable or malformed replicated custom claims cannot acquire suspension authority by naming an owner. Tokens remain issuer-local. Older members do not enforce this suspension rule, so upgrade all serving members before relying on it." + "detail": "Conflict admission counts only well-formed foreign owner grants with authenticated envelope provenance from a keyed, admitted fleet writer, including valid records in degraded envelopes. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity; foreign transitions also require authenticated provenance. Invalid overlays are ignored, retaining the last valid policy. This restriction also applies to local grants. Request-side sealed membership folds populate a separate generation-keyed cache without weakening local sealing. Tokens remain issuer-local. Older members do not enforce suspension, so upgrade all serving members before relying on it." }, "downtime": { "status": "changed", From 1a20821768bb1247e08cf4bfe138856671d66ae2 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 10:09:43 +0100 Subject: [PATCH 08/52] perf(external-grants): bound expiry and revocation conflict probes agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 25 ++++++++++++------- .../external_grants/conflict_tests.rs | 4 +++ docs/st3/principals-and-grants.md | 4 +++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index cabce38fef0..3f830136a50 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -74,22 +74,29 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { // candidate must reach the authenticated fold: SQL cannot verify its signature. // Foreign revocations likewise reach Rust. Local revocations can be prefiltered // only when their origin, owner and immutable grant identity match. +// Materialize issuer-policy subjects once per principal, not once per expired +// grant. CASE gates revocation probes behind expiry eligibility. Pin the +// subject/kind index: the principal expression index is a quadratic revoke plan. const ADMISSION_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND (?5 IS NULL OR origin<>?6 OR NOT EXISTS ( - SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3 + AND (?5 IS NULL OR CASE WHEN + (CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE + COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END) + OR (origin,subject) IN ( + SELECT policy.origin,policy.subject FROM claims AS policy + WHERE policy.kind=?4 AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2) + THEN origin<>?6 OR NOT EXISTS ( + SELECT 1 FROM claims AS revoked INDEXED BY claims_subject_kind_accepted_index + WHERE revoked.subject=claims.subject AND revoked.kind=?3 AND revoked.origin=claims.origin AND revoked.actor=claims.actor AND (json_type(revoked.body,'$.fields.principal') IS NULL OR json_extract(revoked.body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) AND (json_type(revoked.body,'$.fields.profile') IS NULL OR json_extract(revoked.body,'$.fields.profile') IN ('assistant','service')) AND json_extract(revoked.body,'$.fields.issuer') IS json_extract(claims.body,'$.fields.issuer') AND json_extract(revoked.body,'$.fields.grant_id') IS json_extract(claims.body,'$.fields.grant_id') AND COALESCE(json_extract(revoked.body,'$.fields.principal'),'assistant/chatgpt')=COALESCE(json_extract(claims.body,'$.fields.principal'),'assistant/chatgpt') - AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant'))) - AND (?5 IS NULL OR EXISTS ( - SELECT 1 FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 AND policy.origin=claims.origin) - OR CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END)"; + AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant')) + ELSE 0 END)"; #[cfg(feature = "test-support")] pub const fn admission_query_for_test() -> &'static str { ADMISSION_QUERY } @@ -509,7 +516,7 @@ mod tests { connection.execute_batch( "CREATE TABLE claims(id TEXT,subject TEXT,kind TEXT,body TEXT,origin TEXT DEFAULT 'local',actor TEXT DEFAULT 'person/owner',store_index INTEGER PRIMARY KEY); CREATE INDEX principal_scan ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); - CREATE INDEX subject_kind ON claims(subject,kind,store_index);" + CREATE INDEX claims_subject_kind_accepted_index ON claims(subject,kind,store_index);" ).unwrap(); let fixtures = [ ("expired", json!({"fields":{"expires_at_unix_ms":99}}), None, false), diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 3b894fca786..4b22d2bf96d 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -388,4 +388,8 @@ fn admission_scan_uses_the_real_principal_index() { println!("external grant admission query plan:\n{}", plan.join("\n")); assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_index")), "principal admission must use its production index: {plan:?}"); + assert!(plan.iter().any(|step| step.contains("revoked USING INDEX claims_subject_kind_accepted_index")), + "revocation must seek by subject rather than scan the principal: {plan:?}"); + assert!(plan.iter().any(|step| step.contains("LIST SUBQUERY")), + "issuer-policy candidates must be materialized once: {plan:?}"); } diff --git a/docs/st3/principals-and-grants.md b/docs/st3/principals-and-grants.md index aa31f6e55ab..aca88e2504f 100644 --- a/docs/st3/principals-and-grants.md +++ b/docs/st3/principals-and-grants.md @@ -144,6 +144,10 @@ ignored; the last valid policy (or original grant) stays in force. This applies local grants too: an unauthorized newer overlay no longer replaces their policy. The principal expression index prunes expired base grants without issuer policy candidates, and matching local revocations, before the authenticated Rust fold. +The SQL materializes matching-principal issuer-policy subjects once, gates +revocation checks behind expiry eligibility, and pins the existing subject/kind +revocation index. This avoids a correlated policy lookup per expired grant and a +quadratic principal-wide revocation plan as completion/revocation history grows. Foreign revocations and policy candidates reach Rust because SQL cannot verify signatures. The sealed membership fold has a separate generation-keyed cache: request-side cold folds populate it without populating the sealing-path cache. From 13da93859c819be61f44899d025eacd8319716e2 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 11:46:30 +0100 Subject: [PATCH 09/52] Seek active external grants through principal expiry ranges agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 43 ++- .../external_grants/conflict_tests.rs | 5 +- crates/fractal-store/src/store.rs | 6 +- crates/fractal-store/src/store/runtime.rs | 72 +++-- .../tests/daemon_cost/assistant_admission.rs | 8 +- docs/st3/large-value-sites.json | 273 +++++++++--------- docs/st3/large-values.md | 8 +- docs/st3/principals-and-grants.md | 7 +- .../external-grant-profile-conflict.json | 4 +- 9 files changed, 236 insertions(+), 190 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index 3f830136a50..7411993f99b 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -74,29 +74,41 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { // candidate must reach the authenticated fold: SQL cannot verify its signature. // Foreign revocations likewise reach Rust. Local revocations can be prefiltered // only when their origin, owner and immutable grant identity match. -// Materialize issuer-policy subjects once per principal, not once per expired -// grant. CASE gates revocation probes behind expiry eligibility. Pin the -// subject/kind index: the principal expression index is a quadratic revoke plan. +// UNION builds only candidate IDs: indexed expiry ranges prune expired base +// bodies, and the issuer-policy branch preserves renewals for verification. +// Pin revocation's subject/kind index, never its principal-wide expression index. const ADMISSION_QUERY: &str = - "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND (?5 IS NULL OR CASE WHEN - (CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END) - OR (origin,subject) IN ( - SELECT policy.origin,policy.subject FROM claims AS policy - WHERE policy.kind=?4 AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2) - THEN origin<>?6 OR NOT EXISTS ( + "WITH eligible(id) AS ( + SELECT id FROM claims INDEXED BY claims_assistant_v1_principal_index + WHERE ?5 IS NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + UNION + SELECT id FROM claims + WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5 + AND json_type(body,'$.fields.expires_at_unix_ms')='integer' + UNION + SELECT id FROM claims + WHERE ?5 IS NOT NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND json_extract(body,'$.fields.expires_at_unix_ms') IS NULL AND json_type(body,'$.fields') IS NULL + UNION + SELECT granted.id FROM claims AS policy INDEXED BY claims_assistant_v1_principal_index + JOIN claims AS granted INDEXED BY claims_subject_kind_accepted_index + ON granted.subject=policy.subject AND granted.kind=?1 + WHERE ?5 IS NOT NULL AND policy.kind=?4 AND policy.origin=granted.origin + AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND COALESCE(json_extract(granted.body,'$.fields.principal'),'assistant/chatgpt')=?2) + SELECT claims.id FROM eligible JOIN claims ON claims.id=eligible.id + WHERE ?5 IS NULL OR claims.origin<>?6 OR NOT EXISTS ( SELECT 1 FROM claims AS revoked INDEXED BY claims_subject_kind_accepted_index WHERE revoked.subject=claims.subject AND revoked.kind=?3 AND revoked.origin=claims.origin AND revoked.actor=claims.actor + AND json_extract(revoked.body,'$.fields.issuer')=revoked.actor AND (json_type(revoked.body,'$.fields.principal') IS NULL OR json_extract(revoked.body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) AND (json_type(revoked.body,'$.fields.profile') IS NULL OR json_extract(revoked.body,'$.fields.profile') IN ('assistant','service')) AND json_extract(revoked.body,'$.fields.issuer') IS json_extract(claims.body,'$.fields.issuer') AND json_extract(revoked.body,'$.fields.grant_id') IS json_extract(claims.body,'$.fields.grant_id') AND COALESCE(json_extract(revoked.body,'$.fields.principal'),'assistant/chatgpt')=COALESCE(json_extract(claims.body,'$.fields.principal'),'assistant/chatgpt') - AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant')) - ELSE 0 END)"; + AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant'))"; #[cfg(feature = "test-support")] pub const fn admission_query_for_test() -> &'static str { ADMISSION_QUERY } @@ -515,7 +527,8 @@ mod tests { let connection = rusqlite::Connection::open_in_memory().unwrap(); connection.execute_batch( "CREATE TABLE claims(id TEXT,subject TEXT,kind TEXT,body TEXT,origin TEXT DEFAULT 'local',actor TEXT DEFAULT 'person/owner',store_index INTEGER PRIMARY KEY); - CREATE INDEX principal_scan ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); + CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); + CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms')); CREATE INDEX claims_subject_kind_accepted_index ON claims(subject,kind,store_index);" ).unwrap(); let fixtures = [ diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 4b22d2bf96d..409ad44979b 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -390,6 +390,7 @@ fn admission_scan_uses_the_real_principal_index() { "principal admission must use its production index: {plan:?}"); assert!(plan.iter().any(|step| step.contains("revoked USING INDEX claims_subject_kind_accepted_index")), "revocation must seek by subject rather than scan the principal: {plan:?}"); - assert!(plan.iter().any(|step| step.contains("LIST SUBQUERY")), - "issuer-policy candidates must be materialized once: {plan:?}"); + assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_expiry_index") + && step.contains(">?")), + "expired grant bodies must be pruned by an index range: {plan:?}"); } diff --git a/crates/fractal-store/src/store.rs b/crates/fractal-store/src/store.rs index 221793024b0..ab989319e23 100644 --- a/crates/fractal-store/src/store.rs +++ b/crates/fractal-store/src/store.rs @@ -780,7 +780,7 @@ pub struct AgentWorkQueue { /// Fractal's projection tables, and the indexes its folds read the claim log through. The /// graph creates its own tables first; see `smallclaims::store::SCHEMA`. -const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-hb9696ca837f7 owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" +const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-h7e7937d8fad1 owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL; @@ -933,6 +933,10 @@ WHERE kind='custom.client.assistant.v1.granted'; -- Match parameterized admission by kind and effective principal, including legacy ChatGPT grants. CREATE INDEX IF NOT EXISTS claims_assistant_v1_principal_index ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); +-- Seek live base grants without loading expired JSON bodies on each authentication. +CREATE INDEX IF NOT EXISTS claims_assistant_v1_principal_expiry_index +ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), + json_extract(body,'$.fields.expires_at_unix_ms')); -- A runtime incarnation's claims about a subject by acceptance time, so when a session began -- and last changed are two seeks instead of a read of every claim the subject has. The -- expression is INCARNATION_OF_CLAIM, which queries repeat so the planner uses this index. diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index 95bfe580810..1a20a44be0c 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -836,18 +836,42 @@ mod schema_install_tests { const REVOKED: &str = "custom.client.assistant.v1.revoked"; const POLICY: &str = "custom.client.assistant.v1.policy"; const INDEX: &str = "claims_assistant_v1_principal_index"; + const EXPIRY_INDEX: &str = "claims_assistant_v1_principal_expiry_index"; const SELECT: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; + // Keep this differential reference identical to the production constant; + // the API-core real-Store plan test covers that constant directly. const ACTIVE: &str = - "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND (?5 IS NULL OR NOT EXISTS (SELECT 1 FROM claims AS revoked WHERE revoked.subject=claims.subject AND revoked.kind=?3)) - AND (?5 IS NULL OR COALESCE( - (SELECT CASE WHEN json_type(policy.body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(policy.body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5,0) END - FROM claims AS policy WHERE policy.subject=claims.subject AND policy.kind=?4 ORDER BY policy.store_index DESC LIMIT 1), - CASE WHEN json_type(body,'$.fields') IS NULL THEN 1 ELSE - COALESCE(json_type(body,'$.fields.expires_at_unix_ms')='integer' - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5,0) END))"; + "WITH eligible(id) AS ( + SELECT id FROM claims INDEXED BY claims_assistant_v1_principal_index + WHERE ?5 IS NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + UNION + SELECT id FROM claims + WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND json_extract(body,'$.fields.expires_at_unix_ms')>?5 + AND json_type(body,'$.fields.expires_at_unix_ms')='integer' + UNION + SELECT id FROM claims + WHERE ?5 IS NOT NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND json_extract(body,'$.fields.expires_at_unix_ms') IS NULL AND json_type(body,'$.fields') IS NULL + UNION + SELECT granted.id FROM claims AS policy INDEXED BY claims_assistant_v1_principal_index + JOIN claims AS granted INDEXED BY claims_subject_kind_accepted_index + ON granted.subject=policy.subject AND granted.kind=?1 + WHERE ?5 IS NOT NULL AND policy.kind=?4 AND policy.origin=granted.origin + AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND COALESCE(json_extract(granted.body,'$.fields.principal'),'assistant/chatgpt')=?2) + SELECT claims.id FROM eligible JOIN claims ON claims.id=eligible.id + WHERE ?5 IS NULL OR claims.origin<>?6 OR NOT EXISTS ( + SELECT 1 FROM claims AS revoked INDEXED BY claims_subject_kind_accepted_index + WHERE revoked.subject=claims.subject AND revoked.kind=?3 + AND revoked.origin=claims.origin AND revoked.actor=claims.actor + AND json_extract(revoked.body,'$.fields.issuer')=revoked.actor + AND (json_type(revoked.body,'$.fields.principal') IS NULL OR json_extract(revoked.body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) + AND (json_type(revoked.body,'$.fields.profile') IS NULL OR json_extract(revoked.body,'$.fields.profile') IN ('assistant','service')) + AND json_extract(revoked.body,'$.fields.issuer') IS json_extract(claims.body,'$.fields.issuer') + AND json_extract(revoked.body,'$.fields.grant_id') IS json_extract(claims.body,'$.fields.grant_id') + AND COALESCE(json_extract(revoked.body,'$.fields.principal'),'assistant/chatgpt')=COALESCE(json_extract(claims.body,'$.fields.principal'),'assistant/chatgpt') + AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant'))"; fn snapshot(connection: &Connection) -> Vec> { connection @@ -863,7 +887,7 @@ mod schema_install_tests { fn plan(connection: &Connection, sql: &str, active: bool) -> Vec { let parameters: Vec<&dyn rusqlite::ToSql> = if active { - vec![&GRANTED, &"assistant/chatgpt", &REVOKED, &POLICY, &100_u64] + vec![&GRANTED, &"assistant/chatgpt", &REVOKED, &POLICY, &100_u64, &"node"] } else { vec![&GRANTED, &"assistant/chatgpt"] }; @@ -883,28 +907,28 @@ mod schema_install_tests { let connection = Connection::open(&path).unwrap(); connection.execute_batch(smallclaims::store::SCHEMA).unwrap(); install_initial_schema(&connection, true).unwrap(); - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index;").unwrap(); + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index; DROP INDEX claims_assistant_v1_principal_expiry_index;").unwrap(); connection.pragma_update(None, "user_version", version).unwrap(); connection.execute( "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES('batch','node',1,'hash','1')", [], ).unwrap(); for (id, subject, kind, body) in [ - ("legacy", "custom/client/legacy", GRANTED, r#"{"fields":{"expires_at_unix_ms":200}}"#), - ("chatgpt", "custom/client/chatgpt", GRANTED, r#"{"fields":{"principal":"assistant/chatgpt","expires_at_unix_ms":50}}"#), - ("mcp", "custom/client/mcp", GRANTED, r#"{"fields":{"principal":"assistant/mcp","expires_at_unix_ms":200}}"#), - ("policy", "custom/client/chatgpt", POLICY, r#"{"fields":{"expires_at_unix_ms":200}}"#), - ("revoked", "custom/client/legacy", REVOKED, r#"{"fields":{}}"#), + ("legacy", "custom/client/legacy", GRANTED, r#"{"fields":{"issuer":"person/owner","expires_at_unix_ms":200}}"#), + ("chatgpt", "custom/client/chatgpt", GRANTED, r#"{"fields":{"issuer":"person/owner","principal":"assistant/chatgpt","expires_at_unix_ms":50}}"#), + ("mcp", "custom/client/mcp", GRANTED, r#"{"fields":{"issuer":"person/owner","principal":"assistant/mcp","expires_at_unix_ms":200}}"#), + ("policy", "custom/client/chatgpt", POLICY, r#"{"fields":{"issuer":"person/owner","expires_at_unix_ms":200}}"#), + ("revoked", "custom/client/legacy", REVOKED, r#"{"fields":{"issuer":"person/owner"}}"#), ("unrelated", "custom/test/unrelated", "custom.test.recorded", r#"{"fields":{}}"#), ] { connection.execute( - "INSERT INTO claims(id,batch_id,subject,kind,origin,body,predecessors,accepted_at_unix_ms) VALUES(?1,'batch',?2,?3,'node',?4,'[]','1')", + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) VALUES(?1,'batch',?2,?3,'node','person/owner',?4,'[]','1')", params![id, subject, kind, body], ).unwrap(); } let before = snapshot(&connection); - let plans_before = [plan(&connection, SELECT, false), plan(&connection, ACTIVE, true)]; - assert!(plans_before.iter().flatten().all(|detail| !detail.contains(INDEX))); + let plans_before = [plan(&connection, SELECT, false)]; + assert!(plans_before.iter().flatten().all(|detail| !detail.contains(INDEX) && !detail.contains(EXPIRY_INDEX))); drop(connection); let connection = Connection::open(&path).unwrap(); @@ -915,7 +939,7 @@ mod schema_install_tests { connection.pragma_query_value(None, "user_version", |row| row.get::<_, u32>(0)).unwrap(), version, ); - for (sql, active, previous) in [(SELECT, false, &plans_before[0]), (ACTIVE, true, &plans_before[1])] { + for (sql, active, previous) in [(SELECT, false, &plans_before[0]), (ACTIVE, true, &plans_before[0])] { let current = plan(&connection, sql, active); eprintln!("assistant admission version={version} active={active} before={previous:?} after={current:?}"); assert!( @@ -924,6 +948,8 @@ mod schema_install_tests { "version {version}: before={previous:?}; after={current:?}", ); } + assert!(plan(&connection, ACTIVE, true).iter().any(|step| + step.contains(EXPIRY_INDEX) && step.contains(">?"))); for (principal, mut expected) in [ ("assistant/chatgpt", vec!["chatgpt".to_owned(), "legacy".to_owned()]), ("assistant/mcp", vec!["mcp".to_owned()]), @@ -936,11 +962,11 @@ mod schema_install_tests { assert_eq!(found, expected); } let active = connection.prepare(ACTIVE).unwrap() - .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, 100_u64], |row| row.get::<_, String>(0)) + .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, 100_u64, "node"], |row| row.get::<_, String>(0)) .unwrap().collect::>>().unwrap(); assert_eq!(active, vec!["chatgpt"]); let unfiltered = connection.prepare(ACTIVE).unwrap() - .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, Option::::None], |row| row.get::<_, String>(0)) + .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, Option::::None, "node"], |row| row.get::<_, String>(0)) .unwrap().collect::>>().unwrap(); assert_eq!(unfiltered.len(), 2, "no cutoff preserves unfiltered validation candidates"); let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 4fb7b61b472..dbf64be1efa 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -31,8 +31,8 @@ use tokio::sync::Barrier; const OWNER: &str = "person/bench-operator"; const NODE: &str = "benchmark-member"; const GRANTED: &str = "custom.client.assistant.v1.granted"; -const INDEX: &str = "claims_assistant_v1_principal_index"; -const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))"; +const INDEX: &str = "claims_assistant_v1_principal_expiry_index"; +const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms'))"; const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; const INDEXED_QUERY: &str = api::client_v0::external_grants::admission_query_for_test(); const PATH: &str = "/v1/client/assistant/summary"; @@ -253,7 +253,7 @@ async fn authenticated_get_during_pairing() { let index_exists: bool = connection.query_row("SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", [INDEX], |r| r.get(0)).unwrap(); assert_eq!(index_exists, indexed, "build baseline on 98e550cb; indexed on PR3-B"); let (before, after, build_ms) = if indexed { - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index").unwrap(); + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_expiry_index").unwrap(); let before = explain(&connection, query); let started = Instant::now(); connection.execute_batch(CREATE_INDEX).unwrap(); @@ -402,7 +402,7 @@ fn synthetic_large_store_index_build() { [INDEX], |row| row.get(0), ).unwrap(); assert!(installed, "run the large-store index probe on the indexed branch"); - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index").unwrap(); + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_expiry_index").unwrap(); // Copy every native required column rather than depending on a second claims schema. // The native autoincrement store_index, claim ID and subject must remain unique. let columns = { diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index ed399befe88..37439fc7d76 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -385,141 +385,142 @@ {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "table_pattern": "local_work_summary_clock", "columns": [{"name": "singleton", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY CHECK(singleton=1)", "value_size_proven": false}, {"name": "through_ms", "declared_type": "BLOB", "declaration": "BLOB NOT NULL CHECK(length(through_ms)=16)", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "table_pattern": "local_work_summaries", "columns": [{"name": "key", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "progress", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "progress_at", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "completion", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "next_at", "declared_type": "BLOB", "declaration": "BLOB CHECK(next_at IS NULL OR length(next_at)=16)", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "index_pattern": "local_work_summaries_deadline", "table_pattern": "local_work_summaries", "key_expression_and_predicate": "(next_at,key) WHERE next_at IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, - {"site": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_expiry_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), json_extract(body,'$.fields.expires_at_unix_ms'))", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, + {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_id_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "({RUNTIME_ID_FIELD}, subject, store_index) WHERE {ACTUAL_STATE_CLAIM} AND typeof({RUNTIME_ID_FIELD})='text'", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actual_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE {ACTUAL_STATE_CLAIM}", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_origin_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, origin, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='runtime.observed'", "value_size_proven": false}, @@ -2127,7 +2128,7 @@ {"id": "lv-hb73bd4f2f38c", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "700d14798fd37c5da5b5389e3903a51a34c8c957866a0dd94482dfcc246b196b", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 8862, "excerpt": "& canonical_sql ( \"SELECT json_extract(body, '$.fields.session_id') FROM claims WHERE subject=?1 AND kind='harness.session-file' AND json_extract(body, '$.fields.incarnation_id')=?2 AND json_extract(b"}, {"id": "lv-hb7b64cc10c51", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "7a41ee06927a48e907a8b303d67368f1f76113a73b7efcaf20c658e641deaac8", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1838, "excerpt": "params ! [ subject , at_index . unwrap_or ( i64 : : MAX as u64 ) ] , | row | row . get : : < _ , String > ( 0 ) ,"}, {"id": "lv-hb922e5825674", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "a521c5dad40bb69aa774c45feb4115e928e9636649863fd2f9284a6b6dd95c5c", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 15155, "excerpt": "DELETE FROM mission_runs WHERE id=?1"}, - {"id": "lv-hb9696ca837f7", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "0be5ad06badeb1870cc630ed6799adfebd3bffbdf2b2e4a85fb44b0a04b15ad6", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 783, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, + {"id": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "05c4b601885836e66c3fea007a185bdc60754cd8f0317128d594d4f14d6aefaa", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 783, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, {"id": "lv-hba4b0d735af8", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "68c5253450e4ab064ffddaaa91ab3fd123bd25dce5fca8c4f4b63ed02e14e26d", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 11818, "excerpt": "params ! [ subject , at_index ] , | row | { row . get : : < _ , String > ( 0 ) }"}, {"id": "lv-hba707764f720", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "746038271c3a30a5efca3979d788db5d87a588acb47362b3cb27a9a3d4c1d0ce", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 18333, "excerpt": "& canonical_sql ( \"SELECT kind, body, accepted_at_unix_ms FROM claims WHERE subject=?1 AND kind IN ('work.progress','work.submitted','step-run.carried') ORDER BY CANONICAL_DESC(claims)\" , )"}, {"id": "lv-hba80f02be5e7", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "f0cf159db9d7e30d00dd58f281267eb75687e6eaea2c416eddf5df095accc440", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 8212, "excerpt": "& canonical_sql ( \"SELECT body FROM claims WHERE subject=?1 AND kind='resource.observed' ORDER BY CANONICAL_DESC(claims)\" ) ,"}, diff --git a/docs/st3/large-values.md b/docs/st3/large-values.md index e9dc44959dc..12e42083776 100644 --- a/docs/st3/large-values.md +++ b/docs/st3/large-values.md @@ -478,11 +478,11 @@ Inline storage here proves neither encoded size nor execution-cost bounds. ## Assistant principal admission index review -`fractal_store::store` owns schema site `lv-hb9696ca837f7`, replacing -`lv-h22c8c670811c`. The added principal admission index retains claim-kind TEXT +`fractal_store::store` owns schema site `lv-h7e7937d8fad1`, replacing +`lv-hb9696ca837f7`. The principal admission indexes retain claim-kind TEXT and the effective principal JSON field inline; absent principals use the fixed -`assistant/chatgpt` key. The composite seek changes neither claim bodies nor -admission semantics. These keys remain variable-size, and SQLite maintains them +`assistant/chatgpt` key. The added expiry suffix supports live-grant range seeks. +These indexes change neither claim bodies nor admission semantics. Keys remain variable-size, and SQLite maintains them on insertion and deletion; indexed lookup is not a byte-size or startup-cost proof. The producer maintainer retains `chunk-or-reference-variable-columns` responsibility while preserving effective-principal matching and claim authority. diff --git a/docs/st3/principals-and-grants.md b/docs/st3/principals-and-grants.md index aca88e2504f..b72752ddc8a 100644 --- a/docs/st3/principals-and-grants.md +++ b/docs/st3/principals-and-grants.md @@ -144,9 +144,10 @@ ignored; the last valid policy (or original grant) stays in force. This applies local grants too: an unauthorized newer overlay no longer replaces their policy. The principal expression index prunes expired base grants without issuer policy candidates, and matching local revocations, before the authenticated Rust fold. -The SQL materializes matching-principal issuer-policy subjects once, gates -revocation checks behind expiry eligibility, and pins the existing subject/kind -revocation index. This avoids a correlated policy lookup per expired grant and a +The SQL unions indexed live-expiry ranges, legacy records, and matching-principal +issuer-policy subjects. The additive principal/expiry index avoids parsing expired +grant bodies on authentication; the original principal index remains in use for +policy candidates. Revocations use the existing subject/kind index, avoiding a quadratic principal-wide revocation plan as completion/revocation history grows. Foreign revocations and policy candidates reach Rust because SQL cannot verify signatures. The sealed membership fold has a separate generation-keyed cache: diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index ecfa30f5fc5..87a18b477d3 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -7,7 +7,7 @@ }, "schema": { "status": "changed", - "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409, plus inspect-only ?witness=1 opt-in conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients. No grant claim shape or storage migration changes." + "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409, plus inspect-only ?witness=1 opt-in conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients. Adds a principal/expiry expression index at store open without rewriting grant claims." }, "rules": { "status": "changed", @@ -19,7 +19,7 @@ }, "downtime": { "status": "changed", - "detail": "No migration downtime is required. Affected people cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend this interruption until revocations replicate. Unaffected people retain existing authentication behavior." + "detail": "No migration downtime is required, but the first store open builds the additive principal/expiry index over existing claims; its duration depends on retained history. Affected people cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend this interruption until revocations replicate. Unaffected people retain existing authentication behavior." }, "manual": { "status": "changed", From b2599521ce6da1c9372f038a8b9725e3b2ec2803 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 14:00:07 +0100 Subject: [PATCH 10/52] Accept covering expiry index for principal-only migration probe agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-store/src/store/runtime.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index 1a20a44be0c..f6cc02c6135 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -943,7 +943,8 @@ mod schema_install_tests { let current = plan(&connection, sql, active); eprintln!("assistant admission version={version} active={active} before={previous:?} after={current:?}"); assert!( - current.iter().any(|detail| detail.contains("SEARCH") && detail.contains(INDEX) + current.iter().any(|detail| detail.contains("SEARCH") + && (detail.contains(INDEX) || (!active && detail.contains(EXPIRY_INDEX))) && detail.contains("kind=?") && detail.contains("=?")), "version {version}: before={previous:?}; after={current:?}", ); From e62704f04e4ce2c8a9f62c75159575f704f9e2b0 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 19:55:34 +0100 Subject: [PATCH 11/52] Bound authoritative grant transitions and fence owner changes on the subject head Owner revoke, policy and read-trust changes keep the validated policy as authority but fence on the real subject head, so an ignored overlay cannot block revocation. Authentication, read trust and message send share one indexed SQL transition lookup instead of walking overlay history. The policy candidate arm only considers same-origin unexpired policies. Local grants get the same well-formedness check as foreign ones. Bearer and pairing conflict errors no longer carry witnesses. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- .../assistant/authorization_tests.rs | 63 +++++ .../api/client_v0/assistant/authorization.rs | 2 +- .../src/api/client_v0/external_grants.rs | 110 ++++---- .../external_grants/conflict_tests.rs | 84 +++++- crates/fractal-store/src/store.rs | 4 + .../src/store/assistant_write.rs | 204 +++++++++++++- .../tests/daemon_cost/assistant_admission.rs | 248 ++++++++++++++---- .../client-v0/schemas/client-v0.schema.json | 4 +- docs/st3/client-v0/schemas/operations.json | 2 +- docs/st3/principals-and-grants.md | 7 +- .../external-grant-profile-conflict.json | 2 +- 11 files changed, 622 insertions(+), 108 deletions(-) diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs index e75938f58f2..b29a73ab0b9 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs @@ -101,6 +101,69 @@ async fn request(app: Router, credential: &str, method: &str, path: &str, header (status,serde_json::from_slice(&bytes).unwrap(),bytes.len()) } +#[tokio::test] +async fn p1_owner_transitions_ignore_wrong_origin_overlays_but_fence_the_subject_head() { + for kind in [POLICY, REVOKED] { + let fixture = fixture(SCOPES, false).await; + let subject = subject(&fixture.grant).unwrap(); + let granted = latest(&fixture.state, &subject, GRANTED).unwrap().unwrap(); + let peer = Store::open_memory("wrong-origin").unwrap(); + let overlay = || { + let mut value = fields(&granted).unwrap().clone(); + if kind == POLICY { + value["policy_revision"] = json!(999); + value["expires_at_unix_ms"] = json!(1); + value["scopes"] = json!([]); + } + let claim = peer.append_claim(&ClaimInput { + subject: subject.clone(), kind: kind.into(), actor: Some(OWNER.into()), + fields: serde_json::from_value(value).unwrap(), evidence: Vec::new(), + expected_subject: None, idempotency_key: None, + }).unwrap(); + fixture.state.store.import_replication("wrong-origin", &peer.export_replication(0).unwrap()).unwrap(); + assert_eq!(latest(&fixture.state, &subject, kind).unwrap().unwrap().id, claim.id); + assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").unwrap().is_some()); + }; + + overlay(); + let policy = serde_json::from_value::(json!({ + "api_version": CLIENT_API_VERSION, "scopes": SCOPES, "expires_in_seconds": 86400, + "disclosure_consent": true, "consent_evidence": "recorded owner consent", + "minimal_read_mode": "approval-once", + })).unwrap(); + let Json(renewed) = update_policy(State(fixture.state.clone()), + Extension(ClientSession::local(Some(OWNER)).unwrap()), AxumPath(fixture.grant.clone()), + Json(policy)).await.unwrap(); + assert_eq!(renewed["policy_revision"], 2); + assert_eq!(renewed["revoked"], false); + let renewed_claim = effective(&fixture.state, &granted).unwrap(); + assert_eq!(renewed_claim.body["evidence"], json!([granted.id])); + + overlay(); + let Json(pinned) = pin(State(fixture.state.clone()), + Extension(ClientSession::local(Some(OWNER)).unwrap()), AxumPath(fixture.grant.clone()), + Json(fixture.trust_request())).await.unwrap(); + assert_eq!(pinned["policy_revision"], 3); + assert_eq!(pinned["read_trust"]["key_id"], "approval-key/test"); + let pinned_claim = effective(&fixture.state, &granted).unwrap(); + assert_eq!(pinned_claim.body["evidence"], json!([renewed_claim.id])); + + overlay(); + let Json(revoked) = revoke(State(fixture.state.clone()), + Extension(ClientSession::local(Some(OWNER)).unwrap()), + AxumPath(fixture.grant.clone())).await.unwrap(); + assert_eq!(revoked["revoked"], true); + let revocation = latest(&fixture.state, &subject, REVOKED).unwrap().unwrap(); + assert_eq!(revocation.origin, granted.origin); + assert_eq!(revocation.body["evidence"], json!([pinned_claim.id])); + assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").is_err()); + assert_eq!(fixture.request("/v1/client/assistant/summary", None).await.0, StatusCode::FORBIDDEN); + assert_eq!(pin(State(fixture.state.clone()), Extension(ClientSession::local(Some(OWNER)).unwrap()), + AxumPath(fixture.grant.clone()), Json(fixture.trust_request())).await.unwrap_err().status, + StatusCode::FORBIDDEN); + } +} + #[tokio::test] async fn scg_read_accepts_header_aliases_and_binds_presented_domain() { let fixture = fixture(SCOPES, true).await; diff --git a/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs b/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs index 805097b453f..5bedafdc672 100644 --- a/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs +++ b/crates/fractal-api-core/src/api/client_v0/assistant/authorization.rs @@ -122,7 +122,7 @@ pub async fn pin(State(state): State, Extension(session): Extension?5 AND COALESCE(json_extract(granted.body,'$.fields.principal'),'assistant/chatgpt')=?2) SELECT claims.id FROM eligible JOIN claims ON claims.id=eligible.id WHERE ?5 IS NULL OR claims.origin<>?6 OR NOT EXISTS ( - SELECT 1 FROM claims AS revoked INDEXED BY claims_subject_kind_accepted_index + SELECT 1 FROM claims AS revoked INDEXED BY claims_assistant_v1_transition_index WHERE revoked.subject=claims.subject AND revoked.kind=?3 AND revoked.origin=claims.origin AND revoked.actor=claims.actor AND json_extract(revoked.body,'$.fields.issuer')=revoked.actor @@ -122,6 +123,10 @@ fn admission_now_ms() -> u128 { client_now_ms() } fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) -> Result, ApiError> { + candidate_grants_except(state, principal, expiry_cut, None) +} + +fn candidate_grants_except(state: &AppState, principal: &str, expiry_cut: Option, excluded: Option<&str>) -> Result, ApiError> { let owner = owning_person(state)?; let ids = { let connection = state.store.readers.get(); @@ -131,6 +136,7 @@ fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) }; let mut active = Vec::new(); for id in ids { + if excluded == Some(id.as_str()) { continue; } let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? .ok_or_else(|| forbidden("external grant is absent"))?; if grant.actor.as_deref() != Some(owner) @@ -143,8 +149,8 @@ fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) // alone therefore confer no authority to suspend another credential. // Only well-formed owner grants carried by a signed, admitted issuer // count; policies must have the same provenance and immutable identity. - if foreign && (!valid_foreign_grant(state, &grant, &policy)? - || !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)?) { + if !valid_foreign_grant(state, &grant, &policy)? + || (foreign && !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)?) { continue; } let source = fields(&policy)?; @@ -195,12 +201,12 @@ fn witness(grant: &ClaimRecord, profile: Profile) -> Value { "origin":grant.origin,"profile":match profile { Profile::Assistant => "assistant", Profile::Service => "service" }}) } -fn conflict_error(witness: Value) -> ApiError { +fn conflict_error() -> ApiError { ApiError { status: StatusCode::CONFLICT, code: "grant-profile-conflict".into(), message: "principal has active grants of opposite profiles; revoke one to clear the conflict".into(), - details: Box::new(serde_json::Map::from_iter([("conflict".into(), witness)])), + details: Box::default(), } } @@ -220,12 +226,9 @@ fn profile_conflict_at(state: &AppState, granted: &ClaimRecord, now: u64) -> Res fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { let profile = Profile::stored(source)?; - for (grant, other) in candidate_grants(state, principal(source)?, Some(admission_now_ms() as u64))? { + for (_, other) in candidate_grants(state, principal(source)?, Some(admission_now_ms() as u64))? { if profile != other { - return Err(conflict_error(json!({"grants":[ - {"grant_id":source["grant_id"],"origin":state.store.origin(), - "profile":match profile { Profile::Assistant => "assistant", Profile::Service => "service" }}, - witness(&grant, other)]}))); + return Err(conflict_error()); } } Ok(()) @@ -299,11 +302,17 @@ pub fn append(state: &AppState, subject: String, kind: &str, actor: &str, admit_profile(state, &value)?; } } + // Authority/evidence uses the validated policy; fencing uses the real head. + let expected_subject = if matches!(kind, POLICY | REVOKED) { + state.store.latest_claim(&subject, None).map_err(ApiError::internal)?.map(|claim| claim.id) + } else { + previous.map(|claim| claim.id.clone()) + }; state.store.append_claim(&ClaimInput { subject, kind: kind.into(), actor: Some(actor.into()), fields: serde_json::from_value(value).map_err(ApiError::internal)?, evidence: previous.map(|claim| vec![claim.id.clone()]).unwrap_or_default(), - expected_subject: Some(previous.map(|claim| claim.id.clone())), + expected_subject: Some(expected_subject), idempotency_key: None, }).map_err(ApiError::bad) } @@ -336,35 +345,19 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, Ok(()) } -// Ignore unauthoritative overlays, including a newer malformed policy. Walk -// backwards to the last valid issuer transition rather than dropping the grant. +// SQL seeks directly to the latest authoritative transition. Overlay histories +// never reach Rust or increase the number of store reads per authentication. fn transition(state: &AppState, granted: &ClaimRecord, kind: &str) -> Result, ApiError> { - let mut before = None; - loop { - let page = state.store.claims_for_subject_kind_at(&granted.subject, kind, before, true, 32) - .map_err(ApiError::internal)?; - for candidate in page.claims { - if candidate.origin != granted.origin || candidate.actor.as_deref() != Some(owning_person(state)?) { - continue; - } - let (Ok(original), Ok(source)) = (fields(granted), fields(&candidate)) else { continue }; - let consistent = principal(source).ok().zip(principal(original).ok()).is_some_and(|(a, b)| a == b) - && Profile::stored(source).ok().zip(Profile::stored(original).ok()).is_some_and(|(a, b)| a == b) - && ["grant_id", "issuer"].iter().all(|key| source[*key] == original[*key]); - if !consistent || source["issuer"] != owning_person(state)? { continue; } - if kind == POLICY && (!valid_foreign_grant(state, granted, &candidate)? - || source["expires_at_unix_ms"].as_u64().is_none()) { - continue; - } - if granted.origin != state.store.origin() - && !state.store.claim_has_authenticated_member_writer(&candidate.id).map_err(ApiError::internal)? { - continue; - } - return Ok(Some(candidate)); + let candidate = crate::store::assistant_write::validated_transition( + &state.store.readers.get(), granted, owning_person(state)?, state.store.origin(), kind, + ).map_err(ApiError::internal)?; + if let Some(candidate) = &candidate { + if granted.origin != state.store.origin() + && !state.store.claim_has_authenticated_member_writer(&candidate.id).map_err(ApiError::internal)? { + return Ok(None); } - let Some(cursor) = page.next_cursor else { return Ok(None) }; - before = Some(cursor); } + Ok(candidate) } pub fn revoked(state: &AppState, granted: &ClaimRecord) -> Result { @@ -428,10 +421,18 @@ pub fn authenticate(state: &AppState, digest: &str, transport: &'static str) pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) -> Result { let now = client_now_ms() as u64; - if let Some(witness) = profile_conflict_at(state, granted, now)? { - return Err(conflict_error(witness)); - } let policy = effective(state, granted)?; + let is_revoked = revoked(state, granted)?; + if !is_revoked && unexpired(fields(&policy)?, now) + && valid_foreign_grant(state, granted, &policy)? + && (granted.origin == state.store.origin() + || state.store.claim_has_authenticated_member_writer(&granted.id).map_err(ApiError::internal)?) { + let profile = Profile::stored(fields(granted)?)?; + if candidate_grants_except(state, principal(fields(granted)?)?, Some(now), Some(&granted.id))? + .iter().any(|(_, other)| *other != profile) { + return Err(conflict_error()); + } + } let source = fields(&policy)?; let principal = principal(source)?; let granted_fields = fields(granted)?; @@ -447,7 +448,7 @@ pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) || granted.actor.as_deref() != Some(owning_person(state)?) || policy.actor.as_deref() != Some(owning_person(state)?) { return Err(forbidden("assistant requests require the authoritative grant issuer")); } - if revoked(state, granted)? + if is_revoked || !unexpired(source, now) || source["issuer"] != owning_person(state)? || !matches!(source["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) || source["disclosure_consent"] != true { @@ -553,11 +554,12 @@ mod tests { continue; } let policy = effective(state, &grant)?; + if !valid_foreign_grant(state, &grant, &policy)? { continue; } let active = fields(&policy)?; if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > admission_now_ms() { Profile::stored(fields(&grant)?)?.compatible(Profile::stored(active)?)?; if profile != Profile::stored(active)? { - return Err(conflict_error(Value::Null)); + return Err(conflict_error()); } } } @@ -582,9 +584,12 @@ mod tests { ("revoke-of-revoke", json!({"expires_at_unix_ms":101}), vec![], 2, false, false), ("several-policies-live", json!({"expires_at_unix_ms":99}), vec![102, 98, 101], 0, false, true), ("several-policies-expired", json!({"expires_at_unix_ms":101}), vec![99, 102, 100], 0, false, false), + ("renewed-expired-base", json!({"expires_at_unix_ms":99}), vec![98, 100, 102], 0, false, true), + ("shortened-long-policy", json!({"expires_at_unix_ms":99}), vec![1000, 99], 0, false, false), + ("wrong-origin-future-policy", json!({"expires_at_unix_ms":99}), vec![98, 99], 0, false, false), ("unrelated-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, false), ("legacy-default-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), - ("null-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), + ("null-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, false), ("mcp-principal", json!({"expires_at_unix_ms":101}), vec![], 0, false, true), ]; for (name, mut source, policies, revokes, replicated, denied) in cases { @@ -620,6 +625,13 @@ mod tests { policy["expires_at_unix_ms"] = json!(expiry); previous = append_fixture(&state.store, POLICY, policy, Some(&previous)); } + if name == "wrong-origin-future-policy" { + let peer = Store::open_memory("overlay").unwrap(); + let mut forged = source.clone(); + forged["expires_at_unix_ms"] = json!(u64::MAX); + append_fixture(&peer, POLICY, forged, None); + state.store.import_replication("overlay", &peer.export_replication(0).unwrap()).unwrap(); + } if replicated { let peer = Store::open_memory("peer").unwrap(); let revoke = append_fixture(&peer, REVOKED, source.clone(), None); @@ -657,7 +669,8 @@ mod tests { "CREATE TABLE claims(id TEXT,subject TEXT,kind TEXT,body TEXT,origin TEXT DEFAULT 'local',actor TEXT DEFAULT 'person/owner',store_index INTEGER PRIMARY KEY); CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms')); - CREATE INDEX claims_subject_kind_accepted_index ON claims(subject,kind,store_index);" + CREATE INDEX claims_subject_kind_accepted_index ON claims(subject,kind,store_index); + CREATE INDEX claims_assistant_v1_transition_index ON claims(subject,kind,origin,actor,store_index);" ).unwrap(); let fixtures = [ ("expired", json!({"fields":{"expires_at_unix_ms":99}}), None, false), @@ -675,7 +688,7 @@ mod tests { ("shortened", json!({"fields":{"expires_at_unix_ms":101}}), Some(json!({"fields":{"expires_at_unix_ms":99}})), true), ("invalid-policy", json!({"fields":{"expires_at_unix_ms":99}}), - Some(json!({})), true), + Some(json!({})), false), ]; let mut expected = Vec::new(); for (id, grant, policy, included) in fixtures { @@ -723,6 +736,11 @@ mod tests { let service_subject = subject("333333333333333333333333").unwrap(); let mut service = source.clone(); service["profile"] = json!("service"); + service["grant_id"] = json!("333333333333333333333333"); + service["session_actor"] = json!(format!("{PRINCIPAL}/session/333333333333333333333333")); + service["minimal_read_mode"] = json!("approval-once"); + service["disclosure_consent"] = json!(true); + service["scopes"] = json!([]); // Simulate an existing profile record without enabling service issuance. let grant = state.store.append_claim(&ClaimInput { subject: service_subject.clone(), kind: GRANTED.into(), actor: Some("person/owner".into()), diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 409ad44979b..267086faa1f 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -93,6 +93,7 @@ fn assert_conflict(error: &ApiError) { let typed: ErrorCode = serde_json::from_value(json!(error.code)).unwrap(); assert_eq!(typed, ErrorCode::GrantProfileConflict); assert_eq!(error.status, StatusCode::CONFLICT); + assert!(error.details.is_empty(), "bearer errors must not expose owner witnesses"); } fn assert_witness(value: &Value) { @@ -122,7 +123,6 @@ fn disconnected_opposite_profiles_conflict_on_both_members_and_revocation_recove let error = authenticate_id(state, fields(grant).unwrap()["grant_id"].as_str().unwrap()) .err().expect("both credentials must be suspended on either member"); assert_conflict(&error); - assert_witness(&Value::Object((*error.details).clone())["conflict"]); assert_witness(&profile_conflict(state, grant).unwrap().unwrap()); assert_witness(&projection_with_witness(state, grant).unwrap()["conflict"]); } @@ -227,10 +227,27 @@ fn admission_refuses_a_known_authenticated_foreign_opposite_profile() { replicate(&b, &a); let error = issue(&a, ASSISTANT_ID, "assistant").err().unwrap(); assert_conflict(&error); - assert_witness(&Value::Object((*error.details).clone())["conflict"]); assert!(latest(&a, &subject(ASSISTANT_ID).unwrap(), GRANTED).unwrap().is_none()); } +#[test] +fn malformed_local_owner_actor_grants_cannot_suspend_a_local_credential() { + let root = tempfile::tempdir().unwrap(); + for invalid in ["profile", "grant_id", "principal", "issuer", "session_actor", + "minimal_read_mode", "disclosure_consent", "scopes", "credential_hash"] { + let state = member(root.path(), "alder"); + let local = issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let mut source = grant_fields(SERVICE_ID, "service"); + source[invalid] = Value::Null; + let malformed = raw_claim(&state, &subject(SERVICE_ID).unwrap(), GRANTED, OWNER, source); + assert_eq!(malformed.origin, local.origin); + assert_eq!(malformed.actor.as_deref(), Some(OWNER)); + assert!(profile_conflict(&state, &local).unwrap().is_none(), "{invalid}"); + assert!(authenticate_id(&state, ASSISTANT_ID).unwrap().is_some(), "{invalid}"); + assert!(projection_with_witness(&state, &local).unwrap()["conflict"].is_null(), "{invalid}"); + } +} + #[test] fn malformed_authenticated_foreign_grants_cannot_suspend_a_local_credential() { let root = tempfile::tempdir().unwrap(); @@ -388,9 +405,68 @@ fn admission_scan_uses_the_real_principal_index() { println!("external grant admission query plan:\n{}", plan.join("\n")); assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_index")), "principal admission must use its production index: {plan:?}"); - assert!(plan.iter().any(|step| step.contains("revoked USING INDEX claims_subject_kind_accepted_index")), - "revocation must seek by subject rather than scan the principal: {plan:?}"); + assert!(plan.iter().any(|step| step.contains("revoked USING INDEX claims_assistant_v1_transition_index")), + "revocation must seek by subject, kind, origin and actor rather than scan overlays: {plan:?}"); assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_expiry_index") && step.contains(">?")), "expired grant bodies must be pruned by an index range: {plan:?}"); } + +#[test] +fn p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history() { + // Profiling is process-global, so isolate it using the profiler's own + // subprocess convention instead of mutating parallel tests' environment. + const CHILD: &str = "FRACTAL_POLICY_CANDIDATE_PROFILE_CHILD"; + if std::env::var_os(CHILD).is_none() { + let directory = tempfile::tempdir().unwrap(); + let status = std::process::Command::new(std::env::current_exe().unwrap()) + .args(["--exact", + "api::client_v0::external_grants::conflict_tests::p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history", + "--nocapture"]) + .env(CHILD, "1") + .env("ST3_PROFILE_DIR", directory.path()) + .env("ST3_PROFILE_SLOW_MS", "0") + .status().unwrap(); + assert!(status.success(), "isolated policy candidate regression failed"); + let log = std::fs::read_to_string(directory.path().join("slow.jsonl")).unwrap(); + let rows = log.lines().map(|line| serde_json::from_str::(line).unwrap()) + .collect::>(); + let acquisitions = |label: &str| rows.iter().find(|row| row["label"] == label) + .unwrap()["read_acquisitions"].as_u64().unwrap(); + let before = acquisitions("p1-policy-candidates-before"); + let after = acquisitions("p1-policy-candidates-after"); + assert!(before > 0, "the measured scan must acquire real read connections"); + assert_eq!(after, before, "expired policy history and wrong-origin renewals must be pruned before per-grant reads"); + return; + } + smallclaims::profile::init_from_env(); + let root = tempfile::tempdir().unwrap(); + let a = member(root.path(), "alder"); + let b = member(root.path(), "birch"); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let measure = |label: &'static str| { + let operation = smallclaims::profile::Op::start(label, None).unwrap(); + { + let _entered = operation.enter(); + let candidates = candidate_grants(&a, PRINCIPAL, Some(100)).unwrap(); + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].0.id, local.id); + } + operation.finish(); + }; + measure("p1-policy-candidates-before"); + for index in 0..128 { + let id = format!("{:024x}", index + 1000); + let subject = subject(&id).unwrap(); + let mut expired = grant_fields(&id, "service"); + expired["expires_at_unix_ms"] = json!(1); + raw_claim(&a, &subject, GRANTED, OWNER, expired.clone()); + raw_claim(&a, &subject, POLICY, OWNER, expired.clone()); + // A future policy from another origin must not pull this expired + // issuer grant back into the per-candidate Rust authority fold. + expired["expires_at_unix_ms"] = json!(u64::MAX); + raw_claim(&b, &subject, POLICY, OWNER, expired); + } + replicate(&b, &a); + measure("p1-policy-candidates-after"); +} diff --git a/crates/fractal-store/src/store.rs b/crates/fractal-store/src/store.rs index 12d8debc6cc..0cfb418a9fe 100644 --- a/crates/fractal-store/src/store.rs +++ b/crates/fractal-store/src/store.rs @@ -942,6 +942,10 @@ ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chat CREATE INDEX IF NOT EXISTS claims_assistant_v1_principal_expiry_index ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), json_extract(body,'$.fields.expires_at_unix_ms')); +-- Installed on reopen as well as creation: unauthoritative actor/origin overlays +-- must not increase the cost of selecting an issuer's latest valid transition. +CREATE INDEX IF NOT EXISTS claims_assistant_v1_transition_index +ON claims(subject, kind, origin, actor, store_index); -- A runtime incarnation's claims about a subject by acceptance time, so when a session began -- and last changed are two seeks instead of a read of every claim the subject has. The -- expression is INCARNATION_OF_CLAIM, which queries repeat so the planner uses this index. diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 7c5691e3a06..aad51c4a120 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -24,6 +24,89 @@ pub fn principal(fields: &Value) -> Option<&str> { } } +/// Select the last authoritative transition, not the last arbitrary claim overlay. +/// Foreign results still require cryptographic member-writer verification by the +/// caller; the SQL provenance predicate excludes legacy and unsigned records. +pub fn validated_transition( + connection: &Connection, granted: &ClaimRecord, owner: &str, local_origin: &str, kind: &str, +) -> Result, FractalError> { + connection.query_row( + validated_transition_query(), + params![granted.subject, kind, granted.origin, owner, granted.id, local_origin], + claim_from_row, + ).optional().map_err(internal) +} + +/// The origin/actor prefix bounds work independently of unauthoritative overlays. +/// All field checks precede LIMIT, so malformed newer policies cannot hide a +/// previous valid transition. Ordering intentionally matches subject history. +pub fn validated_transition_query() -> &'static str { + static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| format!( + "WITH original AS (SELECT body FROM claims WHERE id=?5) SELECT {CLAIM_COLUMNS} + FROM claims INDEXED BY claims_assistant_v1_transition_index + WHERE claims.subject=?1 AND claims.kind=?2 AND claims.origin=?3 AND claims.actor=?4 + AND ?2 IN ('custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') + AND json_type(body,'$.fields')='object' + AND json_extract(body,'$.fields.issuer')=?4 + AND json_extract(body,'$.fields.grant_id')=json_extract((SELECT body FROM original),'$.fields.grant_id') + AND json_extract(body,'$.fields.issuer')=json_extract((SELECT body FROM original),'$.fields.issuer') + AND (json_type(body,'$.fields.principal') IS NULL + OR json_extract(body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) + AND (json_type((SELECT body FROM original),'$.fields.principal') IS NULL + OR json_extract((SELECT body FROM original),'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) + AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt') + =COALESCE(json_extract((SELECT body FROM original),'$.fields.principal'),'assistant/chatgpt') + AND (json_type(body,'$.fields.profile') IS NULL OR json_extract(body,'$.fields.profile') IN ('assistant','service')) + AND (json_type((SELECT body FROM original),'$.fields.profile') IS NULL OR json_extract((SELECT body FROM original),'$.fields.profile') IN ('assistant','service')) + AND COALESCE(json_extract(body,'$.fields.profile'),'assistant') + =COALESCE(json_extract((SELECT body FROM original),'$.fields.profile'),'assistant') + AND (?2='custom.client.assistant.v1.revoked' OR ( + json_extract(body,'$.fields.session_actor')=json_extract((SELECT body FROM original),'$.fields.session_actor') + AND json_extract(body,'$.fields.profile') IS json_extract((SELECT body FROM original),'$.fields.profile') + AND json_extract(body,'$.fields.session_actor') + =COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt') || '/session/' || json_extract(body,'$.fields.grant_id') + AND ((length(json_extract(body,'$.fields.grant_id'))=24 + AND json_extract(body,'$.fields.grant_id') NOT GLOB '*[^0-9a-fA-F]*' + AND claims.subject='custom/client/assistant-v1-' || json_extract(body,'$.fields.grant_id')) + OR (length(json_extract(body,'$.fields.grant_id'))=40 + AND substr(json_extract(body,'$.fields.grant_id'),1,16)='assistant-grant/' + AND substr(json_extract(body,'$.fields.grant_id'),17) NOT GLOB '*[^0-9a-fA-F]*' + AND claims.subject='custom/client/assistant-v1-' || substr(json_extract(body,'$.fields.grant_id'),17))) + AND json_extract(body,'$.fields.minimal_read_mode') IN ('approval-once','caller-bound-allow') + AND json_type(body,'$.fields.disclosure_consent')='true' + AND json_type(body,'$.fields.expires_at_unix_ms') IN ('integer','real') + AND (body -> '$.fields.expires_at_unix_ms') NOT GLOB '*[^0-9]*' + AND (length(body -> '$.fields.expires_at_unix_ms')<20 + OR (length(body -> '$.fields.expires_at_unix_ms')=20 + AND (body -> '$.fields.expires_at_unix_ms')<='18446744073709551615')) + AND json_type(body,'$.fields.scopes')='array' + AND NOT EXISTS (SELECT 1 FROM json_each(body,'$.fields.scopes') AS scope + WHERE scope.type<>'text' OR scope.value NOT IN ( + 'read.assistant.summary','read.assistant.attention','read.assistant.missions', + 'read.assistant.agents','read.assistant.conversation','read.assistant.terminal', + 'write.assistant.messages','write.assistant.custom-reply','write.assistant.answers')) + AND json_type(body,'$.fields.credential') IS NULL AND json_type(body,'$.fields.code') IS NULL + AND json_type((SELECT body FROM original),'$.fields.credential') IS NULL AND json_type((SELECT body FROM original),'$.fields.code') IS NULL + AND json_type((SELECT body FROM original),'$.fields.credential_hash')='text' + AND length(json_extract((SELECT body FROM original),'$.fields.credential_hash'))=64 + AND json_extract((SELECT body FROM original),'$.fields.credential_hash') NOT GLOB '*[^0-9a-fA-F]*' + AND NOT EXISTS (SELECT 1 FROM json_each(body,'$.fields') AS digest + WHERE digest.key IN ('credential_hash','code_hash') + AND (digest.type<>'text' OR length(digest.value)<>64 OR digest.value GLOB '*[^0-9a-fA-F]*')) + AND NOT EXISTS (SELECT 1 FROM json_each((SELECT body FROM original),'$.fields') AS digest + WHERE digest.key IN ('credential_hash','code_hash') + AND (digest.type<>'text' OR length(digest.value)<>64 OR digest.value GLOB '*[^0-9a-fA-F]*')) + )) + AND (?3=?6 OR EXISTS ( + SELECT 1 FROM replica_records AS records + JOIN replica_envelopes AS envelopes USING(writer,sequence,envelope_hash) + JOIN replica_envelope_signatures AS signatures USING(writer,sequence,envelope_hash) + WHERE records.claim_id=claims.id AND records.writer=claims.origin + AND records.state='valid' AND envelopes.receipt_state IN ('validated','degraded'))) + ORDER BY claims.store_index DESC LIMIT 1")); + QUERY.as_str() +} + pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let granted = authorized_grant(connection, origin, authorization)?; granted.body["fields"]["grant_id"].as_str().filter(|id| id.starts_with("assistant-grant/") && id.len() > "assistant-grant/".len()) @@ -37,9 +120,10 @@ pub fn authorized_grant(connection: &Connection, origin: &str, authorization: &A params![authorization.grant_subject,kind],claim_from_row).optional().map_err(internal) }; let granted = claim("custom.client.assistant.v1.granted")?.ok_or_else(denied)?; - let policy_claim = claim("custom.client.assistant.v1.policy")?; + let policy_claim = validated_transition(connection, &granted, &authorization.owner, origin, "custom.client.assistant.v1.policy")?; let policy = policy_claim.as_ref().unwrap_or(&granted); - if granted.origin != origin || policy.origin != origin || claim("custom.client.assistant.v1.revoked")?.is_some() { + if granted.origin != origin || policy.origin != origin + || validated_transition(connection, &granted, &authorization.owner, origin, "custom.client.assistant.v1.revoked")?.is_some() { return Err(denied()); } let fields = &policy.body["fields"]; @@ -103,6 +187,122 @@ pub fn validate_replicated(kind: &str, actor: Option<&str>, fields: &Value) -> R mod tests { use super::*; + fn transition_fixture() -> (Connection, String, Value) { + let connection = Connection::open_in_memory().unwrap(); + connection.execute_batch(smallclaims::store::SCHEMA).unwrap(); + connection.execute_batch(SCHEMA).unwrap(); + connection.execute("INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES('batch','local',1,'hash','1')", []).unwrap(); + let suffix = "0123456789abcdef01234567"; + let subject = format!("custom/client/assistant-v1-{suffix}"); + let body = json!({"fields":{ + "grant_id":format!("assistant-grant/{suffix}"), "issuer":"person/owner", + "session_actor":format!("assistant/chatgpt/session/assistant-grant/{suffix}"), + "credential_hash":"a".repeat(64), "minimal_read_mode":"approval-once", + "disclosure_consent":true, "scopes":["write.assistant.messages"], + "expires_at_unix_ms":u64::MAX + }}); + insert_transition(&connection, &subject, "original", "custom.client.assistant.v1.granted", "local", "person/owner", &body); + (connection, subject, body) + } + + fn insert_transition(connection: &Connection, subject: &str, id: &str, kind: &str, origin: &str, actor: &str, body: &Value) { + connection.execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,'batch',?2,?3,?4,?5,?6,'[]','1')", + params![id,subject,kind,origin,actor,body.to_string()], + ).unwrap(); + } + + #[test] + fn validated_transition_index_is_installed_for_existing_stores() { + let (connection, _, _) = transition_fixture(); + connection.execute_batch("DROP INDEX claims_assistant_v1_transition_index").unwrap(); + connection.execute_batch(SCHEMA).unwrap(); + let definition: String = connection.query_row( + "SELECT sql FROM sqlite_master WHERE name='claims_assistant_v1_transition_index'", + [], |row| row.get(0), + ).unwrap(); + assert!(definition.contains("(subject, kind, origin, actor, store_index)")); + connection.execute_batch(SCHEMA).unwrap(); + } + + #[test] + fn validated_transition_p1_indexed_seek_is_independent_of_wrong_origin_actor_overlays() { + let (connection, subject, body) = transition_fixture(); + let kind = "custom.client.assistant.v1.policy"; + insert_transition(&connection, &subject, "valid", kind, "local", "person/owner", &body); + let query = validated_transition_query(); + let original = "original"; + let mut prior = None; + for count in [32, 512, 7900] { + for index in 0..count { + insert_transition(&connection, &subject, &format!("overlay-{count}-{index}"), kind, + if index % 2 == 0 { "other" } else { "local" }, + if index % 2 == 0 { "person/owner" } else { "person/other" }, &body); + } + let args = params![subject,kind,"local","person/owner",original,"local"]; + let mut statement = connection.prepare(query).unwrap(); + assert_eq!(statement.query_row(args, |row| row.get::<_, String>(0)).unwrap(), "valid"); + let cost = statement.get_status(rusqlite::StatementStatus::VmStep); + if let Some(prior) = prior { assert!(cost <= prior + 20, "{prior} -> {cost}"); } + prior = Some(cost); + let plan = connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")).unwrap() + .query_map(args, |row| row.get::<_, String>(3)).unwrap() + .collect::>>().unwrap().join("; "); + assert!(plan.contains("claims_assistant_v1_transition_index (subject=? AND kind=? AND origin=? AND actor=?)"), "{plan}"); + assert!(!plan.contains("USE TEMP B-TREE FOR ORDER BY"), "{plan}"); + } + } + + #[test] + fn validated_transition_ignores_malformed_newer_policies_and_revocations() { + let (connection, subject, body) = transition_fixture(); + for kind in ["custom.client.assistant.v1.policy", "custom.client.assistant.v1.revoked"] { + let valid = format!("valid-{kind}"); + insert_transition(&connection, &subject, &valid, kind, "local", "person/owner", &body); + let mut patches = vec![ + json!({"principal":null}), json!({"principal":"assistant/mcp"}), + json!({"profile":null}), json!({"profile":"service"}), + json!({"issuer":"person/other"}), json!({"grant_id":"assistant-grant/other"}), + ]; + if kind.ends_with(".policy") { + patches.extend([ + json!({"session_actor":"assistant/chatgpt/session/other"}), + json!({"minimal_read_mode":"unknown"}), json!({"disclosure_consent":false}), + json!({"expires_at_unix_ms":null}), json!({"expires_at_unix_ms":-1}), + json!({"expires_at_unix_ms":1.5}), json!({"scopes":["unknown"]}), + json!({"expires_at_unix_ms":1e19}), + json!({"scopes":[null]}), json!({"credential":"secret"}), + json!({"credential_hash":"invalid"}), json!({"code_hash":null}), + ]); + } + for (index, patch) in patches.into_iter().enumerate() { + let mut malformed = body.clone(); + malformed["fields"].as_object_mut().unwrap().extend(patch.as_object().unwrap().clone()); + insert_transition(&connection, &subject, &format!("malformed-{kind}-{index}"), kind, "local", "person/owner", &malformed); + } + let selected = connection.query_row(validated_transition_query(), + params![subject,kind,"local","person/owner","original","local"], + |row| row.get::<_, String>(0)).unwrap(); + assert_eq!(selected, valid); + } + } + + #[test] + fn validated_transition_accepts_raw_hex_grant_identity() { + let (connection, subject, mut body) = transition_fixture(); + let suffix = "0123456789abcdef01234567"; + body["fields"]["grant_id"] = json!(suffix); + body["fields"]["session_actor"] = json!(format!("assistant/chatgpt/session/{suffix}")); + connection.execute("UPDATE claims SET body=?1 WHERE id='original'", [body.to_string()]).unwrap(); + let kind = "custom.client.assistant.v1.policy"; + insert_transition(&connection, &subject, "raw-policy", kind, "local", "person/owner", &body); + let selected = connection.query_row(validated_transition_query(), + params![subject,kind,"local","person/owner","original","local"], + |row| row.get::<_, String>(0)).unwrap(); + assert_eq!(selected, "raw-policy"); + } + #[test] fn grant_principal_defaults_only_absent_legacy_fields_to_chatgpt() { assert_eq!(principal(&json!({})), Some("assistant/chatgpt")); diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index dbf64be1efa..d43fdc1d18c 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -1,19 +1,40 @@ //! Opt-in, real HTTP/Unix daemon measurement (not a router oneshot or mocked daemon). -//! Run this same test source on the named revisions, sequentially on the same host: +//! Run this same test source on both revisions, sequentially on the same host, from each +//! worktree root (cargo runs tests from crates/fractal, so pass absolute paths): //! ```sh -//! ST_ADMISSION_VARIANT=baseline cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 -//! ST_ADMISSION_VARIANT=indexed cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 +//! # fixed head: full q39 scenario plus read counts +//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/fixed-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=indexed ST_ADMISSION_FOREIGN_ACTIVE=3 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/fixed.json" CARGO_TARGET_DIR="$PWD/tmp/867-admission/target" cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 +//! # origin/main: read counts only, without overlays its admission does not ignore +//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/main-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=baseline ST_ADMISSION_READ_COUNTS_ONLY=1 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/main.json" CARGO_TARGET_DIR="$PWD/tmp/867-admission/target" cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 //! ``` -//! Copy only this file and its `mod assistant_admission;` registration to the A worktree. -//! The baseline must actually be built from 98e550cb: dropping an index on PR3-B does not -//! restore A's admission query. Use distinct CARGO_TARGET_DIR paths for the two worktrees: -//! Cargo freshness can otherwise reuse the baseline's artifacts for the indexed checkout. +//! For a like-for-like count, also run the fixed head with the origin/main command's +//! ST_ADMISSION_READ_COUNTS_ONLY=1 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 settings +//! (VARIANT=indexed there). Each revision has its own worktree, hence its own tmp/. +//! Backport to origin/main (d477c67ad1), which lacks this file and three head APIs: +//! 1. copy this file to crates/fractal/tests/daemon_cost/assistant_admission.rs and add +//! `mod assistant_admission;` to crates/fractal/tests/daemon_cost.rs; +//! 2. replace the body of `mod revision_api` at the end of this file with the +//! origin/main body documented in its comment. Nothing else changes. +//! On origin/main, only ST_ADMISSION_READ_COUNTS_ONLY=1, ST_ADMISSION_FOREIGN_ACTIVE=0 and +//! ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 are valid: it has no provenance check and does +//! not ignore wrong-origin overlays, and its credential-hash admission has no index probe. //! ST_ADMISSION_HISTORY (default 10000) is expired grants PER principal; ST_ADMISSION_SAMPLES //! (default 200) is measured GET/completion pairs PER read mode. Setup and proof creation are //! outside timing. Each pair starts behind a barrier, with no sleeps, polling, retries or timers. //! ST_ADMISSION_FOREIGN_ACTIVE optionally adds verified same-profile active foreign grants //! (default 0; use 3 for the provenance-check scenario). ST_ADMISSION_REPORT optionally //! saves the complete JSON report. Hardware is observed from uname/lscpu, not inferred. +//! Each expired grant has three still-expired POLICY renewals. Each active session has +//! ST_ADMISSION_WRONG_ORIGIN_OVERLAYS (default 1000; 0 allowed) authenticated wrong-origin +//! overlays, alternating POLICY and REVOKED; every measured read must still succeed. +//! ST_ADMISSION_READ_COUNTS_ONLY=1 measures only read counts: it skips the index probe, +//! candidate SQL, latency pairs, the q39 gate and the release-build requirement. +//! Read counts require a fresh ST3_PROFILE_DIR and ST3_PROFILE_SLOW_MS=0. The existing +//! profile `read_acquisitions` counts pooled read-connection/snapshot acquisitions per +//! operation (not SQL rows), for direct authentication and one standalone GET per mode. +//! SQL work uses existing smallclaims sqlite::work trace counters (statements/VM steps). +//! Authentication work is thread-scoped; standalone GET work is process-global through the +//! receipt flush and can include background daemon SQL. No production code changes. //! The index DDL timing is a synthetic startup migration probe on the populated disposable //! real store, not total daemon startup or cold-disk startup. Latencies use the real daemon's //! bound sockets, bearer middleware, grant lookup, projection and durable approval consumption. @@ -31,10 +52,13 @@ use tokio::sync::Barrier; const OWNER: &str = "person/bench-operator"; const NODE: &str = "benchmark-member"; const GRANTED: &str = "custom.client.assistant.v1.granted"; +const POLICY: &str = "custom.client.assistant.v1.policy"; +const REVOKED: &str = "custom.client.assistant.v1.revoked"; +const POLICY_RENEWALS: usize = 3; const INDEX: &str = "claims_assistant_v1_principal_expiry_index"; const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms'))"; const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; -const INDEXED_QUERY: &str = api::client_v0::external_grants::admission_query_for_test(); +const INDEXED_QUERY: &str = revision_api::ADMISSION_QUERY; const PATH: &str = "/v1/client/assistant/summary"; fn number(name: &str, default: usize) -> usize { @@ -43,6 +67,10 @@ fn number(name: &str, default: usize) -> usize { value } +fn count(name: &str, default: usize) -> usize { + std::env::var(name).map_or(default, |s| s.parse().expect("nonnegative integer setting")) +} + fn value(response: Value) -> Value { response.get("value").cloned().unwrap_or(response) } @@ -103,14 +131,33 @@ fn explain(connection: &rusqlite::Connection, query: &str) -> Vec { plan } -fn p95(samples: &mut [f64]) -> f64 { +fn p95(samples: &mut [f64]) -> Option { samples.sort_by(f64::total_cmp); - samples[(samples.len() * 95).div_ceil(100) - 1] + (!samples.is_empty()).then(|| samples[(samples.len() * 95).div_ceil(100) - 1]) +} + +fn sql_work(work: smallclaims::sqlite::work::SqliteWork) -> Value { + assert!(work.statements > 0, "SQL work instrumentation must be enabled"); + json!({"statements":work.statements,"vm_steps":work.vm_steps, + "fullscan_steps":work.fullscan_steps,"sorts":work.sorts,"autoindex_rows":work.autoindex_rows}) +} + +fn profile_lines(path: &std::path::Path) -> usize { + std::fs::read_to_string(path).map_or(0, |log| log.lines().count()) +} + +/// The read acquisitions of the single `label` operation recorded after line `from`. +fn profile_reads(path: &std::path::Path, from: usize, label: &str) -> u64 { + let log = std::fs::read_to_string(path).expect("profile slow.jsonl must be readable"); + let rows = log.lines().skip(from).map(|line| serde_json::from_str::(line).unwrap()) + .filter(|row| row["label"] == label).collect::>(); + assert_eq!(rows.len(), 1, "expected exactly one new {label} profile row; set ST3_PROFILE_SLOW_MS=0"); + rows[0]["read_acquisitions"].as_u64().expect("profile rows report read_acquisitions") } // Real signed membership and replication, outside measured requests. Merely // copying origin text would not exercise the authentication provenance check. -fn foreign_same_profile(store: &Store, anchor: Arc, template: &Value, count: usize) { +fn foreign_same_profile(store: &Store, anchor: Arc, template: &Value, count: usize, active: &[(String, Value)], overlays: usize) { let fleet = super::super::daemon_bench::FLEET; store.pin_fleet_anchor(anchor.public()).unwrap(); store.set_member_key(Some(anchor.clone())).unwrap(); @@ -150,9 +197,22 @@ fn foreign_same_profile(store: &Store, anchor: Arc 0 { - foreign_same_profile(&store, node_key, &template.body["fields"], foreign_active); + let active = sessions.iter().map(|(_, paired)| { + let subject = format!("custom/client/assistant-v1-{}", paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); + let grant = store.claims_for_subject_kind_at(&subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); + (subject, grant.body["fields"].clone()) + }).collect::>(); + if foreign_active > 0 || overlays > 0 { + foreign_same_profile(&store, node_key, &template.body["fields"], foreign_active, &active, overlays); } let fixture_store = store.clone(); tokio::task::spawn_blocking(move || { @@ -243,25 +315,37 @@ async fn authenticated_get_during_pairing() { fields["session_actor"] = json!(format!("{principal}/session/assistant-grant/{id}")); fields["expires_at_unix_ms"] = json!(1); fields["credential_hash"] = json!(hex::encode(ring::digest::digest(&ring::digest::SHA256, id.as_bytes()).as_ref())); - fixture_store.append_claim(&ClaimInput { subject:format!("custom/client/assistant-v1-{id}"), kind:GRANTED.into(), - actor:Some(OWNER.into()), fields:serde_json::from_value(fields).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); + let subject = format!("custom/client/assistant-v1-{id}"); + fixture_store.append_claim(&ClaimInput { subject:subject.clone(), kind:GRANTED.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields.clone()).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); + for revision in 0..POLICY_RENEWALS { + fields["policy_revision"] = json!(revision + 2); + fields["expires_at_unix_ms"] = json!(revision + 2); + fixture_store.append_claim(&ClaimInput { subject:subject.clone(), kind:POLICY.into(), + actor:Some(OWNER.into()), fields:serde_json::from_value(fields.clone()).unwrap(), + evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); + } } } }).await.unwrap(); let connection = rusqlite::Connection::open(&database).unwrap(); let query = if indexed { INDEXED_QUERY } else { A_QUERY }; - let index_exists: bool = connection.query_row("SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", [INDEX], |r| r.get(0)).unwrap(); - assert_eq!(index_exists, indexed, "build baseline on 98e550cb; indexed on PR3-B"); - let (before, after, build_ms) = if indexed { - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_expiry_index").unwrap(); - let before = explain(&connection, query); - let started = Instant::now(); - connection.execute_batch(CREATE_INDEX).unwrap(); - let elapsed = started.elapsed().as_secs_f64() * 1000.0; - let after = explain(&connection, query); - assert!(after.iter().any(|line| line.contains(INDEX)), "{after:?}"); - (before, after, Some(elapsed)) - } else { (explain(&connection, query), Vec::new(), None) }; + let (before, after, build_ms) = if counts_only { + (Vec::new(), Vec::new(), None) + } else { + let index_exists: bool = connection.query_row("SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", [INDEX], |r| r.get(0)).unwrap(); + assert_eq!(index_exists, indexed, "build baseline on 98e550cb; indexed on PR3-B"); + if indexed { + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_expiry_index").unwrap(); + let before = explain(&connection, query); + let started = Instant::now(); + connection.execute_batch(CREATE_INDEX).unwrap(); + let elapsed = started.elapsed().as_secs_f64() * 1000.0; + let after = explain(&connection, query); + assert!(after.iter().any(|line| line.contains(INDEX)), "{after:?}"); + (before, after, Some(elapsed)) + } else { (explain(&connection, query), Vec::new(), None) } + }; let total_rows: u64 = connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); let mut principal_rows = BTreeMap::new(); for principal in ["assistant/chatgpt", "assistant/mcp"] { @@ -271,28 +355,40 @@ async fn authenticated_get_during_pairing() { // Isolate indexed SQL from claim/policy loading, provenance and locks. // Diagnostic work stays outside HTTP samples; no request-path cache. let mut diagnostics = Vec::new(); - if indexed { for _ in 0..8 { - let started = Instant::now(); - let candidate_ids = connection.prepare(query).unwrap().query_map(rusqlite::params![ - GRANTED,"assistant/chatgpt","custom.client.assistant.v1.revoked","custom.client.assistant.v1.policy", - u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(),NODE - ], |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); - let candidate_sql_ms = started.elapsed().as_secs_f64() * 1000.0; + for _ in 0..8 { + let candidate = (indexed && !counts_only).then(|| { + let started = Instant::now(); + let candidate_ids = connection.prepare(query).unwrap().query_map(rusqlite::params![ + GRANTED,"assistant/chatgpt","custom.client.assistant.v1.revoked","custom.client.assistant.v1.policy", + u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(),NODE + ], |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); + (candidate_ids.len(), started.elapsed().as_secs_f64() * 1000.0) + }); let credential = sessions[0].1["credential"].as_str().unwrap(); let digest = hex::encode(ring::digest::digest(&ring::digest::SHA256, credential.as_bytes()).as_ref()); + let profile_from = profile_lines(&profile_log); let started = Instant::now(); + let authentication_profile = smallclaims::profile::Op::start("admission-bench/authenticate", None).unwrap(); + let entered = authentication_profile.enter(); + let work_scope = smallclaims::sqlite::work::SqliteWorkScope::start(); assert!(api::client_v0::external_grants::authenticate(&state, &digest, "http").unwrap().is_some()); - diagnostics.push(json!({"candidate_count":candidate_ids.len(),"candidate_sql_ms":candidate_sql_ms, - "direct_auth_ms":started.elapsed().as_secs_f64()*1000.0})); - }} + let authentication_sql_work = sql_work(work_scope.finish()); + drop(entered); + authentication_profile.finish(); + let direct_auth_ms = started.elapsed().as_secs_f64()*1000.0; + let authentication_read_acquisitions = profile_reads(&profile_log, profile_from, "admission-bench/authenticate"); + diagnostics.push(json!({"candidate_count":candidate.map(|(count, _)| count), + "candidate_sql_ms":candidate.map(|(_, ms)| ms), + "direct_auth_ms":direct_auth_ms,"authentication_sql_work":authentication_sql_work, + "authentication_read_acquisitions":authentication_read_acquisitions})); + } let inspected = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); let started = Instant::now(); api::client_v0::external_grants::projection(&state, &inspected).unwrap(); let legacy_projection_ms = started.elapsed().as_secs_f64()*1000.0; - let started = Instant::now(); - api::client_v0::external_grants::projection_with_witness(&state, &inspected).unwrap(); - let witness_projection_ms = started.elapsed().as_secs_f64()*1000.0; - println!("ADMISSION_DIAGNOSTICS {}", json!({"plan":explain(&connection, query),"samples":diagnostics, + let witness_projection_ms = revision_api::witness_projection_ms(&state, &inspected); + let plan = if counts_only { Vec::new() } else { explain(&connection, query) }; + println!("ADMISSION_DIAGNOSTICS {}", json!({"plan":plan,"samples":diagnostics, "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms})); drop(connection); api::wait_published_lists_at_least(&store, store.index().unwrap()).await.unwrap(); @@ -306,6 +402,23 @@ async fn authenticated_get_during_pairing() { let warm = if mode == "approval-once" { warm.header(HEADER, proof(&paired, &signer, samples + 1)) } else { warm }; let response = warm.send().await.unwrap(); assert!(response.status().is_success(), "warm GET: {}", response.text().await.unwrap()); + // A separate unpaired read work window avoids attributing pairing completion + // SQL to the GET. Global counters can still include background daemon work. + state.assistant_receipts.flush().await.unwrap(); + api::wait_published_lists_at_least(&store, store.index().unwrap()).await.unwrap(); + let measured_read = http.get(format!("{base}{PATH}")).bearer_auth(credential); + let measured_read = if mode == "approval-once" { + measured_read.header(HEADER, proof(&paired, &signer, samples + 2)) + } else { measured_read }; + let before_read = smallclaims::sqlite::work::total(); + let profile_from = profile_lines(&profile_log); + let response = measured_read.send().await.unwrap(); + let status = response.status(); + let body = response.bytes().await.unwrap(); + state.assistant_receipts.flush().await.unwrap(); + let standalone_read_sql_work = sql_work(smallclaims::sqlite::work::total() - before_read); + assert!(status.is_success(), "standalone GET {status}: {}", String::from_utf8_lossy(&body)); + let standalone_read_acquisitions = profile_reads(&profile_log, profile_from, &format!("GET {PATH}")); for sequence in 0..samples { let challenge = begin(&owner, mode).await; let get = http.get(format!("{base}{PATH}")).bearer_auth(credential); @@ -338,7 +451,10 @@ async fn authenticated_get_during_pairing() { let get_p95 = p95(&mut get_ms); let completion_p95 = p95(&mut completion_ms); measurements.push(json!({"mode":mode,"get_samples":get_ms.len(),"completion_samples":completion_ms.len(), - "get_p95_ms":get_p95,"completion_p95_ms":completion_p95,"q39_budget_ms":100,"q39_pass":get_p95 <= 100.0, + "get_p95_ms":get_p95,"completion_p95_ms":completion_p95,"q39_budget_ms":100, + "q39_pass":get_p95.map(|p95| p95 <= 100.0), + "standalone_read_sql_work":standalone_read_sql_work, + "standalone_read_acquisitions":standalone_read_acquisitions, "get_ms":get_ms,"completion_ms":completion_ms})); } let hardware = |program: &str, args: &[&str]| { @@ -348,11 +464,19 @@ async fn authenticated_get_during_pairing() { }; let final_connection = rusqlite::Connection::open(&database).unwrap(); let final_rows: u64 = final_connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); - let report = json!({"variant":variant,"baseline_revision":"98e550cb75", "hardware_uname":hardware("uname", &["-a"]), + let report = json!({"variant":variant,"read_counts_only":counts_only,"revision_api":revision_api::REVISION, + "hardware_uname":hardware("uname", &["-a"]), "hardware_lscpu":hardware("lscpu", &["-J"]),"hardware_hostname":hardware("hostname", &[]), "host_description":"Observed local benchmark host; no prescribed hardware identity", "fixture_person_ids":[OWNER],"verified_foreign_same_profile_active_grants":foreign_active, "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, + "policy_renewals_per_expired_grant":POLICY_RENEWALS, + "wrong_origin_overlays_per_active_grant":overlays, + "wrong_origin_overlay_active_grants":active.len(), + "sql_work_scope":{"authentication":"current-thread completed traced SQL statements", + "standalone_read":"process-global, unpaired HTTP GET through receipt flush; may include background daemon SQL", + "read_count_limit":"statement/VM work counters, not logical rows read or storage IO", + "read_acquisitions":"existing profile read_acquisitions: pooled read-connection/snapshot acquisitions per operation"}, "final_total_claim_rows":final_rows,"admission_query":query, "conflict_fold_diagnostics":diagnostics, "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms, @@ -362,7 +486,7 @@ async fn authenticated_get_during_pairing() { if let Some(path) = std::env::var_os("ST_ADMISSION_REPORT") { std::fs::write(path, serde_json::to_vec_pretty(&report).unwrap()).unwrap(); } local.abort(); fabric.abort(); - if indexed { + if indexed && !counts_only { assert!(report["measurements"].as_array().unwrap().iter().all(|row| row["q39_pass"] == true), "q39: authenticated GET p95 must be <=100ms; see report"); } } @@ -469,3 +593,29 @@ fn synthetic_large_store_index_build() { std::fs::write(path, serde_json::to_vec_pretty(&report).unwrap()).unwrap(); } } + +/// The only head-specific API surface. To backport the harness to origin/main +/// (d477c67ad1), replace this module's body with exactly: +/// ```ignore +/// use super::*; +/// pub const REVISION: &str = "origin/main"; +/// // origin/main admission is a credential-hash lookup with no candidate query. +/// pub const ADMISSION_QUERY: &str = A_QUERY; +/// pub fn verified_writer(_: &Store, _: &str) -> bool { +/// panic!("origin/main has no provenance check; use FOREIGN_ACTIVE=0 and WRONG_ORIGIN_OVERLAYS=0") +/// } +/// pub fn witness_projection_ms(_: &AppState, _: &fractal_daemon::model::ClaimRecord) -> Option { None } +/// ``` +mod revision_api { + use super::*; + pub const REVISION: &str = "fixed-head"; + pub const ADMISSION_QUERY: &str = api::client_v0::external_grants::admission_query_for_test(); + pub fn verified_writer(store: &Store, id: &str) -> bool { + store.claim_has_authenticated_member_writer(id).unwrap() + } + pub fn witness_projection_ms(state: &AppState, inspected: &fractal_daemon::model::ClaimRecord) -> Option { + let started = Instant::now(); + api::client_v0::external_grants::projection_with_witness(state, inspected).unwrap(); + Some(started.elapsed().as_secs_f64() * 1000.0) + } +} diff --git a/docs/st3/client-v0/schemas/client-v0.schema.json b/docs/st3/client-v0/schemas/client-v0.schema.json index 5b944d1d53a..3e94301c11e 100644 --- a/docs/st3/client-v0/schemas/client-v0.schema.json +++ b/docs/st3/client-v0/schemas/client-v0.schema.json @@ -3868,8 +3868,8 @@ "disclosure_consent": { "type": "boolean" }, "consent_evidence": { "type": "string", "minLength": 1, "maxLength": 512 }, "revoked": { "type": "boolean" }, - "conflict": { "anyOf": [{ "$ref": "#/$defs/GrantProfileConflictWitness" }, { "type": "null" }], "description": "Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses." }, - "cleared_conflicts": { "type": "array", "items": { "$ref": "#/$defs/ClearedGrantProfileConflictWitness" }, "description": "Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null." }, + "conflict": { "anyOf": [{ "$ref": "#/$defs/GrantProfileConflictWitness" }, { "type": "null" }], "description": "Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses." }, + "cleared_conflicts": { "type": "array", "items": { "$ref": "#/$defs/ClearedGrantProfileConflictWitness" }, "description": "Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing." }, "read_trust": { "$ref": "#/$defs/AssistantReadTrust", "description": "Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied." } } }, diff --git a/docs/st3/client-v0/schemas/operations.json b/docs/st3/client-v0/schemas/operations.json index 321ffab52e5..ec65a3c4c2a 100644 --- a/docs/st3/client-v0/schemas/operations.json +++ b/docs/st3/client-v0/schemas/operations.json @@ -135,7 +135,7 @@ { "id": "action.submit", "method": "POST", "path": "/v1/client/actions", "request": "ActionRequest", "response": "ActionResult" }, { "id": "pairing.begin", "method": "POST", "path": "/v1/client/pairings", "request": "PairingBegin", "response": "PairingChallenge", "local_only": true }, { "id": "pairing.complete", "method": "POST", "path": "/v1/client/pairings/{id}/complete", "request": "PairingComplete", "response": "PairedSession" }, - { "id": "assistant.grant.get", "method": "GET", "path": "/v1/client/assistant/grants/{id}", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1", "query": { "witness": "optional; only 1 opts into conflict and cleared_conflicts fields. Omitted or any other value retains the pre-witness response shape. Opt-in applies only to inspection, never pairing or grant mutations; 409 errors may carry conflict witnesses independently." } }, + { "id": "assistant.grant.get", "method": "GET", "path": "/v1/client/assistant/grants/{id}", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1", "query": { "witness": "optional; only 1 opts into conflict and cleared_conflicts fields for daemon-configured-owner inspection. Omitted or any other value retains the pre-witness response shape. Witnesses are owner-only, never exposed by bearer authentication, pairing or grant mutations. Bearer and pairing profile conflicts return HTTP 409 with code grant-profile-conflict and the fixed message principal has active grants of opposite profiles; revoke one to clear the conflict, without witness details." } }, { "id": "assistant.grant.revoke", "method": "POST", "path": "/v1/client/assistant/grants/{id}/revoke", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1" }, { "id": "assistant.grant.policy", "method": "POST", "path": "/v1/client/assistant/grants/{id}/policy", "request": "AssistantGrantPolicy", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1" }, { "id": "assistant.grant.read-trust", "method": "POST", "path": "/v1/client/assistant/grants/{id}/read-trust", "request": "AssistantReadTrustRequest", "response": "AssistantGrant", "local_only": true, "actor": "daemon-configured-owner", "capability": "assistant.grants.v1", "increments_policy_revision": true }, diff --git a/docs/st3/principals-and-grants.md b/docs/st3/principals-and-grants.md index b72752ddc8a..9f0c253da00 100644 --- a/docs/st3/principals-and-grants.md +++ b/docs/st3/principals-and-grants.md @@ -116,8 +116,11 @@ issuance is disabled and service has no assistant route or disclosure rights. Several active grants of a principal's own profile are allowed. Admission refuses a known opposite-profile grant, including one replicated from another issuer. If disconnected issuers create opposite-profile grants, authentication suspends -every conflicting grant with `grant-profile-conflict`; there is no winner. -Inspect with `?witness=1` exposes a `conflict.grants` witness with both grant IDs, origins and +every conflicting grant with HTTP 409 `grant-profile-conflict`; there is no winner. +Bearer authentication and pairing return only that code and the fixed message +`principal has active grants of opposite profiles; revoke one to clear the conflict`, +without witness details. Only the daemon-configured owner can inspect with +`?witness=1` to expose a `conflict.grants` witness with both grant IDs, origins and profiles. Once an owner's revoke replicates (or the opposite grant expires), the remaining grant works again on its authoritative issuer; replication never makes foreign credentials authenticate on another member. diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 87a18b477d3..94879a9c972 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -7,7 +7,7 @@ }, "schema": { "status": "changed", - "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409, plus inspect-only ?witness=1 opt-in conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients. Adds a principal/expiry expression index at store open without rewriting grant claims." + "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409. Bearer authentication and pairing disclose only this code and the fixed message principal has active grants of opposite profiles; revoke one to clear the conflict, without witness details. Only daemon-configured-owner inspection with ?witness=1 exposes conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients. Adds a principal/expiry expression index at store open without rewriting grant claims." }, "rules": { "status": "changed", From d862c279eaf63162ce95d102a7b90636bbd9904a Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 20:03:40 +0100 Subject: [PATCH 12/52] Register the transition index and query as large-value sites; use expect_err The shared transition query and its subject/kind/origin/actor index are new SQL sites. Replace an err().expect() in the conflict tests that clippy flags. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- .../external_grants/conflict_tests.rs | 2 +- crates/fractal-store/src/store.rs | 2 +- .../src/store/assistant_write.rs | 2 +- docs/st3/large-value-sites.json | 276 +++++++++--------- docs/st3/large-values.md | 13 +- 5 files changed, 153 insertions(+), 142 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 267086faa1f..a8d2e64baca 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -121,7 +121,7 @@ fn disconnected_opposite_profiles_conflict_on_both_members_and_revocation_recove for grant in [&assistant, &service] { assert!(state.store.claim_has_authenticated_member_writer(&grant.id).unwrap()); let error = authenticate_id(state, fields(grant).unwrap()["grant_id"].as_str().unwrap()) - .err().expect("both credentials must be suspended on either member"); + .expect_err("both credentials must be suspended on either member"); assert_conflict(&error); assert_witness(&profile_conflict(state, grant).unwrap().unwrap()); assert_witness(&projection_with_witness(state, grant).unwrap()["conflict"]); diff --git a/crates/fractal-store/src/store.rs b/crates/fractal-store/src/store.rs index 0cfb418a9fe..145e5a6d9fc 100644 --- a/crates/fractal-store/src/store.rs +++ b/crates/fractal-store/src/store.rs @@ -785,7 +785,7 @@ pub struct AgentWorkQueue { /// Fractal's projection tables, and the indexes its folds read the claim log through. The /// graph creates its own tables first; see `smallclaims::store::SCHEMA`. -const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-h7e7937d8fad1 owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" +const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-hd7de403d2fec owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL; diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index aad51c4a120..0f926aeceed 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -31,7 +31,7 @@ pub fn validated_transition( connection: &Connection, granted: &ClaimRecord, owner: &str, local_origin: &str, kind: &str, ) -> Result, FractalError> { connection.query_row( - validated_transition_query(), + /* sqlite-large-value: allow-for-now lv-h0fa302b0797b owner=fractal_store::store::assistant_write TODO=trace-statement-and-value-representation */ validated_transition_query(), params![granted.subject, kind, granted.origin, owner, granted.id, local_origin], claim_from_row, ).optional().map_err(internal) diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index 9b6a2a8068f..df3d6407521 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -388,142 +388,143 @@ {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "table_pattern": "local_work_summary_clock", "columns": [{"name": "singleton", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY CHECK(singleton=1)", "value_size_proven": false}, {"name": "through_ms", "declared_type": "BLOB", "declaration": "BLOB NOT NULL CHECK(length(through_ms)=16)", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "table_pattern": "local_work_summaries", "columns": [{"name": "key", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "progress", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "progress_at", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "completion", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "next_at", "declared_type": "BLOB", "declaration": "BLOB CHECK(next_at IS NULL OR length(next_at)=16)", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "index_pattern": "local_work_summaries_deadline", "table_pattern": "local_work_summaries", "key_expression_and_predicate": "(next_at,key) WHERE next_at IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_expiry_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), json_extract(body,'$.fields.expires_at_unix_ms'))", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, - {"site": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_expiry_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), json_extract(body,'$.fields.expires_at_unix_ms'))", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_transition_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, origin, actor, store_index)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, + {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_id_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "({RUNTIME_ID_FIELD}, subject, store_index) WHERE {ACTUAL_STATE_CLAIM} AND typeof({RUNTIME_ID_FIELD})='text'", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actual_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE {ACTUAL_STATE_CLAIM}", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_origin_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, origin, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='runtime.observed'", "value_size_proven": false}, @@ -1044,6 +1045,7 @@ {"id": "lv-h0f4af853a427", "path": "crates/fractal-seats/src/store/reconcile_work_context/tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "670380e6c1568143746eefd5717d30685a73d61436c5663c11ede8fb9d9aec6f", "owner": "fractal_seats::store::reconcile_work_context::tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 412, "excerpt": "& format ! ( \"EXPLAIN QUERY PLAN {query}\" )"}, {"id": "lv-h0f82774c88b3", "path": "crates/smallclaims/src/store/checkpoint_trim/pacing_tests.rs", "kind": "sql-template", "fingerprint": "11cda2afe8f046d8ab9a034d7553f23a4ee6c312f735c09f8875d271f7a57f59", "owner": "smallclaims::store::checkpoint_trim::pacing_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 29, "excerpt": "INSERT INTO replica_envelopes VALUES('writer',10001,'hash')"}, {"id": "lv-h0f84e29accc7", "path": "crates/smallclaims/src/store/checkpoint_staging.rs", "kind": "sql-template", "fingerprint": "801d780479ea140546359d4a836ed44d0fcbc5a2667ea898c798df32fed9417a", "owner": "smallclaims::store::checkpoint_staging", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 574, "excerpt": "INSERT OR REPLACE INTO envelopes VALUES (?1, ?2, ?3, ?4, ?5, 1)"}, + {"id": "lv-h0fa302b0797b", "path": "crates/fractal-store/src/store/assistant_write.rs", "kind": "unresolved-sql-sink", "fingerprint": "6562903c8d2bc207804842e34b4da5a824f3b03ce5db30fe71891c284a70fbba", "owner": "fractal_store::store::assistant_write", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 34, "excerpt": "validated_transition_query ( ) , params ! [ granted . subject , kind , granted . origin , owner , granted . id , local_origin ] , claim_from_row ,"}, {"id": "lv-h0fbead354086", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "79efe7d7d375ce77e79ed9519b96dc98e2414f7b60deb32af4ad805b0c1384f6", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 10292, "excerpt": "INSERT OR IGNORE INTO event_positions(store_index, subject) VALUES (?1, ?2)"}, {"id": "lv-h0fd14f161748", "path": "crates/fractal-missions/src/store/mission_deadline_tests.rs", "kind": "sql-template", "fingerprint": "a5186b3123ce5807dff1a53ab460af0a78879c8679897964ca5d66650e5d1471", "owner": "fractal_missions::store::mission_deadline_tests", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 130, "excerpt": "DROP TABLE mission_run_deadlines; CREATE TABLE mission_run_deadlines ( run_id TEXT PRIMARY KEY REFERENCES mission_runs(id), timeout_ms INTEGER NOT NULL, deadline_at_unix_ms TEXT NOT NULL ); UPDATE pro"}, {"id": "lv-h10009ac67082", "path": "crates/smallclaims/src/store/events.rs", "kind": "sql-template", "fingerprint": "2807d9c856a5f430dc82759f52ee4e5d913f383748cc61aa1691f3a75103dbe4", "owner": "smallclaims::store::events", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 9, "excerpt": "CREATE VIEW events AS SELECT p.store_index,c.kind,p.subject,c.body FROM event_positions p CROSS JOIN claims c ON c.store_index=p.store_index"}, @@ -2842,7 +2844,6 @@ {"id": "lv-h7e34d2a4ccc6", "path": "crates/smallclaims/src/store/transport_observation_index.rs", "kind": "unresolved-sql-sink", "fingerprint": "af02492c5b58d2119a64868815f8067d7602a72d658d5c16dad5758b3d0bd071", "owner": "smallclaims::store::transport_observation_index", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 115, "excerpt": "params ! [ subject , origin ] , | row | { Ok ( ( row . get ( 0 ) ? , row . get ( 1 ) ? ) ) }"}, {"id": "lv-h7e4b750d0950", "path": "crates/fractal-store/src/store/operation_audit.rs", "kind": "unresolved-sql-sink", "fingerprint": "4ec7c53222c8a758c722e2111541035ce700d5ae7bd0898c5f1b1a743e6450fd", "owner": "fractal_store::store::operation_audit", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 91, "excerpt": "sql"}, {"id": "lv-h7e617af16bb5", "path": "crates/smallclaims/src/store/principals/legacy.rs", "kind": "sql-template", "fingerprint": "3256aaf8d7e0123d6e54d2f582d0cadb8a48173e801614cec7b5b8880fca24cd", "owner": "smallclaims::store::principals::legacy", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 83, "excerpt": "INSERT OR IGNORE INTO legacy_claim_verdict_fresh(claim_id) VALUES (?1)"}, - {"id": "lv-h7e7937d8fad1", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "05c4b601885836e66c3fea007a185bdc60754cd8f0317128d594d4f14d6aefaa", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 788, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, {"id": "lv-h7e7d5bb183d4", "path": "crates/fractal-store/src/store/rollouts.rs", "kind": "unresolved-sql-sink", "fingerprint": "7c4843484a5ff2ad87f7c35b9b572881bad538e0f6b3b87d1f7ad11be0884659", "owner": "fractal_store::store::rollouts", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 95, "excerpt": "& canonical_sql ( \"SELECT id,store_index,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms FROM claims WHERE subject=?1 AND store_index<=?2 AND kind IN ('runtime.action.requeste"}, {"id": "lv-h7e82a1369f4c", "path": "crates/fractal-store/src/store/ordered_membership.rs", "kind": "sql-template", "fingerprint": "b3651283034d85939e2f4ba23806aee7ecdc24608c4cc1f913526ba4db950088", "owner": "fractal_store::store::ordered_membership", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 153, "excerpt": "DELETE FROM ordered_membership_live WHERE container=?1 AND member=?2"}, {"id": "lv-h7e8ac599e41d", "path": "crates/fractal-seats/src/store/reconcile_work_context/tests.rs", "kind": "sql-template", "fingerprint": "973e006f6f92f02d98076f3a51ab852b8197bb3e09a283db3e09b01f3b65c0b0", "owner": "fractal_seats::store::reconcile_work_context::tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 286, "excerpt": "UPDATE claims SET accepted_at_unix_ms=?1 WHERE kind IN ('work.person-done','work.person-cancelled')"}, @@ -4308,6 +4309,7 @@ {"id": "lv-hd7cd14b1d0a5", "path": "crates/fractal-store/src/store/message_send_tests.rs", "kind": "sql-template", "fingerprint": "5f2be0ab50a9c7514f427efb36cc8f4cab6feabfe7dc0f4ad8664f1ce605e815", "owner": "fractal_store::store::message_send_tests", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "line_hint": 31, "excerpt": "INSERT INTO checkpoint_claims(id,writer,sequence,envelope_hash,subject,kind, actor,predecessors,operation_id,request_digest,accepted_at_unix_ms,checkpoint) VALUES (?1,'invented-peer',1,'invented-envel"}, {"id": "lv-hd7d92523e785", "path": "crates/smallclaims/src/store/saved_inventory_tests.rs", "kind": "sql-template", "fingerprint": "c7ccec23366bfe885531ec8fdde089ce526c3d76ef218b6d0afc93adef29effd", "owner": "smallclaims::store::saved_inventory_tests", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "line_hint": 332, "excerpt": "INSERT OR IGNORE INTO checkpoint_envelopes(writer, sequence, envelope_hash, accepted_at_unix_ms, checkpoint) SELECT writer, sequence, envelope_hash, 0, 'invented-checkpoint' FROM replica_envelopes WHE"}, {"id": "lv-hd7dc4a36d272", "path": "crates/fractal-store/src/store/observer_actuals_tests.rs", "kind": "sql-template", "fingerprint": "7919957e727355f6fb0d09b92990cdf4ea28b80a15928f645c46e77cfb73c16f", "owner": "fractal_store::store::observer_actuals_tests", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 149, "excerpt": "DROP TABLE projection_digest_repaired_claims; CREATE TABLE projection_digest_repaired_claims(id TEXT PRIMARY KEY) WITHOUT ROWID;"}, + {"id": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "4d8a6bbe014853cbe11e445c1907fe84a96a76af631ac6f2514b435e746f324b", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 788, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, {"id": "lv-hd81a35b60f28", "path": "crates/fractal-api-core/src/api/client_messages_selector_tests.rs", "kind": "sql-template", "fingerprint": "9c1fd01759a0c066cfad05fc874a449588b618537e42c1dea36b70408ae95d56", "owner": "fractal_api_core::api::client_messages_selector_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 661, "excerpt": "UPDATE claims SET accepted_at_unix_ms=?2 WHERE subject=?1"}, {"id": "lv-hd82c937baff5", "path": "crates/fractal-store/src/store/assistant_write.rs", "kind": "unresolved-sql-sink", "fingerprint": "874d4bf9cc46459a8b33435bb94abd6e2ae2362af60e84eacd179a1e2df2e8c6", "owner": "fractal_store::store::assistant_write", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 23, "excerpt": "& latest_claim_of_kind_query ( ) , params ! [ authorization . grant_subject , kind ] , claim_from_row"}, {"id": "lv-hd82cb2e4adf3", "path": "crates/fractal-api-core/src/api/legacy_handler_guard_tests.rs", "kind": "included-source", "fingerprint": "4e162be3f4be5a1bddabf31677419af51c1d5244c05521c685b551bcc21c0f36", "owner": "fractal_api_core::api::legacy_handler_guard_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 12, "excerpt": "include_str ! ( \"fleet.rs\" )"}, diff --git a/docs/st3/large-values.md b/docs/st3/large-values.md index b05e8c95b5b..eb0758963da 100644 --- a/docs/st3/large-values.md +++ b/docs/st3/large-values.md @@ -489,15 +489,24 @@ Inline storage here proves neither encoded size nor execution-cost bounds. ## Assistant principal admission index review -`fractal_store::store` owns schema site `lv-h7e7937d8fad1`, replacing -`lv-hb9696ca837f7`. The principal admission indexes retain claim-kind TEXT +`fractal_store::store` owns schema site `lv-hd7de403d2fec`, replacing +`lv-h7e7937d8fad1`. The principal admission indexes retain claim-kind TEXT and the effective principal JSON field inline; absent principals use the fixed `assistant/chatgpt` key. The added expiry suffix supports live-grant range seeks. +`claims_assistant_v1_transition_index` keys subject, kind, origin, actor and +store index TEXT/INTEGER columns, so an authoritative policy or revocation lookup +seeks past overlays from another origin or actor. These indexes change neither claim bodies nor admission semantics. Keys remain variable-size, and SQLite maintains them on insertion and deletion; indexed lookup is not a byte-size or startup-cost proof. The producer maintainer retains `chunk-or-reference-variable-columns` responsibility while preserving effective-principal matching and claim authority. +`fractal_store::store::assistant_write` owns the read-only sink +`lv-h0fa302b0797b`. The shared validated transition query binds a grant subject, +claim kind, origin, owner actor, grant claim ID and local origin, and returns at +most one claim row. It writes nothing; bodies stay inline, so the exception +establishes neither encoded-size nor execution-cost bounds. + `fractal_api_core::api::client_v0::external_grants` owns the conservative read-only sink `lv-h99f1a302c7b1`. Its prepared admission query binds fixed claim kinds, an assistant principal and an optional expiry cutoff, then returns claim From 7249e85352259aabbc443616471567309ba8f094 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 20:04:27 +0100 Subject: [PATCH 13/52] Expect profile-conflict suspension of the compat counterexample pair With the counterexample, the candidate holds active, well-formed assistant (grant 4) and service (grant 7) grants for one principal, so it suspends both with 409. The old-binary phase is unchanged. A candidate-only daemon test and a unit test reproduce the fixture without the baseline binary. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- .../external_grants/conflict_tests.rs | 21 ++++++++++ crates/fractal/tests/fleet/service_grants.rs | 41 +++++++++++++++---- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index a8d2e64baca..7f0bcd021e3 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -248,6 +248,27 @@ fn malformed_local_owner_actor_grants_cannot_suspend_a_local_credential() { } } +// Same shape as fleet::service_grants' rollback counterexample: a service grant +// with a non-assistant scope (3), an assistant grant (4) and a well-formed service +// grant (7), all active for assistant/chatgpt on one member. +#[test] +fn compat_counterexample_suspends_the_valid_pair_and_refuses_the_malformed_service() { + let root = tempfile::tempdir().unwrap(); + let state = member(root.path(), "issuer"); + let [malformed, assistant, service] = ["000000000000000000000003", + "000000000000000000000004", "000000000000000000000007"]; + let mut source = grant_fields(malformed, "service"); + source["scopes"] = json!(["read.service.status"]); + raw_claim(&state, &subject(malformed).unwrap(), GRANTED, OWNER, source); + issue(&state, assistant, "assistant").unwrap(); + raw_claim(&state, &subject(service).unwrap(), GRANTED, OWNER, grant_fields(service, "service")); + for id in [assistant, service] { + assert_conflict(&authenticate_id(&state, id).expect_err("the valid opposite pair is suspended")); + } + let refused = authenticate_id(&state, malformed).expect_err("service grants never authenticate"); + assert_eq!((refused.status, refused.code.as_str()), (StatusCode::FORBIDDEN, "forbidden")); +} + #[test] fn malformed_authenticated_foreign_grants_cannot_suspend_a_local_credential() { let root = tempfile::tempdir().unwrap(); diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index 404ed444bb9..d59c2956752 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -68,17 +68,36 @@ fn seed(node: &Node, number: u8, profile: &str, principal: &str, scope: &str, // requiring a signed per-read approval, or creating a proposal. A refusal must be exactly 403, // not an unavailable daemon, missing route, bad request, or transport failure. async fn assert_auth(node: &Node, grant: &Grant, accepted: bool) { + assert_status(node, grant, if accepted { 400 } else { 403 }).await; +} + +async fn assert_status(node: &Node, grant: &Grant, expected: u16) { let response = reqwest::Client::builder().unix_socket(node.socket()).build().unwrap() .post("http://localhost/v1/client/assistant/propose") .bearer_auth(&grant.credential).header("content-type", "application/json") .body("{").send().await.unwrap(); let status = response.status(); let body = response.text().await.unwrap(); - assert_eq!(status.as_u16(), if accepted { 400 } else { 403 }, + assert_eq!(status.as_u16(), expected, "{} grant {}: {body}\n{}", node.name, grant.id, node.logs()); let _: Value = node.client().get("/v1/health").await.unwrap(); } +// With the counterexample, assistant grant 4 (index 3) and service grant 7 (index 6) +// are active, well-formed opposite-profile grants for assistant/chatgpt. The +// candidate suspends both with 409 grant-profile-conflict; the conflict fold runs +// before the service-profile refusal. Grant 3 (index 2) has a non-assistant scope, +// so it is malformed for conflicts and stays a plain 403 service refusal. +fn candidate_counterexample_status(index: usize) -> u16 { + if index == 3 || index == 6 { 409 } else { 403 } +} + +async fn assert_candidate_counterexample(node: &Node, grants: &[Grant]) { + for (index, grant) in grants.iter().enumerate() { + assert_status(node, grant, candidate_counterexample_status(index)).await; + } +} + async fn assert_retained(node: &Node, grants: &[Grant]) { let ids: BTreeSet = node.claims().await.into_iter() .map(|claim| claim["id"].as_str().unwrap().to_owned()).collect(); @@ -166,9 +185,7 @@ async fn previous_release_refuses_plugin_service_grants_on_same_database_rollbac assert_candidate_issuance_grammar(&node).await; // Includes the unissuable profile-blind counterexample; candidate must refuse it. let grants = fixtures(&mut node, true).await; - for (index, grant) in grants.iter().enumerate() { - assert_auth(&node, grant, index == 3).await; - } + assert_candidate_counterexample(&node, &grants).await; let state = node.state_dir(); node.stop(); node.binary = old; @@ -188,9 +205,7 @@ async fn previous_release_refuses_plugin_service_grants_on_same_database_rollbac node.binary = PathBuf::from(st3()); node.start().await; assert_eq!(node.state_dir(), state); - for (index, grant) in grants.iter().enumerate() { - assert_auth(&node, grant, index == 3).await; - } + assert_candidate_counterexample(&node, &grants).await; assert_retained(&node, &grants).await; } @@ -204,6 +219,18 @@ async fn candidate_offline_service_fixtures_replicate_without_authorizing_creden mixed_pair(None, false).await; } +// Candidate-only reproduction of the rollback fixture, without a baseline binary. +#[tokio::test(flavor = "multi_thread")] +async fn candidate_suspends_the_offline_counterexample_profile_conflict() { + if fractal_daemon::test_support::supervise_test() { return; } + let root = tempfile::tempdir().unwrap(); + let mut node = Node::new(root.path(), "issuer"); + node.start().await; + let grants = fixtures(&mut node, true).await; + assert_candidate_counterexample(&node, &grants).await; + assert_retained(&node, &grants).await; +} + async fn assert_candidate_issuance_grammar(node: &Node) { let client = reqwest::Client::builder().unix_socket(node.socket()).build().unwrap(); let request = json!({"api_version":"st3.client.v0", "device_name":"fixture", From 1dd5ec360ccfea0385bfc56b98c723debb77d6a7 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 20:05:07 +0100 Subject: [PATCH 14/52] State the conflict-before-service refusal order in the compat test agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- crates/fractal/tests/fleet/service_grants.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index d59c2956752..6efca6f550e 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -85,8 +85,9 @@ async fn assert_status(node: &Node, grant: &Grant, expected: u16) { // With the counterexample, assistant grant 4 (index 3) and service grant 7 (index 6) // are active, well-formed opposite-profile grants for assistant/chatgpt. The -// candidate suspends both with 409 grant-profile-conflict; the conflict fold runs -// before the service-profile refusal. Grant 3 (index 2) has a non-assistant scope, +// candidate suspends both: it refuses with the conflict (409 grant-profile-conflict) +// before the service-profile refusal (403), so grant 7 answers 409, not 403. +// Grant 3 (index 2) has a non-assistant scope, // so it is malformed for conflicts and stays a plain 403 service refusal. fn candidate_counterexample_status(index: usize) -> u16 { if index == 3 || index == 6 { 409 } else { 403 } From a80dc5e84557d6c36b6dbe4346d9f53df5aa3dcd Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 20:06:24 +0100 Subject: [PATCH 15/52] Keep the store migration reference query identical to admission The schema-install test copies the admission query; give it the expiry-bounded policy arm and the transition index, and check that reopening installs it. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- crates/fractal-store/src/store/runtime.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index 34d8be1cf28..e6c4c3f6c95 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -865,15 +865,16 @@ mod schema_install_tests { WHERE ?5 IS NOT NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 AND json_extract(body,'$.fields.expires_at_unix_ms') IS NULL AND json_type(body,'$.fields') IS NULL UNION - SELECT granted.id FROM claims AS policy INDEXED BY claims_assistant_v1_principal_index + SELECT granted.id FROM claims AS policy INDEXED BY claims_assistant_v1_principal_expiry_index JOIN claims AS granted INDEXED BY claims_subject_kind_accepted_index ON granted.subject=policy.subject AND granted.kind=?1 WHERE ?5 IS NOT NULL AND policy.kind=?4 AND policy.origin=granted.origin AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2 + AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5 AND COALESCE(json_extract(granted.body,'$.fields.principal'),'assistant/chatgpt')=?2) SELECT claims.id FROM eligible JOIN claims ON claims.id=eligible.id WHERE ?5 IS NULL OR claims.origin<>?6 OR NOT EXISTS ( - SELECT 1 FROM claims AS revoked INDEXED BY claims_subject_kind_accepted_index + SELECT 1 FROM claims AS revoked INDEXED BY claims_assistant_v1_transition_index WHERE revoked.subject=claims.subject AND revoked.kind=?3 AND revoked.origin=claims.origin AND revoked.actor=claims.actor AND json_extract(revoked.body,'$.fields.issuer')=revoked.actor @@ -918,7 +919,7 @@ mod schema_install_tests { let connection = Connection::open(&path).unwrap(); connection.execute_batch(smallclaims::store::SCHEMA).unwrap(); install_initial_schema(&connection, true).unwrap(); - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index; DROP INDEX claims_assistant_v1_principal_expiry_index;").unwrap(); + connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index; DROP INDEX claims_assistant_v1_principal_expiry_index; DROP INDEX claims_assistant_v1_transition_index;").unwrap(); connection.pragma_update(None, "user_version", version).unwrap(); connection.execute( "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES('batch','node',1,'hash','1')", @@ -962,6 +963,9 @@ mod schema_install_tests { } assert!(plan(&connection, ACTIVE, true).iter().any(|step| step.contains(EXPIRY_INDEX) && step.contains(">?"))); + assert!(plan(&connection, ACTIVE, true).iter().any(|step| + step.contains("claims_assistant_v1_transition_index") + && step.contains("subject=? AND kind=? AND origin=? AND actor=?"))); for (principal, mut expected) in [ ("assistant/chatgpt", vec!["chatgpt".to_owned(), "legacy".to_owned()]), ("assistant/mcp", vec!["mcp".to_owned()]), From 5a6ff902c86bdf017bb14c9412f039d880e64c81 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 21:07:27 +0100 Subject: [PATCH 16/52] Revoke service-grant fixtures the way the owner route does Only an authoritative revocation (owner issuer, matching grant id) clears a grant; the bare {} fixture body is an ignored overlay, so grant 6 stayed active. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- crates/fractal/tests/fleet/service_grants.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index 6efca6f550e..8c4ce1f58b2 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -58,7 +58,11 @@ fn seed(node: &Node, number: u8, profile: &str, principal: &str, scope: &str, let policy = append(node, &id, POLICY, fields, Some(&granted)); let mut claims = BTreeSet::from([granted, policy.clone()]); if revoked { - claims.insert(append(node, &id, REVOKED, json!({}), Some(&policy))); + // Same shape as the owner revoke route: only an authoritative revocation counts. + claims.insert(append(node, &id, REVOKED, json!({ + "version": 1, "grant_id": id, "principal": principal, "issuer": PERSON, + "transport": "fixture", "timestamp": "2026-01-01T00:00:00Z", "outcome": "revoked" + }), Some(&policy))); } Grant { id, credential, claims } } From 3a66dfbe70ace95799e21dce9a10612fdaee0445 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 21:49:04 +0100 Subject: [PATCH 17/52] Regenerate the TypeScript client for the owner-only witness descriptions agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- .../typescript/fractal-client/Schema.generated.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clients/typescript/fractal-client/Schema.generated.ts b/clients/typescript/fractal-client/Schema.generated.ts index b476438cd97..58886603e24 100644 --- a/clients/typescript/fractal-client/Schema.generated.ts +++ b/clients/typescript/fractal-client/Schema.generated.ts @@ -525,10 +525,10 @@ export type GrantProfileConflictWitness = typeof GrantProfileConflictWitness.Typ export type GrantProfileConflictWitnessEncoded = typeof GrantProfileConflictWitness.Encoded export const AssistantGrant = /*#__PURE__*/ (() => Schema.Struct({ - /** Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null. */ - "cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null." }), - /** Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses. */ - "conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses." }), + /** Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing. */ + "cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing." }), + /** Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses. */ + "conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, @@ -944,9 +944,9 @@ export const Envelope = /*#__PURE__*/ (() => Schema.Struct({ "desired_token": Schema.String.annotate({ description: "Selected desired claim, including a stop when the seat is retired." }), "host_id": HostId, "kind": Schema.Literal("agent-workspace"), /** Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory. */ "workspace": Schema.String.annotate({ description: "Declared workspace directory on host_id, not the API gateway's filesystem or the harness's internal state directory." }), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.String.check(Schema.makeFilter((value: string) => !new RegExp("^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$", "u").test(value), { expected: "a string not matching ^(?:resources|ordered-memberships|assistant\\.(?:attention|missions|agents))$" })), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(Resource), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("ordered-memberships"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(OrderedMembership), "kind": Schema.Literal("page"), "page": PageInfo, "replicated": optionalKey(ReplicatedNotice), "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "collection": Schema.Literal("resources"), "filters": Schema.Record(Schema.String, Schema.String), "items": Schema.Array(ResourceObservation), "kind": Schema.Literal("page"), "page": PageInfo, "sync": optionalKey(SyncNotice), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Resource, Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ "header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry), "kind": Schema.Literal("timeline-page"), "page": PageInfo, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ /** Present when conversation-blocks.v1 is negotiated; each field names its value, source and as_of */ -"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ /** Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null. */ -"cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on grant inspection with witness=1 when conflict is null." }), /** Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses. */ -"conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on grant inspection with witness=1; omitted from default inspection, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ +"header": optionalKey(ConversationHeader), "items": Schema.Array(TimelineEntry).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-changes"), "next_cursor": Cursor, "session_id": Id, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "host_id": Id, "incomplete_sources": Schema.Array(Schema.String), "indexed_at": Timestamp, "items": Schema.Array(ConversationSearchHit).check(Schema.isMaxLength(200)), "kind": Schema.Literal("conversation-search"), "page": PageInfo, "refreshing": Schema.Boolean, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "has_more": Schema.Boolean, "items": Schema.Array(ProjectionEvent).check(Schema.isMaxLength(500)), "kind": Schema.Literal("event-page"), "oldest_cursor": Cursor, "resume_cursor": Cursor, "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "action_id": Id, "affected_ids": Schema.Array(Id).check(Schema.isUnique()), "arrangement_revision": optionalKey(Revision), "harness_answer": optionalKey(HarnessAnswerResult), "kind": Schema.Literal("action-result"), "membership_revision": optionalKey(Revision), "operation_id": Id, "private_notes": optionalKey(PrivateNotesFence), "snapshot_id": Id, "status": Schema.Literals(["accepted","completed","rejected"]), "terminal_attachment": Schema.OptionFromOptionalNullOr(TerminalAttachment, NULL_NONE), "accounts": Schema.optionalKey(Schema.Never), "acknowledged_event_ids": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), Schema.Struct({ "acknowledged_event_ids": Schema.Array(ClientDiagnosticUuid).check(Schema.isMaxLength(32)), "accounts": Schema.optionalKey(Schema.Never), "action_id": Schema.optionalKey(Schema.Never), "actions": Schema.optionalKey(Schema.Never), "affected_ids": Schema.optionalKey(Schema.Never), "agent_id": Schema.optionalKey(Schema.Never), "agent_messages": Schema.optionalKey(Schema.Never), "arrangement_revision": Schema.optionalKey(Schema.Never), "as_of": Schema.optionalKey(Schema.Never), "as_of_unix_ms": Schema.optionalKey(Schema.Never), "bytes": Schema.optionalKey(Schema.Never), "capabilities": Schema.optionalKey(Schema.Never), "changed_at_unix_ms": Schema.optionalKey(Schema.Never), "cleanup_command": Schema.optionalKey(Schema.Never), "cleared_conflicts": Schema.optionalKey(Schema.Never), "collection": Schema.optionalKey(Schema.Never), "columns": Schema.optionalKey(Schema.Never), "complete": Schema.optionalKey(Schema.Never), "conflict": Schema.optionalKey(Schema.Never), "conflicts": Schema.optionalKey(Schema.Never), "consent_evidence": Schema.optionalKey(Schema.Never), "count": Schema.optionalKey(Schema.Never), "counts": Schema.optionalKey(Schema.Never), "current_work_ids": Schema.optionalKey(Schema.Never), "cursor": Schema.optionalKey(Schema.Never), "data": Schema.optionalKey(Schema.Never), "declaration": Schema.optionalKey(Schema.Never), "declaration_token": Schema.optionalKey(Schema.Never), "desired": Schema.optionalKey(Schema.Never), "desired_revision": Schema.optionalKey(Schema.Never), "desired_token": Schema.optionalKey(Schema.Never), "device_id": Schema.optionalKey(Schema.Never), "disclosure_consent": Schema.optionalKey(Schema.Never), "event_cursor": Schema.optionalKey(Schema.Never), "expires_at": Schema.optionalKey(Schema.Never), "facts": Schema.optionalKey(Schema.Never), "family": Schema.optionalKey(Schema.Never), "filters": Schema.optionalKey(Schema.Never), "grant_expires_at": Schema.optionalKey(Schema.Never), "grant_id": Schema.optionalKey(Schema.Never), "grant_kind": Schema.optionalKey(Schema.Never), "harness_answer": Schema.optionalKey(Schema.Never), "has_more": Schema.optionalKey(Schema.Never), "header": Schema.optionalKey(Schema.Never), "history": Schema.optionalKey(Schema.Never), "host_id": Schema.optionalKey(Schema.Never), "id": Schema.optionalKey(Schema.Never), "incomplete_sources": Schema.optionalKey(Schema.Never), "indexed_at": Schema.optionalKey(Schema.Never), "issuer": Schema.optionalKey(Schema.Never), "items": Schema.optionalKey(Schema.Never), "kdl": Schema.optionalKey(Schema.Never), "key_id": Schema.optionalKey(Schema.Never), "kind": Schema.optionalKey(Schema.Never), "latest": Schema.optionalKey(Schema.Never), "legacy": Schema.optionalKey(Schema.Never), "limit": Schema.optionalKey(Schema.Never), "limits": Schema.optionalKey(Schema.Never), "lines": Schema.optionalKey(Schema.Never), "live": Schema.optionalKey(Schema.Never), "machine_version": Schema.optionalKey(Schema.Never), "membership_revision": Schema.optionalKey(Schema.Never), "minimal_read_mode": Schema.optionalKey(Schema.Never), "mission": Schema.optionalKey(Schema.Never), "modes": Schema.optionalKey(Schema.Never), "move_count": Schema.optionalKey(Schema.Never), "moves": Schema.optionalKey(Schema.Never), "name": Schema.optionalKey(Schema.Never), "next_cursor": Schema.optionalKey(Schema.Never), "next_sequence": Schema.optionalKey(Schema.Never), "next_work_id": Schema.optionalKey(Schema.Never), "notes": Schema.optionalKey(Schema.Never), "oldest_cursor": Schema.optionalKey(Schema.Never), "oldest_event_cursor": Schema.optionalKey(Schema.Never), "operation_id": Schema.optionalKey(Schema.Never), "otel_ui_url": Schema.optionalKey(Schema.Never), "owner": Schema.optionalKey(Schema.Never), "page": Schema.optionalKey(Schema.Never), "policy_revision": Schema.optionalKey(Schema.Never), "principal": Schema.optionalKey(Schema.Never), "private_notes": Schema.optionalKey(Schema.Never), "published_at": Schema.optionalKey(Schema.Never), "read_trust": Schema.optionalKey(Schema.Never), "recipient_allowlist": Schema.optionalKey(Schema.Never), "ref": Schema.optionalKey(Schema.Never), "reference": Schema.optionalKey(Schema.Never), "references": Schema.optionalKey(Schema.Never), "refreshing": Schema.optionalKey(Schema.Never), "relay": Schema.optionalKey(Schema.Never), "replicated": Schema.optionalKey(Schema.Never), "resume_cursor": Schema.optionalKey(Schema.Never), "retained_from": Schema.optionalKey(Schema.Never), "revision": Schema.optionalKey(Schema.Never), "revoked": Schema.optionalKey(Schema.Never), "rows": Schema.optionalKey(Schema.Never), "runs": Schema.optionalKey(Schema.Never), "runtime_incarnation": Schema.optionalKey(Schema.Never), "samples": Schema.optionalKey(Schema.Never), "schema": Schema.optionalKey(Schema.Never), "schemas": Schema.optionalKey(Schema.Never), "scopes": Schema.optionalKey(Schema.Never), "seat": Schema.optionalKey(Schema.Never), "sender_class": Schema.optionalKey(Schema.Never), "session_actor": Schema.optionalKey(Schema.Never), "session_id": Schema.optionalKey(Schema.Never), "since_ms": Schema.optionalKey(Schema.Never), "size": Schema.optionalKey(Schema.Never), "snapshot_id": Schema.optionalKey(Schema.Never), "status": Schema.optionalKey(Schema.Never), "steps": Schema.optionalKey(Schema.Never), "subject": Schema.optionalKey(Schema.Never), "sync": Schema.optionalKey(Schema.Never), "terminal_attachment": Schema.optionalKey(Schema.Never), "terminal_id": Schema.optionalKey(Schema.Never), "text": Schema.optionalKey(Schema.Never), "threshold_ms": Schema.optionalKey(Schema.Never), "title": Schema.optionalKey(Schema.Never), "token": Schema.optionalKey(Schema.Never), "transport": Schema.optionalKey(Schema.Never), "truncated": Schema.optionalKey(Schema.Never), "until_ms": Schema.optionalKey(Schema.Never), "version": Schema.optionalKey(Schema.Never), "workspace": Schema.optionalKey(Schema.Never) }), PairingChallenge, PairedSession, Schema.Struct({ /** Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing. */ +"cleared_conflicts": optionalKey(Schema.Array(ClearedGrantProfileConflictWitness)).annotate({ description: "Revoked or expired opposite-profile witnesses; emitted only on daemon-configured-owner grant inspection with witness=1 when conflict is null. Never disclosed by bearer authentication errors or pairing." }), /** Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses. */ +"conflict": Schema.OptionFromOptionalNullOr(GrantProfileConflictWitness, NULL_NONE).annotate({ description: "Current opposite-profile conflict, or null when no active conflict exists. Present only on daemon-configured-owner grant inspection with witness=1; omitted from default inspection, bearer authentication errors, pairing and mutation responses." }), "consent_evidence": Schema.String.check(Schema.isMinCodePoints(1)).check(Schema.isMaxCodePoints(512)), "device_id": Id, "disclosure_consent": Schema.Boolean, "expires_at": Timestamp, "id": Id, /** Daemon-configured owning person, sealed by the authoritative grant-issuer member at trusted-local begin. */ "issuer": PersonId, /** SHA-256 of the canonical device public-key string; never a credential digest. */ "key_id": Schema.String.check(Schema.isPattern(new RegExp("^[0-9a-f]{64}$", "u"))).annotate({ description: "SHA-256 of the canonical device public-key string; never a credential digest." }), "kind": Schema.Literal("assistant-grant"), "minimal_read_mode": AssistantMinimalReadMode, "policy_revision": Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)), "principal": AssistantPrincipal, /** Owner-provisioned public pins for SCG read proofs. Absent means every assistant read is denied. */ "read_trust": optionalKey(AssistantReadTrust), /** Stored policy metadata; does not restrict message.send. write.assistant.messages permits any existing agent recipient, never a person. */ From 1b7a91de380bb3ab32a5d36c9208d26504e721b3 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 8 Nov 2026 22:29:33 +0100 Subject: [PATCH 18/52] Replicate admission-bench overlays until every claim has verified provenance Replication exchanges are cut to a body budget; one round left part of the 1000-overlay history without a member signature. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- .../fractal/tests/daemon_cost/assistant_admission.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index d43fdc1d18c..e233b205f14 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -210,11 +210,13 @@ fn foreign_same_profile(store: &Store, anchor: Arc Date: Sun, 8 Nov 2026 23:30:18 +0100 Subject: [PATCH 19/52] Record the pre-index admission plan as unplannable in the cost probe The admission query names its index with INDEXED BY, so SQLite cannot plan it while the probe has the index dropped. agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: anthropic/claude-opus-5-5 --- crates/fractal/tests/daemon_cost/assistant_admission.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index e233b205f14..0ea28ee7292 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -118,7 +118,12 @@ fn proof(paired: &Value, signer: &Ed25519KeyPair, sequence: usize) -> String { } fn explain(connection: &rusqlite::Connection, query: &str) -> Vec { - let mut statement = connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")).unwrap(); + // The production query names its indexes (INDEXED BY); before the probe recreates + // one, SQLite refuses to plan it. Record that instead of a plan. + let mut statement = match connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")) { + Ok(statement) => statement, + Err(error) => return vec![format!("not plannable: {error}")], + }; let mut rows = if query == A_QUERY { statement.query(rusqlite::params![GRANTED, "assistant/chatgpt"]).unwrap() } else { From 3abdd9a48a2605c909d5d3f2b8451d3f4e984503 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 00:52:57 +0100 Subject: [PATCH 20/52] Retain authenticated grant history and batch conflict admission reads agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 147 +++++++++++++----- .../external_grants/conflict_tests.rs | 98 +++++++++++- .../src/store/assistant_write.rs | 57 ++++++- .../tests/daemon_cost/assistant_admission.rs | 147 +++++++++++++++--- crates/smallclaims/src/store.rs | 74 +++++++-- .../src/store/membership_query_tests.rs | 97 ++++++++++++ docs/st3/large-value-sites.json | 7 +- docs/st3/large-values.md | 37 +++-- .../external-grant-profile-conflict.json | 2 +- 9 files changed, 572 insertions(+), 94 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index cd653420926..ba76c2d7ac9 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -123,37 +123,67 @@ fn admission_now_ms() -> u128 { client_now_ms() } fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) -> Result, ApiError> { - candidate_grants_except(state, principal, expiry_cut, None) + candidate_grants_except(state, principal, expiry_cut, None, None) } -fn candidate_grants_except(state: &AppState, principal: &str, expiry_cut: Option, excluded: Option<&str>) -> Result, ApiError> { +fn candidate_grants_except(state: &AppState, principal: &str, expiry_cut: Option, + excluded: Option<&str>, ignored_profile: Option) -> Result, ApiError> { let owner = owning_person(state)?; - let ids = { + static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| + crate::store::assistant_write::validated_candidates_query(ADMISSION_QUERY)); + let ignored_profile = ignored_profile.map(|profile| match profile { + Profile::Assistant => "assistant", Profile::Service => "service", + }); + let rows = { let connection = state.store.readers.get(); - let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-h99f1a302c7b1 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ ADMISSION_QUERY).map_err(ApiError::internal)?; - query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut, state.store.origin()], |row| row.get::<_, String>(0)) - .map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? + let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-hc1c46de6a890 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ &QUERY).map_err(ApiError::internal)?; + query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut, + state.store.origin(), owner, ignored_profile, excluded], |row| { + Ok((row.get::<_, String>(10)?, row.get::<_, String>(11)?, + smallclaims::store::claim_from_row(row)?)) + }).map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? }; - let mut active = Vec::new(); - for id in ids { - if excluded == Some(id.as_str()) { continue; } - let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? - .ok_or_else(|| forbidden("external grant is absent"))?; - if grant.actor.as_deref() != Some(owner) - || (expiry_cut.is_some() && revoked(state, &grant)?) { - continue; + // Verify foreign grants and transitions together: one sealed membership + // snapshot, and each envelope signature at most once for this fold. + let foreign_ids: Vec = rows.iter() + .filter(|(_, _, claim)| claim.origin != state.store.origin()) + .map(|(_, _, claim)| claim.id.clone()).collect(); + let authenticated = if foreign_ids.is_empty() { + std::collections::BTreeSet::new() + } else { + state.store.claim_ids_with_authenticated_member_writers(&foreign_ids).map_err(ApiError::internal)? + }; + let mut candidates = std::collections::BTreeMap::, Option, Option)>::new(); + for (id, role, claim) in rows { + let entry = candidates.entry(id).or_default(); + match role.as_str() { + "grant" => entry.0 = Some(claim), + "policy" => entry.1 = Some(claim), + "revoked" => entry.2 = Some(claim), + _ => unreachable!("candidate query has fixed roles"), } - let policy = effective(state, &grant)?; + } + let mut active = Vec::new(); + for (_, (grant, mut policy, mut revocation)) in candidates { + let grant = grant.ok_or_else(|| ApiError::internal("candidate grant is absent"))?; + if grant.actor.as_deref() != Some(owner) { continue; } let foreign = grant.origin != state.store.origin(); - // Custom fields are open at replication admission. Actor/origin strings - // alone therefore confer no authority to suspend another credential. - // Only well-formed owner grants carried by a signed, admitted issuer - // count; policies must have the same provenance and immutable identity. - if !valid_foreign_grant(state, &grant, &policy)? - || (foreign && !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)?) { - continue; + if foreign { + if !authenticated.contains(&grant.id) { continue; } + // A Legacy-window or invalid signature must not hide an older + // authenticated renewal/revocation from the same issuer. + if let Some(candidate) = policy.as_ref().filter(|row| !authenticated.contains(&row.id)) { + policy = transition_before(state, &grant, POLICY, Some(candidate.store_index))?; + } + if let Some(candidate) = revocation.as_ref().filter(|row| !authenticated.contains(&row.id)) { + revocation = transition_before(state, &grant, REVOKED, Some(candidate.store_index))?; + } } - let source = fields(&policy)?; + if expiry_cut.is_some() && revocation.is_some() { continue; } + let policy = policy.as_ref().unwrap_or(&grant); + if !valid_foreign_grant(state, &grant, policy)? { continue; } + let source = fields(policy)?; if expiry_cut.is_none_or(|now| unexpired(source, now)) { let profile = Profile::stored(fields(&grant)?)?; profile.compatible(Profile::stored(source)?)?; @@ -345,19 +375,26 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, Ok(()) } -// SQL seeks directly to the latest authoritative transition. Overlay histories -// never reach Rust or increase the number of store reads per authentication. +// Seek past unauthenticated issuer rows, not just structurally malformed rows. +// Wrong-origin/actor histories never enter the seek's indexed prefix. fn transition(state: &AppState, granted: &ClaimRecord, kind: &str) -> Result, ApiError> { - let candidate = crate::store::assistant_write::validated_transition( - &state.store.readers.get(), granted, owning_person(state)?, state.store.origin(), kind, - ).map_err(ApiError::internal)?; - if let Some(candidate) = &candidate { - if granted.origin != state.store.origin() - && !state.store.claim_has_authenticated_member_writer(&candidate.id).map_err(ApiError::internal)? { - return Ok(None); + transition_before(state, granted, kind, None) +} + +fn transition_before(state: &AppState, granted: &ClaimRecord, kind: &str, mut before: Option) + -> Result, ApiError> { + let connection = state.store.readers.get(); + loop { + let candidate = crate::store::assistant_write::validated_transition_before( + &connection, granted, owning_person(state)?, state.store.origin(), kind, before, + ).map_err(ApiError::internal)?; + let Some(candidate) = candidate else { return Ok(None); }; + if granted.origin == state.store.origin() + || state.store.claim_has_authenticated_member_writer(&candidate.id).map_err(ApiError::internal)? { + return Ok(Some(candidate)); } + before = Some(candidate.store_index); } - Ok(candidate) } pub fn revoked(state: &AppState, granted: &ClaimRecord) -> Result { @@ -428,7 +465,7 @@ pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) && (granted.origin == state.store.origin() || state.store.claim_has_authenticated_member_writer(&granted.id).map_err(ApiError::internal)?) { let profile = Profile::stored(fields(granted)?)?; - if candidate_grants_except(state, principal(fields(granted)?)?, Some(now), Some(&granted.id))? + if candidate_grants_except(state, principal(fields(granted)?)?, Some(now), Some(&granted.id), Some(profile))? .iter().any(|(_, other)| *other != profile) { return Err(conflict_error()); } @@ -532,9 +569,41 @@ mod tests { (admitted, usable) } + // Deliberately walk subject history rather than reuse the production SQL + // transition selector, effective-policy fold, or revocation helper. + pub(super) fn reference_transition(state: &AppState, grant: &ClaimRecord, kind: &str) + -> Result, ApiError> { + let original = fields(grant)?; + let mut history = state.store.claims_for(&grant.subject, Some(kind)).map_err(ApiError::internal)?; + history.sort_by_key(|claim| std::cmp::Reverse(claim.store_index)); + for claim in history { + let Ok(source) = fields(&claim) else { continue }; + if claim.origin != grant.origin || claim.actor.as_deref() != Some(owning_person(state)?) + || source["issuer"] != owning_person(state)? + || source["grant_id"] != original["grant_id"] + || source["issuer"] != original["issuer"] + || principal(source).ok() != principal(original).ok() + || principal(source).is_err() + || Profile::stored(source).ok() != Profile::stored(original).ok() + || Profile::stored(source).is_err() { + continue; + } + if kind == POLICY && (!valid_foreign_grant(state, grant, &claim)? + || source["expires_at_unix_ms"].as_u64().is_none()) { + continue; + } + if grant.origin != state.store.origin() + && !state.store.claim_has_authenticated_member_writer(&claim.id).map_err(ApiError::internal)? { + continue; + } + return Ok(Some(claim)); + } + Ok(None) + } + // Independent Rust-only candidate scan: C's authenticated transition and // typed-conflict semantics, without the production SQL active prefilter. - fn rust_only_admission(state: &AppState, source: &Value) -> Result<(), ApiError> { + pub(super) fn rust_only_admission(state: &AppState, source: &Value) -> Result<(), ApiError> { let profile = Profile::stored(source)?; let principal = principal(source)?; owning_person(state)?; @@ -549,11 +618,13 @@ mod tests { for id in ids { let grant = state.store.claim_by_id(&id).map_err(ApiError::internal)? .ok_or_else(|| forbidden("external grant is absent"))?; - if grant.origin != state.store.origin() || grant.actor.as_deref() != Some(owning_person(state)?) - || revoked(state, &grant)? { + if grant.actor.as_deref() != Some(owning_person(state)?) + || (grant.origin != state.store.origin() + && !state.store.claim_has_authenticated_member_writer(&grant.id).map_err(ApiError::internal)?) + || reference_transition(state, &grant, REVOKED)?.is_some() { continue; } - let policy = effective(state, &grant)?; + let policy = reference_transition(state, &grant, POLICY)?.unwrap_or_else(|| grant.clone()); if !valid_foreign_grant(state, &grant, &policy)? { continue; } let active = fields(&policy)?; if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > admission_now_ms() { diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 7f0bcd021e3..a130f26edc6 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -44,8 +44,13 @@ fn replicate(from: &AppState, to: &AppState) { } fn admitted_pair(root: &std::path::Path) -> (AppState, AppState) { + admitted_pair_with_floor(root, 0) +} + +fn admitted_pair_with_floor(root: &std::path::Path, floor: u64) -> (AppState, AppState) { let a = member(root, "alder"); let b = member(root, "birch"); + b.store.set_writer_floor(floor).unwrap(); let anchor = Arc::new(MemberKey::generate().unwrap().0); let peer = Arc::new(MemberKey::generate().unwrap().0); for (state, key) in [(&a, &anchor), (&b, &peer)] { @@ -54,7 +59,8 @@ fn admitted_pair(root: &std::path::Path) -> (AppState, AppState) { } a.store.admit_fleet_anchor(FLEET, anchor.public(), "listening").unwrap(); raw_claim(&a, "host/birch", "fleet.member-admitted", OWNER, json!({ - "fleet_id":FLEET,"member_key":peer.public(),"via":"invite","mode":"listening" + "fleet_id":FLEET,"member_key":peer.public(),"via":"invite","mode":"listening", + "writer_floor":floor })); replicate(&a, &b); assert!(matches!(b.store.fleet_membership().unwrap().state("birch"), @@ -362,6 +368,72 @@ fn malformed_same_origin_expired_policy_keeps_the_last_valid_live_policy() { } } +#[test] +fn unauthenticated_legacy_transitions_preserve_authenticated_lifecycle_history() { + let root = tempfile::tempdir().unwrap(); + for (scenario, kind) in [("renewal", POLICY), ("renewal", REVOKED), + ("narrowing", POLICY), ("revocation", REVOKED)] { + let (a, b) = admitted_pair_with_floor(root.path(), 10); + let local = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let mut expired = grant_fields(SERVICE_ID, "service"); + expired["expires_at_unix_ms"] = json!(if scenario == "renewal" { 1_u64 } else { u64::MAX }); + let foreign = raw_claim(&b, &subject(SERVICE_ID).unwrap(), GRANTED, OWNER, expired); + let mut live = fields(&foreign).unwrap().clone(); + live["expires_at_unix_ms"] = json!(if scenario == "narrowing" { 1_u64 } else { u64::MAX }); + let live = raw_claim(&b, &foreign.subject, POLICY, OWNER, live); + let authentic_revoke = (scenario == "revocation").then(|| + raw_claim(&b, &foreign.subject, REVOKED, OWNER, fields(&foreign).unwrap().clone())); + replicate(&b, &a); + assert!(a.store.claim_has_authenticated_member_writer(&foreign.id).unwrap()); + assert!(a.store.claim_has_authenticated_member_writer(&live.id).unwrap()); + if let Some(revoke) = &authentic_revoke { + assert!(a.store.claim_has_authenticated_member_writer(&revoke.id).unwrap()); + } + + // A different incarnation of the same writer sends a signed envelope + // below the admission floor. It is visible Legacy data, not authority, + // even though origin, owner actor and immutable grant identity match. + let legacy = member(root.path(), "birch"); + legacy.store.set_member_key(Some(Arc::new(MemberKey::generate().unwrap().0))).unwrap(); + let mut source = fields(&foreign).unwrap().clone(); + source["expires_at_unix_ms"] = json!(if scenario == "narrowing" { u64::MAX } else { 1_u64 }); + let overlay = raw_claim(&legacy, &foreign.subject, kind, OWNER, source); + replicate(&legacy, &a); + let overlay = a.store.claim_by_id(&overlay.id).unwrap().unwrap(); + let retained = a.store.claim_by_id(&live.id).unwrap().unwrap(); + assert!(overlay.store_index > retained.store_index); + assert_eq!(overlay.origin, foreign.origin); + assert_eq!(overlay.actor, foreign.actor); + let connection = a.store.readers.get(); + let (signatures, sequence): (u64, u64) = connection.query_row( + "SELECT count(*),max(sequence) FROM replica_records JOIN replica_envelope_signatures + USING(writer,sequence,envelope_hash) WHERE claim_id=?1", + [&overlay.id], |row| Ok((row.get(0)?, row.get(1)?))).unwrap(); + assert!(signatures > 0, "this regression must pass the signature-row prefilter"); + drop(connection); + assert!(matches!(a.store.fleet_membership().unwrap().window("birch", sequence), + smallclaims::fleet::Window::Legacy)); + assert!(!a.store.claim_has_authenticated_member_writer(&overlay.id).unwrap()); + assert_eq!(tests::reference_transition(&a, &foreign, POLICY).unwrap().unwrap().id, live.id); + assert_eq!(tests::reference_transition(&a, &foreign, REVOKED).unwrap().map(|claim| claim.id), + authentic_revoke.as_ref().map(|claim| claim.id.clone())); + assert_eq!(effective(&a, &foreign).unwrap().id, live.id); + assert_eq!(revoked(&a, &foreign).unwrap(), scenario == "revocation"); + let candidate = json!({"profile":"assistant","principal":PRINCIPAL}); + let reference = tests::rust_only_admission(&a, &candidate).map_err(|error| error.code); + let production = admit_profile(&a, &candidate).map_err(|error| error.code); + assert_eq!(production, reference, "{scenario}/{kind}: independent provenance-aware oracle"); + assert_eq!(production.is_err(), scenario == "renewal"); + if scenario == "renewal" { + assert_witness(&profile_conflict(&a, &local).unwrap().unwrap()); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).expect_err("the old renewal remains active")); + } else { + assert!(profile_conflict(&a, &local).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + } + } +} + #[test] fn signed_revocation_arriving_before_its_grant_converges_without_conflict() { let root = tempfile::tempdir().unwrap(); @@ -458,6 +530,10 @@ fn p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history() { let after = acquisitions("p1-policy-candidates-after"); assert!(before > 0, "the measured scan must acquire real read connections"); assert_eq!(after, before, "expired policy history and wrong-origin renewals must be pruned before per-grant reads"); + let two = acquisitions("p1-authentication-n2"); + let six = acquisitions("p1-authentication-n6"); + assert!(two > 0, "authentication must acquire real read connections"); + assert_eq!(six, two, "authenticated foreign candidates must use constant-N batched reads"); return; } smallclaims::profile::init_from_env(); @@ -490,4 +566,24 @@ fn p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history() { } replicate(&b, &a); measure("p1-policy-candidates-after"); + + let (a, b) = admitted_pair(root.path()); + issue(&a, ASSISTANT_ID, "assistant").unwrap(); + for (count, label) in [(1, "p1-authentication-n2"), (5, "p1-authentication-n6")] { + let start = if count == 1 { 0 } else { 1 }; + for index in start..count { + let id = format!("{:024x}", index + 2000); + let source = grant_fields(&id, "service"); + let grant = raw_claim(&b, &subject(&id).unwrap(), GRANTED, OWNER, source.clone()); + raw_claim(&b, &grant.subject, POLICY, OWNER, source); + } + replicate(&b, &a); + let operation = smallclaims::profile::Op::start(label, None).unwrap(); + { + let _entered = operation.enter(); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID) + .expect_err("all measured opposite-profile grants remain active")); + } + operation.finish(); + } } diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 0f926aeceed..96e764b0002 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -24,15 +24,30 @@ pub fn principal(fields: &Value) -> Option<&str> { } } -/// Select the last authoritative transition, not the last arbitrary claim overlay. -/// Foreign results still require cryptographic member-writer verification by the -/// caller; the SQL provenance predicate excludes legacy and unsigned records. +/// Select the last structurally valid transition. Foreign results require full +/// cryptographic member-writer verification by the caller, including its keyed +/// membership window; a signature row alone does not authenticate provenance. pub fn validated_transition( connection: &Connection, granted: &ClaimRecord, owner: &str, local_origin: &str, kind: &str, ) -> Result, FractalError> { + validated_transition_before(connection, granted, owner, local_origin, kind, None) +} + +/// Continue an indexed seek past a structurally valid but unauthenticated row. +pub fn validated_transition_before( + connection: &Connection, granted: &ClaimRecord, owner: &str, local_origin: &str, + kind: &str, before: Option, +) -> Result, FractalError> { + static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| { + validated_transition_query().replace( + "ORDER BY claims.store_index DESC LIMIT 1", + "AND (?7 IS NULL OR claims.store_index &'static str { QUERY.as_str() } +/// Hydrate candidates and their latest structurally valid transitions in one +/// statement. `selection` returns grant IDs using parameters 1 through 6; +/// parameter 7 is the owner, 8 an optional profile to ignore, 9 an excluded ID. +/// The correlated subqueries use the same validation as the mutation writer. +pub fn validated_candidates_query(selection: &str) -> String { + let seek = |kind: &str| { + validated_transition_query() + .replace(&format!("SELECT {CLAIM_COLUMNS}"), "SELECT claims.id") + .replace("?5", "granted.id") + .replace("?1", "granted.subject") + .replace("?2", &format!("'{kind}'")) + .replace("?3", "granted.origin") + .replace("?4", "?7") + }; + let policy = seek("custom.client.assistant.v1.policy"); + let revoked = seek("custom.client.assistant.v1.revoked"); + format!( + "WITH selected AS ({selection}), grants AS ( + SELECT claims.* FROM selected JOIN claims ON claims.id=selected.id + WHERE (?9 IS NULL OR claims.id<>?9) + AND (?8 IS NULL OR COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant') IS NOT ?8) + ) + SELECT {CLAIM_COLUMNS}, claims.id, 'grant' FROM grants AS claims + UNION ALL + SELECT {CLAIM_COLUMNS}, granted.id, 'policy' FROM grants AS granted + JOIN claims ON claims.id=({policy}) + UNION ALL + SELECT {CLAIM_COLUMNS}, granted.id, 'revoked' FROM grants AS granted + JOIN claims ON claims.id=({revoked})" + ) +} + pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let granted = authorized_grant(connection, origin, authorization)?; granted.body["fields"]["grant_id"].as_str().filter(|id| id.starts_with("assistant-grant/") && id.len() > "assistant-grant/".len()) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 0ea28ee7292..1544a9453d3 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -1,29 +1,67 @@ //! Opt-in, real HTTP/Unix daemon measurement (not a router oneshot or mocked daemon). -//! Run this same test source on both revisions, sequentially on the same host, from each -//! worktree root (cargo runs tests from crates/fractal, so pass absolute paths): +//! Run this same source sequentially on each revision, from that worktree root. +//! Bind the build to its source revision and select the executable from Cargo JSON, +//! NEVER by searching a shared target directory for `integration-*` (stale head/base +//! binaries can coexist). `baseline` is a scenario label, NOT executable identity. //! ```sh -//! # fixed head: full q39 scenario plus read counts -//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/fixed-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=indexed ST_ADMISSION_FOREIGN_ACTIVE=3 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/fixed.json" CARGO_TARGET_DIR="$PWD/tmp/867-admission/target" cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 -//! # origin/main: read counts only, without overlays its admission does not ignore -//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/main-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=baseline ST_ADMISSION_READ_COUNTS_ONLY=1 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/main.json" CARGO_TARGET_DIR="$PWD/tmp/867-admission/target" cargo test --release -p fractal --test integration daemon_cost::assistant_admission::authenticated_get_during_pairing -- --exact --nocapture --test-threads=1 +//! export ST_ADMISSION_SOURCE_ROOT="$PWD" +//! export ST_ADMISSION_EXPECT_REVISION="$(git rev-parse HEAD)" +//! export ST_ADMISSION_BUILD_REVISION="$ST_ADMISSION_EXPECT_REVISION" +//! export ST_ADMISSION_BUILD_PROVENANCE="git worktree; harness backport only; cargo command below" +//! export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$PWD/tmp/867-admission/target}" +//! mkdir -p "$PWD/tmp/867-admission" +//! cargo test --release -p fractal --test integration --no-run --message-format=json > "$PWD/tmp/867-admission/build.jsonl" +//! export ST_ADMISSION_BINARY="$(jq -rs '[.[] | select(.reason == "compiler-artifact" and .target.name == "integration" and .profile.test and .executable != null) | .executable] | unique | if length == 1 then .[0] else error("expected one integration test executable") end' "$PWD/tmp/867-admission/build.jsonl")" +//! # Like-for-like counts: run N=2 AND N=5 at BOTH revisions; fresh profiles. +//! # Set variant=baseline on base, indexed on head. Do not reuse an old binary. +//! for n in 2 5; do +//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-n$n-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=indexed ST_ADMISSION_LOCAL_ACTIVE="$n" ST_ADMISSION_READ_COUNTS_ONLY=1 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 ST_ADMISSION_FOREIGN_ACTIVE=0 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-n$n.json" "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::authenticated_get_during_pairing --exact --nocapture --test-threads=1 +//! done +//! # Head only, full extended q39: 2 local + 3 authenticated foreign grants, +//! # 10000 expired grants/principal, 3 renewals each, 1000 overlays/active grant, +//! # 200 concurrent GET/completion pairs/mode; do NOT set READ_COUNTS_ONLY. +//! ST3_PROFILE_DIR="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-q39-profile" ST3_PROFILE_SLOW_MS=0 ST_ADMISSION_VARIANT=indexed ST_ADMISSION_LOCAL_ACTIVE=2 ST_ADMISSION_HISTORY=10000 ST_ADMISSION_SAMPLES=200 ST_ADMISSION_FOREIGN_ACTIVE=3 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=1000 ST_ADMISSION_REPORT="$PWD/tmp/867-admission/$ST_ADMISSION_EXPECT_REVISION-q39.json" "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::authenticated_get_during_pairing --exact --nocapture --test-threads=1 //! ``` -//! For a like-for-like count, also run the fixed head with the origin/main command's -//! ST_ADMISSION_READ_COUNTS_ONLY=1 ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 settings -//! (VARIANT=indexed there). Each revision has its own worktree, hence its own tmp/. -//! Backport to origin/main (d477c67ad1), which lacks this file and three head APIs: -//! 1. copy this file to crates/fractal/tests/daemon_cost/assistant_admission.rs and add -//! `mod assistant_admission;` to crates/fractal/tests/daemon_cost.rs; -//! 2. replace the body of `mod revision_api` at the end of this file with the -//! origin/main body documented in its comment. Nothing else changes. -//! On origin/main, only ST_ADMISSION_READ_COUNTS_ONLY=1, ST_ADMISSION_FOREIGN_ACTIVE=0 and -//! ST_ADMISSION_WRONG_ORIGIN_OVERLAYS=0 are valid: it has no provenance check and does -//! not ignore wrong-origin overlays, and its credential-hash admission has no index probe. +//! Backport to base d477c67ad1: copy this file, add `mod assistant_admission;` to +//! crates/fractal/tests/daemon_cost.rs, and replace ONLY `revision_api`'s body +//! with the documented base body below. Build there using the commands above; +//! change VARIANT to baseline in the counts loop. Base supports local N=2/5, +//! but requires READ_COUNTS_ONLY=1, FOREIGN_ACTIVE=0, WRONG_ORIGIN_OVERLAYS=0. +//! It has no provenance API and does not ignore foreign overlays or expose an indexed probe. +//! For a git archive (no .git), set ST_ADMISSION_SOURCE_REVISION to the archived +//! full commit ID and ST_ADMISSION_SOURCE_PROVENANCE to the exact archive command +//! and source/build evidence location; retain the build env above and set EXPECT +//! to that ID explicitly instead of git rev-parse. These are declared provenance, +//! not a claim that a reused binary was built from that archive. The executable's +//! embedded revision MUST match EXPECT; its canonical path and SHA256 are reported. +//! A worktree report records actual `git rev-parse HEAD`; archives record null for +//! that observation and separately record the explicit source revision/evidence. +//! Counts are observations, not expectations: rerun true base N=2 to establish or +//! explain the previously cited 4/12/16 (auth/caller-bound/approval-once) counts. +//! Old base 8/8/9 with identical head SQL is not evidence of base behavior without +//! executable identity. Compare direct auth separately from GET: receipt/proof work +//! and the number of live grants differ. Never relabel an existing report as base. +//! Prior run: `git archive d477c67ad1` into a base directory, harness-only +//! backport, then `cargo test --release -p fractal --test integration ...` in a +//! shared target directory previously used by head. The retained report +//! /var/tmp/867c-evidence/fix/base-counts-1.json lacked executable identity. +//! This fixture serves routers IN PROCESS: daemon_bench's standalone binary +//! discovery cannot explain its direct-auth measurement. A reused integration +//! executable/dependency artifact is a hypothesis, not an established cause. +//! Source inspection of d477c67ad1 authenticate/session implies four acquisitions +//! (digest lookup, claim_by_id, POLICY, REVOKED), independent of N. GET 12/16 must +//! be remeasured with the same route, proof, receipt flush and profiling scope; +//! they are not asserted as expected counts by this fixture. Retain reports and +//! build JSON to distinguish executable reuse from instrumentation/scope differences. //! ST_ADMISSION_HISTORY (default 10000) is expired grants PER principal; ST_ADMISSION_SAMPLES //! (default 200) is measured GET/completion pairs PER read mode. Setup and proof creation are //! outside timing. Each pair starts behind a barrier, with no sleeps, polling, retries or timers. //! ST_ADMISSION_FOREIGN_ACTIVE optionally adds verified same-profile active foreign grants //! (default 0; use 3 for the provenance-check scenario). ST_ADMISSION_REPORT optionally //! saves the complete JSON report. Hardware is observed from uname/lscpu, not inferred. +//! ST_ADMISSION_LOCAL_ACTIVE (default 2, minimum 2) creates that many local active +//! grants, including the two measured modes; total N is local + FOREIGN_ACTIVE. +//! Extra local grants use caller-bound-allow and remain active throughout sampling. //! Each expired grant has three still-expired POLICY renewals. Each active session has //! ST_ADMISSION_WRONG_ORIGIN_OVERLAYS (default 1000; 0 allowed) authenticated wrong-origin //! overlays, alternating POLICY and REVOKED; every measured read must still succeed. @@ -71,6 +109,58 @@ fn count(name: &str, default: usize) -> usize { std::env::var(name).map_or(default, |s| s.parse().expect("nonnegative integer setting")) } +/// Bind source checkout/archive, build declaration and the actual running executable. +/// Embedded env values are Cargo-tracked inputs, not runtime overrides of old artifacts. +fn execution_identity() -> Value { + let required = |name: &str| std::env::var(name).unwrap_or_else(|_| panic!("set {name}; see harness instructions")); + let expected = required("ST_ADMISSION_EXPECT_REVISION"); + assert_eq!(expected.len(), 40, "use a full commit ID"); + assert!(expected.bytes().all(|byte| byte.is_ascii_hexdigit()), "use a full commit ID"); + let built_revision = option_env!("ST_ADMISSION_BUILD_REVISION") + .expect("build with ST_ADMISSION_BUILD_REVISION; do not reuse an unidentified executable"); + let build_provenance = option_env!("ST_ADMISSION_BUILD_PROVENANCE") + .expect("build with ST_ADMISSION_BUILD_PROVENANCE"); + assert!(!build_provenance.trim().is_empty(), "build provenance must not be empty"); + assert_eq!(built_revision, expected, "the executable was built for a different source revision"); + let binary = std::env::current_exe().unwrap().canonicalize().unwrap(); + assert_eq!(binary, PathBuf::from(required("ST_ADMISSION_BINARY")).canonicalize().unwrap(), + "execute the explicitly selected Cargo artifact"); + let source_root = PathBuf::from(required("ST_ADMISSION_SOURCE_ROOT")).canonicalize().unwrap(); + let (git_head, source_revision, source_provenance) = if source_root.join(".git").exists() { + let git = |args: &[&str]| { + let output = std::process::Command::new("git").arg("-C").arg(&source_root).args(args).output().unwrap(); + assert!(output.status.success(), "git identity command failed"); + String::from_utf8(output.stdout).unwrap().trim().to_owned() + }; + assert_eq!(PathBuf::from(git(&["rev-parse", "--show-toplevel"])).canonicalize().unwrap(), source_root); + let head = git(&["rev-parse", "HEAD"]); + assert_eq!(head, expected, "source checkout and executable revision differ"); + let status = git(&["status", "--porcelain", "--untracked-files=no"]); + (Some(head.clone()), head, format!("git worktree; tracked changes:\n{status}")) + } else { + let revision = required("ST_ADMISSION_SOURCE_REVISION"); + let provenance = required("ST_ADMISSION_SOURCE_PROVENANCE"); + assert_eq!(revision, expected, "archive source and executable revision differ"); + assert!(!provenance.trim().is_empty(), "archive evidence must not be empty"); + (None, revision, provenance) + }; + use std::io::Read as _; + let mut executable = std::fs::File::open(&binary).unwrap(); + let mut hash = ring::digest::Context::new(&ring::digest::SHA256); + let mut buffer = [0_u8; 65_536]; + loop { + let bytes = executable.read(&mut buffer).unwrap(); + if bytes == 0 { break; } + hash.update(&buffer[..bytes]); + } + let sha256 = hex::encode(hash.finish().as_ref()); + json!({"git_rev_parse_head":git_head,"source_revision":source_revision, + "source_root":source_root,"source_provenance":source_provenance, + "binary_path":binary,"binary_sha256":sha256,"build_revision":built_revision, + "build_provenance":build_provenance, + "identity_limit":"build/archive provenance is explicitly supplied; SHA256 identifies executed bytes, not independent source attestation"}) +} + fn value(response: Value) -> Value { response.get("value").cloned().unwrap_or(response) } @@ -228,6 +318,8 @@ fn foreign_same_profile(store: &Store, anchor: Arc= 2, "the fixture measures two distinct read modes"); + if variant == "baseline" { + assert!(counts_only && foreign_active == 0 && overlays == 0, + "base requires READ_COUNTS_ONLY=1, FOREIGN_ACTIVE=0, WRONG_ORIGIN_OVERLAYS=0"); + } let root = tempfile::tempdir().unwrap(); let database = root.path().join("admission.sqlite"); let store = Arc::new(Store::open(&database, NODE).unwrap()); @@ -298,12 +396,16 @@ async fn authenticated_get_during_pairing() { } sessions.push((mode, paired)); } + let mut extra_sessions = Vec::new(); + for _ in 2..local_active { + extra_sessions.push(complete(&http, &base, &begin(&owner, "caller-bound-allow").await).await); + } // Synthetic expired grants retain valid production field shapes, native Store envelopes, // origin/actor and per-subject indexes. They are never service-profile fixtures and never // authorize a request. Grant history is deliberately nonempty for BOTH principals. let template_subject = format!("custom/client/assistant-v1-{}", sessions[0].1["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); let template = store.claims_for_subject_kind_at(&template_subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); - let active = sessions.iter().map(|(_, paired)| { + let active = sessions.iter().map(|(_, paired)| paired).chain(extra_sessions.iter()).map(|paired| { let subject = format!("custom/client/assistant-v1-{}", paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/")); let grant = store.claims_for_subject_kind_at(&subject, GRANTED, None, true, 1).unwrap().claims.pop().unwrap(); (subject, grant.body["fields"].clone()) @@ -472,6 +574,7 @@ async fn authenticated_get_during_pairing() { let final_connection = rusqlite::Connection::open(&database).unwrap(); let final_rows: u64 = final_connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); let report = json!({"variant":variant,"read_counts_only":counts_only,"revision_api":revision_api::REVISION, + "execution_identity":identity,"local_active_grants":local_active,"active_grants_n":local_active + foreign_active, "hardware_uname":hardware("uname", &["-a"]), "hardware_lscpu":hardware("lscpu", &["-J"]),"hardware_hostname":hardware("hostname", &[]), "host_description":"Observed local benchmark host; no prescribed hardware identity", @@ -500,14 +603,17 @@ async fn authenticated_get_during_pairing() { /// Synthetic large-store index build, independent of the HTTP latency fixture: /// ```sh -/// ST_ADMISSION_INDEX_BUILD=1 cargo test --release -p fractal --test integration daemon_cost::assistant_admission::synthetic_large_store_index_build -- --exact --nocapture --test-threads=1 +/// ST_ADMISSION_INDEX_BUILD=1 "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::synthetic_large_store_index_build --exact --nocapture --test-threads=1 /// ``` /// ST_ADMISSION_INDEX_ROWS defaults to 1,000,000 total claims. ST_ADMISSION_INDEX_REPORT /// optionally saves JSON. Run on the indexed branch. This measures the exact startup index /// CREATE DDL, not full Store::open, cold-disk startup, admission, or signature verification. +/// Use the same identity-bound build/export commands above (including SOURCE_ROOT, +/// EXPECT_REVISION and BINARY). Every index report carries the same execution identity. #[test] fn synthetic_large_store_index_build() { if std::env::var_os("ST_ADMISSION_INDEX_BUILD").is_none() { return; } + let identity = execution_identity(); assert!(fractal_daemon::test_support::optimized_build(), "use --release"); let rows = number("ST_ADMISSION_INDEX_ROWS", 1_000_000); let root = tempfile::tempdir().unwrap(); @@ -583,6 +689,7 @@ fn synthetic_large_store_index_build() { }; let report = json!({ "measurement":"synthetic startup index CREATE DDL only; not full startup", + "execution_identity":identity, "claims_rows":actual_rows,"synthetic_copied_rows":rows - 1, "fixture_authority":"one native template; SQL copies are not signature-authoritative", "index_name":INDEX,"index_create_sql":CREATE_INDEX,"index_build_ms":elapsed_ms, @@ -606,6 +713,7 @@ fn synthetic_large_store_index_build() { /// ```ignore /// use super::*; /// pub const REVISION: &str = "origin/main"; +/// pub const VARIANT: &str = "baseline"; /// // origin/main admission is a credential-hash lookup with no candidate query. /// pub const ADMISSION_QUERY: &str = A_QUERY; /// pub fn verified_writer(_: &Store, _: &str) -> bool { @@ -616,6 +724,7 @@ fn synthetic_large_store_index_build() { mod revision_api { use super::*; pub const REVISION: &str = "fixed-head"; + pub const VARIANT: &str = "indexed"; pub const ADMISSION_QUERY: &str = api::client_v0::external_grants::admission_query_for_test(); pub fn verified_writer(store: &Store, id: &str) -> bool { store.claim_has_authenticated_member_writer(id).unwrap() diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 4d2909da38d..b4d261a6a57 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -2951,15 +2951,35 @@ impl Store { /// degraded envelope. Legacy and unkeyed writers do not authenticate provenance. Reads only sealed /// membership; this query never seals local batches or scans the replication log. pub fn claim_has_authenticated_member_writer(&self, claim_id: &str) -> Result { + Ok(self.authenticated_member_writer_claim_ids(&serde_json::to_string(&[claim_id])?)? + .contains(claim_id)) + } + + /// The requested claims with fully authenticated keyed-member envelope provenance. + /// Uses the same membership windows, record states, origin check and fleet/shard signature + /// domain as [`Self::claim_has_authenticated_member_writer`]. All claims share one read + /// snapshot and one sealed-membership lookup; identical envelope signatures are verified + /// at most once, including signatures shared by several claims or repeated input IDs. + pub fn claim_ids_with_authenticated_member_writers( + &self, + claim_ids: &[String], + ) -> Result> { + if claim_ids.is_empty() { + return Ok(BTreeSet::new()); + } + self.authenticated_member_writer_claim_ids(&serde_json::to_string(claim_ids)?) + } + + fn authenticated_member_writer_claim_ids(&self, claim_ids: &str) -> Result> { self.read_snapshot(|_| { let membership = self.fleet_membership_sealed()?; let connection = self.readers.get(); let Some(fleet_id) = self.signing_fleet_id(&connection)? else { - return Ok(false); + return Ok(BTreeSet::new()); }; let shard = fleet_meta(&connection, "shard_id")?; let mut statement = connection.prepare_cached( - "SELECT records.writer, records.sequence, records.envelope_hash, + "SELECT records.claim_id, records.writer, records.sequence, records.envelope_hash, signatures.member_key, signatures.signature FROM replica_records AS records JOIN claims ON claims.id=records.claim_id AND claims.origin=records.writer @@ -2967,30 +2987,50 @@ impl Store { USING (writer, sequence, envelope_hash) JOIN replica_envelope_signatures AS signatures USING (writer, sequence, envelope_hash) - WHERE records.claim_id=?1 AND records.state='valid' + WHERE records.claim_id IN (SELECT value FROM json_each(?1)) + AND records.state='valid' AND envelopes.receipt_state IN ('validated', 'degraded')", )?; - let rows = statement.query_map([claim_id], |row| { + let rows = statement.query_map([claim_ids], |row| { Ok(( row.get::<_, String>(0)?, - row.get::<_, u64>(1)?, - row.get::<_, String>(2)?, - row.get::<_, String>(3)?, - row.get::<_, String>(4)?, + ( + row.get::<_, String>(1)?, + row.get::<_, u64>(2)?, + row.get::<_, String>(3)?, + row.get::<_, String>(4)?, + row.get::<_, String>(5)?, + ), )) })?; + let mut authenticated = BTreeSet::new(); + let mut verified = BTreeMap::new(); for row in rows { - let (writer, sequence, hash, key, signature) = row?; - if matches!( - membership.window(&writer, sequence), - crate::fleet::Window::Keyed(keys) if keys.contains(&key) - ) && VerifiedEnvelopeSignature::verify( - shard.as_deref(), &fleet_id, &writer, sequence, &hash, &key, &signature, - ).is_some() { - return Ok(true); + let (claim_id, signature_identity) = row?; + if authenticated.contains(&claim_id) { + continue; + } + let valid = *verified.entry(signature_identity).or_insert_with_key(|identity| { + let (writer, sequence, hash, key, signature) = identity; + if !matches!( + membership.window(writer, *sequence), + crate::fleet::Window::Keyed(keys) if keys.contains(key) + ) { + return false; + } + #[cfg(test)] + membership_query_tests::SIGNATURE_VERIFICATIONS.with(|count| { + count.set(count.get() + 1); + }); + VerifiedEnvelopeSignature::verify( + shard.as_deref(), &fleet_id, writer, *sequence, hash, key, signature, + ).is_some() + }); + if valid { + authenticated.insert(claim_id); } } - Ok(false) + Ok(authenticated) }) } diff --git a/crates/smallclaims/src/store/membership_query_tests.rs b/crates/smallclaims/src/store/membership_query_tests.rs index da53fc5fb3b..17023142724 100644 --- a/crates/smallclaims/src/store/membership_query_tests.rs +++ b/crates/smallclaims/src/store/membership_query_tests.rs @@ -5,6 +5,7 @@ use std::cell::Cell; thread_local! { static STATEMENTS: Cell = const { Cell::new(0) }; + pub(super) static SIGNATURE_VERIFICATIONS: Cell = const { Cell::new(0) }; } fn fixture() -> Connection { @@ -481,12 +482,17 @@ fn authenticated_member_writer_accepts_valid_records_in_a_degraded_envelope() { ).unwrap(); cache_member_window(&store, key.public(), 0); assert!(store.claim_has_authenticated_member_writer(&claim).unwrap()); + assert_eq!( + store.claim_ids_with_authenticated_member_writers(std::slice::from_ref(&claim)).unwrap(), + BTreeSet::from([claim.clone()]), + ); store.connection.write().execute( /* sqlite-large-value: allow-for-now lv-h9e7e7a841384 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ "UPDATE replica_envelope_signatures SET signature='invalid'", [], ).unwrap(); cache_member_window(&store, key.public(), 0); assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); + assert!(store.claim_ids_with_authenticated_member_writers(&[claim]).unwrap().is_empty()); } #[test] @@ -525,6 +531,10 @@ fn authenticated_member_writer_requires_origin_valid_record_admitted_envelope_an store.connection.write().execute_batch(/* sqlite-large-value: allow-for-now lv-h622f4fdd0f6d owner=smallclaims::store::membership_query_tests TODO=trace-statement-and-value-representation */ sql).unwrap(); cache_member_window(&store, key.public(), 0); assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap(), "{sql}"); + assert!( + store.claim_ids_with_authenticated_member_writers(&[claim]).unwrap().is_empty(), + "{sql}", + ); } } @@ -553,5 +563,92 @@ fn authenticated_member_writer_rejects_wrong_fleet_and_shard_signature_domains() drop(connection); cache_member_window(&store, key.public(), 0); assert!(!store.claim_has_authenticated_member_writer(&claim).unwrap()); + assert!(store.claim_ids_with_authenticated_member_writers(&[claim]).unwrap().is_empty()); + } +} + +#[test] +fn batch_authenticated_member_writers_match_scalar_keyed_and_legacy_windows() { + let (store, claim, key) = authenticated_member_fixture(); + let requested = vec![claim.clone(), "missing".into(), claim.clone()]; + let assert_parity = |expected: bool| { + let batch = store.claim_ids_with_authenticated_member_writers(&requested).unwrap(); + assert_eq!( + batch, + if expected { BTreeSet::from([claim.clone()]) } else { BTreeSet::new() }, + ); + for id in &requested { + assert_eq!(batch.contains(id), store.claim_has_authenticated_member_writer(id).unwrap()); + } + }; + assert_parity(true); + // The same signed envelope is legacy before its incarnation's floor. + cache_member_window(&store, key.public(), u64::MAX); + assert_parity(false); + let generation = fleet_generation(&store.readers.get()).unwrap(); + *store.membership_cache.lock().unwrap() = Some((generation, Membership::default())); + assert_parity(false); + let other = crate::fleet::MemberKey::generate().unwrap().0; + cache_member_window(&store, other.public(), 0); + assert_parity(false); + cache_member_window(&store, key.public(), 0); + assert_parity(true); + assert!(store.claim_ids_with_authenticated_member_writers(&[]).unwrap().is_empty()); +} + +#[test] +fn batch_authenticated_member_writers_verify_shared_envelope_signatures_once() { + let (store, claim, key) = authenticated_member_fixture(); + let sibling = store.append_claim(&ClaimInput { + subject: "note/provenance-sibling".into(), + kind: "example.note".into(), + actor: None, + fields: BTreeMap::new(), + evidence: Vec::new(), + expected_subject: None, + idempotency_key: None, + }).unwrap(); + // Invent a second admitted record in the same envelope: only the signed envelope + // identity matters to this query, not the record's retained payload. + { + let connection = store.connection.write(); + connection.execute( + /* sqlite-large-value: allow-for-now lv-hb5e52f377f02 owner=smallclaims::store::membership_query_tests TODO=prepare-body-and-predecessor-values */ + "UPDATE claims SET origin='birch' WHERE id=?1", [&sibling.id], + ).unwrap(); + connection.execute( + /* sqlite-large-value: allow-for-now lv-he6cdb35f9041 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "INSERT INTO replica_records( + record_ref, writer, sequence, envelope_hash, position, raw, state, + claim_id, updated_at_unix_ms + ) SELECT record_ref || '-sibling', writer, sequence, envelope_hash, + position + 1, raw, state, ?1, updated_at_unix_ms + FROM replica_records WHERE claim_id=?2", + params![sibling.id, claim], + ).unwrap(); + } + let requested = vec![claim.clone(), sibling.id.clone(), claim.clone(), sibling.id.clone()]; + for valid in [true, false] { + if !valid { + store.connection.write().execute( + /* sqlite-large-value: allow-for-now lv-h85da58ff0363 owner=smallclaims::store::membership_query_tests TODO=chunk-or-reference-exact-wire-values */ + "UPDATE replica_envelope_signatures SET signature='invalid'", [], + ).unwrap(); + } + cache_member_window(&store, key.public(), 0); + SIGNATURE_VERIFICATIONS.with(|count| count.set(0)); + let batch = store.claim_ids_with_authenticated_member_writers(&requested).unwrap(); + SIGNATURE_VERIFICATIONS.with(|count| assert_eq!(count.get(), 1)); + assert_eq!( + batch, + if valid { + BTreeSet::from([claim.clone(), sibling.id.clone()]) + } else { + BTreeSet::new() + }, + ); + for id in &requested { + assert_eq!(batch.contains(id), store.claim_has_authenticated_member_writer(id).unwrap()); + } } } diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index acdd0b141d4..fea2d768b93 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -1045,7 +1045,6 @@ {"id": "lv-h0f4af853a427", "path": "crates/fractal-seats/src/store/reconcile_work_context/tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "670380e6c1568143746eefd5717d30685a73d61436c5663c11ede8fb9d9aec6f", "owner": "fractal_seats::store::reconcile_work_context::tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 412, "excerpt": "& format ! ( \"EXPLAIN QUERY PLAN {query}\" )"}, {"id": "lv-h0f82774c88b3", "path": "crates/smallclaims/src/store/checkpoint_trim/pacing_tests.rs", "kind": "sql-template", "fingerprint": "11cda2afe8f046d8ab9a034d7553f23a4ee6c312f735c09f8875d271f7a57f59", "owner": "smallclaims::store::checkpoint_trim::pacing_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 29, "excerpt": "INSERT INTO replica_envelopes VALUES('writer',10001,'hash')"}, {"id": "lv-h0f84e29accc7", "path": "crates/smallclaims/src/store/checkpoint_staging.rs", "kind": "sql-template", "fingerprint": "801d780479ea140546359d4a836ed44d0fcbc5a2667ea898c798df32fed9417a", "owner": "smallclaims::store::checkpoint_staging", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 574, "excerpt": "INSERT OR REPLACE INTO envelopes VALUES (?1, ?2, ?3, ?4, ?5, 1)"}, - {"id": "lv-h0fa302b0797b", "path": "crates/fractal-store/src/store/assistant_write.rs", "kind": "unresolved-sql-sink", "fingerprint": "6562903c8d2bc207804842e34b4da5a824f3b03ce5db30fe71891c284a70fbba", "owner": "fractal_store::store::assistant_write", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 34, "excerpt": "validated_transition_query ( ) , params ! [ granted . subject , kind , granted . origin , owner , granted . id , local_origin ] , claim_from_row ,"}, {"id": "lv-h0fbead354086", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "79efe7d7d375ce77e79ed9519b96dc98e2414f7b60deb32af4ad805b0c1384f6", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 10292, "excerpt": "INSERT OR IGNORE INTO event_positions(store_index, subject) VALUES (?1, ?2)"}, {"id": "lv-h0fd14f161748", "path": "crates/fractal-missions/src/store/mission_deadline_tests.rs", "kind": "sql-template", "fingerprint": "a5186b3123ce5807dff1a53ab460af0a78879c8679897964ca5d66650e5d1471", "owner": "fractal_missions::store::mission_deadline_tests", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 130, "excerpt": "DROP TABLE mission_run_deadlines; CREATE TABLE mission_run_deadlines ( run_id TEXT PRIMARY KEY REFERENCES mission_runs(id), timeout_ms INTEGER NOT NULL, deadline_at_unix_ms TEXT NOT NULL ); UPDATE pro"}, {"id": "lv-h10009ac67082", "path": "crates/smallclaims/src/store/events.rs", "kind": "sql-template", "fingerprint": "2807d9c856a5f430dc82759f52ee4e5d913f383748cc61aa1691f3a75103dbe4", "owner": "smallclaims::store::events", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 9, "excerpt": "CREATE VIEW events AS SELECT p.store_index,c.kind,p.subject,c.body FROM event_positions p CROSS JOIN claims c ON c.store_index=p.store_index"}, @@ -1232,6 +1231,7 @@ {"id": "lv-h1c6769be2fee", "path": "crates/fractal-github/src/changes/tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "bb3beb90db6d03b3fab4ef5029cccc3de43c7be1d9cde0dbf6e2e2ec075bb0af", "owner": "fractal_github::changes::tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 286, "excerpt": "fixture . record . clone ( )"}, {"id": "lv-h1c8ff1061589", "path": "crates/fractal-missions/src/store/schedule_active_run_tests.rs", "kind": "sql-template", "fingerprint": "a12b67671e84f2d0c5fd25f9e7a6bf1ea4c375ccfd8c746b8576529292381c97", "owner": "fractal_missions::store::schedule_active_run_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 278, "excerpt": "UPDATE mission_runs SET status='running' WHERE id='cut-old'"}, {"id": "lv-h1c91a0dec004", "path": "crates/smallclaims/src/store/membership_query_tests.rs", "kind": "sql-template", "fingerprint": "701329c99c19076f8b477e2f84c40f1a2ece7974203ef799364c1f2382fd1875", "owner": "smallclaims::store::membership_query_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 520, "excerpt": "UPDATE replica_envelope_signatures SET signature='invalid'"}, + {"id": "lv-h1cad9af7ef23", "path": "crates/fractal-store/src/store/assistant_write.rs", "kind": "unresolved-sql-sink", "fingerprint": "6f921ae5837279a7a2043b0cb27c19816e9cabc6223573b67dff35fb4b2e72ec", "owner": "fractal_store::store::assistant_write", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 48, "excerpt": "& QUERY , params ! [ granted . subject , kind , granted . origin , owner , granted . id , local_origin , before ] , claim_from_row ,"}, {"id": "lv-h1cb47a19f4af", "path": "crates/smallclaims/src/store/principals/legacy.rs", "kind": "unresolved-sql-sink", "fingerprint": "afa4f2f42f5c1e1d453ac252ee5e4b5cf16394c8ade4c7b4faabff40a76b109c", "owner": "smallclaims::store::principals::legacy", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 345, "excerpt": "[ link ]"}, {"id": "lv-h1cbf9f654bef", "path": "crates/fractal-missions/src/store/terminal_step_guard_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "5c837a5d02243070e3c6603ce60216ac048233a983b6f1f132929b1d0d4f1cd6", "owner": "fractal_missions::store::terminal_step_guard_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 256, "excerpt": "sql , [ & run . id ]"}, {"id": "lv-h1ccf70ddc42b", "path": "crates/fractal-store/src/store/publication_facts.rs", "kind": "sql-template", "fingerprint": "497b3cf606200236a44630442de821dd931e1de2e44da4ef517b2be8a170e9de", "owner": "fractal_store::store::publication_facts", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 400, "excerpt": "INSERT OR REPLACE INTO local_publication_starts SELECT id,subject,COALESCE(json_extract(body,'$.fields.incarnation_id'),'') FROM local_observations WHERE id=?1 AND json_extract(body,'$.fields.action')"}, @@ -2984,6 +2984,7 @@ {"id": "lv-h85ba6985cde2", "path": "crates/fractal-api-core/src/api/replication_guard_tests.rs", "kind": "sql-template", "fingerprint": "fb53f45f34c425e53a75b2047afe076b5d4aedb8092b2c1db6e21644723c63f7", "owner": "fractal_api_core::api::replication_guard_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 187, "excerpt": "INSERT INTO replica_envelopes(writer,sequence,envelope_hash,accepted_at_unix_ms,payload,relay,receipt_state,received_at_unix_ms) VALUES('fixture',1,?1,'0',X'','fixture','pending','0')"}, {"id": "lv-h85bbaa862d7c", "path": "crates/smallclaims/src/store/principals/judging.rs", "kind": "sql-template", "fingerprint": "f71930b3a171cf2382a44b39167e6df87bcf88e189dd7a51d72730d2b0fd474c", "owner": "smallclaims::store::principals::judging", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 112, "excerpt": "INSERT OR IGNORE INTO claim_verdict_links(link,claim_id) VALUES (?1,?2)"}, {"id": "lv-h85cea2f5ebf5", "path": "crates/fractal-store/src/store/checkpoint_capture_epoch_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "faa2abd3b66637ce500311e846d011960f3ffa5d74867e5a0cb0940c0f065944", "owner": "fractal_store::store::checkpoint_capture_epoch_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 141, "excerpt": "insert , [ & newer . id ]"}, + {"id": "lv-h85da58ff0363", "path": "crates/smallclaims/src/store/membership_query_tests.rs", "kind": "sql-template", "fingerprint": "701329c99c19076f8b477e2f84c40f1a2ece7974203ef799364c1f2382fd1875", "owner": "smallclaims::store::membership_query_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 632, "excerpt": "UPDATE replica_envelope_signatures SET signature='invalid'"}, {"id": "lv-h85e4d7c741b2", "path": "crates/fractal/src/main_tests.rs", "kind": "included-source", "fingerprint": "ec0fa810263574be541717738b96975251c63f1d8a77b8ca9655743932b3dcaf", "owner": "fractal::main_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 3027, "excerpt": "include_str ! ( \"doctor_cli.rs\" )"}, {"id": "lv-h860a5db13f30", "path": "crates/fractal-api-client-v0/src/api/client_v0/observer_subscription_detail_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "bd2df656dd9fecb1cfcf855790dfc22f057702e1a32474b68cd827f651a2bb34", "owner": "fractal_api_client_v0::api::client_v0::observer_subscription_detail_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 613, "excerpt": "& format ! ( \"SELECT {column} FROM desired WHERE subject=?1\" ) , [ OBSERVER ] , | row | row . get ( 0 ) ,"}, {"id": "lv-h8610ddeb875c", "path": "crates/fractal-store/src/store/notice_authority_tests.rs", "kind": "sql-template", "fingerprint": "2f09062974e3af83b900069bf9d5f1a76653ccc3b734c67d2da9b54653fbdd42", "owner": "fractal_store::store::notice_authority_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 260, "excerpt": "UPDATE desired SET owner_run='mission-run/owner', owner_generation='run-generation/owner' WHERE subject=?1"}, @@ -3289,7 +3290,6 @@ {"id": "lv-h99cdb0609387", "path": "crates/fractal-drivers/src/harness_events.rs", "kind": "sql-template", "fingerprint": "988bd052d249f242a23b7db334804b83925f10fbfbd24eb9b0280c4da3403da3", "owner": "fractal_drivers::harness_events", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 704, "excerpt": "INSERT INTO timeline(incarnation,source,body) VALUES (?1,?2,?3)"}, {"id": "lv-h99cfa91245f0", "path": "crates/fractal-store/src/store/glass_heads.rs", "kind": "sql-template", "fingerprint": "0d901e2260b3a5b2220f797fd4ccdbf91a90b3ff8d568c90c4ab47152472bcb8", "owner": "fractal_store::store::glass_heads", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 207, "excerpt": "DELETE FROM local_glass_head_pending; DELETE FROM local_glass_head_dirty;"}, {"id": "lv-h99da4f16cb38", "path": "crates/fractal-store/src/store/notice_authority_tests.rs", "kind": "included-source", "fingerprint": "95a31f82b0f71a9ff221695a923d435abdd83140e106d53b60be481e59e6b390", "owner": "fractal_store::store::notice_authority_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 21, "excerpt": "include_str ! ( \"../../../../docs/st3/client-v0/fixtures/notice-conformance.json\" )"}, - {"id": "lv-h99f1a302c7b1", "path": "crates/fractal-api-core/src/api/client_v0/external_grants.rs", "kind": "unresolved-sql-sink", "fingerprint": "e43321ad215ad6548370e6aa528d88374c2734277a245c0589a162c3666a7909", "owner": "fractal_api_core::api::client_v0::external_grants", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 128, "excerpt": "ADMISSION_QUERY"}, {"id": "lv-h99f662904dfd", "path": "crates/fractal-store/src/store/message_outbox.rs", "kind": "unresolved-sql-sink", "fingerprint": "bbfac8f07b9a24bc278443aa0d496ef7bbd0019ed35cee7698f44b358102850e", "owner": "fractal_store::store::message_outbox", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 100, "excerpt": "[ ] , | row | row . get ( 0 )"}, {"id": "lv-h9a25f3df63fd", "path": "crates/fractal-store/src/store/declared_admission.rs", "kind": "unresolved-sql-sink", "fingerprint": "846d1339d098e9cdda1cc140de8fd27bc2176ec0efb28389971a0051348a61f7", "owner": "fractal_store::store::declared_admission", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 126, "excerpt": "& canonical_sql ( \"SELECT json_extract(claims.body,'$.fields.features.declared_admission')=1 AND EXISTS(SELECT 1 FROM replica_envelopes e JOIN replica_envelope_signatures s ON s.writer=e.writer AND s."}, {"id": "lv-h9a3345441df1", "path": "crates/fractal-store/src/store/client_messages.rs", "kind": "unresolved-sql-sink", "fingerprint": "f9786d4d7a7cedb786437a545587c7fd01fb992e9a63d5fd9038e2b4a2675ba9", "owner": "fractal_store::store::client_messages", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1108, "excerpt": "& SQL"}, @@ -3728,6 +3728,7 @@ {"id": "lv-hb59357c7152a", "path": "crates/fractal-store/src/store/client_messages.rs", "kind": "sql-template", "fingerprint": "d97d980f5b347ed4a16ab8dd0af3c04363eac83c0ae0810175858d77bd9c1992", "owner": "fractal_store::store::client_messages", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1256, "excerpt": "DROP TABLE IF EXISTS local_client_message_fold_batches;DROP TABLE IF EXISTS local_client_message_publications;"}, {"id": "lv-hb59720c737d2", "path": "crates/fractal-store/src/store/checkpoint_identity_reuse_tests.rs", "kind": "sql-template", "fingerprint": "a466c1bb6842b49c1d34a00a24fdcb27190d6711850fee20c555c3c6c8bfc672", "owner": "fractal_store::store::checkpoint_identity_reuse_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 161, "excerpt": "UPDATE claims SET accepted_at_unix_ms=?1 WHERE id=?2"}, {"id": "lv-hb5d0c6d8b7ed", "path": "crates/smallclaims/src/store/principals/legacy.rs", "kind": "unresolved-sql-sink", "fingerprint": "861ae77d8b9421fa21c0de36fb94ae80d2b589f44a1eb28e3ee97f385d319402", "owner": "smallclaims::store::principals::legacy", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 85, "excerpt": "[ claim_id ]"}, + {"id": "lv-hb5e52f377f02", "path": "crates/smallclaims/src/store/membership_query_tests.rs", "kind": "sql-template", "fingerprint": "087fbc78cff93ffd74f078fca1b000a22c099b870ff4f330db38f048e0b5b0f6", "owner": "smallclaims::store::membership_query_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 616, "excerpt": "UPDATE claims SET origin='birch' WHERE id=?1"}, {"id": "lv-hb5f027ea8580", "path": "crates/fractal-store/src/store/terminal_gate_evidence/native_source_transaction_hooks_shared_seats.rs", "kind": "sql-template", "fingerprint": "6b3823f2f143ab2244075588dbaf9e8bf386ed8250474992d6adfbee5ca02c07", "owner": "fractal_store::store::terminal_gate_evidence::native_source_transaction_hooks_shared_seats", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 125, "excerpt": "UPDATE test_native_terminal_guard SET gap=?1,pending=1 WHERE id=1"}, {"id": "lv-hb5f4a6691287", "path": "crates/smallclaims/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "5b6b40a906a01449b1777c0aa965073d786de369e2f1e74d6af78bfa11963f53", "owner": "smallclaims::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 5834, "excerpt": "\"BEGIN\""}, {"id": "lv-hb60936b2dafb", "path": "crates/smallclaims/src/store.rs", "kind": "sql-template", "fingerprint": "e355841dda64010916db6237966232dd46893ba85fdcdda63c13fb4b1d5fda6b", "owner": "smallclaims::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 5606, "excerpt": "INSERT OR IGNORE INTO blobs(hash,bytes,size) SELECT hash,bytes,size FROM local_blobs WHERE hash=?1"}, @@ -3950,6 +3951,7 @@ {"id": "lv-hc1a7495dab62", "path": "crates/fractal-missions/src/store/mission_list.rs", "kind": "unresolved-sql-sink", "fingerprint": "be824f83b40fb6e1bfa945556ae9be449d492a6e6edd8c5fec6f70c7ce2522da", "owner": "fractal_missions::store::mission_list", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 192, "excerpt": "published_list : : CLAIMS_SINCE"}, {"id": "lv-hc1ac3d35bbf4", "path": "crates/fractal-store/src/store/client_messages.rs", "kind": "sql-template", "fingerprint": "b00efd86cc227528fbfa988943c50c7bc8f88c73ef6908072ddf7ed7cac1bc74", "owner": "fractal_store::store::client_messages", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1253, "excerpt": "DELETE FROM meta WHERE key=?1"}, {"id": "lv-hc1b4b7df7d60", "path": "crates/smallclaims/src/sqlite.rs", "kind": "unresolved-sql-sink", "fingerprint": "ce922519a3c3ecaf9b0986c2449c7680895c15f4b0e9818e994e14a4d28b6aaf", "owner": "smallclaims::sqlite", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 929, "excerpt": "transaction"}, + {"id": "lv-hc1c46de6a890", "path": "crates/fractal-api-core/src/api/client_v0/external_grants.rs", "kind": "unresolved-sql-sink", "fingerprint": "b7eafcbb01a79e6feb02839905b41bafc8a5be2f355d21ab6b4b392a34092eac", "owner": "fractal_api_core::api::client_v0::external_grants", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 139, "excerpt": "& QUERY"}, {"id": "lv-hc1c6ea0cb228", "path": "crates/fractal-store/src/store/terminal_gate_evidence/native_source_tests_shared.rs", "kind": "sql-template", "fingerprint": "740d295c2a21b85f7e9f3cfc6e07c1cddb61c6d0698f1d79e9cb732ef1e0c259", "owner": "fractal_store::store::terminal_gate_evidence::native_source_tests_shared", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 87, "excerpt": "WITH RECURSIVE pages(n) AS (SELECT 0 UNION ALL SELECT n+1 FROM pages WHERE n<(?1-1)/64) INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) SELECT 'foreign-page/'||n,'node',1000+n"}, {"id": "lv-hc1db65df6dce", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "f364d8ca6168ffa8cad7d686c9cbe491d919c3fcdda7ba967af6912aaffb62ae", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 5612, "excerpt": "& format ! ( \"{} LIMIT 1\" , newest_claims_of_kind_query ( \"claims.origin\" , \"runtime.observed\" ) )"}, {"id": "lv-hc1e68820d94d", "path": "crates/smallclaims/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "789b44b9990c7d88da3542aa5c6b25148409a57d64b88f00362513cda78a031f", "owner": "smallclaims::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1084, "excerpt": "\"COMMIT\""}, @@ -4551,6 +4553,7 @@ {"id": "lv-he689627b23bd", "path": "crates/fractal-delivery/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "fc981f0d7fee4248cb8715706d70a3287f28d28d8fb5deafa1af8b0ba0989c22", "owner": "fractal_delivery::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 172, "excerpt": "& format ! ( \"SELECT DISTINCT claims.kind, claims.origin FROM claims INDEXED BY claims_subject_kind_index WHERE claims.subject=?1 AND claims.store_index<=?2 AND {ACTUAL_STATE_CLAIM} AND {UNREPAIRED_CL"}, {"id": "lv-he69938b2fc65", "path": "crates/fractal-store/src/store/ordered_membership.rs", "kind": "sql-template", "fingerprint": "f03addec467af6f507720744f7babd7c11eb2d0dbabd30eb14bf820b37da9a5c", "owner": "fractal_store::store::ordered_membership", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 213, "excerpt": "INSERT INTO meta(key,value) VALUES('local_ordered_membership_repair_index',?1) ON CONFLICT(key) DO UPDATE SET value=CAST(MAX(CAST(meta.value AS INTEGER),CAST(excluded.value AS INTEGER)) AS TEXT)"}, {"id": "lv-he69a7f7121fc", "path": "crates/smallclaims/src/store/principals/legacy.rs", "kind": "sql-template", "fingerprint": "d3364edb2859c67f3776bcd181ec6a7384bf937cf701731a101d3375434b0062", "owner": "smallclaims::store::principals::legacy", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 430, "excerpt": "INSERT OR IGNORE INTO legacy_claim_verdict_queue(claim_id) VALUES (?1)"}, + {"id": "lv-he6cdb35f9041", "path": "crates/smallclaims/src/store/membership_query_tests.rs", "kind": "sql-template", "fingerprint": "87cb097907853e192c0d5392447f3b60ee89edaea405979c0cfcf2a91c50d557", "owner": "smallclaims::store::membership_query_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 619, "excerpt": "INSERT INTO replica_records( record_ref, writer, sequence, envelope_hash, position, raw, state, claim_id, updated_at_unix_ms ) SELECT record_ref || '-sibling', writer, sequence, envelope_hash, positio"}, {"id": "lv-he6d1d9f14a2c", "path": "crates/fractal-seats/src/store/accounts.rs", "kind": "unresolved-sql-sink", "fingerprint": "01abbe3220198f67387ec701743f0127f772e11d373e372c2baf50c1392dc034", "owner": "fractal_seats::store::accounts", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 61, "excerpt": "& canonical_sql ( \"SELECT claims.id, claims.store_index, claims.batch_id, claims.subject, claims.kind, claims.origin, claims.actor, claims.body, claims.predecessors, claims.accepted_at_unix_ms FROM cl"}, {"id": "lv-he6dafe2f904c", "path": "crates/smallclaims/src/ivm.rs", "kind": "sql-template", "fingerprint": "43a2a96ce900b14f48d3932a6f247c6171e534fbc991c429d380e7d66c1f29e8", "owner": "smallclaims::ivm", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 984, "excerpt": "UPDATE ivm_views SET generation=generation+1 WHERE name=?1"}, {"id": "lv-he6e3040252e3", "path": "crates/fractal-api-client-v0/src/api/client_v0/observer_subscription_detail_tests.rs", "kind": "sql-template", "fingerprint": "b41394c6c4f6b2c1747aeaa99b81f93fb2a537c86162ddb3d360dab2d95dd496", "owner": "fractal_api_client_v0::api::client_v0::observer_subscription_detail_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 668, "excerpt": "UPDATE desired SET kind={value} WHERE subject=?1"}, diff --git a/docs/st3/large-values.md b/docs/st3/large-values.md index eb0758963da..5a32f646df8 100644 --- a/docs/st3/large-values.md +++ b/docs/st3/large-values.md @@ -502,19 +502,34 @@ proof. The producer maintainer retains `chunk-or-reference-variable-columns` responsibility while preserving effective-principal matching and claim authority. `fractal_store::store::assistant_write` owns the read-only sink -`lv-h0fa302b0797b`. The shared validated transition query binds a grant subject, -claim kind, origin, owner actor, grant claim ID and local origin, and returns at -most one claim row. It writes nothing; bodies stay inline, so the exception -establishes neither encoded-size nor execution-cost bounds. +`lv-h1cad9af7ef23`, replacing `lv-h0fa302b0797b`. The shared validated transition +query binds a grant subject, claim kind, origin, owner actor, grant claim ID, +local origin and optional store-index seek boundary, and returns at most one +claim row. The boundary allows callers to continue past a structurally valid but +cryptographically unauthenticated foreign transition. It writes nothing; bodies +stay inline, so the exception establishes neither encoded-size nor execution-cost bounds. `fractal_api_core::api::client_v0::external_grants` owns the conservative -read-only sink `lv-h99f1a302c7b1`. Its prepared admission query binds fixed claim -kinds, an assistant principal and an optional expiry cutoff, then returns claim -IDs after revocation and latest-policy filtering. It adds no writer or body copy; -principal, subject and claim-ID TEXT keys remain variable-size. The producer -maintainer retains `trace-statement-and-value-representation` responsibility for -these bindings and returned identifiers; fewer candidates and indexed seeks do -not establish encoded-size or execution-cost bounds. +read-only sink `lv-hc1c46de6a890`, replacing `lv-h99f1a302c7b1`. Its dynamically +composed candidate query binds fixed claim kinds, an assistant principal, an +optional expiry cutoff, local origin, owner actor, and optional ignored profile +and excluded claim ID. It returns candidate grant/transition claim rows for one +batch full-provenance check before latest-policy and revocation filtering. +It adds no writer or persistent body copy; principal, subject, claim-ID TEXT keys +and returned inline bodies remain variable-size. The producer maintainer retains +`trace-statement-and-value-representation` responsibility for these bindings and +returned values; fewer candidates and indexed seeks do not establish encoded-size +or execution-cost bounds. + +The `smallclaims::store::membership_query_tests` maintainer owns test-only sites +`lv-hb5e52f377f02`, `lv-he6cdb35f9041` and `lv-h85da58ff0363`. These change a +fixture claim's origin, copy an admitted record's inline raw bytes and identity +into a sibling record, and replace a fixture signature with fixed invalid text. +They exercise batch/scalar parity and shared-signature verification deduplication +in an in-memory store; they add no production writer. The maintainer retains the +listed body/predecessor and exact-wire representation TODOs for these fixture +copies; this exception is not a byte-size or execution-cost proof. + ## Incremental observed credit heads `fractal_store::store::usage_credits` owns `lv-he501efb4d29a`, diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 94879a9c972..6ab4eda7c8d 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -15,7 +15,7 @@ }, "compatibility": { "status": "changed", - "detail": "Conflict admission counts only well-formed foreign owner grants with authenticated envelope provenance from a keyed, admitted fleet writer, including valid records in degraded envelopes. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity; foreign transitions also require authenticated provenance. Invalid overlays are ignored, retaining the last valid policy. This restriction also applies to local grants. Request-side sealed membership folds populate a separate generation-keyed cache without weakening local sealing. Tokens remain issuer-local. Older members do not enforce suspension, so upgrade all serving members before relying on it." + "detail": "Conflict admission counts only well-formed owner grants; foreign grants require authenticated envelope provenance from a keyed, admitted fleet writer, including valid records in degraded envelopes. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. Foreign transitions require both a keyed membership window and a valid signature; a newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Candidate claims and latest transitions are fetched together, foreign provenance is checked in one membership snapshot with deduplicated envelope signature verification, and same-profile candidates can be skipped during authentication because they cannot conflict. No provenance result is cached by fleet generation alone. Tokens remain issuer-local. Older members do not enforce suspension, so upgrade all serving members before relying on it." }, "downtime": { "status": "changed", From dc75b63ee820ced28439c42b70cb4b4b5efe6868 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 02:03:42 +0100 Subject: [PATCH 21/52] Validate optional benchmark build identity only when measurement is requested agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../fractal/tests/daemon_cost/assistant_admission.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 1544a9453d3..58568e84052 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -116,10 +116,12 @@ fn execution_identity() -> Value { let expected = required("ST_ADMISSION_EXPECT_REVISION"); assert_eq!(expected.len(), 40, "use a full commit ID"); assert!(expected.bytes().all(|byte| byte.is_ascii_hexdigit()), "use a full commit ID"); - let built_revision = option_env!("ST_ADMISSION_BUILD_REVISION") - .expect("build with ST_ADMISSION_BUILD_REVISION; do not reuse an unidentified executable"); - let build_provenance = option_env!("ST_ADMISSION_BUILD_PROVENANCE") - .expect("build with ST_ADMISSION_BUILD_PROVENANCE"); + let (Some(built_revision), Some(build_provenance)) = ( + option_env!("ST_ADMISSION_BUILD_REVISION"), + option_env!("ST_ADMISSION_BUILD_PROVENANCE"), + ) else { + panic!("opt-in measurement requires build revision and provenance; see harness instructions"); + }; assert!(!build_provenance.trim().is_empty(), "build provenance must not be empty"); assert_eq!(built_revision, expected, "the executable was built for a different source revision"); let binary = std::env::current_exe().unwrap().canonicalize().unwrap(); From 5f0ada37075d5b77d49070eec5aafb39671abfde Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 07:30:30 +0100 Subject: [PATCH 22/52] Project authenticated external-grant authority incrementally and permit owner service revocation agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../Sources/FractalClient/Models.swift | 3 + .../fractal-client/Models.generated.ts | 1 + .../fractal-client/ReadSchema.generated.ts | 1 + .../fractal-client/Schema.generated.ts | 3 +- .../src/api/client_v0/assistant.rs | 147 +++++- crates/fractal-api-core/src/api.rs | 2 + .../src/api/client_v0/external_grants.rs | 368 +++++--------- .../external_grants/conflict_tests.rs | 26 +- .../templates/Models.swift.in | 3 + .../templates/generated.rs.in | 1 + .../templates/lib.rs.in | 1 + crates/fractal-client/src/generated.rs | 1 + crates/fractal-store/src/store.rs | 13 +- .../src/store/assistant_write.rs | 273 +++-------- crates/fractal-store/src/store/runtime.rs | 255 +++++----- crates/fractal/src/main.rs | 22 + crates/smallclaims/src/store.rs | 36 +- .../src/store/assistant_grant_authority.rs | 411 ++++++++++++++++ .../store/assistant_grant_authority_bench.rs | 322 +++++++++++++ .../store/assistant_grant_authority_tests.rs | 448 ++++++++++++++++++ .../src/store/prepared_envelope.rs | 3 + crates/smallclaims/src/store/prepared_seal.rs | 8 + .../client-v0/schemas/client-v0.schema.json | 1 + docs/st3/client-v0/schemas/operations.json | 10 + docs/st3/large-value-sites.json | 324 +++++++------ .../external-grant-profile-conflict.json | 14 +- 26 files changed, 1929 insertions(+), 768 deletions(-) create mode 100644 crates/smallclaims/src/store/assistant_grant_authority.rs create mode 100644 crates/smallclaims/src/store/assistant_grant_authority_bench.rs create mode 100644 crates/smallclaims/src/store/assistant_grant_authority_tests.rs diff --git a/clients/swift/FractalClient/Sources/FractalClient/Models.swift b/clients/swift/FractalClient/Sources/FractalClient/Models.swift index f9617d5dd13..079a3fa7c57 100644 --- a/clients/swift/FractalClient/Sources/FractalClient/Models.swift +++ b/clients/swift/FractalClient/Sources/FractalClient/Models.swift @@ -154,6 +154,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case validationFailed case idempotencyConflict case grantProfileConflict + case assistantGrantAuthorityNotReady case agentsPublicationRowTooLarge case attentionMigrated case invalidAnswer, notAnswerable @@ -247,6 +248,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case "validation-failed": .validationFailed case "idempotency-conflict": .idempotencyConflict case "grant-profile-conflict": .grantProfileConflict + case "assistant-grant-authority-not-ready": .assistantGrantAuthorityNotReady case "stale-fence": .staleFence case "issuer-required": .issuerRequired case "pairing-origin-required": .pairingOriginRequired @@ -340,6 +342,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case .validationFailed: "validation-failed" case .idempotencyConflict: "idempotency-conflict" case .grantProfileConflict: "grant-profile-conflict" + case .assistantGrantAuthorityNotReady: "assistant-grant-authority-not-ready" case .staleFence: "stale-fence" case .issuerRequired: "issuer-required" case .pairingOriginRequired: "pairing-origin-required" diff --git a/clients/typescript/fractal-client/Models.generated.ts b/clients/typescript/fractal-client/Models.generated.ts index 0b5413d60b4..0ba64b5d9e7 100644 --- a/clients/typescript/fractal-client/Models.generated.ts +++ b/clients/typescript/fractal-client/Models.generated.ts @@ -1860,6 +1860,7 @@ export type ErrorCode = ( | "validation-failed" | "idempotency-conflict" | "grant-profile-conflict" + | "assistant-grant-authority-not-ready" | "legacy-action-receipt-untrusted" | "issuer-required" | "pairing-origin-required" diff --git a/clients/typescript/fractal-client/ReadSchema.generated.ts b/clients/typescript/fractal-client/ReadSchema.generated.ts index 01c51c5088e..1ade5c36a1f 100644 --- a/clients/typescript/fractal-client/ReadSchema.generated.ts +++ b/clients/typescript/fractal-client/ReadSchema.generated.ts @@ -1699,6 +1699,7 @@ export const ErrorCode = /*#__PURE__*/ (() => openEnum([ "validation-failed", "idempotency-conflict", "grant-profile-conflict", + "assistant-grant-authority-not-ready", "legacy-action-receipt-untrusted", "issuer-required", "pairing-origin-required", diff --git a/clients/typescript/fractal-client/Schema.generated.ts b/clients/typescript/fractal-client/Schema.generated.ts index b79ca03f4c4..f42ab731c51 100644 --- a/clients/typescript/fractal-client/Schema.generated.ts +++ b/clients/typescript/fractal-client/Schema.generated.ts @@ -1037,6 +1037,7 @@ export const ErrorEnvelope = /*#__PURE__*/ (() => Schema.Union([ Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("validation-failed"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("idempotency-conflict"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("grant-profile-conflict"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("assistant-grant-authority-not-ready"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("legacy-action-receipt-untrusted"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("issuer-required"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("pairing-origin-required"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), @@ -1081,7 +1082,7 @@ export const ErrorEnvelope = /*#__PURE__*/ (() => Schema.Union([ Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("invalid-answer"), "details": HarnessInvalidAnswerDetails, "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("not-answerable"), "details": HarnessNotAnswerableDetails, "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": Schema.Literal("internal"), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }), - Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": unknownCase(["recipient-retired","agents-publication-row-too-large","identity-cycle","identity-occupied","identity-retired-source","identity-cross-kind","identity-unknown","lifecycle-unavailable","retirement-upgrade-required","retire-revision-mismatch","retire-incarnation-mismatch","invalid-custody-successor","custody-pending","attention-migrated","arrangement-exists","arrangement-folder-exists","arrangement-retired","arrangement-limit","arrangement-folder-deleted","arrangement-cycle","arrangement-body-too-large","arrangement-owner-forbidden","invalid-arrangement-subject","invalid-arrangement-action","invalid-arrangement-operations","invalid-arrangement-folder","invalid-arrangement-name","invalid-arrangement-key","invalid-arrangement-version","invalid-arrangement-body","unsupported-membership-container","membership-owner-forbidden","invalid-membership-member","invalid-membership-bucket","invalid-membership-key","invalid-membership-operations","membership-edit-too-large","invalid-subject-reference","not-found","forbidden","unsupported-capability","peer-too-old","validation-failed","idempotency-conflict","grant-profile-conflict","legacy-action-receipt-untrusted","issuer-required","pairing-origin-required","pairing-restart-required","suspend-authored-session-selection","stale-fence","cursor-gap","page-cursor-expired","agent-roster-not-ready","agent-roster-cut-not-ready","message-selectors-not-ready","rate-limited","runtime-not-local","runtime-authority-indeterminate","runtime-list-not-ready","runtime-list-ended","remote-unavailable","terminal-unavailable","inventory-unavailable","terminal-ended","timeline-history-incomplete","projection-detail-too-large","projection-detail-invalid-source","conversation-content-invalidated","transcript-unavailable","blob-too-large","unsupported-media-type","blob-content-mismatch","blob-quota-exceeded","blob-not-found","blob-expired","message-too-large","message-store-full","long-message-signature-unsupported","response-budget-exceeded","content-not-text","invalid-document-reference","document-not-synced","private-notes-unreachable","private-notes-carrier-conflict","private-notes-indeterminate","invalid-answer","not-answerable","internal"]), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }) + Schema.Struct({ "api_version": Schema.Literals(["st3.client.v0","fractal.client.v0"]), "applied": optionalKey(Schema.Literals(["none","unknown"])), "code": unknownCase(["recipient-retired","agents-publication-row-too-large","identity-cycle","identity-occupied","identity-retired-source","identity-cross-kind","identity-unknown","lifecycle-unavailable","retirement-upgrade-required","retire-revision-mismatch","retire-incarnation-mismatch","invalid-custody-successor","custody-pending","attention-migrated","arrangement-exists","arrangement-folder-exists","arrangement-retired","arrangement-limit","arrangement-folder-deleted","arrangement-cycle","arrangement-body-too-large","arrangement-owner-forbidden","invalid-arrangement-subject","invalid-arrangement-action","invalid-arrangement-operations","invalid-arrangement-folder","invalid-arrangement-name","invalid-arrangement-key","invalid-arrangement-version","invalid-arrangement-body","unsupported-membership-container","membership-owner-forbidden","invalid-membership-member","invalid-membership-bucket","invalid-membership-key","invalid-membership-operations","membership-edit-too-large","invalid-subject-reference","not-found","forbidden","unsupported-capability","peer-too-old","validation-failed","idempotency-conflict","grant-profile-conflict","assistant-grant-authority-not-ready","legacy-action-receipt-untrusted","issuer-required","pairing-origin-required","pairing-restart-required","suspend-authored-session-selection","stale-fence","cursor-gap","page-cursor-expired","agent-roster-not-ready","agent-roster-cut-not-ready","message-selectors-not-ready","rate-limited","runtime-not-local","runtime-authority-indeterminate","runtime-list-not-ready","runtime-list-ended","remote-unavailable","terminal-unavailable","inventory-unavailable","terminal-ended","timeline-history-incomplete","projection-detail-too-large","projection-detail-invalid-source","conversation-content-invalidated","transcript-unavailable","blob-too-large","unsupported-media-type","blob-content-mismatch","blob-quota-exceeded","blob-not-found","blob-expired","message-too-large","message-store-full","long-message-signature-unsupported","response-budget-exceeded","content-not-text","invalid-document-reference","document-not-synced","private-notes-unreachable","private-notes-carrier-conflict","private-notes-indeterminate","invalid-answer","not-answerable","internal"]), "details": Schema.StructWithRest(Schema.Struct({ "applied": optionalKey(Schema.Literals(["none","unknown"])), "refusal": optionalKey(MessageSendRefusal) }), [Schema.Record(Schema.String, Schema.Unknown)]), "error_version": Schema.Literals(["st3.client.error.v0","fractal.client.error.v0"]), "message": Schema.String, "request_id": Id, "retry_after_ms": optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.decodeTo(Schema.Duration.check(durationMillisRange), wholeUnits(1)))), "retryable": Schema.Boolean }) ], { mode: "oneOf" }).annotate({ identifier: "ErrorEnvelope" }))() export type ErrorEnvelope = typeof ErrorEnvelope.Type export type ErrorEnvelopeEncoded = typeof ErrorEnvelope.Encoded diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs index 7b808c795e6..3a4586396e6 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant.rs @@ -218,9 +218,16 @@ async fn revoke_inner(State(state): State, Extension(session): Extensi } if !revoked(&state, &granted)? { let previous = effective(&state, &granted)?; - append(&state, subject, REVOKED, issuer, json!({"version":1,"grant_id":fields(&granted)?["grant_id"], - "principal":principal(fields(&granted)?)?,"issuer":issuer,"transport":session.transport, - "timestamp":client_timestamp(client_now_ms()),"outcome":"revoked"}), Some(&previous))?; + let source = fields(&granted)?; + let mut value = json!({"version":1,"grant_id":source["grant_id"], + "principal":principal(source)?,"issuer":issuer,"transport":session.transport, + "timestamp":client_timestamp(client_now_ms()),"outcome":"revoked"}); + // Revocation is not issuance: retain the immutable profile, including + // the absence of a profile on legacy assistant grants. + if let Some(profile) = source.get("profile") { + value["profile"] = profile.clone(); + } + append(&state, subject, REVOKED, issuer, value, Some(&previous))?; signal_changed(&state); } Ok(Json(projection(&state, &granted)?)) @@ -296,6 +303,107 @@ mod tests { &request, "fabric-loopback").await.unwrap().unwrap().0 } + fn seeded_grant(state: &AppState, profile: Option<&str>) -> ClaimRecord { + let id = "111111111111111111111111"; + let mut source = json!({"version":1,"grant_id":format!("assistant-grant/{id}"), + "principal":PRINCIPAL,"sender_class":"external-assistant","issuer":ISSUER, + "session_actor":format!("{PRINCIPAL}/session/assistant-grant/{id}"), + "credential_hash":credential_digest("reserved-service-credential"), + "device_id":"device/service-history","key_id":"service-history", + "scopes":SCOPES[..4],"expires_at_unix_ms":client_now_ms()+3_600_000, + "policy_revision":1,"minimal_read_mode":"approval-once","recipient_allowlist":[], + "disclosure_consent":true,"consent_evidence":"recorded owner consent"}); + if let Some(profile) = profile { + source["profile"] = json!(profile); + } + // Retain pre-existing evidence without opening the production issuance gate. + state.store.append_claim(&ClaimInput { + subject: subject(id).unwrap(), kind: GRANTED.into(), actor: Some(ISSUER.into()), + fields: serde_json::from_value(source).unwrap(), evidence: Vec::new(), + expected_subject: None, idempotency_key: None, + }).unwrap() + } + + #[tokio::test] + async fn owner_revoke_endpoint_preserves_profiles_and_is_idempotent() { + use axum::{body::{Body, to_bytes}, http::Request}; + use tower::ServiceExt; + + for profile in [None, Some("assistant"), Some("service")] { + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let granted = seeded_grant(&state, profile); + let app = super::super::super::router_for_transport(state.clone(), + ClientTransportBoundary::Unix, &[crate::api::client_v0::routes]); + let path = "/v1/client/assistant/grants/111111111111111111111111/revoke"; + // An arbitrary local person must not gain the owner's revocation right. + let mut denied = Request::builder().method("POST").uri(path) + .header(LOCAL_PERSON_HEADER, "person/other").body(Body::empty()).unwrap(); + denied.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + assert_eq!(app.clone().oneshot(denied).await.unwrap().status(), StatusCode::FORBIDDEN); + assert!(latest(&state, &granted.subject, REVOKED).unwrap().is_none()); + + let mut revocation_id = None; + for _ in 0..2 { + let mut request = Request::builder().method("POST").uri(path) + .header(LOCAL_PERSON_HEADER, ISSUER).body(Body::empty()).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + let response = app.clone().oneshot(request).await.unwrap(); + assert_eq!(response.status(), StatusCode::OK, "{profile:?}"); + let body: Value = serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap()).unwrap(); + assert_eq!(body["value"]["revoked"], true); + let revoked = latest(&state, &granted.subject, REVOKED).unwrap().unwrap(); + assert_eq!(fields(&revoked).unwrap().get("profile"), fields(&granted).unwrap().get("profile")); + assert_eq!(revoked.actor.as_deref(), Some(ISSUER)); + assert_eq!(revoked.origin, granted.origin); + if let Some(id) = &revocation_id { + assert_eq!(&revoked.id, id, "repeat revocation must not append another transition"); + } else { + revocation_id = Some(revoked.id); + } + } + } + } + + #[tokio::test] + async fn service_history_does_not_enable_issuance_policy_or_requests() { + use axum::{body::Body, http::Request}; + use tower::ServiceExt; + + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let granted = seeded_grant(&state, Some("service")); + let app = super::super::super::router_for_transport(state.clone(), + ClientTransportBoundary::Unix, &[crate::api::client_v0::routes]); + for path in ["/v1/client/assistant/summary", "/v1/client/capabilities"] { + let request = Request::builder().uri(path) + .header(AUTHORIZATION, "Bearer reserved-service-credential") + .body(Body::empty()).unwrap(); + assert_eq!(app.clone().oneshot(request).await.unwrap().status(), StatusCode::FORBIDDEN); + } + let policy = json!({"api_version":CLIENT_API_VERSION,"scopes":SCOPES[..4], + "expires_in_seconds":3600,"disclosure_consent":true, + "consent_evidence":"recorded owner consent","minimal_read_mode":"approval-once"}); + let mut request = Request::builder().method("POST") + .uri("/v1/client/assistant/grants/111111111111111111111111/policy") + .header(LOCAL_PERSON_HEADER, ISSUER).header("content-type", "application/json") + .body(Body::from(policy.to_string())).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + assert_eq!(app.clone().oneshot(request).await.unwrap().status(), StatusCode::FORBIDDEN); + assert!(latest(&state, &granted.subject, POLICY).unwrap().is_none()); + + let issuance = json!({"api_version":CLIENT_API_VERSION,"device_name":"service", + "assistant_id":PRINCIPAL,"profile":"service","scopes":SCOPES[..4], + "expires_in_seconds":3600,"disclosure_consent":true, + "consent_evidence":"recorded owner consent"}); + let mut request = Request::builder().method("POST").uri("/v1/client/pairings") + .header(LOCAL_PERSON_HEADER, ISSUER).header("content-type", "application/json") + .body(Body::from(issuance.to_string())).unwrap(); + request.extensions_mut().insert(super::super::super::LocalPeer { pid: 8, peer_process: None, ancestor: None }); + assert_eq!(app.oneshot(request).await.unwrap().status(), StatusCode::UNPROCESSABLE_ENTITY); + assert!(state.store.claims_for_kind_at(BEGUN, None, true, 10).unwrap().claims.is_empty()); + } + // Frozen pre-witness shape, independent of today's generated grant model. #[derive(Deserialize)] #[serde(deny_unknown_fields)] @@ -605,6 +713,39 @@ mod tests { assert!(!String::from_utf8(body.to_vec()).unwrap().contains("max_message_bytes")); } + #[tokio::test] + async fn authority_backfill_refusal_is_typed_retryable_and_recovers() { + let root = tempfile::tempdir().unwrap(); + let state = state(root.path()); + let paired = paired(&state).await; + state.store.connection.write().execute( + "DELETE FROM meta WHERE key='assistant_grant_authority_version'", [], + ).unwrap(); + let app = super::super::super::router_for_transport( + state.clone(), ClientTransportBoundary::Unix, &[crate::api::client_v0::routes], + ); + let inspect = format!("/v1/client/assistant/grants/{}", + urlencoding::encode(paired["grant"]["id"].as_str().unwrap())); + for (path, bearer) in [("/v1/client/assistant/summary", true), (inspect.as_str(), false)] { + let mut request = Request::builder().uri(path); + if bearer { + request = request.header(AUTHORIZATION, + format!("Bearer {}", paired["credential"].as_str().unwrap())); + } else { + request = request.header(LOCAL_PERSON_HEADER, ISSUER); + } + let response = app.clone().oneshot(request.body(Body::empty()).unwrap()).await.unwrap(); + assert_eq!(response.status(), StatusCode::SERVICE_UNAVAILABLE); + let body = axum::body::to_bytes(response.into_body(), usize::MAX).await.unwrap(); + let value: Value = serde_json::from_slice(&body).unwrap(); + assert_eq!(value["code"], "assistant-grant-authority-not-ready"); + assert_eq!(value["retryable"], true); + } + while !state.store.advance_assistant_grant_authority_backfill().unwrap() {} + assert!(authenticate(&state, + &credential_digest(paired["credential"].as_str().unwrap()), "unix").unwrap().is_some()); + } + #[tokio::test] async fn assistant_revocation_and_expiry_survive_restart() { let root=tempfile::tempdir().unwrap(); let state1=state(root.path()); let paired1=paired(&state1).await; diff --git a/crates/fractal-api-core/src/api.rs b/crates/fractal-api-core/src/api.rs index aff414d635d..29b57d9cfe9 100644 --- a/crates/fractal-api-core/src/api.rs +++ b/crates/fractal-api-core/src/api.rs @@ -499,6 +499,7 @@ impl ApiError { "identity-unknown" | "lane-not-found" | "not-found" => StatusCode::NOT_FOUND, "private-notes-unreachable" | "private-notes-indeterminate" => StatusCode::SERVICE_UNAVAILABLE, "database-busy" | "database-locked" | "message-selectors-not-ready" + | "assistant-grant-authority-not-ready" | "checkpoint-proof-in-progress" | "backup-busy" => StatusCode::SERVICE_UNAVAILABLE, "client-diagnostics-rate-limit" => StatusCode::TOO_MANY_REQUESTS, "read-deadline" => StatusCode::GATEWAY_TIMEOUT, @@ -2060,6 +2061,7 @@ pub fn client_error_code(code: Option<&str>) -> String { | "mission-list-not-ready" | "mission-list-ended" | "message-selectors-not-ready" + | "assistant-grant-authority-not-ready" | "response-too-large" | "runtime-not-local" | "runtime-authority-indeterminate" diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index ba76c2d7ac9..5685061bbda 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -1,6 +1,6 @@ -//! Claim-backed external credentials. Storage names remain stable across profiles. +//! Projection-backed external authority. Raw pairing and audit history remain evidence, not authorization. use super::*; -use rusqlite::OptionalExtension as _; +use smallclaims::store::assistant_grant_authority as authority; pub const ROUTES: &[(&str, &str)] = &[ ("summary", "read.assistant.summary"), ("attention", "read.assistant.attention"), ("attention-content", "read.assistant.attention"), @@ -68,53 +68,6 @@ fn digest_only(source: &Value) -> Result<(), ApiError> { Ok(()) } -// Admission and authentication share the principal-indexed active-grant fold. -// append owns the admission lock; several grants of the same profile are allowed. -// Expired base grants without issuer policies are pruned in SQL. A policy -// candidate must reach the authenticated fold: SQL cannot verify its signature. -// Foreign revocations likewise reach Rust. Local revocations can be prefiltered -// only when their origin, owner and immutable grant identity match. -// UNION builds only candidate IDs: indexed expiry ranges prune expired base -// bodies, and the issuer-policy branch preserves renewals for verification. -// Pin revocation's subject/kind index, never its principal-wide expression index. -const ADMISSION_QUERY: &str = - "WITH eligible(id) AS ( - SELECT id FROM claims INDEXED BY claims_assistant_v1_principal_index - WHERE ?5 IS NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - UNION - SELECT id FROM claims - WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5 - AND json_type(body,'$.fields.expires_at_unix_ms')='integer' - UNION - SELECT id FROM claims - WHERE ?5 IS NOT NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND json_extract(body,'$.fields.expires_at_unix_ms') IS NULL AND json_type(body,'$.fields') IS NULL - UNION - SELECT granted.id FROM claims AS policy INDEXED BY claims_assistant_v1_principal_expiry_index - JOIN claims AS granted INDEXED BY claims_subject_kind_accepted_index - ON granted.subject=policy.subject AND granted.kind=?1 - WHERE ?5 IS NOT NULL AND policy.kind=?4 AND policy.origin=granted.origin - AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5 - AND COALESCE(json_extract(granted.body,'$.fields.principal'),'assistant/chatgpt')=?2) - SELECT claims.id FROM eligible JOIN claims ON claims.id=eligible.id - WHERE ?5 IS NULL OR claims.origin<>?6 OR NOT EXISTS ( - SELECT 1 FROM claims AS revoked INDEXED BY claims_assistant_v1_transition_index - WHERE revoked.subject=claims.subject AND revoked.kind=?3 - AND revoked.origin=claims.origin AND revoked.actor=claims.actor - AND json_extract(revoked.body,'$.fields.issuer')=revoked.actor - AND (json_type(revoked.body,'$.fields.principal') IS NULL OR json_extract(revoked.body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) - AND (json_type(revoked.body,'$.fields.profile') IS NULL OR json_extract(revoked.body,'$.fields.profile') IN ('assistant','service')) - AND json_extract(revoked.body,'$.fields.issuer') IS json_extract(claims.body,'$.fields.issuer') - AND json_extract(revoked.body,'$.fields.grant_id') IS json_extract(claims.body,'$.fields.grant_id') - AND COALESCE(json_extract(revoked.body,'$.fields.principal'),'assistant/chatgpt')=COALESCE(json_extract(claims.body,'$.fields.principal'),'assistant/chatgpt') - AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant'))"; - -#[cfg(feature = "test-support")] -pub const fn admission_query_for_test() -> &'static str { ADMISSION_QUERY } - - fn admission_now_ms() -> u128 { #[cfg(test)] if let Some(now) = tests::ADMISSION_NOW.get() { @@ -128,103 +81,21 @@ fn candidate_grants(state: &AppState, principal: &str, expiry_cut: Option) fn candidate_grants_except(state: &AppState, principal: &str, expiry_cut: Option, excluded: Option<&str>, ignored_profile: Option) -> Result, ApiError> { - let owner = owning_person(state)?; - static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| - crate::store::assistant_write::validated_candidates_query(ADMISSION_QUERY)); let ignored_profile = ignored_profile.map(|profile| match profile { Profile::Assistant => "assistant", Profile::Service => "service", }); - let rows = { - let connection = state.store.readers.get(); - let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-hc1c46de6a890 owner=fractal_api_core::api::client_v0::external_grants TODO=trace-statement-and-value-representation */ &QUERY).map_err(ApiError::internal)?; - query.query_map(rusqlite::params![GRANTED, principal, REVOKED, POLICY, expiry_cut, - state.store.origin(), owner, ignored_profile, excluded], |row| { - Ok((row.get::<_, String>(10)?, row.get::<_, String>(11)?, - smallclaims::store::claim_from_row(row)?)) - }).map_err(ApiError::internal)?.collect::, _>>().map_err(ApiError::internal)? - }; - // Verify foreign grants and transitions together: one sealed membership - // snapshot, and each envelope signature at most once for this fold. - let foreign_ids: Vec = rows.iter() - .filter(|(_, _, claim)| claim.origin != state.store.origin()) - .map(|(_, _, claim)| claim.id.clone()).collect(); - let authenticated = if foreign_ids.is_empty() { - std::collections::BTreeSet::new() - } else { - state.store.claim_ids_with_authenticated_member_writers(&foreign_ids).map_err(ApiError::internal)? - }; - let mut candidates = std::collections::BTreeMap::, Option, Option)>::new(); - for (id, role, claim) in rows { - let entry = candidates.entry(id).or_default(); - match role.as_str() { - "grant" => entry.0 = Some(claim), - "policy" => entry.1 = Some(claim), - "revoked" => entry.2 = Some(claim), - _ => unreachable!("candidate query has fixed roles"), - } - } - let mut active = Vec::new(); - for (_, (grant, mut policy, mut revocation)) in candidates { - let grant = grant.ok_or_else(|| ApiError::internal("candidate grant is absent"))?; - if grant.actor.as_deref() != Some(owner) { continue; } - let foreign = grant.origin != state.store.origin(); - if foreign { - if !authenticated.contains(&grant.id) { continue; } - // A Legacy-window or invalid signature must not hide an older - // authenticated renewal/revocation from the same issuer. - if let Some(candidate) = policy.as_ref().filter(|row| !authenticated.contains(&row.id)) { - policy = transition_before(state, &grant, POLICY, Some(candidate.store_index))?; - } - if let Some(candidate) = revocation.as_ref().filter(|row| !authenticated.contains(&row.id)) { - revocation = transition_before(state, &grant, REVOKED, Some(candidate.store_index))?; - } - } - if expiry_cut.is_some() && revocation.is_some() { continue; } - let policy = policy.as_ref().unwrap_or(&grant); - if !valid_foreign_grant(state, &grant, policy)? { continue; } - let source = fields(policy)?; - if expiry_cut.is_none_or(|now| unexpired(source, now)) { + authority::candidates(&state.store.readers.get(), principal, owning_person(state)?, + expiry_cut, excluded, ignored_profile).map_err(ApiError::bad)? + .into_iter().map(|grant| { let profile = Profile::stored(fields(&grant)?)?; - profile.compatible(Profile::stored(source)?)?; - active.push((grant, profile)); - } - } - Ok(active) + Ok((grant, profile)) + }).collect() } fn unexpired(source: &Value, now: u64) -> bool { source["expires_at_unix_ms"].as_u64().is_some_and(|expires| expires > now) } -fn valid_foreign_grant(state: &AppState, grant: &ClaimRecord, policy: &ClaimRecord) -> Result { - let validate = || -> Result<(), ApiError> { - let original = fields(grant)?; - let source = fields(policy)?; - let principal = principal(original)?; - let id = original["grant_id"].as_str().ok_or_else(|| forbidden("grant ID absent"))?; - if subject(id)? != grant.subject || policy.origin != grant.origin - || policy.actor.as_deref() != Some(owning_person(state)?) - || self::principal(source)? != principal - || ["grant_id", "session_actor", "issuer", "profile"].iter().any(|key| source[*key] != original[*key]) - || source["issuer"] != owning_person(state)? - || source["session_actor"].as_str().and_then(|actor| actor.strip_prefix(principal)) - .and_then(|suffix| suffix.strip_prefix("/session/")) != Some(id) - || !matches!(source["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) - || source["disclosure_consent"] != true - || !original["credential_hash"].as_str().is_some_and(|digest| digest.len() == 64 - && digest.bytes().all(|byte| byte.is_ascii_hexdigit())) - || !source["scopes"].as_array().is_some_and(|scopes| - scopes.iter().all(|scope| scope.as_str().is_some_and(|scope| SCOPES.contains(&scope)))) { - return Err(forbidden("invalid foreign external grant")); - } - digest_only(original)?; - digest_only(source)?; - Profile::stored(original)?.compatible(Profile::stored(source)?)?; - Ok(()) - }; - Ok(validate().is_ok()) -} fn witness(grant: &ClaimRecord, profile: Profile) -> Value { json!({"grant_id":fields(grant).ok().and_then(|source| source.get("grant_id")), @@ -265,13 +136,11 @@ fn admit_profile(state: &AppState, source: &Value) -> Result<(), ApiError> { } pub fn principal(source: &Value) -> Result<&str, ApiError> { - crate::store::assistant_write::principal(source) + authority::principal(source) .ok_or_else(|| forbidden("invalid assistant principal")) } pub const BEGUN: &str = "custom.client.assistant.v1.begun"; -pub const GRANTED: &str = "custom.client.assistant.v1.granted"; -pub const POLICY: &str = "custom.client.assistant.v1.policy"; -pub const REVOKED: &str = "custom.client.assistant.v1.revoked"; +pub use authority::{GRANTED, POLICY, REVOKED}; pub const SCOPES: &[&str] = &[ "read.assistant.summary", "read.assistant.attention", "read.assistant.missions", "read.assistant.agents", "read.assistant.conversation", "read.assistant.terminal", @@ -309,6 +178,9 @@ pub fn fields(claim: &ClaimRecord) -> Result<&Value, ApiError> { claim.body.get("fields").ok_or_else(|| forbidden("invalid assistant grant claim")) } pub fn latest(state: &AppState, subject: &str, kind: &str) -> Result, ApiError> { + if matches!(kind, GRANTED | POLICY | REVOKED) { + return authority::latest(&state.store.readers.get(), subject, kind).map_err(ApiError::bad); + } Ok(state.store.claims_for_subject_kind_at(subject, kind, None, true, 1) .map_err(ApiError::internal)?.claims.into_iter().next()) } @@ -322,7 +194,21 @@ pub fn append(state: &AppState, subject: String, kind: &str, actor: &str, None }; if matches!(kind, BEGUN | GRANTED | POLICY | REVOKED) { - assistant_profile(&value)?; + if kind == REVOKED { + Profile::stored(&value)?; + let granted = authority::latest(&state.store.readers.get(), &subject, GRANTED) + .map_err(ApiError::bad)?.ok_or_else(|| forbidden("assistant grant is absent"))?; + if actor != owning_person(state)? || granted.actor.as_deref() != Some(actor) + || granted.origin != state.store.origin() + || previous.is_none() + || principal(&value)? != principal(fields(&granted)?)? + || ["grant_id", "issuer", "profile"].iter() + .any(|key| value.get(*key) != granted.body["fields"].get(*key)) { + return Err(forbidden("assistant revocation requires the authoritative grant owner and immutable identity")); + } + } else { + assistant_profile(&value)?; + } digest_only(&value)?; if let Some(previous) = previous { let previous = fields(previous)?; @@ -355,7 +241,9 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, let mut audit_principal = actor.split_once("/session/").map(|(principal, _)| principal.to_owned()); if let Some(subject) = grant_id.and_then(|id| subject(id).ok()) { for kind in [BEGUN, GRANTED, POLICY, REVOKED] { - if let Some(claim) = latest(state, &subject, kind)? { + // Audit references retained evidence, including unauthoritative overlays. + if let Some(claim) = state.store.claims_for_subject_kind_at(&subject, kind, None, true, 1) + .map_err(ApiError::internal)?.claims.into_iter().next() { audit_principal = Some(principal(fields(&claim)?)?.to_owned()); referenced.push(claim.id); } @@ -375,26 +263,8 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, Ok(()) } -// Seek past unauthenticated issuer rows, not just structurally malformed rows. -// Wrong-origin/actor histories never enter the seek's indexed prefix. fn transition(state: &AppState, granted: &ClaimRecord, kind: &str) -> Result, ApiError> { - transition_before(state, granted, kind, None) -} - -fn transition_before(state: &AppState, granted: &ClaimRecord, kind: &str, mut before: Option) - -> Result, ApiError> { - let connection = state.store.readers.get(); - loop { - let candidate = crate::store::assistant_write::validated_transition_before( - &connection, granted, owning_person(state)?, state.store.origin(), kind, before, - ).map_err(ApiError::internal)?; - let Some(candidate) = candidate else { return Ok(None); }; - if granted.origin == state.store.origin() - || state.store.claim_has_authenticated_member_writer(&candidate.id).map_err(ApiError::internal)? { - return Ok(Some(candidate)); - } - before = Some(candidate.store_index); - } + authority::transition(&state.store.readers.get(), granted, kind).map_err(ApiError::bad) } pub fn revoked(state: &AppState, granted: &ClaimRecord) -> Result { @@ -446,24 +316,20 @@ pub fn projection_with_witness(state: &AppState, granted: &ClaimRecord) -> Resul pub fn authenticate(state: &AppState, digest: &str, transport: &'static str) -> Result, ApiError> { - let id: Option = state.store.readers.get().query_row( - "SELECT id FROM claims WHERE kind=?1 AND json_extract(body,'$.fields.credential_hash')=?2 ORDER BY store_index DESC LIMIT 1", - rusqlite::params![GRANTED, digest], |row| row.get(0)) - .optional().map_err(ApiError::internal)?; - let Some(id) = id else { return Ok(None) }; - let granted = state.store.claim_by_id(&id).map_err(ApiError::internal)? - .ok_or_else(|| forbidden("assistant grant is absent"))?; + let Some(granted) = authority::by_credential(&state.store.readers.get(), digest) + .map_err(ApiError::bad)? else { return Ok(None); }; session(state, &granted, transport).map(Some) } pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) -> Result { + if !authority::contains(&state.store.readers.get(), &granted.id).map_err(ApiError::bad)? { + return Err(forbidden("assistant grant is absent or unauthenticated")); + } let now = client_now_ms() as u64; let policy = effective(state, granted)?; let is_revoked = revoked(state, granted)?; if !is_revoked && unexpired(fields(&policy)?, now) - && valid_foreign_grant(state, granted, &policy)? - && (granted.origin == state.store.origin() - || state.store.claim_has_authenticated_member_writer(&granted.id).map_err(ApiError::internal)?) { + && authority::structurally_valid(granted, &policy) { let profile = Profile::stored(fields(granted)?)?; if candidate_grants_except(state, principal(fields(granted)?)?, Some(now), Some(&granted.id), Some(profile))? .iter().any(|(_, other)| *other != profile) { @@ -475,10 +341,7 @@ pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) let granted_fields = fields(granted)?; assistant_profile(granted_fields)?; assistant_profile(source)?; - if self::principal(granted_fields)? != principal - || ["grant_id", "session_actor", "issuer"].iter().any(|key| source[*key] != granted_fields[*key]) - || source["session_actor"].as_str().and_then(|actor| actor.strip_prefix(principal)) - .and_then(|suffix| suffix.strip_prefix("/session/")) != source["grant_id"].as_str() { + if !authority::structurally_valid(granted, &policy) { return Err(forbidden("assistant grant principal and session are inconsistent")); } if granted.origin != state.store.origin() || policy.origin != granted.origin @@ -486,9 +349,7 @@ pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) return Err(forbidden("assistant requests require the authoritative grant issuer")); } if is_revoked - || !unexpired(source, now) - || source["issuer"] != owning_person(state)? - || !matches!(source["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) || source["disclosure_consent"] != true { + || !unexpired(source, now) { return Err(forbidden("assistant grant was revoked, expired, or has invalid policy")); } let scopes = source["scopes"].as_array().ok_or_else(|| forbidden("assistant scopes absent"))? @@ -569,6 +430,44 @@ mod tests { (admitted, usable) } + // Independent raw-history oracle. Intentionally does not call the projection's + // validator: original identity/digests and effective policy rights have distinct roles. + fn reference_structure(state: &AppState, grant: &ClaimRecord, policy: &ClaimRecord) -> bool { + let Some(original) = grant.body.get("fields").filter(|value| value.is_object()) else { return false }; + let Some(effective) = policy.body.get("fields").filter(|value| value.is_object()) else { return false }; + let parse_principal = |source: &Value| match source.get("principal") { + None => Some(PRINCIPAL), + Some(Value::String(value)) if value == PRINCIPAL => Some(PRINCIPAL), + Some(Value::String(value)) if value == MCP_PRINCIPAL => Some(MCP_PRINCIPAL), + _ => None, + }; + let valid = |claim: &ClaimRecord, source: &Value| { + let Some(principal) = parse_principal(source) else { return false }; + let Some(id) = source["grant_id"].as_str() else { return false }; + subject(id).is_ok_and(|subject| subject == claim.subject) + && claim.actor.as_deref() == state.owning_person.as_deref() + && source["issuer"].as_str() == state.owning_person.as_deref() + && source["session_actor"].as_str() == Some(format!("{principal}/session/{id}").as_str()) + && matches!(source.get("profile"), None | Some(Value::String(_))) + && source.get("profile").is_none_or(|value| value == "assistant" || value == "service") + && !["credential", "code"].iter().any(|key| source.get(*key).is_some()) + && ["credential_hash", "code_hash"].iter().all(|key| source.get(*key).is_none_or(|value| + value.as_str().is_some_and(|digest| digest.len() == 64 + && digest.bytes().all(|byte| byte.is_ascii_hexdigit())))) + }; + grant.origin == policy.origin && grant.subject == policy.subject + && valid(grant, original) && valid(policy, effective) + && matches!(effective["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) + && effective["disclosure_consent"] == true + && effective["expires_at_unix_ms"].as_u64().is_some() + && effective["scopes"].as_array().is_some_and(|scopes| + scopes.iter().all(|scope| scope.as_str().is_some_and(|scope| SCOPES.contains(&scope)))) + && original["credential_hash"].as_str().is_some() + && parse_principal(original) == parse_principal(effective) + && ["grant_id", "session_actor", "issuer", "profile"].iter() + .all(|key| original.get(*key) == effective.get(*key)) + } + // Deliberately walk subject history rather than reuse the production SQL // transition selector, effective-policy fold, or revocation helper. pub(super) fn reference_transition(state: &AppState, grant: &ClaimRecord, kind: &str) @@ -588,8 +487,7 @@ mod tests { || Profile::stored(source).is_err() { continue; } - if kind == POLICY && (!valid_foreign_grant(state, grant, &claim)? - || source["expires_at_unix_ms"].as_u64().is_none()) { + if kind == POLICY && !reference_structure(state, grant, &claim) { continue; } if grant.origin != state.store.origin() @@ -625,7 +523,7 @@ mod tests { continue; } let policy = reference_transition(state, &grant, POLICY)?.unwrap_or_else(|| grant.clone()); - if !valid_foreign_grant(state, &grant, &policy)? { continue; } + if !reference_structure(state, &grant, &policy) { continue; } let active = fields(&policy)?; if active["expires_at_unix_ms"].as_u64().map(u128::from).unwrap_or(0) > admission_now_ms() { Profile::stored(fields(&grant)?)?.compatible(Profile::stored(active)?)?; @@ -707,7 +605,7 @@ mod tests { let peer = Store::open_memory("peer").unwrap(); let revoke = append_fixture(&peer, REVOKED, source.clone(), None); state.store.import_replication("peer", &peer.export_replication(0).unwrap()).unwrap(); - let imported = latest(&state, &subject, REVOKED).unwrap().unwrap(); + let imported = state.store.claim_by_id(&revoke.id).map_err(ApiError::internal).unwrap().unwrap(); assert_eq!(imported.id, revoke.id); assert_eq!(imported.origin, "peer"); } else { @@ -734,53 +632,37 @@ mod tests { } #[test] - fn admission_sql_keeps_policy_candidates_for_the_authenticated_fold() { - let connection = rusqlite::Connection::open_in_memory().unwrap(); - connection.execute_batch( - "CREATE TABLE claims(id TEXT,subject TEXT,kind TEXT,body TEXT,origin TEXT DEFAULT 'local',actor TEXT DEFAULT 'person/owner',store_index INTEGER PRIMARY KEY); - CREATE INDEX claims_assistant_v1_principal_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); - CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms')); - CREATE INDEX claims_subject_kind_accepted_index ON claims(subject,kind,store_index); - CREATE INDEX claims_assistant_v1_transition_index ON claims(subject,kind,origin,actor,store_index);" - ).unwrap(); - let fixtures = [ - ("expired", json!({"fields":{"expires_at_unix_ms":99}}), None, false), - ("live", json!({"fields":{"expires_at_unix_ms":101}}), None, true), - ("boundary", json!({"fields":{"expires_at_unix_ms":100}}), None, false), - ("max", json!({"fields":{"expires_at_unix_ms":u64::MAX}}), None, true), - ("negative", json!({"fields":{"expires_at_unix_ms":-1}}), None, false), - ("string", json!({"fields":{"expires_at_unix_ms":"101"}}), None, false), - ("float", json!({"fields":{"expires_at_unix_ms":101.0}}), None, false), - ("absent-expiry", json!({"fields":{}}), None, false), - // Missing fields must still reach fields() and its existing error. - ("absent-fields", json!({}), None, true), - ("renewed", json!({"fields":{"expires_at_unix_ms":99}}), - Some(json!({"fields":{"expires_at_unix_ms":101}})), true), - ("shortened", json!({"fields":{"expires_at_unix_ms":101}}), - Some(json!({"fields":{"expires_at_unix_ms":99}})), true), - ("invalid-policy", json!({"fields":{"expires_at_unix_ms":99}}), - Some(json!({})), false), - ]; - let mut expected = Vec::new(); - for (id, grant, policy, included) in fixtures { - connection.execute("INSERT INTO claims(id,subject,kind,body) VALUES(?1,?1,?2,?3)", - rusqlite::params![id, GRANTED, grant.to_string()]).unwrap(); - if let Some(policy) = policy { - connection.execute("INSERT INTO claims(id,subject,kind,body) VALUES(?1,?2,?3,?4)", - rusqlite::params![format!("{id}-policy"), id, POLICY, policy.to_string()]).unwrap(); + fn projection_candidates_apply_effective_expiry_including_repaired_original_expiry() { + for (expiry, policy_expiry, included) in [ + (json!(99), None, false), (json!(101), None, true), + (json!(100), None, false), (json!(u64::MAX), None, true), + (json!(-1), None, false), (json!("101"), None, false), + (json!(101.0), None, false), (Value::Null, None, false), + (json!(99), Some(101), true), (json!(101), Some(99), false), + (Value::Null, Some(101), true), + ] { + let root = tempfile::tempdir().unwrap(); + let mut state = crate::api::tests_shared::state(root.path()); + state.owning_person = Some("person/owner".into()); + let id = "0123456789abcdef01234567"; + let subject = subject(id).unwrap(); + let mut source = json!({"grant_id":id,"issuer":"person/owner", + "session_actor":format!("{PRINCIPAL}/session/{id}"), + "credential_hash":"a".repeat(64),"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":[],"expires_at_unix_ms":expiry}); + let append = |kind: &str, source: Value| state.store.append_claim(&ClaimInput { + subject:subject.clone(),kind:kind.into(),actor:Some("person/owner".into()), + fields:serde_json::from_value(source).unwrap(),evidence:Vec::new(), + expected_subject:None,idempotency_key:None, + }).unwrap(); + let granted = append(GRANTED, source.clone()); + if let Some(expiry) = policy_expiry { + source["expires_at_unix_ms"] = json!(expiry); + append(POLICY, source); } - if included { expected.push(id.to_owned()); } + let candidates = candidate_grants(&state, PRINCIPAL, Some(100)).unwrap(); + assert_eq!(candidates.iter().any(|(claim, _)| claim.id == granted.id), included); } - let mut found = connection.prepare(ADMISSION_QUERY).unwrap() - .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, 100_u64, "local"], - |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); - found.sort(); - expected.sort(); - assert_eq!(found, expected); - let unfiltered = connection.prepare(ADMISSION_QUERY).unwrap() - .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, Option::::None, "local"], - |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); - assert_eq!(unfiltered.len(), 12, "invalid owner configuration must not hide validation errors"); } #[test] @@ -799,9 +681,12 @@ mod tests { let root = tempfile::tempdir().unwrap(); let mut state = crate::api::tests_shared::state(root.path()); state.owning_person = Some("person/owner".into()); - let source = json!({"principal":PRINCIPAL,"issuer":"person/owner", - "expires_at_unix_ms":u64::MAX,"credential_hash":credential_digest("private bearer")}); + let mut source = json!({"principal":PRINCIPAL,"issuer":"person/owner", + "expires_at_unix_ms":u64::MAX,"credential_hash":credential_digest("private bearer"), + "minimal_read_mode":"approval-once","disclosure_consent":true,"scopes":[]}); for id in ["111111111111111111111111", "222222222222222222222222"] { + source["grant_id"] = json!(id); + source["session_actor"] = json!(format!("{PRINCIPAL}/session/{id}")); append(&state, subject(id).unwrap(), GRANTED, "person/owner", source.clone(), None).unwrap(); } let service_subject = subject("333333333333333333333333").unwrap(); @@ -819,19 +704,20 @@ mod tests { expected_subject: Some(None), idempotency_key: None, }).unwrap(); let next = subject("444444444444444444444444").unwrap(); + source["grant_id"] = json!("444444444444444444444444"); + source["session_actor"] = json!(format!("{PRINCIPAL}/session/444444444444444444444444")); assert!(append(&state, next.clone(), GRANTED, "person/owner", source.clone(), None).is_err()); assert!(latest(&state, &next, GRANTED).unwrap().is_none()); - state.store.append_claim(&ClaimInput { - subject: service_subject, kind: REVOKED.into(), actor: Some("person/owner".into()), - fields: serde_json::from_value(fields(&grant).unwrap().clone()).unwrap(), evidence: vec![grant.id.clone()], - expected_subject: Some(Some(grant.id.clone())), idempotency_key: None, - }).unwrap(); - let candidates = { - let connection = state.store.readers.get(); - connection.prepare(ADMISSION_QUERY).unwrap() - .query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, client_now_ms() as u64, state.store.origin()], |row| row.get::<_, String>(0)) - .unwrap().collect::, _>>().unwrap() - }; + let mut forged = fields(&grant).unwrap().clone(); + forged["profile"] = json!("assistant"); + assert!(append(&state, service_subject.clone(), REVOKED, "person/owner", + forged, Some(&grant)).is_err()); + assert!(append(&state, service_subject.clone(), REVOKED, "person/other", + fields(&grant).unwrap().clone(), Some(&grant)).is_err()); + append(&state, service_subject, REVOKED, "person/owner", + fields(&grant).unwrap().clone(), Some(&grant)).unwrap(); + let candidates = candidate_grants(&state, PRINCIPAL, Some(client_now_ms() as u64)).unwrap() + .into_iter().map(|(grant, _)| grant.id).collect::>(); assert_eq!(candidates.len(), 2); assert!(!candidates.contains(&grant.id), "revoked history must not reach the admission loop"); assert!(append(&state, next, GRANTED, "person/owner", source, None).is_ok()); @@ -893,7 +779,7 @@ mod tests { fields:serde_json::from_value(source).unwrap(), evidence:vec![granted.id.clone()], expected_subject:Some(Some(granted.id)), idempotency_key:None, }).unwrap(); - assert!(authenticate(&state, &credential_digest(&id), "unix").is_err()); + assert!(!matches!(authenticate(&state, &credential_digest(&id), "unix"), Ok(Some(_)))); } } diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index a130f26edc6..a9375858b34 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -486,23 +486,23 @@ fn unverifiable_foreign_grant_cannot_suspend_a_local_credential() { } #[test] -fn admission_scan_uses_the_real_principal_index() { +fn admission_reads_the_authority_projection_index() { let root = tempfile::tempdir().unwrap(); let state = member(root.path(), "alder"); - issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let grant = issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let candidates = candidate_grants(&state, PRINCIPAL, Some(client_now_ms() as u64)).unwrap(); + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].0.id, grant.id); let connection = state.store.readers.get(); - let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-hf4201606586b owner=fractal_api_core::api::client_v0::external_grants::conflict_tests TODO=trace-statement-and-value-representation */ &format!("EXPLAIN QUERY PLAN {ADMISSION_QUERY}")).unwrap(); - let plan = query.query_map(rusqlite::params![GRANTED, PRINCIPAL, REVOKED, POLICY, - Some(client_now_ms() as u64), state.store.origin()], |row| row.get::<_, String>(3)).unwrap() + let mut query = connection.prepare(/* sqlite-large-value: allow-for-now lv-ha14d9df71ca8 owner=fractal_api_core::api::client_v0::external_grants::conflict_tests TODO=trace-statement-and-value-representation */ &format!("EXPLAIN QUERY PLAN {}", authority::CANDIDATES_QUERY)).unwrap(); + let expiry = authority::expiry_key(client_now_ms() as u64); + let plan = query.query_map(rusqlite::params![PRINCIPAL, OWNER, expiry, + Option::<&str>::None, Option::<&str>::None], |row| row.get::<_, String>(3)).unwrap() .collect::, _>>().unwrap(); - println!("external grant admission query plan:\n{}", plan.join("\n")); - assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_index")), - "principal admission must use its production index: {plan:?}"); - assert!(plan.iter().any(|step| step.contains("revoked USING INDEX claims_assistant_v1_transition_index")), - "revocation must seek by subject, kind, origin and actor rather than scan overlays: {plan:?}"); - assert!(plan.iter().any(|step| step.contains("claims_assistant_v1_principal_expiry_index") - && step.contains(">?")), - "expired grant bodies must be pruned by an index range: {plan:?}"); + assert!(plan.iter().any(|step| step.contains("assistant_grant_effective_active_index")), + "admission must use the effective authority projection: {plan:?}"); + assert!(plan.iter().all(|step| !step.contains("claims")), + "admission must never scan raw claim history: {plan:?}"); } #[test] diff --git a/crates/fractal-client-codegen/templates/Models.swift.in b/crates/fractal-client-codegen/templates/Models.swift.in index 97e0a7248a2..f95035ab8c9 100644 --- a/crates/fractal-client-codegen/templates/Models.swift.in +++ b/crates/fractal-client-codegen/templates/Models.swift.in @@ -154,6 +154,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case validationFailed case idempotencyConflict case grantProfileConflict + case assistantGrantAuthorityNotReady case agentsPublicationRowTooLarge case attentionMigrated case invalidAnswer, notAnswerable @@ -247,6 +248,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case "validation-failed": .validationFailed case "idempotency-conflict": .idempotencyConflict case "grant-profile-conflict": .grantProfileConflict + case "assistant-grant-authority-not-ready": .assistantGrantAuthorityNotReady case "stale-fence": .staleFence case "issuer-required": .issuerRequired case "pairing-origin-required": .pairingOriginRequired @@ -340,6 +342,7 @@ public enum ErrorCode: Codable, Sendable, Equatable { case .validationFailed: "validation-failed" case .idempotencyConflict: "idempotency-conflict" case .grantProfileConflict: "grant-profile-conflict" + case .assistantGrantAuthorityNotReady: "assistant-grant-authority-not-ready" case .staleFence: "stale-fence" case .issuerRequired: "issuer-required" case .pairingOriginRequired: "pairing-origin-required" diff --git a/crates/fractal-client-codegen/templates/generated.rs.in b/crates/fractal-client-codegen/templates/generated.rs.in index fffab57f450..195ea6015ff 100644 --- a/crates/fractal-client-codegen/templates/generated.rs.in +++ b/crates/fractal-client-codegen/templates/generated.rs.in @@ -135,6 +135,7 @@ pub enum ErrorCode { ValidationFailed, IdempotencyConflict, GrantProfileConflict, + AssistantGrantAuthorityNotReady, LegacyActionReceiptUntrusted, IssuerRequired, PairingOriginRequired, diff --git a/crates/fractal-client-codegen/templates/lib.rs.in b/crates/fractal-client-codegen/templates/lib.rs.in index b103f8743e9..fa9d34c9c63 100644 --- a/crates/fractal-client-codegen/templates/lib.rs.in +++ b/crates/fractal-client-codegen/templates/lib.rs.in @@ -1195,6 +1195,7 @@ fn render_message(code: Option<&ErrorCode>, message: &str, human: bool) -> Strin | ErrorCode::RuntimeNotLocal | ErrorCode::PrivateNotesCarrierConflict | ErrorCode::GrantProfileConflict + | ErrorCode::AssistantGrantAuthorityNotReady | ErrorCode::PrivateNotesUnreachable | ErrorCode::PrivateNotesIndeterminate | ErrorCode::ArrangementExists diff --git a/crates/fractal-client/src/generated.rs b/crates/fractal-client/src/generated.rs index 13bb72abd29..1691601da97 100644 --- a/crates/fractal-client/src/generated.rs +++ b/crates/fractal-client/src/generated.rs @@ -135,6 +135,7 @@ pub enum ErrorCode { ValidationFailed, IdempotencyConflict, GrantProfileConflict, + AssistantGrantAuthorityNotReady, LegacyActionReceiptUntrusted, IssuerRequired, PairingOriginRequired, diff --git a/crates/fractal-store/src/store.rs b/crates/fractal-store/src/store.rs index 122ea5fa283..af93973c0e5 100644 --- a/crates/fractal-store/src/store.rs +++ b/crates/fractal-store/src/store.rs @@ -787,7 +787,7 @@ pub struct AgentWorkQueue { /// Fractal's projection tables, and the indexes its folds read the claim log through. The /// graph creates its own tables first; see `smallclaims::store::SCHEMA`. -const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-hd7de403d2fec owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" +const SCHEMA: &str = /* sqlite-large-value: allow-for-now lv-h22c8c670811c owner=fractal_store::store TODO=chunk-or-reference-variable-columns */ r#" -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL; @@ -937,17 +937,6 @@ WHERE kind='custom.client.pairing-completed'; CREATE INDEX IF NOT EXISTS claims_assistant_v1_credential_index ON claims(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'; --- Match parameterized admission by kind and effective principal, including legacy ChatGPT grants. -CREATE INDEX IF NOT EXISTS claims_assistant_v1_principal_index -ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); --- Seek live base grants without loading expired JSON bodies on each authentication. -CREATE INDEX IF NOT EXISTS claims_assistant_v1_principal_expiry_index -ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), - json_extract(body,'$.fields.expires_at_unix_ms')); --- Installed on reopen as well as creation: unauthoritative actor/origin overlays --- must not increase the cost of selecting an issuer's latest valid transition. -CREATE INDEX IF NOT EXISTS claims_assistant_v1_transition_index -ON claims(subject, kind, origin, actor, store_index); -- A runtime incarnation's claims about a subject by acceptance time, so when a session began -- and last changed are two seeks instead of a read of every claim the subject has. The -- expression is INCARNATION_OF_CLAIM, which queries repeat so the planner uses this index. diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 96e764b0002..10b9fd5e07c 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -1,5 +1,6 @@ -//! Server-established assistant provenance, checked in the mutation's writer transaction. +//! Server-established assistant provenance, rechecked against projected authority in the mutation's writer transaction. use super::*; +use smallclaims::store::assistant_grant_authority as authority; #[derive(Clone, Debug)] pub struct AssistantWriteAuthorization { @@ -17,142 +18,6 @@ impl AssistantWriteAuthorization { } } -pub fn principal(fields: &Value) -> Option<&str> { - match fields.get("principal") { - None => Some("assistant/chatgpt"), - Some(value) => value.as_str().filter(|principal| matches!(*principal, "assistant/chatgpt" | "assistant/mcp")), - } -} - -/// Select the last structurally valid transition. Foreign results require full -/// cryptographic member-writer verification by the caller, including its keyed -/// membership window; a signature row alone does not authenticate provenance. -pub fn validated_transition( - connection: &Connection, granted: &ClaimRecord, owner: &str, local_origin: &str, kind: &str, -) -> Result, FractalError> { - validated_transition_before(connection, granted, owner, local_origin, kind, None) -} - -/// Continue an indexed seek past a structurally valid but unauthenticated row. -pub fn validated_transition_before( - connection: &Connection, granted: &ClaimRecord, owner: &str, local_origin: &str, - kind: &str, before: Option, -) -> Result, FractalError> { - static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| { - validated_transition_query().replace( - "ORDER BY claims.store_index DESC LIMIT 1", - "AND (?7 IS NULL OR claims.store_index &'static str { - static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| format!( - "WITH original AS (SELECT body FROM claims WHERE id=?5) SELECT {CLAIM_COLUMNS} - FROM claims INDEXED BY claims_assistant_v1_transition_index - WHERE claims.subject=?1 AND claims.kind=?2 AND claims.origin=?3 AND claims.actor=?4 - AND ?2 IN ('custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') - AND json_type(body,'$.fields')='object' - AND json_extract(body,'$.fields.issuer')=?4 - AND json_extract(body,'$.fields.grant_id')=json_extract((SELECT body FROM original),'$.fields.grant_id') - AND json_extract(body,'$.fields.issuer')=json_extract((SELECT body FROM original),'$.fields.issuer') - AND (json_type(body,'$.fields.principal') IS NULL - OR json_extract(body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) - AND (json_type((SELECT body FROM original),'$.fields.principal') IS NULL - OR json_extract((SELECT body FROM original),'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) - AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt') - =COALESCE(json_extract((SELECT body FROM original),'$.fields.principal'),'assistant/chatgpt') - AND (json_type(body,'$.fields.profile') IS NULL OR json_extract(body,'$.fields.profile') IN ('assistant','service')) - AND (json_type((SELECT body FROM original),'$.fields.profile') IS NULL OR json_extract((SELECT body FROM original),'$.fields.profile') IN ('assistant','service')) - AND COALESCE(json_extract(body,'$.fields.profile'),'assistant') - =COALESCE(json_extract((SELECT body FROM original),'$.fields.profile'),'assistant') - AND (?2='custom.client.assistant.v1.revoked' OR ( - json_extract(body,'$.fields.session_actor')=json_extract((SELECT body FROM original),'$.fields.session_actor') - AND json_extract(body,'$.fields.profile') IS json_extract((SELECT body FROM original),'$.fields.profile') - AND json_extract(body,'$.fields.session_actor') - =COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt') || '/session/' || json_extract(body,'$.fields.grant_id') - AND ((length(json_extract(body,'$.fields.grant_id'))=24 - AND json_extract(body,'$.fields.grant_id') NOT GLOB '*[^0-9a-fA-F]*' - AND claims.subject='custom/client/assistant-v1-' || json_extract(body,'$.fields.grant_id')) - OR (length(json_extract(body,'$.fields.grant_id'))=40 - AND substr(json_extract(body,'$.fields.grant_id'),1,16)='assistant-grant/' - AND substr(json_extract(body,'$.fields.grant_id'),17) NOT GLOB '*[^0-9a-fA-F]*' - AND claims.subject='custom/client/assistant-v1-' || substr(json_extract(body,'$.fields.grant_id'),17))) - AND json_extract(body,'$.fields.minimal_read_mode') IN ('approval-once','caller-bound-allow') - AND json_type(body,'$.fields.disclosure_consent')='true' - AND json_type(body,'$.fields.expires_at_unix_ms') IN ('integer','real') - AND (body -> '$.fields.expires_at_unix_ms') NOT GLOB '*[^0-9]*' - AND (length(body -> '$.fields.expires_at_unix_ms')<20 - OR (length(body -> '$.fields.expires_at_unix_ms')=20 - AND (body -> '$.fields.expires_at_unix_ms')<='18446744073709551615')) - AND json_type(body,'$.fields.scopes')='array' - AND NOT EXISTS (SELECT 1 FROM json_each(body,'$.fields.scopes') AS scope - WHERE scope.type<>'text' OR scope.value NOT IN ( - 'read.assistant.summary','read.assistant.attention','read.assistant.missions', - 'read.assistant.agents','read.assistant.conversation','read.assistant.terminal', - 'write.assistant.messages','write.assistant.custom-reply','write.assistant.answers')) - AND json_type(body,'$.fields.credential') IS NULL AND json_type(body,'$.fields.code') IS NULL - AND json_type((SELECT body FROM original),'$.fields.credential') IS NULL AND json_type((SELECT body FROM original),'$.fields.code') IS NULL - AND json_type((SELECT body FROM original),'$.fields.credential_hash')='text' - AND length(json_extract((SELECT body FROM original),'$.fields.credential_hash'))=64 - AND json_extract((SELECT body FROM original),'$.fields.credential_hash') NOT GLOB '*[^0-9a-fA-F]*' - AND NOT EXISTS (SELECT 1 FROM json_each(body,'$.fields') AS digest - WHERE digest.key IN ('credential_hash','code_hash') - AND (digest.type<>'text' OR length(digest.value)<>64 OR digest.value GLOB '*[^0-9a-fA-F]*')) - AND NOT EXISTS (SELECT 1 FROM json_each((SELECT body FROM original),'$.fields') AS digest - WHERE digest.key IN ('credential_hash','code_hash') - AND (digest.type<>'text' OR length(digest.value)<>64 OR digest.value GLOB '*[^0-9a-fA-F]*')) - )) - AND (?3=?6 OR EXISTS ( - SELECT 1 FROM replica_records AS records - JOIN replica_envelopes AS envelopes USING(writer,sequence,envelope_hash) - JOIN replica_envelope_signatures AS signatures USING(writer,sequence,envelope_hash) - WHERE records.claim_id=claims.id AND records.writer=claims.origin - AND records.state='valid' AND envelopes.receipt_state IN ('validated','degraded'))) - ORDER BY claims.store_index DESC LIMIT 1")); - QUERY.as_str() -} - -/// Hydrate candidates and their latest structurally valid transitions in one -/// statement. `selection` returns grant IDs using parameters 1 through 6; -/// parameter 7 is the owner, 8 an optional profile to ignore, 9 an excluded ID. -/// The correlated subqueries use the same validation as the mutation writer. -pub fn validated_candidates_query(selection: &str) -> String { - let seek = |kind: &str| { - validated_transition_query() - .replace(&format!("SELECT {CLAIM_COLUMNS}"), "SELECT claims.id") - .replace("?5", "granted.id") - .replace("?1", "granted.subject") - .replace("?2", &format!("'{kind}'")) - .replace("?3", "granted.origin") - .replace("?4", "?7") - }; - let policy = seek("custom.client.assistant.v1.policy"); - let revoked = seek("custom.client.assistant.v1.revoked"); - format!( - "WITH selected AS ({selection}), grants AS ( - SELECT claims.* FROM selected JOIN claims ON claims.id=selected.id - WHERE (?9 IS NULL OR claims.id<>?9) - AND (?8 IS NULL OR COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant') IS NOT ?8) - ) - SELECT {CLAIM_COLUMNS}, claims.id, 'grant' FROM grants AS claims - UNION ALL - SELECT {CLAIM_COLUMNS}, granted.id, 'policy' FROM grants AS granted - JOIN claims ON claims.id=({policy}) - UNION ALL - SELECT {CLAIM_COLUMNS}, granted.id, 'revoked' FROM grants AS granted - JOIN claims ON claims.id=({revoked})" - ) -} pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let granted = authorized_grant(connection, origin, authorization)?; @@ -162,28 +27,23 @@ pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &As pub fn authorized_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let denied = || FractalError::new("forbidden", "assistant write authorization changed or expired before commit"); - let claim = |kind: &str| -> Result, FractalError> { - connection.query_row(/* sqlite-large-value: allow-for-now lv-hd82c937baff5 owner=fractal_store::store::assistant_write TODO=trace-statement-and-value-representation */ &latest_claim_of_kind_query(), - params![authorization.grant_subject,kind],claim_from_row).optional().map_err(internal) - }; - let granted = claim("custom.client.assistant.v1.granted")?.ok_or_else(denied)?; - let policy_claim = validated_transition(connection, &granted, &authorization.owner, origin, "custom.client.assistant.v1.policy")?; + let granted = authority::latest(connection, &authorization.grant_subject, authority::GRANTED)? + .ok_or_else(denied)?; + let policy_claim = authority::transition(connection, &granted, authority::POLICY)?; let policy = policy_claim.as_ref().unwrap_or(&granted); if granted.origin != origin || policy.origin != origin - || validated_transition(connection, &granted, &authorization.owner, origin, "custom.client.assistant.v1.revoked")?.is_some() { + || !authority::structurally_valid(&granted, policy) + || authority::transition(connection, &granted, authority::REVOKED)?.is_some() { return Err(denied()); } let fields = &policy.body["fields"]; - let principal = principal(fields).ok_or_else(denied)?; - if self::principal(&granted.body["fields"]) != Some(principal) - || ["grant_id", "session_actor", "issuer"].iter().any(|key| fields[*key] != granted.body["fields"][*key]) + let principal = authority::principal(fields).ok_or_else(denied)?; + if fields.get("profile").is_some_and(|profile| profile != "assistant") || authorization.principal() != principal || fields["session_actor"] != authorization.actor - || fields["session_actor"].as_str().and_then(|actor| actor.strip_prefix(principal)) - .and_then(|suffix| suffix.strip_prefix("/session/")) != fields["grant_id"].as_str() || granted.actor.as_deref() != Some(authorization.owner.as_str()) || policy.actor.as_deref() != Some(authorization.owner.as_str()) - || fields["issuer"] != authorization.owner || fields["disclosure_consent"] != true + || fields["issuer"] != authorization.owner || fields["policy_revision"].as_u64() != Some(authorization.policy_revision) || fields["expires_at_unix_ms"].as_u64().map(u128::from).is_none_or(|expiry| expiry <= now_ms()) || !fields["scopes"].as_array().is_some_and(|scopes| scopes.iter().any(|scope| scope.as_str() == Some(&authorization.scope))) @@ -234,11 +94,8 @@ pub fn validate_replicated(kind: &str, actor: Option<&str>, fields: &Value) -> R mod tests { use super::*; - fn transition_fixture() -> (Connection, String, Value) { - let connection = Connection::open_in_memory().unwrap(); - connection.execute_batch(smallclaims::store::SCHEMA).unwrap(); - connection.execute_batch(SCHEMA).unwrap(); - connection.execute("INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES('batch','local',1,'hash','1')", []).unwrap(); + fn transition_fixture() -> (Store, String, Value) { + let store = Store::open_memory("local").unwrap(); let suffix = "0123456789abcdef01234567"; let subject = format!("custom/client/assistant-v1-{suffix}"); let body = json!({"fields":{ @@ -248,65 +105,53 @@ mod tests { "disclosure_consent":true, "scopes":["write.assistant.messages"], "expires_at_unix_ms":u64::MAX }}); - insert_transition(&connection, &subject, "original", "custom.client.assistant.v1.granted", "local", "person/owner", &body); - (connection, subject, body) + insert_transition(&store, &subject, authority::GRANTED, "person/owner", &body); + (store, subject, body) } - fn insert_transition(connection: &Connection, subject: &str, id: &str, kind: &str, origin: &str, actor: &str, body: &Value) { - connection.execute( - "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) - VALUES(?1,'batch',?2,?3,?4,?5,?6,'[]','1')", - params![id,subject,kind,origin,actor,body.to_string()], - ).unwrap(); + fn insert_transition(store: &Store, subject: &str, kind: &str, actor: &str, body: &Value) -> ClaimRecord { + store.append_claim(&ClaimInput { + subject: subject.into(), kind: kind.into(), actor: Some(actor.into()), + fields: serde_json::from_value(body["fields"].clone()).unwrap(), + evidence: Vec::new(), expected_subject: None, idempotency_key: None, + }).unwrap() } #[test] - fn validated_transition_index_is_installed_for_existing_stores() { - let (connection, _, _) = transition_fixture(); - connection.execute_batch("DROP INDEX claims_assistant_v1_transition_index").unwrap(); - connection.execute_batch(SCHEMA).unwrap(); - let definition: String = connection.query_row( - "SELECT sql FROM sqlite_master WHERE name='claims_assistant_v1_transition_index'", - [], |row| row.get(0), - ).unwrap(); - assert!(definition.contains("(subject, kind, origin, actor, store_index)")); - connection.execute_batch(SCHEMA).unwrap(); - } - - #[test] - fn validated_transition_p1_indexed_seek_is_independent_of_wrong_origin_actor_overlays() { - let (connection, subject, body) = transition_fixture(); - let kind = "custom.client.assistant.v1.policy"; - insert_transition(&connection, &subject, "valid", kind, "local", "person/owner", &body); - let query = validated_transition_query(); - let original = "original"; + fn projected_transition_ignores_actor_overlay_flood() { + let (store, subject, body) = transition_fixture(); + let granted = authority::latest(&store.readers.get(), &subject, authority::GRANTED).unwrap().unwrap(); + let valid = insert_transition(&store, &subject, authority::POLICY, "person/owner", &body); let mut prior = None; for count in [32, 512, 7900] { for index in 0..count { - insert_transition(&connection, &subject, &format!("overlay-{count}-{index}"), kind, - if index % 2 == 0 { "other" } else { "local" }, - if index % 2 == 0 { "person/owner" } else { "person/other" }, &body); + let mut overlay = body.clone(); + overlay["fields"]["nonce"] = json!(format!("{count}-{index}")); + insert_transition(&store, &subject, authority::POLICY, "person/other", &overlay); } - let args = params![subject,kind,"local","person/owner",original,"local"]; - let mut statement = connection.prepare(query).unwrap(); - assert_eq!(statement.query_row(args, |row| row.get::<_, String>(0)).unwrap(), "valid"); + let selected = authority::transition(&store.readers.get(), &granted, authority::POLICY).unwrap().unwrap(); + assert_eq!(selected.id, valid.id); + let connection = store.readers.get(); + let args = params![subject, authority::POLICY, granted.origin, "person/owner", granted.id]; + let mut statement = connection.prepare(authority::TRANSITION_QUERY).unwrap(); + let _: String = statement.query_row(args, |row| row.get(0)).unwrap(); let cost = statement.get_status(rusqlite::StatementStatus::VmStep); if let Some(prior) = prior { assert!(cost <= prior + 20, "{prior} -> {cost}"); } prior = Some(cost); - let plan = connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")).unwrap() + let plan = connection.prepare(&format!("EXPLAIN QUERY PLAN {}", authority::TRANSITION_QUERY)).unwrap() .query_map(args, |row| row.get::<_, String>(3)).unwrap() .collect::>>().unwrap().join("; "); - assert!(plan.contains("claims_assistant_v1_transition_index (subject=? AND kind=? AND origin=? AND actor=?)"), "{plan}"); + assert!(plan.contains("assistant_grant_authority_transition_index"), "{plan}"); assert!(!plan.contains("USE TEMP B-TREE FOR ORDER BY"), "{plan}"); } } #[test] - fn validated_transition_ignores_malformed_newer_policies_and_revocations() { - let (connection, subject, body) = transition_fixture(); - for kind in ["custom.client.assistant.v1.policy", "custom.client.assistant.v1.revoked"] { - let valid = format!("valid-{kind}"); - insert_transition(&connection, &subject, &valid, kind, "local", "person/owner", &body); + fn projected_transition_ignores_malformed_newer_policies_and_revocations() { + let (store, subject, body) = transition_fixture(); + let granted = authority::latest(&store.readers.get(), &subject, authority::GRANTED).unwrap().unwrap(); + for kind in [authority::POLICY, authority::REVOKED] { + let valid = insert_transition(&store, &subject, kind, "person/owner", &body); let mut patches = vec![ json!({"principal":null}), json!({"principal":"assistant/mcp"}), json!({"profile":null}), json!({"profile":"service"}), @@ -323,41 +168,39 @@ mod tests { json!({"credential_hash":"invalid"}), json!({"code_hash":null}), ]); } - for (index, patch) in patches.into_iter().enumerate() { + for patch in patches { let mut malformed = body.clone(); malformed["fields"].as_object_mut().unwrap().extend(patch.as_object().unwrap().clone()); - insert_transition(&connection, &subject, &format!("malformed-{kind}-{index}"), kind, "local", "person/owner", &malformed); + insert_transition(&store, &subject, kind, "person/owner", &malformed); } - let selected = connection.query_row(validated_transition_query(), - params![subject,kind,"local","person/owner","original","local"], - |row| row.get::<_, String>(0)).unwrap(); - assert_eq!(selected, valid); + let selected = authority::transition(&store.readers.get(), &granted, kind).unwrap().unwrap(); + assert_eq!(selected.id, valid.id); } } #[test] - fn validated_transition_accepts_raw_hex_grant_identity() { - let (connection, subject, mut body) = transition_fixture(); + fn projected_transition_accepts_raw_hex_grant_identity() { + let store = Store::open_memory("local").unwrap(); let suffix = "0123456789abcdef01234567"; - body["fields"]["grant_id"] = json!(suffix); - body["fields"]["session_actor"] = json!(format!("assistant/chatgpt/session/{suffix}")); - connection.execute("UPDATE claims SET body=?1 WHERE id='original'", [body.to_string()]).unwrap(); - let kind = "custom.client.assistant.v1.policy"; - insert_transition(&connection, &subject, "raw-policy", kind, "local", "person/owner", &body); - let selected = connection.query_row(validated_transition_query(), - params![subject,kind,"local","person/owner","original","local"], - |row| row.get::<_, String>(0)).unwrap(); - assert_eq!(selected, "raw-policy"); + let subject = format!("custom/client/assistant-v1-{suffix}"); + let body = json!({"fields":{"grant_id":suffix,"issuer":"person/owner", + "session_actor":format!("assistant/chatgpt/session/{suffix}"), + "credential_hash":"a".repeat(64),"minimal_read_mode":"approval-once", + "disclosure_consent":true,"scopes":[],"expires_at_unix_ms":u64::MAX}}); + let granted = insert_transition(&store, &subject, authority::GRANTED, "person/owner", &body); + let valid = insert_transition(&store, &subject, authority::POLICY, "person/owner", &body); + let selected = authority::transition(&store.readers.get(), &granted, authority::POLICY).unwrap().unwrap(); + assert_eq!(selected.id, valid.id); } #[test] fn grant_principal_defaults_only_absent_legacy_fields_to_chatgpt() { - assert_eq!(principal(&json!({})), Some("assistant/chatgpt")); + assert_eq!(authority::principal(&json!({})), Some("assistant/chatgpt")); for expected in ["assistant/chatgpt", "assistant/mcp"] { - assert_eq!(principal(&json!({"principal":expected})), Some(expected)); + assert_eq!(authority::principal(&json!({"principal":expected})), Some(expected)); } for forged in [Value::Null, json!("assistant/other"), json!("person/other"), json!(7)] { - assert_eq!(principal(&json!({"principal":forged})), None); + assert_eq!(authority::principal(&json!({"principal":forged})), None); } } diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index bd62b1cc0b4..d187a326d64 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -846,48 +846,15 @@ mod schema_install_tests { use super::*; #[test] - fn assistant_principal_index_installs_on_existing_claims_and_reopens_without_ddl() { - const GRANTED: &str = "custom.client.assistant.v1.granted"; - const REVOKED: &str = "custom.client.assistant.v1.revoked"; - const POLICY: &str = "custom.client.assistant.v1.policy"; - const INDEX: &str = "claims_assistant_v1_principal_index"; - const EXPIRY_INDEX: &str = "claims_assistant_v1_principal_expiry_index"; - const SELECT: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; - // Keep this differential reference identical to the production constant; - // the API-core real-Store plan test covers that constant directly. - const ACTIVE: &str = - "WITH eligible(id) AS ( - SELECT id FROM claims INDEXED BY claims_assistant_v1_principal_index - WHERE ?5 IS NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - UNION - SELECT id FROM claims - WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND json_extract(body,'$.fields.expires_at_unix_ms')>?5 - AND json_type(body,'$.fields.expires_at_unix_ms')='integer' - UNION - SELECT id FROM claims - WHERE ?5 IS NOT NULL AND kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND json_extract(body,'$.fields.expires_at_unix_ms') IS NULL AND json_type(body,'$.fields') IS NULL - UNION - SELECT granted.id FROM claims AS policy INDEXED BY claims_assistant_v1_principal_expiry_index - JOIN claims AS granted INDEXED BY claims_subject_kind_accepted_index - ON granted.subject=policy.subject AND granted.kind=?1 - WHERE ?5 IS NOT NULL AND policy.kind=?4 AND policy.origin=granted.origin - AND COALESCE(json_extract(policy.body,'$.fields.principal'),'assistant/chatgpt')=?2 - AND json_extract(policy.body,'$.fields.expires_at_unix_ms')>?5 - AND COALESCE(json_extract(granted.body,'$.fields.principal'),'assistant/chatgpt')=?2) - SELECT claims.id FROM eligible JOIN claims ON claims.id=eligible.id - WHERE ?5 IS NULL OR claims.origin<>?6 OR NOT EXISTS ( - SELECT 1 FROM claims AS revoked INDEXED BY claims_assistant_v1_transition_index - WHERE revoked.subject=claims.subject AND revoked.kind=?3 - AND revoked.origin=claims.origin AND revoked.actor=claims.actor - AND json_extract(revoked.body,'$.fields.issuer')=revoked.actor - AND (json_type(revoked.body,'$.fields.principal') IS NULL OR json_extract(revoked.body,'$.fields.principal') IN ('assistant/chatgpt','assistant/mcp')) - AND (json_type(revoked.body,'$.fields.profile') IS NULL OR json_extract(revoked.body,'$.fields.profile') IN ('assistant','service')) - AND json_extract(revoked.body,'$.fields.issuer') IS json_extract(claims.body,'$.fields.issuer') - AND json_extract(revoked.body,'$.fields.grant_id') IS json_extract(claims.body,'$.fields.grant_id') - AND COALESCE(json_extract(revoked.body,'$.fields.principal'),'assistant/chatgpt')=COALESCE(json_extract(claims.body,'$.fields.principal'),'assistant/chatgpt') - AND COALESCE(json_extract(revoked.body,'$.fields.profile'),'assistant')=COALESCE(json_extract(claims.body,'$.fields.profile'),'assistant'))"; + fn assistant_projection_backfills_existing_claims_without_changing_baseline_schema() { + use smallclaims::store::assistant_grant_authority as authority; + use std::time::Duration; + + const OBSOLETE_INDEXES: [&str; 3] = [ + "claims_assistant_v1_principal_index", + "claims_assistant_v1_principal_expiry_index", + "claims_assistant_v1_transition_index", + ]; fn snapshot(connection: &Connection) -> Vec> { connection @@ -901,106 +868,138 @@ mod schema_install_tests { .unwrap() } - fn plan(connection: &Connection, sql: &str, active: bool) -> Vec { - let parameters: Vec<&dyn rusqlite::ToSql> = if active { - vec![&GRANTED, &"assistant/chatgpt", &REVOKED, &POLICY, &100_u64, &"node"] - } else { - vec![&GRANTED, &"assistant/chatgpt"] - }; + fn claims_indexes(connection: &Connection) -> Vec<(String, Option)> { connection - .prepare(&format!("EXPLAIN QUERY PLAN {sql}")) + .prepare("SELECT name,sql FROM sqlite_schema WHERE type='index' AND tbl_name='claims' ORDER BY name") .unwrap() - .query_map(parameters.as_slice(), |row| row.get(3)) + .query_map([], |row| Ok((row.get(0)?, row.get(1)?))) .unwrap() .collect::>() .unwrap() } - // These supported stores need additive DDL, not a data or version conversion. - for version in [18, 19, fractal_schema::STORAGE_VERSION] { - let directory = tempfile::tempdir().unwrap(); - let path = directory.path().join("claims.sqlite"); - let connection = Connection::open(&path).unwrap(); - connection.execute_batch(smallclaims::store::SCHEMA).unwrap(); - install_initial_schema(&connection, true).unwrap(); - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_index; DROP INDEX claims_assistant_v1_principal_expiry_index; DROP INDEX claims_assistant_v1_transition_index;").unwrap(); - connection.pragma_update(None, "user_version", version).unwrap(); + fn append(connection: &Connection, id: &str, slot: u8, kind: &str, principal: &str, expiry: u64) { + let suffix = format!("{slot:024x}"); + let grant_id = format!("assistant-grant/{suffix}"); + let body = json!({"fields": { + "grant_id": grant_id, + "issuer": "person/owner", + "principal": principal, + "profile": "assistant", + "session_actor": format!("{principal}/session/{grant_id}"), + "credential_hash": "a".repeat(64), + "minimal_read_mode": "approval-once", + "disclosure_consent": true, + "expires_at_unix_ms": expiry, + "scopes": ["read.assistant.summary"] + }}); connection.execute( - "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES('batch','node',1,'hash','1')", - [], + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,'batch',?2,?3,'node','person/owner',?4,'[]','1')", + params![id, format!("custom/client/assistant-v1-{suffix}"), kind, body.to_string()], ).unwrap(); - for (id, subject, kind, body) in [ - ("legacy", "custom/client/legacy", GRANTED, r#"{"fields":{"issuer":"person/owner","expires_at_unix_ms":200}}"#), - ("chatgpt", "custom/client/chatgpt", GRANTED, r#"{"fields":{"issuer":"person/owner","principal":"assistant/chatgpt","expires_at_unix_ms":50}}"#), - ("mcp", "custom/client/mcp", GRANTED, r#"{"fields":{"issuer":"person/owner","principal":"assistant/mcp","expires_at_unix_ms":200}}"#), - ("policy", "custom/client/chatgpt", POLICY, r#"{"fields":{"issuer":"person/owner","expires_at_unix_ms":200}}"#), - ("revoked", "custom/client/legacy", REVOKED, r#"{"fields":{"issuer":"person/owner"}}"#), - ("unrelated", "custom/test/unrelated", "custom.test.recorded", r#"{"fields":{}}"#), - ] { + } + + // Supported older stores retain their version and raw evidence. An intermediate + // build's indexes must also survive: rollback is additive, never DROP INDEX. + for version in [18, 19, fractal_schema::STORAGE_VERSION] { + for had_obsolete_indexes in [false, true] { + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("claims.sqlite"); + // Use the public constructor so fleet-generation state and all other + // smallclaims initialization exist before exercising historical raw writes. + drop(Store::open(&path, "node").unwrap()); + let connection = Connection::open(&path).unwrap(); + let baseline_indexes = claims_indexes(&connection); + assert!(baseline_indexes.iter().any(|(name, _)| name == "claims_assistant_v1_credential_index")); + assert!(baseline_indexes.iter().all(|(name, _)| !OBSOLETE_INDEXES.contains(&name.as_str()))); + if had_obsolete_indexes { + // Historical DDL is a rollback fixture, not a production installation. + connection.execute_batch( + "CREATE INDEX claims_assistant_v1_principal_index + ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')); + CREATE INDEX claims_assistant_v1_principal_expiry_index + ON claims(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), + json_extract(body,'$.fields.expires_at_unix_ms')); + CREATE INDEX claims_assistant_v1_transition_index + ON claims(subject, kind, origin, actor, store_index);" + ).unwrap(); + } + connection.pragma_update(None, "user_version", version).unwrap(); connection.execute( - "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) VALUES(?1,'batch',?2,?3,'node','person/owner',?4,'[]','1')", - params![id, subject, kind, body], + "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch','node',1,'hash','1')", [], ).unwrap(); - } - let before = snapshot(&connection); - let plans_before = [plan(&connection, SELECT, false)]; - assert!(plans_before.iter().flatten().all(|detail| !detail.contains(INDEX) && !detail.contains(EXPIRY_INDEX))); - drop(connection); - - let connection = Connection::open(&path).unwrap(); - migrate_schema(&connection).unwrap(); - install_initial_schema(&connection, false).unwrap(); - assert_eq!(snapshot(&connection), before, "version {version}: claim bytes"); - assert_eq!( - connection.pragma_query_value(None, "user_version", |row| row.get::<_, u32>(0)).unwrap(), - version, - ); - for (sql, active, previous) in [(SELECT, false, &plans_before[0]), (ACTIVE, true, &plans_before[0])] { - let current = plan(&connection, sql, active); - eprintln!("assistant admission version={version} active={active} before={previous:?} after={current:?}"); - assert!( - current.iter().any(|detail| detail.contains("SEARCH") - && (detail.contains(INDEX) || (!active && detail.contains(EXPIRY_INDEX))) - && detail.contains("kind=?") && detail.contains("=?")), - "version {version}: before={previous:?}; after={current:?}", + append(&connection, "active", 1, authority::GRANTED, "assistant/chatgpt", 50); + append(&connection, "extended", 1, authority::POLICY, "assistant/chatgpt", 200); + append(&connection, "expired", 2, authority::GRANTED, "assistant/chatgpt", 50); + append(&connection, "revoked", 3, authority::GRANTED, "assistant/chatgpt", 200); + append(&connection, "revoke", 3, authority::REVOKED, "assistant/chatgpt", 200); + append(&connection, "mcp", 4, authority::GRANTED, "assistant/mcp", 200); + append(&connection, "unrelated", 5, "custom.test.recorded", "assistant/chatgpt", 200); + let before = snapshot(&connection); + let indexes_before = claims_indexes(&connection); + drop(connection); + + let connection = Connection::open(&path).unwrap(); + migrate_schema(&connection).unwrap(); + install_initial_schema(&connection, false).unwrap(); + authority::install(&connection, "node").unwrap(); + assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).is_err()); + // A zero-budget slice makes partial progress without marking it ready. + assert!(!authority::backfill_slice(&connection, Duration::ZERO).unwrap()); + assert!(authority::ready(&connection).is_err()); + while !authority::backfill_slice(&connection, Duration::from_secs(1)).unwrap() {} + authority::ready(&connection).unwrap(); + assert_eq!(snapshot(&connection), before, "version {version}: raw evidence"); + assert_eq!(claims_indexes(&connection), indexes_before, "projection must not build or drop raw claims indexes"); + assert_eq!( + connection.pragma_query_value(None, "user_version", |row| row.get::<_, u32>(0)).unwrap(), + version, ); - } - assert!(plan(&connection, ACTIVE, true).iter().any(|step| - step.contains(EXPIRY_INDEX) && step.contains(">?"))); - assert!(plan(&connection, ACTIVE, true).iter().any(|step| - step.contains("claims_assistant_v1_transition_index") - && step.contains("subject=? AND kind=? AND origin=? AND actor=?"))); - for (principal, mut expected) in [ - ("assistant/chatgpt", vec!["chatgpt".to_owned(), "legacy".to_owned()]), - ("assistant/mcp", vec!["mcp".to_owned()]), - ] { - let mut found = connection.prepare(SELECT).unwrap() - .query_map(params![GRANTED, principal], |row| row.get::<_, String>(0)) + let active = authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).unwrap(); + assert_eq!(active.iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert_eq!( + authority::candidates(&connection, "assistant/mcp", "person/owner", Some(100), None, None).unwrap() + .iter().map(|claim| claim.id.as_str()).collect::>(), + vec!["mcp"], + ); + assert_eq!( + authority::candidates(&connection, "assistant/chatgpt", "person/owner", None, None, None).unwrap().len(), + 3, + "no cutoff retains expired and revoked validation candidates", + ); + let plan = connection.prepare(&format!("EXPLAIN QUERY PLAN {}", authority::CANDIDATES_QUERY)).unwrap() + .query_map(params!["assistant/chatgpt", "person/owner", authority::expiry_key(100), Option::::None, Option::::None], |row| row.get::<_, String>(3)) .unwrap().collect::>>().unwrap(); - found.sort(); - expected.sort(); - assert_eq!(found, expected); + assert!(plan.iter().any(|step| step.contains("SEARCH") + && step.contains("assistant_grant_effective_active_index") + && step.contains("principal=? AND owner=? AND revoked=? AND expires_at>?")), "{plan:?}"); + assert!(plan.iter().all(|step| !step.contains("SCAN claims") && !step.contains("SEARCH claims")), "{plan:?}"); + + // An older build can append raw evidence after backfill. The additive + // trigger closes admission until that evidence has been projected. + append(&connection, "late-revoke", 1, authority::REVOKED, "assistant/chatgpt", 200); + assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).is_err()); + while !authority::backfill_slice(&connection, Duration::from_secs(1)).unwrap() {} + assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).unwrap().is_empty()); + let after = snapshot(&connection); + let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); + drop(connection); + + let connection = Connection::open(&path).unwrap(); + migrate_schema(&connection).unwrap(); + install_initial_schema(&connection, false).unwrap(); + authority::install(&connection, "node").unwrap(); + authority::ready(&connection).unwrap(); + assert_eq!(snapshot(&connection), after); + assert_eq!(claims_indexes(&connection), indexes_before); + assert_eq!( + connection.pragma_query_value(None, "schema_version", |row| row.get::<_, u32>(0)).unwrap(), + cookie, + "an unchanged reopen must not rebuild projection or baseline indexes", + ); } - let active = connection.prepare(ACTIVE).unwrap() - .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, 100_u64, "node"], |row| row.get::<_, String>(0)) - .unwrap().collect::>>().unwrap(); - assert_eq!(active, vec!["chatgpt"]); - let unfiltered = connection.prepare(ACTIVE).unwrap() - .query_map(params![GRANTED, "assistant/chatgpt", REVOKED, POLICY, Option::::None, "node"], |row| row.get::<_, String>(0)) - .unwrap().collect::>>().unwrap(); - assert_eq!(unfiltered.len(), 2, "no cutoff preserves unfiltered validation candidates"); - let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); - drop(connection); - - let connection = Connection::open(&path).unwrap(); - migrate_schema(&connection).unwrap(); - install_initial_schema(&connection, false).unwrap(); - assert_eq!(snapshot(&connection), before); - assert_eq!( - connection.pragma_query_value(None, "schema_version", |row| row.get::<_, u32>(0)).unwrap(), - cookie, - "an unchanged reopen must not rebuild the index", - ); } } diff --git a/crates/fractal/src/main.rs b/crates/fractal/src/main.rs index 230d0e7539f..c734f6af6c2 100644 --- a/crates/fractal/src/main.rs +++ b/crates/fractal/src/main.rs @@ -7746,6 +7746,7 @@ async fn run_up(args: UpArgs) -> Result<()> { spawn_publication_evidence(store.clone()); tokio::spawn(build_transport_observation_index(store.clone())); tokio::spawn(build_operation_claim_digests(store.clone())); + tokio::spawn(build_assistant_grant_authority(store.clone())); startup_telemetry.serving(); let ready_at = Instant::now(); startup_phases.log_ready( @@ -20733,6 +20734,27 @@ async fn build_transport_observation_index(store: Arc) { } } +/// Continue the persisted authority cursor after serving begins. Authorization +/// fails closed until the final page commits; requests never advance the cursor. +async fn build_assistant_grant_authority(store: Arc) { + loop { + let worker = store.clone(); + let result = tokio::task::spawn_blocking(move || + worker.advance_assistant_grant_authority_backfill()).await; + match result { + Ok(Ok(true)) => return, + Ok(Ok(false)) => {} + Ok(Err(error)) if maintenance_contention(&error) => {} + error => { + stderr_message("st", format_args!("assistant grant authority backfill stopped: {error:?}; restart resumes its committed cursor")); + return; + } + } + // Finite, persisted cursor work; yield the writer between pages. + tokio::time::sleep(Duration::from_millis(100)).await; + } +} + /// This starts only after both APIs serve. Each page reads up to 32 operation claims on a /// reader, then joins the managed background writer queue only to insert their keys, and /// yields for 100 ms. The operation audit reads bodies until the last page marks it ready. diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 5cb195ecf72..6f5cb318c40 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -43,6 +43,11 @@ pub use admitted::{AdmittedStore, STORE_DATABASE_FILES}; mod proof; pub mod prepared_envelope; +pub mod assistant_grant_authority; +#[cfg(test)] +mod assistant_grant_authority_tests; +#[cfg(test)] +mod assistant_grant_authority_bench; mod replica_record; use crate::operation_metadata::OperationMetadata; #[cfg(test)] @@ -1268,6 +1273,14 @@ impl Store { readers.path == path && readers.shared_memory == shared_memory, "st database writer and read pool must use the same opened database path and mode" ); + assistant_grant_authority::install(&connection, &origin)?; + { + let transaction = connection.unchecked_transaction()?; + assistant_grant_authority::backfill_slice( + &transaction, std::time::Duration::from_secs(2), + )?; + transaction.commit()?; + } // Batch rowids are the sealing frontier. Checkpoint adoption can remove the highest // rows, so SQLite's default rowid allocator cannot be used: it reuses those keys and // leaves new local batches behind the frontier. Persist the allocation high water. @@ -2179,7 +2192,11 @@ pub /* sqlite-large-value-flow: allow-for-now flow-h8ff255a3c271 owner=smallclai serde_json::to_string(predecessors)?, now.to_string(), ])?; - Ok(transaction.last_insert_rowid() as u64) + let store_index = transaction.last_insert_rowid() as u64; + if matches!(kind, assistant_grant_authority::GRANTED | assistant_grant_authority::POLICY | assistant_grant_authority::REVOKED) { + assistant_grant_authority::refresh_claim(transaction, id, true)?; + } + Ok(store_index) } /// The next sequence for a local batch: one past the writer's highest batch, including one a @@ -3702,7 +3719,7 @@ impl<'a> VerifiedEnvelopeSignature<'a> { } fn store(&self, transaction: &Transaction<'_>, now: &str) -> Result { - Ok(transaction + let inserted = transaction .prepare_cached( /* sqlite-large-value: allow-for-now lv-hece070718e6e owner=smallclaims::store TODO=chunk-or-reference-exact-wire-values */ "INSERT OR IGNORE INTO replica_envelope_signatures( writer, sequence, envelope_hash, member_key, signature, stored_at_unix_ms @@ -3715,7 +3732,11 @@ impl<'a> VerifiedEnvelopeSignature<'a> { self.member_key, self.signature, now - ])?) + ])?; + assistant_grant_authority::refresh_envelope( + transaction, self.writer, self.sequence, self.envelope_hash, + )?; + Ok(inserted) } } @@ -7158,7 +7179,12 @@ impl Store { ); self.fleet_authority .set(authority) - .map_err(|_| anyhow::anyhow!("this shard already has a fleet authority")) + .map_err(|_| anyhow::anyhow!("this shard already has a fleet authority"))?; + let mut connection = self.connection.write_background(); + let transaction = connection.transaction()?; + self.sync_assistant_grant_membership(&transaction)?; + transaction.commit()?; + Ok(()) } /// The fleet this store's envelopes sign for: its authority's, for a shard. @@ -7948,6 +7974,7 @@ impl Store { let transaction = connection .transaction_with_behavior(rusqlite::TransactionBehavior::Immediate) .map_err(internal)?; + self.sync_assistant_grant_membership(&transaction).map_err(internal)?; let counts = (|transaction: &Transaction<'_>| -> Result<(usize, usize, usize, u128), FractalError> { let mut received = 0; let mut duplicate = 0; @@ -8470,6 +8497,7 @@ impl Store { membership = None; continue; } + self.sync_assistant_grant_membership(&pass)?; let started = std::time::Instant::now(); let end = (next + ADMISSION_CHUNK_ENVELOPES).min(pending.len()); let first = next; diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs new file mode 100644 index 00000000000..9cfafc5d746 --- /dev/null +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -0,0 +1,411 @@ +//! Incremental, authenticated external-grant authority. Raw claims remain evidence only. +use super::*; +use std::time::{Duration, Instant}; + +pub const GRANTED: &str = "custom.client.assistant.v1.granted"; +pub const POLICY: &str = "custom.client.assistant.v1.policy"; +pub const REVOKED: &str = "custom.client.assistant.v1.revoked"; +const VERSION: &str = "1"; +const KINDS: [&str; 3] = [GRANTED, POLICY, REVOKED]; +const SCOPES: &[&str] = &[ + "read.assistant.summary", "read.assistant.attention", "read.assistant.missions", + "read.assistant.agents", "read.assistant.conversation", "read.assistant.terminal", + "write.assistant.messages", "write.assistant.custom-reply", "write.assistant.answers", +]; + +pub fn principal(fields: &Value) -> Option<&str> { + match fields.get("principal") { + None => Some("assistant/chatgpt"), + Some(value) => value.as_str().filter(|value| matches!(*value, "assistant/chatgpt" | "assistant/mcp")), + } +} +fn profile(fields: &Value) -> Option<&str> { + match fields.get("profile") { + None => Some("assistant"), + Some(value) => value.as_str().filter(|value| matches!(*value, "assistant" | "service")), + } +} +fn digest(value: &Value) -> bool { + value.as_str().is_some_and(|value| value.len() == 64 && value.bytes().all(|byte| byte.is_ascii_hexdigit())) +} +fn digest_only(fields: &Value) -> bool { + fields.get("credential").is_none() && fields.get("code").is_none() + && ["credential_hash", "code_hash"].iter().all(|key| fields.get(*key).is_none_or(digest)) +} +fn identity(claim: &ClaimRecord) -> bool { + let fields = &claim.body["fields"]; + let Some(id) = fields["grant_id"].as_str() else { return false; }; + let suffix = id.strip_prefix("assistant-grant/").unwrap_or(id); + fields.is_object() && principal(fields).is_some() && profile(fields).is_some() + && suffix.len() == 24 && suffix.bytes().all(|byte| byte.is_ascii_hexdigit()) + && claim.subject.strip_prefix("custom/client/assistant-v1-") == Some(suffix) + && claim.actor.as_deref().is_some_and(|actor| fields["issuer"].as_str() == Some(actor)) +} +fn policy_fields(claim: &ClaimRecord) -> bool { + let fields = &claim.body["fields"]; + identity(claim) && digest_only(fields) + && fields["session_actor"].as_str().and_then(|actor| + principal(fields).and_then(|principal| actor.strip_prefix(principal))) + .and_then(|suffix| suffix.strip_prefix("/session/")) == fields["grant_id"].as_str() + && matches!(fields["minimal_read_mode"].as_str(), Some("approval-once" | "caller-bound-allow")) + && fields["disclosure_consent"] == true + && fields["expires_at_unix_ms"].as_u64().is_some() + && fields["scopes"].as_array().is_some_and(|scopes| + scopes.iter().all(|scope| scope.as_str().is_some_and(|scope| SCOPES.contains(&scope)))) +} +fn base_valid(claim: &ClaimRecord) -> bool { + identity(claim) && digest_only(&claim.body["fields"]) + && digest(&claim.body["fields"]["credential_hash"]) +} +/// Shared validation for admission projection and consumers. The reference oracle +/// deliberately does not call this function. +pub fn structurally_valid(grant: &ClaimRecord, policy: &ClaimRecord) -> bool { + base_valid(grant) && policy_fields(policy) && grant.subject == policy.subject + && grant.origin == policy.origin && grant.actor == policy.actor + && principal(&grant.body["fields"]) == principal(&policy.body["fields"]) + && ["grant_id", "session_actor", "issuer", "profile"].iter() + .all(|key| grant.body["fields"][*key] == policy.body["fields"][*key]) +} +pub fn transition_valid(grant: &ClaimRecord, transition: &ClaimRecord) -> bool { + if transition.kind == POLICY { return structurally_valid(grant, transition); } + transition.kind == REVOKED && base_valid(grant) && identity(transition) + && transition.origin == grant.origin && transition.actor == grant.actor + && transition.subject == grant.subject + && transition.body["fields"]["grant_id"] == grant.body["fields"]["grant_id"] + && transition.body["fields"]["issuer"] == grant.body["fields"]["issuer"] + && principal(&transition.body["fields"]) == principal(&grant.body["fields"]) + && profile(&transition.body["fields"]) == profile(&grant.body["fields"]) +} + +pub fn expiry_key(value: u64) -> String { format!("{value:020}") } + +pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { + connection.execute_batch( + /* sqlite-large-value: allow-for-now lv-h19226e0dde9c owner=smallclaims::store::assistant_grant_authority TODO=chunk-or-reference-variable-columns */ + "CREATE TABLE IF NOT EXISTS assistant_grant_authority ( + claim_id TEXT NOT NULL, base_claim_id TEXT NOT NULL, + grant_subject TEXT NOT NULL, kind TEXT NOT NULL, origin TEXT NOT NULL, + actor TEXT NOT NULL, principal TEXT NOT NULL, profile TEXT NOT NULL, + expires_at TEXT NOT NULL, store_index INTEGER NOT NULL, + credential_hash TEXT, record TEXT NOT NULL, + PRIMARY KEY(claim_id,base_claim_id)); + CREATE INDEX IF NOT EXISTS assistant_grant_authority_transition_index + ON assistant_grant_authority(grant_subject,kind,origin,actor,base_claim_id,store_index DESC); + CREATE INDEX IF NOT EXISTS assistant_grant_authority_latest_index + ON assistant_grant_authority(grant_subject,kind,store_index DESC); + CREATE INDEX IF NOT EXISTS assistant_grant_authority_credential_index + ON assistant_grant_authority(credential_hash,store_index DESC) WHERE kind='custom.client.assistant.v1.granted'; + CREATE TABLE IF NOT EXISTS assistant_grant_effective ( + claim_id TEXT PRIMARY KEY, grant_subject TEXT NOT NULL, principal TEXT NOT NULL, + owner TEXT NOT NULL, profile TEXT NOT NULL, expires_at TEXT NOT NULL, + revoked INTEGER NOT NULL, grant_record TEXT NOT NULL); + CREATE INDEX IF NOT EXISTS assistant_grant_effective_active_index + ON assistant_grant_effective(principal,owner,revoked,expires_at,profile); + CREATE INDEX IF NOT EXISTS assistant_grant_effective_subject_index + ON assistant_grant_effective(grant_subject); + CREATE TABLE IF NOT EXISTS assistant_grant_pending ( + claim_id TEXT PRIMARY KEY, grant_subject TEXT NOT NULL, kind TEXT NOT NULL, + origin TEXT NOT NULL, sequence INTEGER NOT NULL, authenticated INTEGER NOT NULL, + record TEXT NOT NULL); + CREATE INDEX IF NOT EXISTS assistant_grant_pending_subject_index + ON assistant_grant_pending(grant_subject,authenticated); + CREATE INDEX IF NOT EXISTS assistant_grant_pending_writer_index + ON assistant_grant_pending(origin,sequence,authenticated); + CREATE TABLE IF NOT EXISTS assistant_grant_dirty (claim_id TEXT PRIMARY KEY); + CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims + WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') + BEGIN INSERT OR IGNORE INTO assistant_grant_dirty VALUES(NEW.id); END; + CREATE TABLE IF NOT EXISTS assistant_grant_membership_windows ( + writer TEXT NOT NULL, member_key TEXT NOT NULL, start INTEGER NOT NULL, end INTEGER, + PRIMARY KEY(writer,member_key));" + )?; + connection.execute(/* sqlite-large-value: allow-for-now lv-h3f117dab1bdd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_local_origin',?1)", [local_origin])?; + Ok(()) +} + +pub fn ready(connection: &Connection) -> Result<(), FractalError> { + let version: Option = connection.query_row( + "SELECT value FROM meta WHERE key='assistant_grant_authority_version'", [], |row| row.get(0), + ).optional().map_err(internal)?; + let dirty: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_dirty)", [], |row| row.get(0), + ).map_err(internal)?; + if version.as_deref() != Some(VERSION) || dirty { + return Err(FractalError::new("assistant-grant-authority-not-ready", "external-grant authority backfill is in progress; retry after it completes")); + } + Ok(()) +} +fn decode(record: String) -> Result { + serde_json::from_str(&record).map_err(internal) +} +pub const TRANSITION_QUERY: &str = "SELECT record FROM assistant_grant_authority + WHERE grant_subject=?1 AND kind=?2 AND origin=?3 AND actor=?4 AND base_claim_id=?5 + ORDER BY store_index DESC LIMIT 1"; +pub fn transition(connection: &Connection, granted: &ClaimRecord, kind: &str) -> Result, FractalError> { + ready(connection)?; + transition_unchecked(connection, granted, kind).map_err(internal) +} +fn transition_unchecked(connection: &Connection, granted: &ClaimRecord, kind: &str) -> Result> { + let record: Option = connection.query_row(/* sqlite-large-value: allow-for-now lv-h80fb9d4725e0 owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ TRANSITION_QUERY, + params![granted.subject, kind, granted.origin, granted.actor, granted.id], |row| row.get(0)).optional()?; + record.map(|record| serde_json::from_str(&record).map_err(Into::into)).transpose() +} +pub fn latest(connection: &Connection, subject: &str, kind: &str) -> Result, FractalError> { + ready(connection)?; + let record: Option = connection.query_row( + "SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2 ORDER BY store_index DESC LIMIT 1", + params![subject,kind], |row| row.get(0)).optional().map_err(internal)?; + record.map(decode).transpose() +} +pub const CANDIDATES_QUERY: &str = "SELECT grant_record FROM assistant_grant_effective + WHERE ?3 IS NOT NULL AND principal=?1 AND owner=?2 AND revoked=0 AND expires_at>?3 + AND (?4 IS NULL OR claim_id<>?4) AND (?5 IS NULL OR profile<>?5) + UNION ALL + SELECT grant_record FROM assistant_grant_effective + WHERE ?3 IS NULL AND principal=?1 AND owner=?2 + AND (?4 IS NULL OR claim_id<>?4) AND (?5 IS NULL OR profile<>?5)"; +pub fn candidates(connection: &Connection, principal: &str, owner: &str, expiry_cut: Option, excluded: Option<&str>, ignored_profile: Option<&str>) -> Result, FractalError> { + ready(connection)?; + let mut statement = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h556bdadaf8cd owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ CANDIDATES_QUERY).map_err(internal)?; + let records = statement.query_map(params![principal,owner,expiry_cut.map(expiry_key),excluded,ignored_profile], |row| row.get::<_,String>(0)) + .map_err(internal)?.collect::>>().map_err(internal)?; + records.into_iter().map(decode).collect() +} +pub fn by_credential(connection: &Connection, digest: &str) -> Result, FractalError> { + ready(connection)?; + let record: Option = connection.query_row( + "SELECT record FROM assistant_grant_authority WHERE credential_hash=?1 AND kind='custom.client.assistant.v1.granted' ORDER BY store_index DESC LIMIT 1", + [digest], |row| row.get(0)).optional().map_err(internal)?; + record.map(decode).transpose() +} +pub fn contains(connection: &Connection, claim_id: &str) -> Result { + ready(connection)?; + connection.query_row("SELECT EXISTS(SELECT 1 FROM assistant_grant_authority WHERE claim_id=?1)", [claim_id], |row| row.get(0)).map_err(internal) +} + +fn insert_authority(connection: &Connection, claim: &ClaimRecord, base: &ClaimRecord) -> Result { + let fields = &claim.body["fields"]; + Ok(connection.execute( + /* sqlite-large-value: allow-for-now lv-h60572e3ac6a5 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ + "INSERT OR IGNORE INTO assistant_grant_authority + (claim_id,base_claim_id,grant_subject,kind,origin,actor,principal,profile,expires_at,store_index,credential_hash,record) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12)", + params![claim.id,base.id,claim.subject,claim.kind,claim.origin,claim.actor,principal(fields),profile(fields), + expiry_key(fields["expires_at_unix_ms"].as_u64().unwrap_or(0)),claim.store_index, + if claim.kind==GRANTED { fields["credential_hash"].as_str() } else { None },serde_json::to_string(claim)?], + )? != 0) +} +/// The only writer of effective rows. Rebuilding a subject uses authenticated +/// authority alone, including an earlier-arriving revoke, in the same transaction. +pub fn rebuild_subject(connection: &Connection, subject: &str) -> Result<()> { + connection.execute(/* sqlite-large-value: allow-for-now lv-h47619972ac92 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_effective WHERE grant_subject=?1", [subject])?; + let mut statement = connection.prepare_cached("SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2")?; + let records = statement.query_map(params![subject,GRANTED], |row| row.get::<_,String>(0))?.collect::>>()?; + for record in records { + let grant: ClaimRecord = serde_json::from_str(&record)?; + let policy = transition_unchecked(connection,&grant,POLICY)?.unwrap_or_else(|| grant.clone()); + if !structurally_valid(&grant,&policy) { continue; } + let fields = &policy.body["fields"]; + connection.execute(/* sqlite-large-value: allow-for-now lv-h2909dd1a0b9c owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_effective(claim_id,grant_subject,principal,owner,profile,expires_at,revoked,grant_record) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8)", + params![grant.id,grant.subject,principal(fields),grant.actor,profile(fields), + expiry_key(fields["expires_at_unix_ms"].as_u64().unwrap_or(0)), + transition_unchecked(connection,&grant,REVOKED)?.is_some(),record])?; + } + Ok(()) +} +fn attach_subject(connection: &Connection, subject: &str) -> Result<()> { + let records = { + let mut statement = connection.prepare_cached("SELECT record FROM assistant_grant_pending WHERE grant_subject=?1 AND authenticated=1")?; + statement.query_map([subject], |row| row.get::<_,String>(0))?.collect::>>()? + }; + let claims: Vec = records.into_iter().map(|record| serde_json::from_str(&record)).collect::>()?; + let mut changed = false; + for grant in claims.iter().filter(|claim| claim.kind==GRANTED) { + changed |= insert_authority(connection,grant,grant)?; + for transition in claims.iter().filter(|claim| claim.kind!=GRANTED) { + if transition_valid(grant,transition) { changed |= insert_authority(connection,transition,grant)?; } + } + } + if changed { rebuild_subject(connection,subject)?; } + Ok(()) +} +fn local_origin(connection: &Connection) -> Result { + Ok(connection.query_row("SELECT value FROM meta WHERE key='assistant_grant_authority_local_origin'", [], |row| row.get(0))?) +} +/// Admission pays structural/authentication cost once. Invalid rows never enter +/// the authority or the pending-authentication writer/window index. +pub fn refresh_claim(connection: &Connection, id: &str, trusted_local: bool) -> Result<()> { + static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| + format!("SELECT {CLAIM_COLUMNS} FROM claims WHERE id=?1")); + let claim = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h1665a4a8cfdf owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ &QUERY)?.query_row(/* sqlite-large-value: allow-for-now lv-h5520ddeb5d20 owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ [id], claim_from_row).optional()?; + let Some(claim) = claim else { return Ok(()); }; + if !KINDS.contains(&claim.kind.as_str()) { return Ok(()); } + let valid = if claim.kind==GRANTED { base_valid(&claim) } + else if claim.kind==POLICY { policy_fields(&claim) } else { identity(&claim) }; + if valid { + let sequence: u64 = connection.query_row("SELECT replica_sequence FROM batches WHERE id=?1", [&claim.batch_id], |row| row.get(0))?; + let authenticated = (trusted_local && claim.origin == local_origin(connection)?) + || authenticated_claim(connection,&claim.id)?; + connection.execute(/* sqlite-large-value: allow-for-now lv-h4276e804ce28 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,sequence,authenticated,record) + VALUES(?1,?2,?3,?4,?5,?6,?7) ON CONFLICT(claim_id) DO UPDATE SET authenticated=MAX(authenticated,excluded.authenticated)", + params![claim.id,claim.subject,claim.kind,claim.origin,sequence,authenticated,serde_json::to_string(&claim)?])?; + if authenticated { attach_subject(connection,&claim.subject)?; } + } + connection.execute(/* sqlite-large-value: allow-for-now lv-h3221720b83b7 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_dirty WHERE claim_id=?1", [id])?; + Ok(()) +} +fn authenticated_claim(connection: &Connection, id: &str) -> Result { + let fleet_id = fleet_meta(connection,"assistant_grant_authority_fleet_id")?; + let Some(fleet_id) = fleet_id else { return Ok(false); }; + let shard = fleet_meta(connection,"shard_id")?; + let mut statement = connection.prepare_cached( + "SELECT records.writer,records.sequence,records.envelope_hash,signatures.member_key,signatures.signature + FROM replica_records AS records JOIN claims ON claims.id=records.claim_id AND claims.origin=records.writer + JOIN replica_envelopes AS envelopes USING(writer,sequence,envelope_hash) + JOIN replica_envelope_signatures AS signatures USING(writer,sequence,envelope_hash) + JOIN assistant_grant_membership_windows AS windows + ON windows.writer=records.writer AND windows.member_key=signatures.member_key + AND records.sequence>=windows.start AND (windows.end IS NULL OR records.sequence<=windows.end) + WHERE records.claim_id=?1 AND records.state='valid' AND envelopes.receipt_state IN ('validated','degraded')")?; + let rows = statement.query_map([id], |row| Ok((row.get::<_,String>(0)?,row.get::<_,u64>(1)?,row.get::<_,String>(2)?,row.get::<_,String>(3)?,row.get::<_,String>(4)?)))?; + for row in rows { + let (writer,sequence,hash,key,signature) = row?; + if VerifiedEnvelopeSignature::verify(shard.as_deref(),&fleet_id,&writer,sequence,&hash,&key,&signature).is_some() { return Ok(true); } + } + Ok(false) +} +/// Refresh only this envelope's grant records, after receipt/signature state has +/// been written, and before its transaction is committed. +pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, hash: &str) -> Result<()> { + refresh_membership(connection)?; + let ids = { + let mut statement = connection.prepare_cached("SELECT records.claim_id FROM replica_records AS records JOIN claims ON claims.id=records.claim_id + WHERE records.writer=?1 AND records.sequence=?2 AND records.envelope_hash=?3 + AND claims.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked')")?; + statement.query_map(params![writer,sequence,hash], |row| row.get::<_,String>(0))?.collect::>>()? + }; + // A replicated same-origin claim does NOT acquire the local-write exception. + for id in ids { refresh_claim(connection,&id,false)?; } + Ok(()) +} +/// Membership changes promote pending rows only in newly changed keyed windows. +/// Authentication is an admission fact, not a live membership predicate: a later +/// removal/fence cannot retract authentication already established for a past +/// sequence. It can only prevent a pending row from first acquiring it. +pub fn refresh_membership(connection: &Connection) -> Result<()> { + if fleet_meta(connection,"assistant_grant_authority_shared_fleet")?.is_some() { + return Ok(()); + } + let generation = fleet_generation(connection)?; + let previous: Option = connection.query_row("SELECT CAST(value AS INTEGER) FROM meta WHERE key='assistant_grant_authority_membership_generation'",[],|row| row.get(0)).optional()?; + if previous==Some(generation) { return Ok(()); } + refresh_membership_from(connection, &fleet_membership_tx(connection)?, generation, fleet_meta(connection,"fleet_id")?.as_deref())?; + Ok(()) +} + +fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::Membership, generation: i64, fleet_id: Option<&str>) -> Result<()> { + let mut changed = Vec::new(); + for incarnation in membership.incarnations() { + let prior: Option<(u64,Option)> = connection.query_row( + "SELECT start,end FROM assistant_grant_membership_windows WHERE writer=?1 AND member_key=?2", + params![incarnation.name,incarnation.member_key], |row| Ok((row.get(0)?,row.get(1)?))).optional()?; + if prior!=Some((incarnation.start,incarnation.end)) { + changed.push((incarnation.name.clone(),incarnation.start,incarnation.end)); + } + } + // Replace the window snapshot before promotions, including removal of keys + // no longer present in a conflicted membership fold. + connection.execute(/* sqlite-large-value: allow-for-now lv-hd11f3b7cf006 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_membership_windows", [])?; + for incarnation in membership.incarnations() { + connection.execute(/* sqlite-large-value: allow-for-now lv-h679dd6776599 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_membership_windows(writer,member_key,start,end) VALUES(?1,?2,?3,?4)", + params![incarnation.name,incarnation.member_key,incarnation.start,incarnation.end])?; + } + if let Some(fleet_id) = fleet_id { + connection.execute(/* sqlite-large-value: allow-for-now lv-h0ce05c43b4a2 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_fleet_id',?1)",[fleet_id])?; + } else { + connection.execute(/* sqlite-large-value: allow-for-now lv-ha3bce0201694 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM meta WHERE key='assistant_grant_authority_fleet_id'", [])?; + } + connection.execute(/* sqlite-large-value: allow-for-now lv-hbcecffaa18c4 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_membership_generation',?1)",[generation.to_string()])?; + for (writer,start,end) in changed { + let ids = { + let mut statement = connection.prepare_cached("SELECT claim_id FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index + WHERE origin=?1 AND sequence>=?2 AND (?3 IS NULL OR sequence<=?3) AND authenticated=0")?; + statement.query_map(params![writer,start,end], |row| row.get::<_,String>(0))?.collect::>>()? + }; + for id in ids { refresh_claim(connection,&id,false)?; } + } + Ok(()) +} +/// Resumable, idempotent versioned backfill. Each page uses claims_kind_index; +/// unrelated claims are never visited. Cursor and projection changes commit +/// together in the caller's transaction. Old-build appends are captured by the +/// additive dirty trigger even after the version has completed. +pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result { + let started = Instant::now(); + let origin = local_origin(connection)?; + refresh_membership(connection)?; + let complete = ready(connection).is_ok(); + if !complete { + for kind in KINDS { + let key = format!("assistant_grant_authority_cursor/{kind}"); + loop { + let cursor: u64 = connection.query_row("SELECT CAST(value AS INTEGER) FROM meta WHERE key=?1",[&key],|row|row.get(0)).optional()?.unwrap_or(0); + let rows = { + let mut statement = connection.prepare_cached("SELECT id,store_index,origin FROM claims INDEXED BY claims_kind_index WHERE kind=?1 AND store_index>?2 ORDER BY store_index LIMIT 64")?; + statement.query_map(params![kind,cursor],|row|Ok((row.get::<_,String>(0)?,row.get::<_,u64>(1)?,row.get::<_,String>(2)?)))?.collect::>>()? + }; + if rows.is_empty() { break; } + for (id,index,writer) in rows { + refresh_claim(connection,&id,writer==origin)?; + connection.execute(/* sqlite-large-value: allow-for-now lv-h3f49c0e579cd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES(?1,?2)",params![key,index.to_string()])?; + if started.elapsed()>=budget { return Ok(false); } + } + } + } + } + loop { + let rows = { + let mut statement = connection.prepare_cached("SELECT claim_id FROM assistant_grant_dirty ORDER BY claim_id LIMIT 64")?; + statement.query_map([],|row|row.get::<_,String>(0))?.collect::>>()? + }; + if rows.is_empty() { break; } + for id in rows { + let writer: Option = connection.query_row("SELECT origin FROM claims WHERE id=?1",[&id],|row|row.get(0)).optional()?; + refresh_claim(connection,&id,writer.as_deref()==Some(origin.as_str()))?; + connection.execute(/* sqlite-large-value: allow-for-now lv-hd91341d01a91 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_dirty WHERE claim_id=?1",[&id])?; + if started.elapsed()>=budget { return Ok(false); } + } + } + refresh_membership(connection)?; + connection.execute(/* sqlite-large-value: allow-for-now lv-h9b70e51e754e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_version',?1)",[VERSION])?; + Ok(true) +} + +impl Store { + /// Background work only; request handlers never call this method. + pub fn advance_assistant_grant_authority_backfill(&self) -> Result { + let mut connection = self.connection.write_background(); + let transaction = connection.transaction()?; + self.sync_assistant_grant_membership(&transaction)?; + let done = backfill_slice(&transaction,Duration::from_millis(100))?; + transaction.commit()?; + Ok(done) + } + + pub(super) fn sync_assistant_grant_membership(&self, connection: &Connection) -> Result<()> { + let Some(authority) = self.fleet_authority.get() else { + return refresh_membership(connection); + }; + let generation = authority.fleet_generation()?; + let previous: Option = connection.query_row( + "SELECT CAST(value AS INTEGER) FROM meta WHERE key='assistant_grant_authority_membership_generation'", [], |row| row.get(0), + ).optional()?; + if previous==Some(generation) && fleet_meta(connection,"assistant_grant_authority_shared_fleet")?.is_some() { + return Ok(()); + } + let membership = authority.fleet_membership_sealed()?; + connection.execute(/* sqlite-large-value: allow-for-now lv-h437f9d145151 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_shared_fleet','1')", [])?; + refresh_membership_from(connection,&membership,generation,authority.fleet_id()?.as_deref()) + } +} diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs new file mode 100644 index 00000000000..8d4be66e2ee --- /dev/null +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -0,0 +1,322 @@ +//! Opt-in, disk-backed authority migration measurement, not an index-build proxy. +//! +//! Run alone in a fresh test process: Linux VmHWM is process-lifetime high water, +//! including fixture preparation. No claim history is retained in Rust memory. +//! Defaults describe a synthetic workload, not measured production proportions: +//! 1% authority-kind rows; five events per grant (grant, three policy revisions, +//! then revoke for 25% of groups or another policy); 10% malformed groups and +//! 20% unsigned remote groups, disjoint. +//! Unrelated JSON bodies are 70% quarter-size, 25% base-size, 5% four-times-size. +//! All ordinary Store indexes and durability settings stay enabled during setup. +//! Only authority projection work is disabled, so timed work is the actual +//! install + resumable backfill, not insert-time maintenance. +use super::*; +use std::time::{Duration, Instant}; + +const LOCAL: &str = "authority-bench-local"; +const REMOTE: &str = "authority-bench-unsigned"; +const EVENTS: u64 = 5; +const DENOMINATOR: u64 = 10_000; + +struct Config { + rows: u64, + authority_bps: u64, + malformed_bps: u64, + unauthenticated_bps: u64, + revoked_bps: u64, + unrelated_body_bytes: usize, + authority_body_bytes: usize, + transaction_rows: u64, + slice_ms: u64, + startup_ms: u64, + target_bytes: u64, +} + +fn setting(name: &str, default: u64) -> u64 { + match std::env::var(name) { + Ok(value) => value.parse().unwrap_or_else(|_| panic!("{name} must be an unsigned integer")), + Err(std::env::VarError::NotPresent) => default, + Err(error) => panic!("{name}: {error}"), + } +} + +impl Config { + fn from_env() -> Self { + let config = Self { + rows: setting("AUTHORITY_BENCH_ROWS", 1_000_000), + authority_bps: setting("AUTHORITY_BENCH_AUTHORITY_BPS", 100), + malformed_bps: setting("AUTHORITY_BENCH_MALFORMED_BPS", 1_000), + unauthenticated_bps: setting("AUTHORITY_BENCH_UNAUTHENTICATED_BPS", 2_000), + revoked_bps: setting("AUTHORITY_BENCH_REVOKED_BPS", 2_500), + unrelated_body_bytes: usize::try_from(setting("AUTHORITY_BENCH_BODY_BYTES", 4_096)).unwrap(), + authority_body_bytes: usize::try_from(setting("AUTHORITY_BENCH_AUTHORITY_BODY_BYTES", 1_024)).unwrap(), + transaction_rows: setting("AUTHORITY_BENCH_TRANSACTION_ROWS", 1_000), + slice_ms: setting("AUTHORITY_BENCH_SLICE_MS", 100), + startup_ms: setting("AUTHORITY_BENCH_STARTUP_MS", 2_000), + target_bytes: setting("AUTHORITY_BENCH_TARGET_BYTES", 50_000_000_000), + }; + assert!(config.rows >= DENOMINATOR && config.rows.is_multiple_of(DENOMINATOR)); + assert!(config.authority_bps > 0 && config.authority_bps < DENOMINATOR); + assert!(config.authority_bps.is_multiple_of(EVENTS)); + assert!(config.malformed_bps + config.unauthenticated_bps < DENOMINATOR); + assert!(config.revoked_bps <= DENOMINATOR); + assert!(config.unrelated_body_bytes >= 256 && config.authority_body_bytes >= 1_024); + assert!(config.transaction_rows > 0 && config.slice_ms > 0 && config.target_bytes > 0); + config + } +} + +fn padded_body(mut body: Value, bytes: usize) -> String { + body["fields"]["measurement_padding"] = json!(""); + let empty = serde_json::to_string(&body).unwrap(); + assert!(empty.len() <= bytes, "configured body size smaller than fixture fields"); + body["fields"]["measurement_padding"] = json!("x".repeat(bytes - empty.len())); + let serialized = serde_json::to_string(&body).unwrap(); + assert_eq!(serialized.len(), bytes); + serialized +} + +fn authority_body(group: u64, event: u64, malformed: bool, bytes: usize) -> String { + let grant_id = format!("assistant-grant/{group:024x}"); + let mut body = json!({"fields": { + "grant_id": grant_id, + "issuer": "person/perf-operator", + "principal": "assistant/chatgpt", + "profile": if group.is_multiple_of(4) { "service" } else { "assistant" }, + "session_actor": format!("assistant/chatgpt/session/{grant_id}"), + "credential_hash": format!("{group:064x}"), + "minimal_read_mode": "approval-once", + "disclosure_consent": true, + "expires_at_unix_ms": 4_102_444_800_000_u64 + event, + "scopes": ["read.assistant.summary", "read.assistant.attention", "write.assistant.messages"] + }}); + // Every event of a malformed group fails identity validation; valid remote + // groups are structurally sound but have no signed envelope/membership proof. + if malformed { + body["fields"]["issuer"] = json!(17); + } + padded_body(body, bytes) +} + +fn open_connection(path: &Path) -> Connection { + let connection = Connection::open(path).unwrap(); + projection_digest::register(&connection).unwrap(); + connection.execute_batch( + "PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; + PRAGMA foreign_keys=ON; PRAGMA busy_timeout=5000;", + ).unwrap(); + connection.pragma_update(None, "cache_size", -(crate::sqlite::WRITE_CACHE_KIB as i64)).unwrap(); + connection +} + +fn physical_bytes(path: &Path) -> (u64, u64) { + let db = fs::metadata(path).unwrap().len(); + let wal = fs::metadata(path.with_file_name("claims.sqlite3-wal")) + .map_or_else(|error| { + assert_eq!(error.kind(), std::io::ErrorKind::NotFound); + 0 + }, |metadata| metadata.len()); + (db, wal) +} + +fn memory_kib() -> (u64, u64) { + let status = fs::read_to_string("/proc/self/status") + .expect("authority backfill memory measurement requires Linux /proc/self/status"); + let field = |name: &str| -> u64 { + status.lines().find_map(|line| { + line.strip_prefix(name).map(|value| value.split_whitespace().next().unwrap().parse().unwrap()) + }).unwrap_or_else(|| panic!("missing {name} in /proc/self/status")) + }; + (field("VmRSS:"), field("VmHWM:")) +} + +fn cursors(connection: &Connection) -> Vec<(String, String)> { + let mut statement = connection.prepare( + "SELECT key,value FROM meta WHERE key LIKE 'assistant_grant_authority_cursor/%' ORDER BY key", + ).unwrap(); + statement.query_map([], |row| Ok((row.get(0)?, row.get(1)?))) + .unwrap().collect::>().unwrap() +} + +fn slice(connection: &mut Connection, budget: Duration) -> (bool, Duration) { + assert!(assistant_grant_authority::ready(connection).is_err()); + let started = Instant::now(); + let transaction = connection.transaction().unwrap(); + let done = assistant_grant_authority::backfill_slice(&transaction, budget).unwrap(); + assert_eq!(assistant_grant_authority::ready(&transaction).is_ok(), done); + transaction.commit().unwrap(); + assert_eq!(assistant_grant_authority::ready(connection).is_ok(), done); + (done, started.elapsed()) +} + +#[test] +#[ignore = "opt-in disk/RSS authority backfill measurement; run alone with --ignored --nocapture"] +fn assistant_grant_authority_measure_realistic_backfill() { + let config = Config::from_env(); + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("claims.sqlite3"); + let store = Store::open(&path, LOCAL, Arc::new(runtime::Plain)).unwrap(); + let mut expected_effective = 0_u64; + let mut expected_revoked = 0_u64; + let mut raw_revocations = 0_u64; + let mut expected_malformed_rows = 0_u64; + let mut expected_unauthenticated_rows = 0_u64; + let mut authority_body_bytes = 0_u64; + let mut unrelated_body_bytes = 0_u64; + { + let mut connection = store.connection.write(); + connection.execute_batch( + /* sqlite-large-value: allow-for-now lv-h6064c7271014 owner=smallclaims::store::assistant_grant_authority_bench TODO=bound-or-reference-values-and-reclamation */ + "DROP TRIGGER IF EXISTS assistant_grant_dirty_insert; + DELETE FROM assistant_grant_authority; + DELETE FROM assistant_grant_effective; + DELETE FROM assistant_grant_pending; + DELETE FROM assistant_grant_dirty; + DELETE FROM assistant_grant_membership_windows; + DELETE FROM meta WHERE key='assistant_grant_authority_version' + OR key LIKE 'assistant_grant_authority_cursor/%' + OR key='assistant_grant_authority_membership_generation';", + ).unwrap(); + // Fixed small pool of representative unrelated JSON sizes, not a history. + let unrelated_bodies = [ + padded_body(json!({"fields": {"text": "synthetic conversation summary"}}), config.unrelated_body_bytes / 4), + padded_body(json!({"fields": {"text": "synthetic conversation message"}}), config.unrelated_body_bytes), + padded_body(json!({"fields": {"text": "synthetic terminal output"}}), config.unrelated_body_bytes.checked_mul(4).unwrap()), + ]; + for start in (0..config.rows).step_by(usize::try_from(config.transaction_rows).unwrap()) { + let transaction = connection.transaction().unwrap(); + { + let mut batch = transaction.prepare_cached( + /* sqlite-large-value: allow-for-now lv-h2686d79044aa owner=smallclaims::store::assistant_grant_authority_bench TODO=chunk-or-reference-exact-wire-values */ + "INSERT INTO batches(id,origin,replica_sequence,previous_hash,hash,accepted_at_unix_ms) + VALUES(?1,?2,?3,NULL,?4,'1791849600000')", + ).unwrap(); + let mut claim = transaction.prepare_cached( + /* sqlite-large-value: allow-for-now lv-h1d162e19a0a1 owner=smallclaims::store::assistant_grant_authority_bench TODO=prepare-body-and-predecessor-values */ + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,?2,?3,?4,?5,?6,?7,'[]','1791849600000')", + ).unwrap(); + // Two writer batches per bounded transaction; no per-row envelope + // allocation and no growing collection of claim IDs or subjects. + let sequence = start / config.transaction_rows + 1; + for writer in [LOCAL, REMOTE] { + batch.execute(/* sqlite-large-value: allow-for-now lv-he7097c5f9f00 owner=smallclaims::store::assistant_grant_authority_bench TODO=trace-statement-and-value-representation */ params![format!("batch/{writer}/{sequence:064x}"), writer, sequence, format!("{sequence:064x}")]).unwrap(); + } + for row in start..config.rows.min(start.saturating_add(config.transaction_rows)) { + let offset = row % DENOMINATOR; + let id = format!("{:064x}", row + 1); + if offset < config.authority_bps { + let group = (row / DENOMINATOR) * (config.authority_bps / EVENTS) + offset / EVENTS; + let event = offset % EVENTS; + // A coprime stride spreads categories across short samples. + let category = group.wrapping_mul(7_919) % DENOMINATOR; + let malformed = category < config.malformed_bps; + let unauthenticated = !malformed && category < config.malformed_bps + config.unauthenticated_bps; + let writer = if unauthenticated { REMOTE } else { LOCAL }; + let revoked_group = group.wrapping_mul(3_571) % DENOMINATOR < config.revoked_bps; + let kind = match event { + 0 => assistant_grant_authority::GRANTED, + 4 if revoked_group => assistant_grant_authority::REVOKED, + _ => assistant_grant_authority::POLICY, + }; + raw_revocations += u64::from(kind == assistant_grant_authority::REVOKED); + let body = authority_body(group, event, malformed, config.authority_body_bytes); + authority_body_bytes += body.len() as u64; + expected_malformed_rows += u64::from(malformed); + expected_unauthenticated_rows += u64::from(unauthenticated); + if event == 0 && !malformed && !unauthenticated { + expected_effective += 1; + expected_revoked += u64::from(revoked_group); + } + claim.execute(/* sqlite-large-value: allow-for-now lv-hb16dbad8dff5 owner=smallclaims::store::assistant_grant_authority_bench TODO=trace-statement-and-value-representation */ params![id, format!("batch/{writer}/{sequence:064x}"), + format!("custom/client/assistant-v1-{group:024x}"), kind, writer, + "person/perf-operator", body]).unwrap(); + } else { + let bucket = match row % 100 { 0..=69 => 0, 70..=94 => 1, _ => 2 }; + let body = &unrelated_bodies[bucket]; + unrelated_body_bytes += body.len() as u64; + claim.execute(/* sqlite-large-value: allow-for-now lv-h5820156720c0 owner=smallclaims::store::assistant_grant_authority_bench TODO=trace-statement-and-value-representation */ params![id, format!("batch/{LOCAL}/{sequence:064x}"), + format!("conversation/synthetic/{:08x}", row % 100_000), + format!("synthetic.message.kind{}", row % 16), LOCAL, + "person/perf-operator", body]).unwrap(); + } + } + } + transaction.commit().unwrap(); + } + assert_eq!(connection.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_, u64>(0)).unwrap(), 0); + let checkpoint: (i64, i64, i64) = connection.query_row("PRAGMA wal_checkpoint(TRUNCATE)", [], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?))).unwrap(); + assert_eq!(checkpoint, (0, 0, 0)); + } + drop(store); + let mut connection = open_connection(&path); + let raw_rows: u64 = connection.query_row("SELECT COUNT(*) FROM claims", [], |row| row.get(0)).unwrap(); + let raw_authority_rows: u64 = connection.query_row( + "SELECT COUNT(*) FROM claims WHERE kind IN (?1,?2,?3)", + params![assistant_grant_authority::GRANTED, assistant_grant_authority::POLICY, assistant_grant_authority::REVOKED], |row| row.get(0), + ).unwrap(); + assert_eq!(raw_rows, config.rows); + assert_eq!(raw_authority_rows, config.rows / DENOMINATOR * config.authority_bps); + let (fixture_db_bytes, fixture_wal_bytes) = physical_bytes(&path); + let (baseline_rss_kib, baseline_peak_kib) = memory_kib(); + + let started = Instant::now(); + let install_started = Instant::now(); + assistant_grant_authority::install(&connection, LOCAL).unwrap(); + let install_elapsed = install_started.elapsed(); + assert!(assistant_grant_authority::ready(&connection).is_err()); + // Force a resume probe even when the configured startup budget would finish + // the sample. Zero budget still processes and commits one real row. + let (done, resume_probe_elapsed) = slice(&mut connection, Duration::ZERO); + assert!(!done, "first slice must leave migration unready"); + let saved_cursors = cursors(&connection); + assert!(!saved_cursors.is_empty()); + drop(connection); + connection = open_connection(&path); + assert_eq!(cursors(&connection), saved_cursors, "cursor must survive connection restart"); + assert!(assistant_grant_authority::ready(&connection).is_err()); + let (mut done, startup_slice_elapsed) = slice(&mut connection, Duration::from_millis(config.startup_ms)); + let mut slices = 2_u64; + let mut max_slice = startup_slice_elapsed.max(resume_probe_elapsed); + let mut slice_elapsed = startup_slice_elapsed + resume_probe_elapsed; + while !done { + let (finished, elapsed) = slice(&mut connection, Duration::from_millis(config.slice_ms)); + done = finished; + slices += 1; + max_slice = max_slice.max(elapsed); + slice_elapsed += elapsed; + } + let backfill_elapsed = started.elapsed(); + let (final_db_bytes, final_wal_bytes) = physical_bytes(&path); + let (final_rss_kib, peak_rss_kib) = memory_kib(); + let effective: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_effective", [], |row| row.get(0)).unwrap(); + let revoked: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_effective WHERE revoked=1", [], |row| row.get(0)).unwrap(); + let authority: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_authority", [], |row| row.get(0)).unwrap(); + let unauthenticated: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_pending WHERE authenticated=0", [], |row| row.get(0)).unwrap(); + assert_eq!(effective, expected_effective); + assert!(effective > 0, "sample must include authenticated valid groups"); + assert_eq!(revoked, expected_revoked); + assert_eq!(authority, expected_effective * EVENTS); + assert_eq!(unauthenticated, expected_unauthenticated_rows); + assert_eq!(connection.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_, u64>(0)).unwrap(), 0); + assert_eq!(connection.query_row("SELECT value FROM meta WHERE key='assistant_grant_authority_version'", [], |row| row.get::<_, String>(0)).unwrap(), "1"); + // A second maintenance pass must not duplicate resumed rows or alter readiness. + let transaction = connection.transaction().unwrap(); + assert!(assistant_grant_authority::backfill_slice(&transaction, Duration::from_millis(config.slice_ms)).unwrap()); + transaction.commit().unwrap(); + assert_eq!(connection.query_row("SELECT COUNT(*) FROM assistant_grant_authority", [], |row| row.get::<_, u64>(0)).unwrap(), authority); + + let scale = config.target_bytes as f64 / fixture_db_bytes as f64; + println!("authority_backfill_fixture raw_claims={raw_rows} grant_kind_claims={raw_authority_rows} granted={} policies={} revocations={raw_revocations} malformed_rows={expected_malformed_rows} unauthenticated_rows={expected_unauthenticated_rows} effective_grants={effective} authority_rows={authority} authority_bps={} malformed_group_bps={} unauthenticated_group_bps={} revoked_group_bps={} unrelated_json_bytes={unrelated_body_bytes} authority_json_bytes={authority_body_bytes} fixture_db_bytes={fixture_db_bytes} fixture_wal_bytes={fixture_wal_bytes} final_db_bytes={final_db_bytes} final_wal_bytes={final_wal_bytes} transaction_rows={}", + raw_authority_rows / EVENTS, raw_authority_rows - raw_authority_rows / EVENTS - raw_revocations, + config.authority_bps, config.malformed_bps, config.unauthenticated_bps, config.revoked_bps, config.transaction_rows); + println!("authority_backfill_timing install_ms={:.3} startup_slice_ms={:.3} startup_total_ms={:.3} startup_budget_ms={} continuation_budget_ms={} slices={slices} max_slice_ms={:.3} slice_sum_ms={:.3} elapsed_with_restart_ms={:.3} resume_probe_ms={:.3} restart_count=1 readiness_checked_each_slice=true", + install_elapsed.as_secs_f64() * 1_000.0, startup_slice_elapsed.as_secs_f64() * 1_000.0, + (install_elapsed + startup_slice_elapsed).as_secs_f64() * 1_000.0, config.startup_ms, config.slice_ms, + max_slice.as_secs_f64() * 1_000.0, slice_elapsed.as_secs_f64() * 1_000.0, backfill_elapsed.as_secs_f64() * 1_000.0, + resume_probe_elapsed.as_secs_f64() * 1_000.0); + println!("authority_backfill_memory baseline_rss_kib={baseline_rss_kib} baseline_process_peak_kib={baseline_peak_kib} final_rss_kib={final_rss_kib} peak_rss_kib={peak_rss_kib} high_water_increase_kib={} sqlite_cache_kib={}", peak_rss_kib.saturating_sub(baseline_peak_kib), crate::sqlite::WRITE_CACHE_KIB); + println!("authority_backfill_extrapolation target_bytes={} scale={scale:.6} estimated_raw_claims={:.0} estimated_grant_kind_claims={:.0} linear_elapsed_seconds={:.3} fixed_working_set_peak_kib={peak_rss_kib} pessimistic_linear_peak_kib={:.0} methodology=target_divided_by_checkpointed_fixture_db_bytes_times_observed_work warning=synthetic_mix_not_production_distribution;time_assumes_constant_throughput_and_same_indexes_cache_storage;memory_fixed_cache_hypothesis_not_proven_at_50GB;linear_peak_is_sensitivity_not_prediction;VmHWM_includes_fixture_and_test_process;WAL_is_physical_recycled_bytes;startup_excludes_Store_open_and_includes_one_prior_resume_probe_row;no_cold_cache_claim", + config.target_bytes, raw_rows as f64 * scale, raw_authority_rows as f64 * scale, + backfill_elapsed.as_secs_f64() * scale, peak_rss_kib as f64 * scale); +} diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs new file mode 100644 index 00000000000..2db037b426a --- /dev/null +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -0,0 +1,448 @@ +//! Maintenance controls use real sealed envelopes; the reference reads raw history only. +use super::assistant_grant_authority::{self as authority, GRANTED, POLICY, REVOKED}; +use super::runtime::Plain; +use super::*; +use crate::claim::ReplicaEnvelopeSignature; +use crate::fleet::MemberKey; +use crate::replication::ReplicationExchange; +use rusqlite::{StatementStatus, types::Value as SqlValue}; +use std::time::Duration; + +const FLEET: &str = "assistant-authority-maintenance"; +const SUBJECT: &str = "custom/client/assistant-v1-0123456789abcdef01234567"; +const OWNER: &str = "human/owner"; + +fn node(name: &str, anchor: Option<&str>) -> Store { + let store = Store::open_memory(name, Arc::new(Plain)).unwrap(); + store.bind_fleet(FLEET).unwrap(); + if let Some(anchor) = anchor { + store.pin_fleet_anchor(anchor).unwrap(); + } + store +} + +fn source() -> (Store, Arc) { + let store = node("anchor", None); + let key = Arc::new(MemberKey::generate().unwrap().0); + store.pin_fleet_anchor(key.public()).unwrap(); + store.set_member_key(Some(key.clone())).unwrap(); + store.admit_fleet_anchor(FLEET, key.public(), "listening").unwrap(); + store.seal_local_batches().unwrap(); + (store, key) +} + +fn fields() -> Value { + json!({ + "grant_id": "assistant-grant/0123456789abcdef01234567", + "issuer": OWNER, + "principal": "assistant/chatgpt", + "profile": "assistant", + "session_actor": "assistant/chatgpt/session/assistant-grant/0123456789abcdef01234567", + "credential_hash": "a".repeat(64), + "minimal_read_mode": "approval-once", + "disclosure_consent": true, + "expires_at_unix_ms": 10000, + "scopes": ["read.assistant.summary"] + }) +} + +fn append(store: &Store, subject: &str, kind: &str, fields: Value) -> ClaimRecord { + store.append_claim(&ClaimInput { + subject: subject.into(), kind: kind.into(), actor: Some(OWNER.into()), + fields: serde_json::from_value(fields).unwrap(), evidence: Vec::new(), + expected_subject: None, idempotency_key: None, + }).unwrap() +} + +fn export(source: &Store, target: &Store) -> ReplicationExchange { + source.seal_local_batches().unwrap(); + source.export_replication_exchange(FLEET, &target.replication_inventory().unwrap()).unwrap() +} + +fn receive(target: &Store, exchange: &ReplicationExchange) { + target.receive_replication_exchange(&exchange.peer, FLEET, exchange).unwrap(); + target.validate_replication_backlog().unwrap(); + target.project_replication_backlog().unwrap(); +} + +fn unsigned(exchange: &ReplicationExchange) -> ReplicationExchange { + let mut result = exchange.clone(); + result.signatures.clear(); + for envelope in &mut result.envelopes { + envelope.member_key = None; + envelope.signature = None; + } + result +} + +fn signatures(exchange: &ReplicationExchange) -> ReplicationExchange { + let mut result = exchange.clone(); + result.signatures.extend(result.envelopes.iter().filter_map(|envelope| { + Some(ReplicaEnvelopeSignature { + writer: envelope.writer.clone(), sequence: envelope.sequence, + hash: envelope.hash.clone(), member_key: envelope.member_key.clone()?, + signature: envelope.signature.clone()?, + }) + })); + result.envelopes.clear(); + result +} + +fn snapshot(connection: &Connection) -> Vec> { + let mut statement = connection.prepare( + "SELECT claim_id,grant_subject,principal,owner,profile,expires_at,revoked,grant_record + FROM assistant_grant_effective ORDER BY claim_id" + ).unwrap(); + statement.query_map([], |row| (0..8).map(|index| row.get(index)).collect()) + .unwrap().collect::>().unwrap() +} + +fn raw_claims(store: &Store) -> Vec { + store.readers.get().prepare(/* sqlite-large-value: allow-for-now lv-hef28dd74e68f owner=smallclaims::store::assistant_grant_authority_tests TODO=trace-statement-and-value-representation */ &format!("SELECT {CLAIM_COLUMNS} FROM claims ORDER BY store_index")) + .unwrap().query_map([], claim_from_row).unwrap() + .collect::>().unwrap() +} + +// This intentionally knows the fixture's wire contract, not the projection's validator, +// pending table, or authority rows. Authentication goes through the public raw-provenance API. +fn reference(store: &Store) -> Vec<(String, String, bool)> { + let claims = raw_claims(store); + let trusted = |claim: &ClaimRecord| { + claim.origin == store.origin + || store.claim_has_authenticated_member_writer(&claim.id).unwrap() + }; + let identity = |claim: &ClaimRecord| { + let f = &claim.body["fields"]; + claim.subject == SUBJECT && claim.actor.as_deref() == Some(OWNER) + && f["issuer"] == OWNER && f["grant_id"] == fields()["grant_id"] + && f["principal"] == "assistant/chatgpt" && f["profile"] == "assistant" + }; + let policy = |claim: &ClaimRecord| { + let f = &claim.body["fields"]; + identity(claim) && f["session_actor"] == fields()["session_actor"] + && f["minimal_read_mode"] == "approval-once" && f["disclosure_consent"] == true + && f["expires_at_unix_ms"].as_u64().is_some() + && f["scopes"] == json!(["read.assistant.summary"]) + && f.get("credential").is_none() && f.get("code").is_none() + && f["credential_hash"].as_str().is_some_and(|s| s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit())) + }; + let mut expected = Vec::new(); + for grant in claims.iter().filter(|claim| claim.kind == GRANTED && trusted(claim) && policy(claim)) { + let selected = claims.iter().rev().find(|claim| { + claim.kind == POLICY && claim.origin == grant.origin && trusted(claim) && policy(claim) + }).unwrap_or(grant); + let revoked = claims.iter().any(|claim| { + claim.kind == REVOKED && claim.origin == grant.origin && trusted(claim) && identity(claim) + }); + expected.push((grant.id.clone(), format!("{:020}", selected.body["fields"]["expires_at_unix_ms"].as_u64().unwrap()), revoked)); + } + expected.sort(); + expected +} + +fn assert_reference_and_rebuild(store: &Store) { + let expected = reference(store); + let mut connection = store.connection.write(); + let actual: Vec<(String, String, bool)> = connection.prepare( + "SELECT claim_id,expires_at,revoked FROM assistant_grant_effective ORDER BY claim_id" + ).unwrap().query_map([], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?))) + .unwrap().collect::>().unwrap(); + assert_eq!(actual, expected, "incremental rows disagree with independent raw history"); + let before = snapshot(&connection); + let transaction = connection.transaction().unwrap(); + let subjects: Vec = transaction.prepare( + "SELECT DISTINCT grant_subject FROM assistant_grant_authority UNION SELECT grant_subject FROM assistant_grant_effective" + ).unwrap().query_map([], |row| row.get(0)).unwrap() + .collect::>().unwrap(); + for subject in subjects { + authority::rebuild_subject(&transaction, &subject).unwrap(); + } + assert_eq!(snapshot(&transaction), before, "full subject rebuild changed incremental state"); + transaction.commit().unwrap(); +} + +fn decisions(store: &Store, now: u64) -> Vec { + authority::candidates(&store.readers.get(), "assistant/chatgpt", OWNER, Some(now), None, None) + .unwrap().into_iter().map(|claim| claim.id).collect() +} + +#[test] +fn late_envelope_signature_promotes_previously_admitted_grant() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + receive(&target, &export(&source, &target)); + let grant = append(&source, SUBJECT, GRANTED, fields()); + let exchange = export(&source, &target); + receive(&target, &unsigned(&exchange)); + assert!(raw_claims(&target).iter().any(|claim| claim.id == grant.id)); + assert!(decisions(&target, 0).is_empty()); + assert_reference_and_rebuild(&target); + receive(&target, &signatures(&exchange)); + assert_eq!(decisions(&target, 0), vec![grant.id]); + assert_reference_and_rebuild(&target); + receive(&target, &signatures(&exchange)); + assert_reference_and_rebuild(&target); +} + +#[test] +fn membership_sealed_after_grant_admission_promotes_pending_authority() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let grant = append(&source, SUBJECT, GRANTED, fields()); + let exchange = export(&source, &target); + let mut delayed_anchor_signature = exchange.clone(); + let anchor_sequence = exchange.envelopes.iter().map(|e| e.sequence).min().unwrap(); + for envelope in &mut delayed_anchor_signature.envelopes { + if envelope.sequence == anchor_sequence { + envelope.member_key = None; + envelope.signature = None; + } + } + delayed_anchor_signature.signatures.retain(|s| s.sequence != anchor_sequence); + receive(&target, &delayed_anchor_signature); + assert!(raw_claims(&target).iter().any(|claim| claim.id == grant.id)); + assert!(decisions(&target, 0).is_empty()); + assert_reference_and_rebuild(&target); + let mut seal = signatures(&exchange); + seal.signatures.retain(|s| s.sequence == anchor_sequence); + receive(&target, &seal); + assert!(target.claim_has_authenticated_member_writer(&grant.id).unwrap()); + assert_eq!(decisions(&target, 0), vec![grant.id]); + assert_reference_and_rebuild(&target); +} + +#[test] +fn sealing_local_membership_promotes_an_already_received_peer_grant() { + let target = node("anchor", None); + let anchor_key = Arc::new(MemberKey::generate().unwrap().0); + target.pin_fleet_anchor(anchor_key.public()).unwrap(); + target.set_member_key(Some(anchor_key.clone())).unwrap(); + target.admit_fleet_anchor(FLEET, anchor_key.public(), "listening").unwrap(); + target.seal_local_batches().unwrap(); + + let peer = node("peer", Some(anchor_key.public())); + let peer_key = Arc::new(MemberKey::generate().unwrap().0); + peer.set_member_key(Some(peer_key.clone())).unwrap(); + let grant = append(&peer, SUBJECT, GRANTED, fields()); + receive(&target, &export(&peer, &target)); + assert!(raw_claims(&target).iter().any(|claim| claim.id == grant.id)); + assert!(decisions(&target, 0).is_empty()); + assert_reference_and_rebuild(&target); + + append(&target, "host/peer", "fleet.member-admitted", json!({ + "member_key": peer_key.public(), "via": "member", "sponsor": "anchor", + "writer_floor": 0, "mode": "listening" + })); + // The membership claim exists but does not yet have a sealed signer. + assert!(!target.claim_has_authenticated_member_writer(&grant.id).unwrap()); + assert!(decisions(&target, 0).is_empty()); + target.seal_local_batches().unwrap(); + assert!(target.claim_has_authenticated_member_writer(&grant.id).unwrap()); + assert_eq!(decisions(&target, 0), vec![grant.id]); + assert_reference_and_rebuild(&target); +} + +#[test] +fn revoke_before_grant_never_temporarily_authorizes() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + receive(&target, &export(&source, &target)); + append(&source, SUBJECT, REVOKED, fields()); + receive(&target, &export(&source, &target)); + assert!(decisions(&target, 0).is_empty()); + assert_reference_and_rebuild(&target); + let grant = append(&source, SUBJECT, GRANTED, fields()); + receive(&target, &export(&source, &target)); + assert!(authority::contains(&target.readers.get(), &grant.id).unwrap()); + assert!(decisions(&target, 0).is_empty()); + assert_reference_and_rebuild(&target); +} + +#[test] +fn deterministic_event_permutations_match_raw_history_and_subject_rebuilds() { + // Each seed shuffles raw grant/policy/revoke receipt, their signatures, and the + // anchor signature that seals membership. Signatures may arrive before records. + for seed in 1_u64..=16 { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let grant = append(&source, SUBJECT, GRANTED, fields()); + source.seal_local_batches().unwrap(); + let mut changed = fields(); + changed["expires_at_unix_ms"] = json!(20000); + append(&source, SUBJECT, POLICY, changed); + source.seal_local_batches().unwrap(); + append(&source, SUBJECT, REVOKED, fields()); + let exchange = export(&source, &target); + assert_eq!(exchange.envelopes.len(), 4); + let mut events = Vec::new(); + for envelope in &exchange.envelopes { + let mut single = exchange.clone(); + single.envelopes = vec![envelope.clone()]; + single.signatures.clear(); + events.push(unsigned(&single)); + events.push(signatures(&single)); + } + let mut state = seed; + for index in (1..events.len()).rev() { + state ^= state << 13; + state ^= state >> 7; + state ^= state << 17; + let selected = (state % (index as u64 + 1)) as usize; + events.swap(index, selected); + } + for event in events { + receive(&target, &event); + assert_reference_and_rebuild(&target); + } + // Drain predecessors that an out-of-order envelope initially held. + target.validate_replication_backlog().unwrap(); + target.project_replication_backlog().unwrap(); + assert_reference_and_rebuild(&target); + assert!(authority::contains(&target.readers.get(), &grant.id).unwrap()); + assert_eq!(reference(&target), vec![(grant.id, format!("{:020}", 20000), true)]); + assert!(decisions(&target, 0).is_empty()); + } +} + +fn reset_projection(connection: &Connection) { + connection.execute_batch( + /* sqlite-large-value: allow-for-now lv-h9fa3ab767307 owner=smallclaims::store::assistant_grant_authority_tests TODO=bound-or-reference-values-and-reclamation */ + "DELETE FROM assistant_grant_effective; + DELETE FROM assistant_grant_authority; + DELETE FROM assistant_grant_pending; + DELETE FROM assistant_grant_membership_windows; + DELETE FROM assistant_grant_dirty; + DELETE FROM meta WHERE key='assistant_grant_authority_version' + OR key='assistant_grant_authority_membership_generation' + OR key LIKE 'assistant_grant_authority_cursor/%';" + ).unwrap(); +} + +#[test] +fn committed_backfill_slice_resumes_after_reopen_and_is_idempotent() { + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("authority.sqlite3"); + let expected; + { + let store = Store::open(&path, "anchor", Arc::new(Plain)).unwrap(); + for _ in 0..70 { + append(&store, SUBJECT, GRANTED, fields()); + } + let mut changed = fields(); + changed["expires_at_unix_ms"] = json!(20000); + append(&store, SUBJECT, POLICY, changed); + append(&store, SUBJECT, REVOKED, fields()); + let mut connection = store.connection.write(); + expected = snapshot(&connection); + assert_eq!(expected.len(), 70); + reset_projection(&connection); + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction, Duration::ZERO).unwrap()); + let cursor: String = transaction.query_row( + "SELECT value FROM meta WHERE key=?1", [format!("assistant_grant_authority_cursor/{GRANTED}")], |row| row.get(0) + ).unwrap(); + assert!(cursor.parse::().unwrap() > 0); + assert!(authority::ready(&transaction).is_err()); + transaction.commit().unwrap(); + } + // Reopen the durable connection before Store's startup continuation can finish it. + { + let mut connection = Connection::open(&path).unwrap(); + assert!(authority::ready(&connection).is_err()); + let remaining: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_authority", [], |row| row.get(0)).unwrap(); + assert_eq!(remaining, 1); + let mut slices = 0; + loop { + let transaction = connection.transaction().unwrap(); + let complete = authority::backfill_slice(&transaction, Duration::ZERO).unwrap(); + transaction.commit().unwrap(); + slices += 1; + if complete { break; } + assert!(slices < 200, "backfill failed to make durable forward progress"); + } + assert!(slices > 1); + assert_eq!(snapshot(&connection), expected); + let transaction = connection.transaction().unwrap(); + assert!(authority::backfill_slice(&transaction, Duration::ZERO).unwrap()); + assert_eq!(snapshot(&transaction), expected); + transaction.commit().unwrap(); + } + let reopened = Store::open(&path, "anchor", Arc::new(Plain)).unwrap(); + assert_eq!(snapshot(&reopened.readers.get()), expected); + assert_reference_and_rebuild(&reopened); + assert!(decisions(&reopened, 0).is_empty()); +} + +fn transition_cost(store: &Store, grant: &ClaimRecord) -> (String, i32, i32, usize) { + let connection = store.readers.get(); + let mut statement = connection.prepare(/* sqlite-large-value: allow-for-now lv-h611b5b2ef9a9 owner=smallclaims::store::assistant_grant_authority_tests TODO=trace-statement-and-value-representation */ authority::TRANSITION_QUERY).unwrap(); + let mut rows = statement.query(params![grant.subject, POLICY, grant.origin, grant.actor, grant.id]).unwrap(); + let mut records = Vec::new(); + while let Some(row) = rows.next().unwrap() { + records.push(row.get::<_, String>(0).unwrap()); + } + drop(rows); + let record: ClaimRecord = serde_json::from_str(&records[0]).unwrap(); + (record.id, statement.get_status(StatementStatus::VmStep), statement.get_status(StatementStatus::FullscanStep), records.len()) +} + +fn candidate_cost(store: &Store) -> (Vec, i32, i32) { + let connection = store.readers.get(); + let mut statement = connection.prepare(/* sqlite-large-value: allow-for-now lv-he990dace4c7d owner=smallclaims::store::assistant_grant_authority_tests TODO=trace-statement-and-value-representation */ authority::CANDIDATES_QUERY).unwrap(); + let mut rows = statement.query(params![ + "assistant/chatgpt", OWNER, format!("{:020}", 15000), + Option::::None, Option::::None + ]).unwrap(); + let mut ids = Vec::new(); + while let Some(row) = rows.next().unwrap() { + let record: String = row.get(0).unwrap(); + ids.push(serde_json::from_str::(&record).unwrap().id); + } + drop(rows); + (ids, statement.get_status(StatementStatus::VmStep), statement.get_status(StatementStatus::FullscanStep)) +} + +#[test] +fn malformed_and_unsigned_same_origin_flood_preserves_previous_authority_and_constant_reads() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + receive(&target, &export(&source, &target)); + let grant = append(&source, SUBJECT, GRANTED, fields()); + let mut valid = fields(); + valid["expires_at_unix_ms"] = json!(20000); + let policy = append(&source, SUBJECT, POLICY, valid); + receive(&target, &export(&source, &target)); + let before = transition_cost(&target, &grant); + assert_eq!(before.0, policy.id); + assert_eq!(before.2, 0); + assert_eq!(before.3, 1); + let candidate_before = candidate_cost(&target); + assert_eq!(candidate_before.0, vec![grant.id.clone()]); + assert_eq!(candidate_before.2, 0); + for count in [1, 128] { + for index in 0..count { + let mut malformed = fields(); + if index % 2 == 0 { malformed["issuer"] = json!("human/not-owner"); } + else { malformed["scopes"] = json!(["read.everything"]); } + append(&source, SUBJECT, POLICY, malformed); + } + // Malformed rows are genuinely signed by the correct same-origin member. + let mut malformed_rows = export(&source, &target); + // Do not accidentally deliver requested signatures for the earlier unsigned flood. + malformed_rows.signatures.clear(); + receive(&target, &malformed_rows); + for _ in 0..count { + let mut unauthenticated = fields(); + unauthenticated["expires_at_unix_ms"] = json!(30000); + append(&source, SUBJECT, POLICY, unauthenticated); + append(&source, SUBJECT, REVOKED, fields()); + } + let unsigned_rows = export(&source, &target); + receive(&target, &unsigned(&unsigned_rows)); + let after = transition_cost(&target, &grant); + assert_eq!(after, before, "same-origin flood changed selected authority or request VM/read cost at {count}"); + assert_eq!(candidate_cost(&target), candidate_before, "candidate request cost grew at {count}"); + assert_eq!(decisions(&target, 15000), vec![grant.id.clone()]); + assert_reference_and_rebuild(&target); + } +} diff --git a/crates/smallclaims/src/store/prepared_envelope.rs b/crates/smallclaims/src/store/prepared_envelope.rs index d4e58679cf1..014f5ecbd24 100644 --- a/crates/smallclaims/src/store/prepared_envelope.rs +++ b/crates/smallclaims/src/store/prepared_envelope.rs @@ -561,5 +561,8 @@ pub fn admit_prepared_envelope_tx( batch.id, ]) .map_err(internal)?; + super::assistant_grant_authority::refresh_envelope( + transaction, &envelope.writer, envelope.sequence, &envelope.hash, + ).map_err(internal)?; Ok(()) } diff --git a/crates/smallclaims/src/store/prepared_seal.rs b/crates/smallclaims/src/store/prepared_seal.rs index 9b1d25ad0a2..788500f5cd8 100644 --- a/crates/smallclaims/src/store/prepared_seal.rs +++ b/crates/smallclaims/src/store/prepared_seal.rs @@ -349,6 +349,9 @@ pub(crate) fn write_sealed_batch_tx( ], )?; } + super::assistant_grant_authority::refresh_envelope( + transaction, &batch.writer, batch.sequence, &sealed.envelope_hash, + )?; Ok(()) } @@ -537,6 +540,7 @@ impl Store { transaction: &Transaction<'_>, prepared: &PreparedSeal, ) -> Result { + self.sync_assistant_grant_membership(transaction)?; if prepared.origin != self.origin { return Ok(false); } @@ -618,8 +622,12 @@ impl Store { now ], )?; + super::assistant_grant_authority::refresh_envelope( + transaction, &self.origin, envelope.0, &envelope.1, + )?; } } + super::assistant_grant_authority::refresh_membership(transaction)?; Ok(true) } } diff --git a/docs/st3/client-v0/schemas/client-v0.schema.json b/docs/st3/client-v0/schemas/client-v0.schema.json index aa910c21c77..fd57cabfb92 100644 --- a/docs/st3/client-v0/schemas/client-v0.schema.json +++ b/docs/st3/client-v0/schemas/client-v0.schema.json @@ -593,6 +593,7 @@ "validation-failed", "idempotency-conflict", "grant-profile-conflict", + "assistant-grant-authority-not-ready", "legacy-action-receipt-untrusted", "issuer-required", "pairing-origin-required", diff --git a/docs/st3/client-v0/schemas/operations.json b/docs/st3/client-v0/schemas/operations.json index ec65a3c4c2a..9411a43148f 100644 --- a/docs/st3/client-v0/schemas/operations.json +++ b/docs/st3/client-v0/schemas/operations.json @@ -17,6 +17,16 @@ "public_listener": false, "remote_mode": "online-thin-client" }, + "assistant_grant_authority_contract": { + "projection_version": 1, + "backfill": "resumable-background", + "authorization_during_backfill": "fail-closed", + "not_ready_error": { + "code": "assistant-grant-authority-not-ready", + "http_status": 503, + "retryable": true + } + }, "agents_publication_contract": { "description": "Complete current agents publications with an explicit version-1 collections-stream opt-in. No HTTP endpoint or capability availability is added.", "metadata": "AgentsPublicationMetadata", diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index 55c9ff70d8c..40076692a9e 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -391,143 +391,140 @@ {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "table_pattern": "local_work_summary_clock", "columns": [{"name": "singleton", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY CHECK(singleton=1)", "value_size_proven": false}, {"name": "through_ms", "declared_type": "BLOB", "declaration": "BLOB NOT NULL CHECK(length(through_ms)=16)", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "table_pattern": "local_work_summaries", "columns": [{"name": "key", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "progress", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "progress_at", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "completion", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "next_at", "declared_type": "BLOB", "declaration": "BLOB CHECK(next_at IS NULL OR length(next_at)=16)", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h932a52c91553", "path": "crates/fractal-store/src/store/work_summaries_ivm.rs", "index_pattern": "local_work_summaries_deadline", "table_pattern": "local_work_summaries", "key_expression_and_predicate": "(next_at,key) WHERE next_at IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'))", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_principal_expiry_index", "table_pattern": "claims", "key_expression_and_predicate": "(kind, COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'), json_extract(body,'$.fields.expires_at_unix_ms'))", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_transition_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, origin, actor, store_index)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, - {"site": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "desired", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_generation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_requests", "columns": [{"name": "operation_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "request_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "message_index", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "closed", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_native_delivery_receipts_v2", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES claims(id) ON DELETE CASCADE", "value_size_proven": false}, {"name": "claim_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "native_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "capabilities", "columns": [{"name": "secret_hash", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "used", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_revisions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}, {"name": "created_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_definitions", "columns": [{"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "state", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES claims(id)", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_runs", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "initial_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "current_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "root_run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "parent_step_run", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "inputs", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "phase", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_deadlines", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "timeout_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "deadline_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "mission_run_after", "columns": [{"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "after_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "run_generations", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "predecessor_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "step_runs", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "step_path", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "definition_hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "assignee", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "available_to", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}, {"name": "agentless", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 1", "value_size_proven": false}, {"name": "title", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "goals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "worker_reported", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "blocked_reason", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "activated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "readiness_epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "constraints", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '[]'", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_harness_question_generations", "columns": [{"name": "question", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "generation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_owners", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_argv_bindings", "columns": [{"name": "token", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "member", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_mailbox_leases", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "component", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "provider", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "session", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "pid", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "process_token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "token", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "epoch", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_work_lease_renewals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "attempt", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "lease_owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_incarnation", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "lease_expires_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_observations", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}, {"name": "after_store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "body", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "dedupe_key", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "request_digest", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "client_diagnostic_receipts", "columns": [{"name": "device", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "event_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "accepted_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_subscription_mission_deferrals", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "not_before_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "attempts", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_spend", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "incarnation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "model", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_run", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner_step", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "host", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "input_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "output_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cache_write_1h_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cached_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "total_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "reported_cost_microusd", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "unpriced_tokens", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL DEFAULT 0", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_provenance", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pricing", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_limit_stops", "columns": [{"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "episode", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "seat", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "stopped_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_seat_accounts", "columns": [{"name": "seat", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "account", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "chosen_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_usage_responses", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "source_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "observed_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "local_latest_slots", "columns": [{"name": "subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "slot", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "published_at_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "published_fields", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "pending_local_id", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "claims_stored", "columns": [{"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "since_unix_ms", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "claims", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "bytes", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "revision_proposals", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "run_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES mission_runs(id)", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES run_generations(id)", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reason", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "cutover", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "compatible_steps", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "reviewers", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "approvals", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "preview_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "successor_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_sessions", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "mission_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "request_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "workspace", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "requester", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "planner_spec_json", "declared_type": "TEXT", "declaration": "TEXT NOT NULL DEFAULT '{\"provider\":\"codex\"}'", "value_size_proven": false}, {"name": "status", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "target_run_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "source_generation_id", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "published_revision", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "updated_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_candidates", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "markdown_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kdl_ref", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_revision", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "submitted_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "table_pattern": "planning_previews", "columns": [{"name": "session_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL REFERENCES planning_sessions(id)", "value_size_proven": false}, {"name": "variant", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "candidate_revision", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "hash", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "graph", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "diff", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "mission_response", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "created_at_unix_ms", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_owned_set_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE json_extract(body,'$.owned_set') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_history_index", "table_pattern": "claims", "key_expression_and_predicate": "(store_index) WHERE kind IN ('mission-run.state','step-run.state','work.failed') AND json_extract(body,'$.fields.status') IN ('failed','cancelled','completed')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_terminal_capability_hash_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.capability_hash'), store_index) WHERE kind='custom.client.terminal-attached'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_receipt_actor_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.receipt.actor_key'), origin, subject) WHERE kind='harness-question.resolved' AND actor IS NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), subject) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_report_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.report_to'), subject) WHERE kind IN ('mission-run.created','mission-run.report-to')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_to_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.to'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_legacy_from_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.from'), store_index) WHERE kind='message.sent' AND json_type(body, '$.fields') IS NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_resume_host_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.host'), subject) WHERE kind='runtime.action.requested' AND json_extract(body,'$.fields.action')='resume'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind IN ('work.progress', 'work.submitted')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_from_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.from'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_activity_time_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms, store_index) WHERE kind='harness.timeline' AND json_extract(body, '$.fields.entry_type') IN ('message','content','tool_call','tool_result')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actor_work_activity_index", "table_pattern": "claims", "key_expression_and_predicate": "(actor, json_extract(body, '$.fields.claim_incarnation'), store_index) WHERE kind IN ('work.claimed', 'work.progress')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_max_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id'), CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_ended_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.subagent_id')) WHERE kind='subagent.ended'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_appeared_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.appeared'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subagent_renewed_lease_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.lease_expires_at_unix_ms') AS INTEGER)) WHERE kind='subagent.renewed'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_timeline_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, kind, json_extract(body, '$.fields.incarnation_id'), store_index) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_finished_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind IN ( 'subscription.mission-started', 'subscription.mission-failed', 'subscription.mission-request-cancelled' )", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_delivery_key_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.delivery_key')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_started_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission_run')) WHERE kind='subscription.mission-started'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_mission_resource_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.mission'), json_extract(body, '$.fields.resource')) WHERE kind='subscription.mission-requested'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_url_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.url')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_authored_pull_request_number_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.facts.repository'), json_extract(body, '$.fields.facts.number')) WHERE kind='resource.observed' AND subject LIKE 'resource/mission-run/%/pull-request'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request'), store_index) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_subscription_deferred_deadline_index", "table_pattern": "claims", "key_expression_and_predicate": "(CAST(json_extract(body, '$.fields.not_before_unix_ms') AS INTEGER)) WHERE kind='subscription.mission-deferred'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_schedule_started_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.request')) WHERE kind='schedule.work-started'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_message_to_order_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.to'), store_index) WHERE kind='message.sent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_current_view_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='intent.desired' OR json_extract(body, '$.fields.status') NOT IN ('stopped', 'absent', 'exited') OR json_extract(body, '$.status') NOT IN ('stopped', 'absent', 'exited')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), store_index) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_reassignment_reviewer_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.request')) WHERE kind='gate.reviewer-reassigned'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_answer_request_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.request'), subject) WHERE kind='gate.result'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_human_gate_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner'), json_extract(body, '$.fields.reviewer'), json_extract(body, '$.fields.attempt'), json_extract(body, '$.fields.mission_revision'), json_extract(body, '$.fields.step_definition')) WHERE kind='gate.requested' AND json_extract(body, '$.fields.reviewer') IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, store_index) WHERE kind='runtime.observed'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_client_pairing_actor_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.session_actor')) WHERE kind='custom.client.pairing-completed'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_assistant_v1_credential_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.credential_hash'), store_index) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_episode_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.ownership_sequence'), json_extract(body, '$.fields.transition_sequence'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_unnamed_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND (json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) IS NULL OR typeof(json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END))!='text')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_claude_attachment_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END), store_index ) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('claude-channel-unattached','claude-channel-attached')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_state_incarnation_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "( subject, CASE WHEN json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END)='text' THEN json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.incarnation_id' ELSE '$.fields.incarnation_id' END) END, length(accepted_at_unix_ms), accepted_at_unix_ms ) WHERE kind='harness.observed' AND json_type(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='text'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_incarnation_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.observed' AND json_type(body, '$.fields.provider_auth') IN ('true','false')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_auth_diagnostic_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='harness.diagnostic' AND json_extract(body, '$.fields.code') IN ('provider-auth-expired','provider-auth-restored')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_harness_login_candidate_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject) WHERE (kind='harness.observed' AND ( json_type(body, '$.fields.provider_auth')='false' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.reason' ELSE '$.fields.reason' END)='providerAuth' OR json_extract(body, CASE WHEN json_type(body, '$.fields') IS NULL THEN '$.state' ELSE '$.fields.state' END)='needs-login')) OR (kind='harness.diagnostic' AND json_extract(body, '$.fields.code')='provider-auth-expired')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_step_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_step, subject)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_owner_run_index", "table_pattern": "desired", "key_expression_and_predicate": "(owner_run, subject)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_claim_index", "table_pattern": "desired", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_agent_host_index", "table_pattern": "desired", "key_expression_and_predicate": "(json_extract(member, '$.host'), subject) WHERE kind='agent'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_message_subject_index", "table_pattern": "desired", "key_expression_and_predicate": "(subject) WHERE kind='message'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "desired_watch_agent_index", "table_pattern": "desired", "key_expression_and_predicate": "(substr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), instr(substr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), instr(substr(substr(subject, 20), instr(substr(subject, 20), '/') + 1), '/') + 1), '/') + 1)) WHERE subject >= 'subscription/watch/' AND subject < 'subscription/watch0'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_root_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.root_mission_run')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.current_generation')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_run_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='mission-run.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_generation_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.revision')) WHERE kind='run-generation.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_proposal_revision_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.candidate_revision')) WHERE kind='revision-proposal.created'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_generation_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.generation')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_run_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_owner_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.owner_run')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_origin_step_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.origin_step')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_person_ask_recipient_index", "table_pattern": "claims", "key_expression_and_predicate": "(json_extract(body, '$.fields.person')) WHERE kind='work.person-asked'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "message_index_open", "table_pattern": "message_index", "key_expression_and_predicate": "(closed, created_index)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_identity_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(session_id, native_id, actor, origin, store_index)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_native_delivery_owner_cut_v2", "table_pattern": "local_native_delivery_receipts_v2", "key_expression_and_predicate": "(actor, store_index)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_revisions_claim_index", "table_pattern": "mission_revisions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_definitions_claim_index", "table_pattern": "mission_definitions", "key_expression_and_predicate": "(claim_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_mission_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_requester_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(requester)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_latest_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, created_at_unix_ms DESC, id DESC)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_collection_live_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(mission_id, status) WHERE status IN ('running','standing')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_root_page_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(root_run_id, created_at_unix_ms, id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_open_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(created_at_unix_ms, id) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "run_generations_run_index", "table_pattern": "run_generations", "key_expression_and_predicate": "(run_id, created_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_run_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id, generation_id, step_path)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_generation_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(generation_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_definition_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(definition_hash, run_id, generation_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "mission_runs_parent_step_index", "table_pattern": "mission_runs", "key_expression_and_predicate": "(parent_step_run) WHERE parent_step_run IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_assignee_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(assignee, status)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_lease_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(lease_owner) WHERE lease_owner IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_single_agent_offer_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(available_to, run_id) WHERE CASE WHEN json_valid(available_to) THEN json_array_length(available_to)=1 ELSE 0 END", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_available_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(run_id) WHERE available_to!='[]'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "step_runs_open_index", "table_pattern": "step_runs", "key_expression_and_predicate": "(created_at_unix_ms, step_path) WHERE status NOT IN ('completed','failed','cancelled')", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_kind_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, kind, id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_subject_id_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_after_store_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(after_store_index)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_time_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_dedupe_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(dedupe_key) WHERE dedupe_key IS NOT NULL", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_timeline_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(subject, json_extract(body, '$.fields.incarnation_id'), id) WHERE kind='harness.timeline'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_observations_roster_frontier_index", "table_pattern": "local_observations", "key_expression_and_predicate": "(id, after_store_index) WHERE kind='harness.timeline' AND subject LIKE 'agent/%'", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "client_diagnostic_receipts_device_time_index", "table_pattern": "client_diagnostic_receipts", "key_expression_and_predicate": "(device, accepted_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_subscription_mission_deferrals_deadline_index", "table_pattern": "local_subscription_mission_deferrals", "key_expression_and_predicate": "(not_before_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "local_usage_responses_age_index", "table_pattern": "local_usage_responses", "key_expression_and_predicate": "(observed_at_unix_ms)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_run_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(run_id)", "value_size_proven": false}, + {"site": "lv-h22c8c670811c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "revision_proposals_generation_index", "table_pattern": "revision_proposals", "key_expression_and_predicate": "(source_generation_id)", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_id_subject_index", "table_pattern": "claims", "key_expression_and_predicate": "({RUNTIME_ID_FIELD}, subject, store_index) WHERE {ACTUAL_STATE_CLAIM} AND typeof({RUNTIME_ID_FIELD})='text'", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_actual_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE {ACTUAL_STATE_CLAIM}", "value_size_proven": false}, {"site": "lv-h7792d6e9101c", "path": "crates/fractal-store/src/store.rs", "index_pattern": "claims_runtime_origin_accepted_index", "table_pattern": "claims", "key_expression_and_predicate": "(subject, origin, length(accepted_at_unix_ms), accepted_at_unix_ms) WHERE kind='runtime.observed'", "value_size_proven": false}, @@ -585,6 +582,18 @@ {"site": "lv-h3f7d4d7d63f4", "path": "crates/smallclaims/src/sqlite/read_lifetime/tests.rs", "table_pattern": "payload", "columns": [{"name": "value", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h1ba817f95aef", "path": "crates/smallclaims/src/sqlite/writer_queue/tests.rs", "table_pattern": "claims", "columns": [{"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h1ba817f95aef", "path": "crates/smallclaims/src/sqlite/writer_queue/tests.rs", "table_pattern": "values_", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_authority", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "base_claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "principal", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "profile", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "expires_at", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "credential_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_effective", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "principal", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "profile", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "expires_at", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "grant_record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_pending", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "authenticated", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_dirty", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_membership_windows", "columns": [{"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member_key", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "start", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "end", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_transition_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(grant_subject,kind,origin,actor,base_claim_id,store_index DESC)", "value_size_proven": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_latest_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(grant_subject,kind,store_index DESC)", "value_size_proven": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_credential_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(credential_hash,store_index DESC) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_effective_active_index", "table_pattern": "assistant_grant_effective", "key_expression_and_predicate": "(principal,owner,revoked,expires_at,profile)", "value_size_proven": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_effective_subject_index", "table_pattern": "assistant_grant_effective", "key_expression_and_predicate": "(grant_subject)", "value_size_proven": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_pending_subject_index", "table_pattern": "assistant_grant_pending", "key_expression_and_predicate": "(grant_subject,authenticated)", "value_size_proven": false}, + {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_pending_writer_index", "table_pattern": "assistant_grant_pending", "key_expression_and_predicate": "(origin,sequence,authenticated)", "value_size_proven": false}, {"site": "lv-ha962eb0285cf", "path": "crates/smallclaims/src/store/canonical.rs", "table_pattern": "claim_positions", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "position", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h315c8b6f5aa8", "path": "crates/smallclaims/src/store/checkpoint.rs", "table_pattern": "canonical_index", "columns": [{"name": "old", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY", "value_size_proven": false}, {"name": "new", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h298c5b9a94f9", "path": "crates/smallclaims/src/store/checkpoint.rs", "table_pattern": "sealed_claims", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, @@ -789,11 +798,11 @@ {"id": "flow-hae49bfcdc951", "path": "crates/fractal-store/src/store.rs", "function": "insert_event", "owner": "fractal_store::store", "fingerprint": "9cdeca113f2b75bcf56424758796dc68d0158e63ba3c7520de898551700bbf4e", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "description": "Event positions/publication must retain canonical pointer/body and ordering semantics."}, {"id": "flow-hcc1764594fd2", "path": "crates/fractal-store/src/store/backup.rs", "function": "receive_backup_page", "owner": "fractal_store::store::backup", "fingerprint": "35b1ec2cf1835ef24f9f29107f60813ca41eb4197e8a2be9a98b5771cbccaed7", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "description": "Backup import permits valid historical records under its own record/page limits, not client extractor limits."}, {"id": "flow-he7b2f39a2da2", "path": "crates/smallclaims/src/store.rs", "function": "append_claim_record_tx", "owner": "smallclaims::store", "fingerprint": "fd48ee537bf54b5b208b4e3da218640c9239c63fd3b76ab3e836cf6ef81b97b8", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "description": "Local append serializes the logical body and predecessor identities; no route-limit inference."}, - {"id": "flow-h8ff255a3c271", "path": "crates/smallclaims/src/store.rs", "function": "insert_claim", "owner": "smallclaims::store", "fingerprint": "c1f2beebb8654792635657bffc14ee4fa7e2f3303e803360b91feb922790e708", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "description": "Direct claim insert: body, predecessors and identifiers; bound parameters enter claims."}, + {"id": "flow-h8ff255a3c271", "path": "crates/smallclaims/src/store.rs", "function": "insert_claim", "owner": "smallclaims::store", "fingerprint": "2a9e7930ce2825e52deb860c3037b1ce6a5fd0ab4a6b97c37e780694bcc5485b", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "description": "Direct claim insert: body, predecessors and identifiers; bound parameters enter claims."}, {"id": "flow-h9a1973bf379a", "path": "crates/smallclaims/src/store.rs", "function": "promote_claim_blobs", "owner": "smallclaims::store", "fingerprint": "3a7eace9c6a74cbe44a5fbe23b9321f47c241c2662186a405ce7e863170442d5", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "description": "Blob promotion copies staged bytes to durable graph storage without changing logical identity."}, {"id": "flow-hd4562283f4d7", "path": "crates/smallclaims/src/store.rs", "function": "put_blob", "owner": "smallclaims::store", "fingerprint": "46f2545418004329783b4f1be7c2e0c5d5bd0a271694c3168a91ad3264c354ec", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "description": "Immutable blob bytes are independently variable values; retain digest/length/promotion semantics."}, {"id": "flow-h5298e6bf0818", "path": "crates/smallclaims/src/store.rs", "function": "put_document_as", "owner": "smallclaims::store", "fingerprint": "1e506aa4b6b4fbea69af79a2ce98c3220bb8b41f127de139e327fd6fedc6a7c9", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "description": "Document API/local producer body, identity and predecessors reach the common claim writer."}, - {"id": "flow-h7818827323a6", "path": "crates/smallclaims/src/store.rs", "function": "receive_replication_exchange_via", "owner": "smallclaims::store", "fingerprint": "7fac5944c99444ba5e7e6024033ae70f75fe4e71784443e6a0ea77de8be7b8f4", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "description": "Exchange importer delegates admission and projection; wire/decompression bounds are not a universal stored-cell cap."}, + {"id": "flow-h7818827323a6", "path": "crates/smallclaims/src/store.rs", "function": "receive_replication_exchange_via", "owner": "smallclaims::store", "fingerprint": "305bf4a2e671e691e0494b4370baea493808b9adc601f0596ee19d52b00be2bc", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "description": "Exchange importer delegates admission and projection; wire/decompression bounds are not a universal stored-cell cap."}, {"id": "flow-he3fba1ec9f02", "path": "crates/smallclaims/src/store.rs", "function": "seed_replica_envelopes_signed_tx", "owner": "smallclaims::store", "fingerprint": "e8bca83e997622c80dbc8208225b55e51bf69a8d329a524a1aa61a2a2fa95180", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "description": "Local sealing serializes admitted history into exact signed raw envelopes; body/wire representations both matter."}, {"id": "flow-hc220cedadab9", "path": "crates/smallclaims/src/store.rs", "function": "separate_staged_blobs", "owner": "smallclaims::store", "fingerprint": "691fbc18013b213398f54c34218b5e72735c4b2300534ff1ed68822f17d8b4e7", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "description": "Legacy staged blob migration/copy may contain valid historical large cells."}, {"id": "flow-h3b22d926e1f0", "path": "crates/smallclaims/src/store.rs", "function": "validate_and_admit_envelope_tx", "owner": "smallclaims::store", "fingerprint": "aaf5ba5ff019ea3e20fe3dd71eb7e097d3ff883676b2e6485d52c0b93f48dd72", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "description": "Replication admission: raw CBOR, claim body, dependencies, blobs and signed metadata must retain exact identity."}, @@ -1011,6 +1020,7 @@ {"id": "lv-h0c96917a1e85", "path": "crates/fractal-attention/src/store/attention.rs", "kind": "unresolved-sql-sink", "fingerprint": "ddeff9e9abf773cc2802f751233e89fb87b31bb0b50b2b8c852af9df9bdd7835", "owner": "fractal_attention::store::attention", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 12, "excerpt": "& canonical_sql ( \"SELECT request.id, request.store_index, request.batch_id, request.subject, request.kind, request.origin, request.actor, request.body, request.predecessors, request.accepted_at_unix_"}, {"id": "lv-h0c9cd59bf805", "path": "crates/smallclaims/src/store/checkpoint_staging.rs", "kind": "sql-template", "fingerprint": "3821719cd9da9c7336b0bc4df86f909befb861c0beebc5f63ddb5497dd3a5579", "owner": "smallclaims::store::checkpoint_staging", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1134, "excerpt": "UPDATE meta SET plan=NULL WHERE id=1"}, {"id": "lv-h0c9f4b3ffede", "path": "crates/fractal-store/src/store/ordered_membership.rs", "kind": "sql-template", "fingerprint": "e32a001f16ab76dc15f424dbb35e9d0fab4c21741a7ee76041e637f50449d0fa", "owner": "fractal_store::store::ordered_membership", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 305, "excerpt": "INSERT INTO ordered_membership_heads(container,member,position,revision,winner) VALUES(?1,?2,?3,?4,?5) ON CONFLICT(container,member) DO UPDATE SET position=excluded.position,revision=excluded.revision"}, + {"id": "lv-h0ce05c43b4a2", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "f7412e6b548e10558b244b2fddac940865d0ba0ea06704ee689f162668f676e0", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 325, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_fleet_id',?1)"}, {"id": "lv-h0cfe32b4b70b", "path": "crates/fractal-store/src/store/message_send_tests.rs", "kind": "sql-template", "fingerprint": "0bd2d5c434f44597ecbcc5314b9145e9e7eb02befdb5fe272c0227b94fc3d18a", "owner": "fractal_store::store::message_send_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 36, "excerpt": "DELETE FROM operations WHERE id='op/invented-parity'"}, {"id": "lv-h0d17d2d43780", "path": "crates/smallclaims/src/ivm/claim_source.rs", "kind": "sql-template", "fingerprint": "1927c02e6052e0416b46a82eaaea94815ca0b8805edcf46d02c26f04e0c067f9", "owner": "smallclaims::ivm::claim_source", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 159, "excerpt": "CREATE TRIGGER IF NOT EXISTS ivm_install_claim_{name} {event} WHEN {condition} BEGIN UPDATE ivm_install_sources SET available=0 WHERE name IN ({sources}); UPDATE ivm_install_jobs SET phase='stopped',e"}, {"id": "lv-h0d1d3d43ff50", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "da375a6ef935682d924483cbd6c26b9c32a0a576b639560d3ec18290cfd5125b", "owner": "fractal_store::store::resources_preparation_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 1205, "excerpt": "DELETE FROM claims WHERE id=?1"}, @@ -1142,6 +1152,7 @@ {"id": "lv-h164d197fb0c6", "path": "crates/fractal-store/src/store/checkpoint_identity_reuse_tests.rs", "kind": "sql-template", "fingerprint": "15decfaeb5c26cecac153848d12c87738052d4cae641e66c1505ade456c89476", "owner": "fractal_store::store::checkpoint_identity_reuse_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 123, "excerpt": "UPDATE claims SET accepted_at_unix_ms='5000' WHERE id IN ( SELECT records.claim_id FROM replica_records records JOIN replica_envelopes envelopes ON records.writer=envelopes.writer AND records.sequence"}, {"id": "lv-h1650bf6a58bc", "path": "crates/fractal-missions/src/store/resource_preparation/tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "713a1c59ffff86cb801fa5892aec98a04d6796cb005c7ef94339e94c3da332f6", "owner": "fractal_missions::store::resource_preparation::tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 117, "excerpt": "& other , | _ | ( )"}, {"id": "lv-h16586c1e56da", "path": "crates/smallclaims/src/store/principals.rs", "kind": "sql-template", "fingerprint": "bf5873267aa948343437eaa2ca0053f5e123c1b8d089c7c933a34e432baa6d90", "owner": "smallclaims::store::principals", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 279, "excerpt": "INSERT OR IGNORE INTO claim_signature_candidates(claim_id,signature,key,nonce) VALUES (?1,?2,?3,?4)"}, + {"id": "lv-h1665a4a8cfdf", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "unresolved-sql-sink", "fingerprint": "b7eafcbb01a79e6feb02839905b41bafc8a5be2f355d21ab6b4b392a34092eac", "owner": "smallclaims::store::assistant_grant_authority", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 241, "excerpt": "& QUERY"}, {"id": "lv-h166835b7b8cb", "path": "crates/smallclaims/src/store/saved_inventory.rs", "kind": "unresolved-sql-sink", "fingerprint": "fca5d96f6c68c4cc7e0a68c2245ed850d4a3f62fc48485354ad7706c45b31ac4", "owner": "smallclaims::store::saved_inventory", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 73, "excerpt": "[ rowid ] , | row | { Ok ( ReplicaEnvelopeId { writer : row . get ( 0 ) ? , sequence : row . get ( 1 ) ? , hash : row . get ( 2 ) ? , } ) }"}, {"id": "lv-h1693db03cced", "path": "crates/smallclaims/src/store/prepared_envelope.rs", "kind": "sql-template", "fingerprint": "7512424f1b97db6e6318c1bce828a00664863a9c0fca3740e0629c5e37936fe6", "owner": "smallclaims::store::prepared_envelope", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 455, "excerpt": "INSERT INTO replica_records( record_ref, writer, sequence, envelope_hash, position, raw, state, claim_id, subject_hint, kind_hint, error_code, error_message, updated_at_unix_ms ) VALUES (?1, ?2, ?3, ?"}, {"id": "lv-h16a68f6ab5e8", "path": "crates/fractal-kernel/src/conversation_search.rs", "kind": "unresolved-sql-sink", "fingerprint": "b9543199298420fe9e37bb76665ae9eb0e08741f55cce132d2c0d5adc31f65eb", "owner": "fractal_kernel::conversation_search", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 45, "excerpt": "\"CREATE VIRTUAL TABLE entries USING fts5(source UNINDEXED, conversation_id UNINDEXED, entry_id UNINDEXED, agent_id UNINDEXED, timestamp UNINDEXED, entry_type UNINDEXED, text, tokenize='unicode61');\" ,"}, @@ -1179,6 +1190,7 @@ {"id": "lv-h18dd79b21618", "path": "crates/fractal-store/src/store/notice_authority_tests.rs", "kind": "sql-template", "fingerprint": "1d306ca6f8d0ac404bd039bda5b4330f1befc3c5af2cbb683b0ea08b3b3a7a25", "owner": "fractal_store::store::notice_authority_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 185, "excerpt": "DELETE FROM documents WHERE name=?1 AND hash=?2"}, {"id": "lv-h18e23473abaf", "path": "crates/fractal-delivery/src/store/terminal_gate_evidence/native_source/tests.rs", "kind": "sql-template", "fingerprint": "5a66247d8f7ecaea9d55cd03b41096c4c0175a3572cf61790f6930987c671751", "owner": "fractal_delivery::store::terminal_gate_evidence::native_source::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 312, "excerpt": "UPDATE test_native_terminal_guard SET pending=0 WHERE id=1"}, {"id": "lv-h18f468b699f4", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "4ec7c53222c8a758c722e2111541035ce700d5ae7bd0898c5f1b1a743e6450fd", "owner": "fractal_store::store::resources_preparation_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 820, "excerpt": "sql"}, + {"id": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "c8bd40e012fde548f016ce2eeebd726b14a096f3b40b6c056a2994b0d05e3f67", "owner": "smallclaims::store::assistant_grant_authority", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 85, "excerpt": "CREATE TABLE IF NOT EXISTS assistant_grant_authority ( claim_id TEXT NOT NULL, base_claim_id TEXT NOT NULL, grant_subject TEXT NOT NULL, kind TEXT NOT NULL, origin TEXT NOT NULL, actor TEXT NOT NULL, "}, {"id": "lv-h1923419271b7", "path": "crates/smallclaims/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "19f6c92406524d4f1e21d93717491852ee29c50077d9a6ff1384164a75a51579", "owner": "smallclaims::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 5760, "excerpt": "& canonical_sql ( LATEST_CLAIM_QUERY )"}, {"id": "lv-h193645d36e0f", "path": "crates/fractal-reconcile/src/reconcile.rs", "kind": "included-source", "fingerprint": "23bef6856b048e52b60b69a713a07339768128a512d6487d2388a7ffaba34a1c", "owner": "fractal_reconcile::reconcile", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 42048, "excerpt": "include_str ! ( \"../../fractal-drivers/tests/fixtures/blocking-screens/claude-login.txt\" )"}, {"id": "lv-h1939f319556d", "path": "crates/fractal-store/src/store/arrangements.rs", "kind": "sql-template", "fingerprint": "8326b0def65d092d55ca567201f98deb44744f6078e4566c7df9423c49a602e4", "owner": "fractal_store::store::arrangements", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 59, "excerpt": "DELETE FROM meta WHERE key>=?1 AND key ( 0 )"}, {"id": "lv-h3f0f377d0d3b", "path": "crates/smallclaims/src/store/checkpoint_trim.rs", "kind": "unresolved-sql-sink", "fingerprint": "6a8bc964399f5a0d2b85daf17489b50e8d75ff83f232d1a1b72fd95b8d8daca8", "owner": "smallclaims::store::checkpoint_trim", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1068, "excerpt": "params ! [ envelope . writer , envelope . sequence , envelope . envelope_hash ] , | row | row . get ( 0 )"}, + {"id": "lv-h3f117dab1bdd", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "801a71dd84fdd9b15bd1daead009f00c28527f55cd56eed75d659cb819273233", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 122, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_local_origin',?1)"}, {"id": "lv-h3f4254f45299", "path": "crates/fractal-store/src/store/observer_subscription_detail.rs", "kind": "unresolved-sql-sink", "fingerprint": "90dbe74bec90013705bd92e02619372a20cb7733a5375be33830ea72c895a370", "owner": "fractal_store::store::observer_subscription_detail", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 124, "excerpt": "[ subject ] , | row | row . get ( 0 )"}, + {"id": "lv-h3f49c0e579cd", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "d32ac2e4d08dda85b0bdcd99da38e8413afd3c164a0de0295122f56508ee57ce", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 361, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES(?1,?2)"}, {"id": "lv-h3f5784d30226", "path": "crates/fractal-store/src/store/backup_ledgers.rs", "kind": "sql-template", "fingerprint": "db9d5daac3d9c10af3297e8724dfd6d386f827e0d6ba268f0979bca285e3d6ee", "owner": "fractal_store::store::backup_ledgers", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 102, "excerpt": "INSERT OR IGNORE INTO retired_claim_ancestry(claim_id, subject, kind, predecessors) \\ VALUES ({0}, {1}, {2}, {3})"}, {"id": "lv-h3f5f5a18a499", "path": "crates/smallclaims/src/store/prepared_seal_tests.rs", "kind": "sql-template", "fingerprint": "4c324910290e8101c7e0877e900b61cc935f6391fa3f309a48d81786ddbd658a", "owner": "smallclaims::store::prepared_seal_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 449, "excerpt": "UPDATE meta SET value=?1 WHERE key='fleet_id'"}, {"id": "lv-h3f6355c99f88", "path": "crates/smallclaims/src/store/fleet_residue_page_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "a8b771920b8319e47251d1360f5e880bc18e8d329b0f0d003ea3c7e615558947", "owner": "smallclaims::store::fleet_residue_page_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 70, "excerpt": "query"}, @@ -1845,6 +1863,7 @@ {"id": "lv-h4249b590ecda", "path": "crates/fractal-store/src/store/person_work.rs", "kind": "sql-template", "fingerprint": "84b5e8a8cddaedd19c2c6f034c07f033fb928fdd4341e4d456821e9be719f5e5", "owner": "fractal_store::store::person_work", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 478, "excerpt": "UPDATE mission_revisions SET claim_id=?3 WHERE mission_id=?1 AND revision=?2"}, {"id": "lv-h42590a6b7f39", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "8d2a871754dfcdb917cbb402701f67a9b9c9374ec2767a43a456c81600b74997", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 16726, "excerpt": "UPDATE step_runs SET status=?2, worker_reported=?3, lease_owner=?4, lease_incarnation=?5, lease_expires_at_unix_ms=?6, blocked_reason=?7, readiness_epoch=COALESCE(?8, readiness_epoch), updated_at_unix"}, {"id": "lv-h427148ddeaa2", "path": "crates/fractal-github/src/changes/tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "70ce871f8a3d3fb449bc3c3ace6547cef02dfc74ffe48d912532a724bfdbe5b9", "owner": "fractal_github::changes::tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 324, "excerpt": "record"}, + {"id": "lv-h4276e804ce28", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "7eb24f52c51faac039072b870ba59fcb0bdccae502522813a9fa1d252ab62bc0", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 250, "excerpt": "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,sequence,authenticated,record) VALUES(?1,?2,?3,?4,?5,?6,?7) ON CONFLICT(claim_id) DO UPDATE SET authenticated=MAX(authenticated,e"}, {"id": "lv-h42a085359417", "path": "crates/fractal-reconcile/src/reconcile/github_plugin_store.rs", "kind": "sql-template", "fingerprint": "ccc4965afee3bca282f5b7d2c70a8d296e313fcd8ecca4a46b994a2fd9170bf3", "owner": "fractal_reconcile::reconcile::github_plugin_store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 593, "excerpt": "INSERT INTO mirror_repositories(repository, observer, locator) VALUES (?1, ?2, ?3) ON CONFLICT(repository) DO UPDATE SET observer=excluded.observer, locator=excluded.locator"}, {"id": "lv-h42ae322d7bea", "path": "crates/fractal-delivery/src/store/terminal_gate_evidence/native_source/tests.rs", "kind": "sql-template", "fingerprint": "abb58e88801766b919b951fb8f22f8a435ebed904b0379612fd3e0a8c1ef9ca5", "owner": "fractal_delivery::store::terminal_gate_evidence::native_source::tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 125, "excerpt": "INSERT INTO claims(id,batch_id,subject,kind,origin,body,predecessors,accepted_at_unix_ms) VALUES(?1,?2,?3,'harness.observed','node','{}','[]','1')"}, {"id": "lv-h42ae3e27a51b", "path": "crates/fractal-store/src/store/retirements.rs", "kind": "unresolved-sql-sink", "fingerprint": "7de654164476b315f774b0a13d4920ba7261a28f74f02ccd39abdbaca1898b2f", "owner": "fractal_store::store::retirements", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 55, "excerpt": "params ! [ subject , at ] , claim_from_row"}, @@ -1865,6 +1884,7 @@ {"id": "lv-h4366714f9010", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "a8b771920b8319e47251d1360f5e880bc18e8d329b0f0d003ea3c7e615558947", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 15625, "excerpt": "query"}, {"id": "lv-h4368bbfe977e", "path": "crates/fractal-store/src/store/marks_switch.rs", "kind": "unresolved-sql-sink", "fingerprint": "80763cd993a551aed46eaee6efb4eacdc6059e75b8f5e8d4aed0c63963810057", "owner": "fractal_store::store::marks_switch", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 62, "excerpt": "& writer_seek ( table , column )"}, {"id": "lv-h437d619987cd", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "e07a4d28e54787034c419046b1ddb85c71444fb1db1ed57766d5a4bf9a4aee22", "owner": "fractal_store::store::resources_preparation_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1093, "excerpt": "DELETE FROM local_resource_preparation_claims WHERE subject=?1"}, + {"id": "lv-h437f9d145151", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "34addb038ed70c9db05a568f04f54703acd9ea11193885e325242d7a23bc27b0", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 408, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_shared_fleet','1')"}, {"id": "lv-h43a8ecb87729", "path": "crates/fractal-store/src/store/person_work.rs", "kind": "unresolved-sql-sink", "fingerprint": "5cc27cba8b6e6061ac97316cda9eb723d2b4ff6ee63f4b3cdb75abef9a92a7d9", "owner": "fractal_store::store::person_work", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 90, "excerpt": "& canonical_sql ( \"SELECT id, store_index, batch_id, subject, kind, origin, actor, body, predecessors, accepted_at_unix_ms FROM claims WHERE subject=?1 AND kind='work.person-asked' ORDER BY CANONICAL_"}, {"id": "lv-h43acfbf85a46", "path": "crates/smallclaims/src/store/checkpoint_staging.rs", "kind": "sql-template", "fingerprint": "ba62c112babd8aca873aba816c7e6ece1fbddf9f02e0c36579a8268994162f45", "owner": "smallclaims::store::checkpoint_staging", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 709, "excerpt": "INSERT OR IGNORE INTO cited(id) VALUES (?1)"}, {"id": "lv-h43b695edb31d", "path": "crates/fractal-api-client-v0/src/api/client_v0/observer_subscription_detail_tests.rs", "kind": "sql-template", "fingerprint": "bbfd2cd8cc0f3e6fb17c385da9904559980085b5d11da6935ea870e530ce1ce1", "owner": "fractal_api_client_v0::api::client_v0::observer_subscription_detail_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 544, "excerpt": "UPDATE claims SET accepted_at_unix_ms=?2 WHERE store_index=?1"}, @@ -1927,6 +1947,7 @@ {"id": "lv-h47454d1a25b6", "path": "crates/smallclaims/src/store/repair_operation_tests.rs", "kind": "sql-template", "fingerprint": "d1afaa8c9a82bd6bf778c0b93f3e14dbf2bd37bcc8edf7181f59d23060ac954f", "owner": "smallclaims::store::repair_operation_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 585, "excerpt": "UPDATE operations SET request_digest='wrong'"}, {"id": "lv-h4746913336a7", "path": "crates/fractal-store/src/store/resources_preparation.rs", "kind": "unresolved-sql-sink", "fingerprint": "b7eafcbb01a79e6feb02839905b41bafc8a5be2f355d21ab6b4b392a34092eac", "owner": "fractal_store::store::resources_preparation", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 538, "excerpt": "& QUERY"}, {"id": "lv-h475b9c435b3b", "path": "crates/smallclaims/src/store/prepared_envelope_tests.rs", "kind": "sql-template", "fingerprint": "86a3507a2d90f069218b25e0f4583211402e34c38f3366a24130d5adf9ae9592", "owner": "smallclaims::store::prepared_envelope_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1161, "excerpt": "INSERT INTO meta(key, value) VALUES ('gate', 'open')"}, + {"id": "lv-h47619972ac92", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "ec83ce1a2406c4a7f2dbd893f1b4fc59db477b26a34ece0658659bea09b1d7b2", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 201, "excerpt": "DELETE FROM assistant_grant_effective WHERE grant_subject=?1"}, {"id": "lv-h476756b0f558", "path": "crates/fractal-store/src/store/client_messages.rs", "kind": "unresolved-sql-sink", "fingerprint": "ffab679bb75b8a325d503bcd0b5026ea6500de964c0bd80aa0be822e0b4e1851", "owner": "fractal_store::store::client_messages", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 705, "excerpt": "[ BACKFILL_MARKER ] , | row | row . get ( 0 )"}, {"id": "lv-h479424100c1a", "path": "crates/smallclaims/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "096dec60c53b20d1b3af93a466b7d7159879452d670da3cecd70bd0f3e591211", "owner": "smallclaims::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 7962, "excerpt": "\"RELEASE project_incremental\""}, {"id": "lv-h47a0a723f1b0", "path": "crates/fractal/src/main_tests.rs", "kind": "included-source", "fingerprint": "ade115a25cbf169314b7a727ce07ca2995c0e33b3cac801ac29f37b3e7a883cc", "owner": "fractal::main_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 3039, "excerpt": "include_str ! ( \"main.rs\" )"}, @@ -2168,12 +2189,14 @@ {"id": "lv-h54cdeb4d9314", "path": "crates/fractal-store/src/store/tests_shared_seats.rs", "kind": "sql-template", "fingerprint": "eb3b43e13f0aa93fc3ba3a7ae917e281e3c9a4a9af2fdbe5295841e929e0b7e6", "owner": "fractal_store::store::tests_shared_seats", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 127, "excerpt": "INSERT INTO claims(id, batch_id, subject, kind, origin, actor, body, predecessors, accepted_at_unix_ms) VALUES (?1, 'batch/raw', ?2, ?3, 'node', NULL, '{}', '[]', '1')"}, {"id": "lv-h551e460e7382", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "da375a6ef935682d924483cbd6c26b9c32a0a576b639560d3ec18290cfd5125b", "owner": "fractal_store::store::resources_preparation_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 1032, "excerpt": "DELETE FROM claims WHERE id=?1"}, {"id": "lv-h5520c75fb611", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "da375a6ef935682d924483cbd6c26b9c32a0a576b639560d3ec18290cfd5125b", "owner": "fractal_store::store::resources_preparation_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 1404, "excerpt": "DELETE FROM claims WHERE id=?1"}, + {"id": "lv-h5520ddeb5d20", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "unresolved-sql-sink", "fingerprint": "735525e0a58519ab770592beb88cb50d15239ecddb919afbec52304acc2ee89c", "owner": "smallclaims::store::assistant_grant_authority", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 241, "excerpt": "[ id ] , claim_from_row"}, {"id": "lv-h5537ddf8da09", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "e821840e8d46483d38b7772c3b3dd8d941d38242cfe30aa4fdadebaf8e277b38", "owner": "fractal_store::store::resources_preparation_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 480, "excerpt": "UPDATE batches SET origin='example-common',replica_sequence=CASE WHEN id=(SELECT batch_id FROM claims WHERE id=?1) THEN 100 ELSE 1 END WHERE id IN (SELECT batch_id FROM claims WHERE id IN (?1,?2))"}, {"id": "lv-h554a3f319a10", "path": "crates/smallclaims/src/ivm/install/prepared.rs", "kind": "unresolved-sql-sink", "fingerprint": "2fba33b0cd5a1d1285ab55f8cbeb18658e2833e18dab5d5b1cdfa93bc181470d", "owner": "smallclaims::ivm::install::prepared", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 963, "excerpt": "\"RELEASE ivm_prepared_page\""}, {"id": "lv-h555bfa5aa4b3", "path": "crates/fractal-delivery/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "f651dfbd998ac732797c555666f9759e436f6e14d65a0373c119155eb8faa461", "owner": "fractal_delivery::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 191, "excerpt": "& format ! ( \"SELECT claims.body FROM claims INDEXED BY claims_subject_kind_accepted_index JOIN batches ON batches.id=claims.batch_id WHERE claims.subject=?1 AND claims.kind='runtime.observed' AND cla"}, {"id": "lv-h555d6ec0084c", "path": "crates/fractal-store/src/store/message_outbox.rs", "kind": "sql-template", "fingerprint": "91dc3637a77c85dbcca62657dd2040d88939fc875d701bc2f2ca30639abdf87b", "owner": "fractal_store::store::message_outbox", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 28, "excerpt": " CREATE TABLE IF NOT EXISTS local_message_outbox ( subject TEXT PRIMARY KEY, claim TEXT NOT NULL, queued_at_unix_ms INTEGER NOT NULL, attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT ); CREATE IND"}, {"id": "lv-h5565b4adb53d", "path": "crates/smallclaims/src/store/events.rs", "kind": "sql-template", "fingerprint": "f852f66e72da8c87a5e616403c2447f60d34dfa5167920024b96f99037dc32aa", "owner": "smallclaims::store::events", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 45, "excerpt": "DROP VIEW events; CREATE VIEW events AS SELECT p.store_index,c.kind,p.subject,c.body FROM event_positions p CROSS JOIN claims c ON c.store_index=p.store_index UNION ALL SELECT p.store_index,c.kind,p.s"}, {"id": "lv-h556b74d6044a", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "9579ec05a5dc2b199e9dbe717739274cad8dad7c65bb2a0360fad919917a01ac", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 7119, "excerpt": "INSERT INTO planning_sessions(id, mission_id, request_ref, workspace, requester, planner, planner_spec_json, status, target_run_id, source_generation_id, created_at_unix_ms, updated_at_unix_ms) VALUES"}, + {"id": "lv-h556bdadaf8cd", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "unresolved-sql-sink", "fingerprint": "4a1d7a0df6f881609532183c9937f12f48f2a7697a30524a292e2c4131164d9a", "owner": "smallclaims::store::assistant_grant_authority", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 169, "excerpt": "CANDIDATES_QUERY"}, {"id": "lv-h556d5f52a3a9", "path": "crates/smallclaims/src/store/checkpoint_trim.rs", "kind": "unresolved-sql-sink", "fingerprint": "7d788c02089938e7c87fdc6553c374064f435a2fbf0b04a56aef360b3e0bf7f0", "owner": "smallclaims::store::checkpoint_trim", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 620, "excerpt": "[ ] , | row | Ok ( ( row . get : : < _ , i64 > ( 0 ) ? , row . get : : < _ , String > ( 1 ) ? ) )"}, {"id": "lv-h5574f8672a86", "path": "crates/fractal-missions/src/store/operations.rs", "kind": "sql-template", "fingerprint": "a4240e1e69cc045aa71479d5607e94d0ceb68ed08adf51e20a11f8c826275e9a", "owner": "fractal_missions::store::operations", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 65, "excerpt": "INSERT INTO run_generations SELECT ?1,?2,revision,NULL,?3,actor,reason,?4,?4 FROM run_generations WHERE id=?5"}, {"id": "lv-h557fd2adb2ea", "path": "crates/fractal-drivers/src/harness_events.rs", "kind": "sql-template", "fingerprint": "2d8265c85563eeb6058a43315b73eb3a50be80407ccb2d92108379464a3f4aa8", "owner": "fractal_drivers::harness_events", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 315, "excerpt": "UPDATE metadata SET value=?1 WHERE key='pending-bytes'"}, @@ -2219,6 +2242,7 @@ {"id": "lv-h5807a1101987", "path": "crates/fractal-store/src/store/completion_state.rs", "kind": "sql-template", "fingerprint": "6fbf81728b4e78bfb022ed799c80fd7cfdbfe883d04304f7ef9d6cf20ed6f3ab", "owner": "fractal_store::store::completion_state", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 227, "excerpt": "DELETE FROM local_completion_health_v1_claims WHERE claim_id=?1"}, {"id": "lv-h580eec954622", "path": "crates/fractal-store/src/store/tests.rs", "kind": "sql-template", "fingerprint": "ca00bf71e63d7a44fcc9d8aa75ce4f583d9c760665a19ab32e0ffe0b2945c035", "owner": "fractal_store::store::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 7172, "excerpt": "UPDATE mission_runs SET status='completed' WHERE id='run-example'"}, {"id": "lv-h581d2d15b664", "path": "crates/fractal-store/src/store/idle_mail.rs", "kind": "sql-template", "fingerprint": "f04f1cbf586659252f3d0a49923faed45656a176d5e31210a9e3ba31a598ab46", "owner": "fractal_store::store::idle_mail", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 171, "excerpt": "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) VALUES(?1,?2,?3,?4,'fixture',NULL,?5,'[]',?6)"}, + {"id": "lv-h5820156720c0", "path": "crates/smallclaims/src/store/assistant_grant_authority_bench.rs", "kind": "unresolved-sql-sink", "fingerprint": "59b4dbf78175f7e6e792032a53e966a89a0afa9d605487128e54573600011c83", "owner": "smallclaims::store::assistant_grant_authority_bench", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 238, "excerpt": "params ! [ id , format ! ( \"batch/{LOCAL}/{sequence:064x}\" ) , format ! ( \"conversation/synthetic/{:08x}\" , row % 1 0 0 _000 ) , format ! ( \"synthetic.message.kind{}\" , row % 1 6 ) , LOCAL , \"person/p"}, {"id": "lv-h582a34b5ce55", "path": "crates/fractal-store/src/store/ordered_membership.rs", "kind": "sql-template", "fingerprint": "00588d4f2313b213bcf242af52810c444d9e1479f3b8ff9884fde92ac7118037", "owner": "fractal_store::store::ordered_membership", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 265, "excerpt": "INSERT OR IGNORE INTO declared_resource_edges(owner,relation,name,target) VALUES(?1,'ordered-membership',?2,?2)"}, {"id": "lv-h582aabe243d0", "path": "crates/fractal-missions/src/store/person_work.rs", "kind": "unresolved-sql-sink", "fingerprint": "8612167e28c162a2fee1c63ec4be5673bd9fd8221b3cf742ed8f17fa613dcd17", "owner": "fractal_missions::store::person_work", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 569, "excerpt": "\"SAVEPOINT tell_ask_ended\""}, {"id": "lv-h582e5366bbee", "path": "crates/smallclaims/src/store/principals.rs", "kind": "unresolved-sql-sink", "fingerprint": "b9583a3b1a1be6db59892cb754cd0fcfb1ec702b7fe72b60bdd18505b2bab00a", "owner": "smallclaims::store::principals", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1054, "excerpt": "[ REQUEUE , REQUEUE_END ] , | row | { Ok ( ( row . get : : < _ , String > ( 0 ) ? , row . get : : < _ , String > ( 1 ) ? ) ) }"}, @@ -2344,7 +2368,9 @@ {"id": "lv-h604856482f09", "path": "crates/fractal-reconcile/src/reconcile.rs", "kind": "included-source", "fingerprint": "3616f97100c38f3c2e4c541b6f2c7ec51e906225ef6122a06f50332af7263d36", "owner": "fractal_reconcile::reconcile", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 41952, "excerpt": "include_str ! ( \"../../fractal-drivers/tests/fixtures/blocking-screens/omp-no-key.txt\" )"}, {"id": "lv-h604afa5bb192", "path": "crates/smallclaims/src/store.rs", "kind": "sql-template", "fingerprint": "b395e768bda4bf52a0313b592bbcc8ba3ad9b6a6e75130bd5a3765af1d4cdd52", "owner": "smallclaims::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 6250, "excerpt": "INSERT INTO local_blob_uploads(hash, actor, media_type, size, uploaded_ms) VALUES (?1,?2,?3,?4,?5) ON CONFLICT(hash, actor) DO UPDATE SET uploaded_ms=excluded.uploaded_ms"}, {"id": "lv-h604d12b1d064", "path": "crates/fractal-seats/src/store/limits.rs", "kind": "sql-template", "fingerprint": "221992ea0dc30cf06f7393168e6ee36d595f6dd4e45ad1b2af0e41b02c70a732", "owner": "fractal_seats::store::limits", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 408, "excerpt": "INSERT OR IGNORE INTO local_limit_stops(account, episode, seat, stopped_at_unix_ms) VALUES (?1, ?2, ?3, ?4)"}, + {"id": "lv-h60572e3ac6a5", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "4057b5ea4425eae5245388f9b99c2e85be224354079f4e476f16d61dccb3fd67", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 190, "excerpt": "INSERT OR IGNORE INTO assistant_grant_authority (claim_id,base_claim_id,grant_subject,kind,origin,actor,principal,profile,expires_at,store_index,credential_hash,record) VALUES(?1,?2,?3,?4,?5,?6,?7,?8,"}, {"id": "lv-h605b32403e38", "path": "crates/fractal/src/projection_contention_retry_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "f10e20728e77f302935d7b4f1031c77dca8743a680305ee8cdf2f818e584bbb5", "owner": "fractal::projection_contention_retry_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 156, "excerpt": "\"ROLLBACK\""}, + {"id": "lv-h6064c7271014", "path": "crates/smallclaims/src/store/assistant_grant_authority_bench.rs", "kind": "sql-template", "fingerprint": "79a6687f3f5d42c71d7224125b49903b66422f045ad73a3fab11aed827399b6c", "owner": "smallclaims::store::assistant_grant_authority_bench", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 170, "excerpt": "DROP TRIGGER IF EXISTS assistant_grant_dirty_insert; DELETE FROM assistant_grant_authority; DELETE FROM assistant_grant_effective; DELETE FROM assistant_grant_pending; DELETE FROM assistant_grant_dirt"}, {"id": "lv-h606a2ea2c17e", "path": "crates/smallclaims/src/store/checkpoint_trim.rs", "kind": "sql-template", "fingerprint": "0f1f0127b2d374c5972ec8fd2024dc3712927a18c2e69a6f61955de79f712de6", "owner": "smallclaims::store::checkpoint_trim", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 114, "excerpt": "INSERT OR IGNORE INTO temp.adopted_envelopes(writer, sequence, envelope_hash) VALUES (?1, ?2, ?3)"}, {"id": "lv-h607728b48402", "path": "crates/fractal-store/src/store/tests.rs", "kind": "sql-template", "fingerprint": "3fdbff1254292b0b91b474a6f360f3a7b2d09a96ec1c04a356fb3398724aa0d6", "owner": "fractal_store::store::tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 6844, "excerpt": "UPDATE claims SET body=json_remove(body,'$.fields.incarnation_id') WHERE id='legacy-5'"}, {"id": "lv-h608592d729cd", "path": "crates/fractal-store/src/store/completion_state_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "dc372daedd324b47f1261987900c1a08eff3ccdf253bfcf666d0ebecf17142ad", "owner": "fractal_store::store::completion_state_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 293, "excerpt": "& store , | _ | ( )"}, @@ -2358,6 +2384,7 @@ {"id": "lv-h60e669c72d60", "path": "crates/fractal-store/src/store/schedule_active_run_tests.rs", "kind": "sql-template", "fingerprint": "6258e7b30cb316691726c25d811e65db1910919ad217c6fc023fd30ad2a2ce3c", "owner": "fractal_store::store::schedule_active_run_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 151, "excerpt": "INSERT INTO claims VALUES(?1,'schedule.work-started',?2)"}, {"id": "lv-h610d826d833a", "path": "crates/fractal-api-core/src/api/legacy_handler_guard_tests.rs", "kind": "included-source", "fingerprint": "664d70adeccc63552d83219d6f314b35d4605b9fc9aa834c54c5f078e27e6cdd", "owner": "fractal_api_core::api::legacy_handler_guard_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 18, "excerpt": "include_str ! ( \"runs.rs\" )"}, {"id": "lv-h61152c78e9ef", "path": "crates/smallclaims/src/store/sealed_view_cache_tests/mutation_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "57631b1a4179343162c8e90fe588d3d5894dd5fffcae7871a8894c2eb45ea826", "owner": "smallclaims::store::sealed_view_cache_tests::mutation_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 63, "excerpt": "rusqlite : : params_from_iter ( row . unwrap ( ) )"}, + {"id": "lv-h611b5b2ef9a9", "path": "crates/smallclaims/src/store/assistant_grant_authority_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "00e61e5879bc3ca260fa39bc00b1a5fe489e6d5a1e9a09d06c607f6738388253", "owner": "smallclaims::store::assistant_grant_authority_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 378, "excerpt": "authority : : TRANSITION_QUERY"}, {"id": "lv-h613b05daf268", "path": "crates/fractal-api-core/src/api/agents_request_slo/ledger.rs", "kind": "sql-template", "fingerprint": "d3e10efe4a41b8aa0bb63debcfc8e3ac0cb94399c0aa6866cf162915783e1c06", "owner": "fractal_api_core::api::agents_request_slo::ledger", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 71, "excerpt": "INSERT INTO minute_receipts VALUES (?1, ?2, ?3)"}, {"id": "lv-h6140c9d34075", "path": "crates/smallclaims/src/store.rs", "kind": "sql-template", "fingerprint": "19986eebe3a9173fa46a9514c6e12ec0a7c0e632b1c4857bb392c9f08ddda0c2", "owner": "smallclaims::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 2827, "excerpt": "UPDATE fleet_generation SET value=value+1,trigger_version=?1 WHERE id=1"}, {"id": "lv-h616066b27e8c", "path": "crates/fractal-store/src/store/wake_lookup.rs", "kind": "sql-template", "fingerprint": "259fce15c3099ff88b6e0a4a2ae93c3f2ff0f31eb80ae972b6c95bd0f94a12e0", "owner": "fractal_store::store::wake_lookup", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 143, "excerpt": "INSERT OR IGNORE INTO local_work_wake_tags "}, @@ -2468,6 +2495,7 @@ {"id": "lv-h673570e7b51b", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "c5a0dfd33fdcc5b2350935ffea47d2324f7bc3f67178675cd2dd079fe1ac7014", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 7344, "excerpt": "UPDATE planning_sessions SET status='cancelled', updated_at_unix_ms=?2 WHERE id=?1"}, {"id": "lv-h675571bb6dcc", "path": "crates/fractal-missions/src/store/missions.rs", "kind": "sql-template", "fingerprint": "5d3baa4cb1a6ebdc4527226258f80f2f07dfd1bd8aa4ff43204d68c70a101ee7", "owner": "fractal_missions::store::missions", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 4048, "excerpt": "INSERT INTO idempotency(operation_id, response) VALUES (?1, ?2)"}, {"id": "lv-h67888f2c1780", "path": "crates/fractal-seats/src/store/person_work.rs", "kind": "sql-template", "fingerprint": "c49dc475e365797527b8a198411c5ecae5bdb85a1372fc2069f22526cd81cc19", "owner": "fractal_seats::store::person_work", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 429, "excerpt": "UPDATE desired SET owner_generation='run-generation/old' WHERE subject='subscription/intake'"}, + {"id": "lv-h679dd6776599", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "9f0f6e06ef89765bbeb847263ac45ae34e471d2ab466204ab60d60e6cd9dccc8", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 321, "excerpt": "INSERT INTO assistant_grant_membership_windows(writer,member_key,start,end) VALUES(?1,?2,?3,?4)"}, {"id": "lv-h67b994dca42f", "path": "crates/smallclaims/src/store/projection_digest.rs", "kind": "sql-template", "fingerprint": "016cfb67f1f22de644ed92fdea97c2227aab5b540c6815847a0f02252b998811", "owner": "smallclaims::store::projection_digest", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 174, "excerpt": "DELETE FROM projection_digest_operation_rows"}, {"id": "lv-h67cd460ba33d", "path": "crates/smallclaims/src/store/checkpoint.rs", "kind": "sql-template", "fingerprint": "996753730d02ef5c4350fd87061ee554e215a86673110ceee475e4814dca5f0d", "owner": "smallclaims::store::checkpoint", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 673, "excerpt": "DELETE FROM claims WHERE id NOT IN (SELECT id FROM temp.sealed_claims); DELETE FROM blobs WHERE hash NOT IN (SELECT hash FROM temp.sealed_blobs); DELETE FROM replica_records WHERE NOT EXISTS ( SELECT "}, {"id": "lv-h67d08b9ee5cc", "path": "crates/smallclaims/src/sync/worker_tests.rs", "kind": "sql-template", "fingerprint": "8cb1072302449a5baf37c7c3ca58a673ba8c8d3a0d1f626e613242bceecefc1d", "owner": "smallclaims::sync::worker_tests", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "line_hint": 325, "excerpt": "INSERT INTO checkpoint_envelopes VALUES (?1, ?2, ?3, 0, ?4)"}, @@ -2918,6 +2946,7 @@ {"id": "lv-h80e87fffa918", "path": "crates/fractal-seats/src/store/runtime_starts.rs", "kind": "sql-template", "fingerprint": "9f2d6535131e7215e54df5c384f9df81f409770a0ff328a7c9df9ff06bad607e", "owner": "fractal_seats::store::runtime_starts", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 984, "excerpt": "UPDATE local_runtime_starts SET cleanup_verified=1,result=?2 WHERE id=?1"}, {"id": "lv-h80f54cac496c", "path": "crates/smallclaims/src/ivm.rs", "kind": "sql-template", "fingerprint": "c4a9286f648a6e56ae1dc0e2d4dbbe34367e491fd1c316c2a086bbd9370ad069", "owner": "smallclaims::ivm", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 859, "excerpt": "INSERT INTO ivm_heads VALUES(?1,?2,?3,?4,?5,?6) ON CONFLICT(view,key,register) DO UPDATE SET value=excluded.value,claim_id=excluded.claim_id,rank=excluded.rank"}, {"id": "lv-h80fb3476454f", "path": "crates/fractal-api-client-v0/src/api/client_v0/conversation_blocks/conformance_tests.rs", "kind": "included-source", "fingerprint": "28b8b33224c8fd44f648b926bd65c286c7a6a4b9e64db801836a8c39823b71a3", "owner": "fractal_api_client_v0::api::client_v0::conversation_blocks::conformance_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 35, "excerpt": "include_str ! ( \"../../../../../fractal-daemon/fixtures/native-records/claude.jsonl\" )"}, + {"id": "lv-h80fb9d4725e0", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "unresolved-sql-sink", "fingerprint": "7bac5ebfffac69fd99c3fda6627fe33f1f53d8371f2d4676b31eafe0aed2222d", "owner": "smallclaims::store::assistant_grant_authority", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 149, "excerpt": "TRANSITION_QUERY , params ! [ granted . subject , kind , granted . origin , granted . actor , granted . id ] , | row | row . get ( 0 )"}, {"id": "lv-h810468890407", "path": "crates/fractal-store/src/store/attention_ivm.rs", "kind": "sql-template", "fingerprint": "6b1e1f274ac274db45e76b8ddb5a2b5c2e2f5ec50350f31f172edf3c38a1291a", "owner": "fractal_store::store::attention_ivm", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 125, "excerpt": "CREATE TRIGGER IF NOT EXISTS attention_open_record_{action} AFTER {action} ON replica_records BEGIN INSERT INTO local_attention_open_dirty SELECT family,source FROM local_attention_open_dependencies W"}, {"id": "lv-h810b1410be6a", "path": "crates/fractal-seats/src/store/resource_preparation/tests.rs", "kind": "sql-template", "fingerprint": "238d29ffdf8759d09f6821c6e95f4140738235edeeed9d36863cc4b8c6313423", "owner": "fractal_seats::store::resource_preparation::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 99, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES('invented-unrelated-write',?1)"}, {"id": "lv-h8129930894d4", "path": "crates/fractal-store/src/store/observer_subscription_detail.rs", "kind": "unresolved-sql-sink", "fingerprint": "3742ae7e222e6ca68d223d10fc4c783a1072bf646b9adef513d3053178e1afe1", "owner": "fractal_store::store::observer_subscription_detail", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 113, "excerpt": "DECLARATION_KIND_METADATA_SQL"}, @@ -3328,6 +3357,7 @@ {"id": "lv-h9b3b2893e731", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "8edb630b01a1f78d4abc5ee08b714ce7a8578b35d2269aec45684bf19ac1e4fc", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 5694, "excerpt": "& query"}, {"id": "lv-h9b4924d4a878", "path": "crates/fractal-missions/src/store/missions.rs", "kind": "unresolved-sql-sink", "fingerprint": "f72cc7aca17eb71574b8e970455c1013b67d78da66a206519950483606343b19", "owner": "fractal_missions::store::missions", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 6697, "excerpt": "& canonical_sql ( \"SELECT json_extract(request.body, '$.fields.attempt') FROM claims request WHERE request.subject=?1 AND request.kind='observer.refresh-requested' AND ( json_extract(request.body, '$."}, {"id": "lv-h9b594f38a048", "path": "crates/smallclaims/src/store/schema_install_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "9ff21cc7560331f62097a428335acc6ef7c7c1320dc75b2e3399b991e9c6fceb", "owner": "smallclaims::store::schema_install_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 65, "excerpt": "FRESH_SCHEMA"}, + {"id": "lv-h9b70e51e754e", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "a317ff0bd03a3e2d0c8c1820543b2bbb2e98c7bc46d2b1b238ed9ab39aa11d2b", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 381, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_version',?1)"}, {"id": "lv-h9b93bbbdbb39", "path": "crates/fractal-missions/src/store/lanes.rs", "kind": "unresolved-sql-sink", "fingerprint": "ff9e4ca5b7a4370a3a2d73456bca304f1badd8e2dfe36651c8e8ecadce0e00eb", "owner": "fractal_missions::store::lanes", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 36, "excerpt": "if run . is_some ( ) { \"SELECT subject, kind, body, member, owner_run, owner_generation, owner_step FROM desired WHERE owner_run=?1 AND kind='lane' ORDER BY subject\" } else { \"SELECT subject, kind, bo"}, {"id": "lv-h9bc0d44f925c", "path": "crates/smallclaims/src/store/saved_inventory_tests.rs", "kind": "sql-template", "fingerprint": "b3146e6453d128849b29448d71f9ae9c7fdd07692029bee76e7de8983a3056ac", "owner": "smallclaims::store::saved_inventory_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 488, "excerpt": "UPDATE retired_envelopes SET sequence=sequence+1000000"}, {"id": "lv-h9bdfd18f2c1e", "path": "crates/smallclaims/src/store/checkpoint.rs", "kind": "unresolved-sql-sink", "fingerprint": "b483328b9c557f0e72710de93cd41c3f2ddf18097b08be732c22f42be133659f", "owner": "smallclaims::store::checkpoint", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 426, "excerpt": "params ! [ envelope . writer , envelope . sequence , envelope . envelope_hash ]"}, @@ -3392,6 +3422,7 @@ {"id": "lv-h9f7a9a4c64b4", "path": "crates/fractal-store/src/store/client_messages_version_benchmark.rs", "kind": "sql-template", "fingerprint": "874760f835538f1cbcc1a7f33aeafdb487ae040e8058c319cd322fa5d9f93d23", "owner": "fractal_store::store::client_messages_version_benchmark", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 85, "excerpt": "INSERT INTO local_client_message_retirements VALUES(?1,?2)"}, {"id": "lv-h9f7dd8c2f244", "path": "crates/fractal-missions/src/store/missions.rs", "kind": "sql-template", "fingerprint": "5d3baa4cb1a6ebdc4527226258f80f2f07dfd1bd8aa4ff43204d68c70a101ee7", "owner": "fractal_missions::store::missions", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 6195, "excerpt": "INSERT INTO idempotency(operation_id, response) VALUES (?1, ?2)"}, {"id": "lv-h9f843f0fa9a7", "path": "crates/smallclaims/src/store/claim_ranges.rs", "kind": "unresolved-sql-sink", "fingerprint": "4f8cb79e5ac393d372b2657b7c88374573ce7e8b9925e04ed46391963f64d7a3", "owner": "smallclaims::store::claim_ranges", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 172, "excerpt": "params ! [ namespace , level , range ] , | row | Ok ( ( row . get ( 0 ) ? , row . get ( 1 ) ? ) )"}, + {"id": "lv-h9fa3ab767307", "path": "crates/smallclaims/src/store/assistant_grant_authority_tests.rs", "kind": "sql-template", "fingerprint": "0c0135e37b8c8426226294d2e889a67b3fcee6cdcbeee87c3730db061370af1f", "owner": "smallclaims::store::assistant_grant_authority_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 310, "excerpt": "DELETE FROM assistant_grant_effective; DELETE FROM assistant_grant_authority; DELETE FROM assistant_grant_pending; DELETE FROM assistant_grant_membership_windows; DELETE FROM assistant_grant_dirty; DE"}, {"id": "lv-h9fa7391642d7", "path": "crates/fractal-store/src/store/client_messages_version_benchmark.rs", "kind": "sql-template", "fingerprint": "46db6a9419469250dcd8859423aca12166196ff25b8a23dded0eab5355a633be", "owner": "fractal_store::store::client_messages_version_benchmark", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 118, "excerpt": "DELETE FROM local_client_message_pending WHERE subject=?1"}, {"id": "lv-h9fafc13e1337", "path": "crates/fractal-seats/src/store/ordered_membership_tests.rs", "kind": "sql-template", "fingerprint": "18770fd2b3c20d091bec930d5970dbad5c82d3a96814e764687c73c56aa09a5c", "owner": "fractal_seats::store::ordered_membership_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1216, "excerpt": "DROP TRIGGER migration_failure"}, {"id": "lv-h9fd311aebf47", "path": "crates/fractal-secrets/src/sekrets/store.rs", "kind": "sql-template", "fingerprint": "aabb28027a022832784fb45263470e6e81ee081a7b14dfac124cdaf97c5e423b", "owner": "fractal_secrets::sekrets::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 298, "excerpt": "UPDATE profiles SET policy = ?2, updated_at = ?3 WHERE id = ?1"}, @@ -3422,6 +3453,7 @@ {"id": "lv-ha1358f6db412", "path": "crates/fractal-store/src/store/seats.rs", "kind": "unresolved-sql-sink", "fingerprint": "293e064325d0ba33755c39a24e45995485b87aa0ed01c76d07035290e8b1cd4c", "owner": "fractal_store::store::seats", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 199, "excerpt": "params ! [ agent , snapshot_index ] , | row | row . get ( 0 )"}, {"id": "lv-ha13d8dc7b51f", "path": "crates/fractal-seats/src/store/runtime_starts.rs", "kind": "sql-template", "fingerprint": "4a45978cde4f683e0fdcb5308930ea6938a04a66f039e3a1a0ffcc3eddf92e84", "owner": "fractal_seats::store::runtime_starts", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 596, "excerpt": "UPDATE local_runtime_starts SET receipted=1,result=?2 WHERE id=?1"}, {"id": "lv-ha1440c494a1a", "path": "crates/smallclaims/src/store/fleet_residue_page_tests.rs", "kind": "sql-template", "fingerprint": "76cad149e9b1d0b9bbfea871682966e89877b3cf04b700314233de08d894541f", "owner": "smallclaims::store::fleet_residue_page_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 35, "excerpt": "INSERT INTO replica_envelope_signatures(writer, sequence, envelope_hash, member_key, signature, stored_at_unix_ms) VALUES (?1, ?2, ?3, ?4, 'invented-signature', '0')"}, + {"id": "lv-ha14d9df71ca8", "path": "crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "c21c486aaa244d81e150531b070c9489f8f2cbc0d3cf66a1cdf9e427de233205", "owner": "fractal_api_core::api::client_v0::external_grants::conflict_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 497, "excerpt": "& format ! ( \"EXPLAIN QUERY PLAN {}\" , authority : : CANDIDATES_QUERY )"}, {"id": "lv-ha160f037c55f", "path": "crates/smallclaims/src/ivm/install/capture.rs", "kind": "sql-template", "fingerprint": "d4dd943ea549c2f400559f9a810680397025d94d44a4d5aabde93aa942ceacd3", "owner": "smallclaims::ivm::install::capture", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 249, "excerpt": "UPDATE ivm_install_sources SET available=0 WHERE name={source}; \\ UPDATE ivm_install_roots SET ready=0,status_revision=status_revision+1,error='{reason}' \\ WHERE source={source} AND (ready<>0 OR error"}, {"id": "lv-ha175ed71501d", "path": "crates/fractal-store/src/store/tests.rs", "kind": "sql-template", "fingerprint": "8b44a9e15237b4de2b3c2a997349101e17eacf47a1cf262d6f0d9928dc1466e2", "owner": "fractal_store::store::tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 6784, "excerpt": "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) VALUES ('legacy-batch','legacy-seek',1,'synthetic','1')"}, {"id": "lv-ha1763c1a36dd", "path": "crates/fractal-reconcile/src/reconcile/github_plugin_store.rs", "kind": "sql-template", "fingerprint": "543f2982cbbb7bfed04e5e099facbb070025ddf5d130c7303f1aa052c919f0cb", "owner": "fractal_reconcile::reconcile::github_plugin_store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 132, "excerpt": "CREATE TABLE IF NOT EXISTS plugin_meta(key TEXT PRIMARY KEY, value TEXT NOT NULL) WITHOUT ROWID;"}, @@ -3464,6 +3496,7 @@ {"id": "lv-ha38a74be9319", "path": "crates/fractal-store/src/store/message_outbox.rs", "kind": "unresolved-sql-sink", "fingerprint": "2b86ef06cf9adb398c237f395acdec24b8930ec25fe776801420ce02f13e4afd", "owner": "fractal_store::store::message_outbox", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 84, "excerpt": "[ ] , | row | Ok ( ( row . get ( 0 ) ? , row . get ( 1 ) ? ) )"}, {"id": "lv-ha39be727e750", "path": "crates/fractal-missions/src/store/tests.rs", "kind": "sql-template", "fingerprint": "1ba4fdc8a1dd62bd2c17727a28457739c7e5ece1cdea20fcb2f65af8bd592bf3", "owner": "fractal_missions::store::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 2792, "excerpt": "DELETE FROM operations WHERE id='op/unrelated-upgrade'"}, {"id": "lv-ha3b0673506b4", "path": "crates/smallclaims/src/store/claim_ranges.rs", "kind": "sql-template", "fingerprint": "82eb9025577e1eed06a310c640b88462364d1b4eaf4cdbfffa34a5ab77b0e25f", "owner": "smallclaims::store::claim_ranges", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 358, "excerpt": "DELETE FROM retired_range_import"}, + {"id": "lv-ha3bce0201694", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "3720b2c9c1d102e26014cd421ffc58cc6d8653b01c59abb3fc1865a04e90586a", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 327, "excerpt": "DELETE FROM meta WHERE key='assistant_grant_authority_fleet_id'"}, {"id": "lv-ha3c5feea65a0", "path": "crates/smallclaims/src/store/principals.rs", "kind": "unresolved-sql-sink", "fingerprint": "d709c4b53198c61961b802ca03f38a23581d22fd1bf987e8b7f03393be1b2d50", "owner": "smallclaims::store::principals", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 220, "excerpt": "[ claim_id ] , | row | row . get ( 0 )"}, {"id": "lv-ha3d4449c40cb", "path": "crates/smallclaims/src/store/saved_inventory_tests.rs", "kind": "sql-template", "fingerprint": "cacab32515e03b567c70397405b17c7a16e0a55e7c353cd8aa28c83e35587eba", "owner": "smallclaims::store::saved_inventory_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 445, "excerpt": "DELETE FROM replica_envelopes WHERE rowid=(SELECT MIN(rowid)+1 FROM replica_envelopes)"}, {"id": "lv-ha3ee7bbe9a8e", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "f10e20728e77f302935d7b4f1031c77dca8743a680305ee8cdf2f818e584bbb5", "owner": "fractal_store::store::resources_preparation_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 447, "excerpt": "\"ROLLBACK\""}, @@ -3658,6 +3691,7 @@ {"id": "lv-hb13e43c5dd77", "path": "crates/smallclaims/src/store/checkpoint.rs", "kind": "unresolved-sql-sink", "fingerprint": "b2cbbe76784ce7e1e5c37479f1d38c960c8035dd74974ae04e0aad4649d0dc87", "owner": "smallclaims::store::checkpoint", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1012, "excerpt": "\"BEGIN IMMEDIATE\""}, {"id": "lv-hb1556feaa1e5", "path": "crates/fractal-secrets/src/sekrets/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "1f955dfa59b790d855c4591bb24f78d51a668cb0b16f48b7fa6e56011f3e3fa7", "owner": "fractal_secrets::sekrets::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 385, "excerpt": "& format ! ( \"SELECT id, profile, grantee, policy, until_ms, granted_by, created_at FROM grants WHERE {condition} ORDER BY created_at\" )"}, {"id": "lv-hb16ae5c869ea", "path": "crates/fractal-missions/src/store/work_list.rs", "kind": "unresolved-sql-sink", "fingerprint": "43e32be2fa928193cbeb175d2a9abb1d55f1a8848755a28b58c8ed362456aa58", "owner": "fractal_missions::store::work_list", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 229, "excerpt": "params ! [ subject , time . min ( i64 : : MAX as u128 ) as i64 ] , | row | row . get : : < _ , Option < i64 > > ( 0 )"}, + {"id": "lv-hb16dbad8dff5", "path": "crates/smallclaims/src/store/assistant_grant_authority_bench.rs", "kind": "unresolved-sql-sink", "fingerprint": "4e7cdbc299b188ecd16a440f84f10784cb0c142287d57bf1d90db18be28c27d8", "owner": "smallclaims::store::assistant_grant_authority_bench", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 231, "excerpt": "params ! [ id , format ! ( \"batch/{writer}/{sequence:064x}\" ) , format ! ( \"custom/client/assistant-v1-{group:024x}\" ) , kind , writer , \"person/perf-operator\" , body ]"}, {"id": "lv-hb1717289cd89", "path": "crates/fractal-missions/src/store/authored_pull_requests_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "8edb630b01a1f78d4abc5ee08b714ce7a8578b35d2269aec45684bf19ac1e4fc", "owner": "fractal_missions::store::authored_pull_requests_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 232, "excerpt": "& query"}, {"id": "lv-hb17751306672", "path": "crates/fractal-daemon/src/store_tests/attention_ivm.rs", "kind": "sql-template", "fingerprint": "701c72a8841369cec4d767840eb848e6f3a33f442b4485c19a405fb0f5b49af3", "owner": "fractal_daemon::store_tests::attention_ivm", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 371, "excerpt": "UPDATE mission_runs SET status=?1 WHERE id=?2"}, {"id": "lv-hb17e92309d45", "path": "crates/fractal-missions/src/store/tests.rs", "kind": "sql-template", "fingerprint": "14b883e4cfc79305d3b6eb6756468eb767f78986e417bccebc61a53343aae959", "owner": "fractal_missions::store::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 2891, "excerpt": "UPDATE step_runs SET blocked_reason=?2, updated_at_unix_ms=?3 WHERE subject=?1"}, @@ -3867,6 +3901,7 @@ {"id": "lv-hbccafe49f0c6", "path": "crates/smallclaims/src/store/document_pages/tests.rs", "kind": "sql-template", "fingerprint": "cdd3366bff427d7d30bd4c90a4ebfb14fe5b958d0f651945f2e42b4fb7e182aa", "owner": "smallclaims::store::document_pages::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 580, "excerpt": "DELETE FROM blobs WHERE hash=(SELECT hash FROM documents WHERE name='doc/b')"}, {"id": "lv-hbcd207df08b2", "path": "crates/fractal-api-client-v0/src/api/client_v0/collection_refresh_tests.rs", "kind": "included-source", "fingerprint": "5d604bf3342897bb94342ddbdbe8296d87ee778849bee124dd73f3c81b8f6a26", "owner": "fractal_api_client_v0::api::client_v0::collection_refresh_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 475, "excerpt": "include_str ! ( \"../../../../../examples/fractal/custom-review.json\" )"}, {"id": "lv-hbcda5cda38a1", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "2076c92ab7648083e19f0874b156fbee36adb6774511b383280784ae93c3a198", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 11176, "excerpt": "params ! [ subject , at_index , incarnation ] , | row | { Ok ( ( row . get : : < _ , String > ( 0 ) ? , row . get : : < _ , String > ( 1 ) ? , row . get : : < _ , String > ( 2 ) ? ) ) }"}, + {"id": "lv-hbcecffaa18c4", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "59b734a2259b26d6458db2efea75a900c7196fc0e9af09840efca58d8e4344e7", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 329, "excerpt": "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_membership_generation',?1)"}, {"id": "lv-hbcf472355ed4", "path": "crates/fractal-store/src/store/tests.rs", "kind": "sql-template", "fingerprint": "7ba5fc50258bff63918434640c5d3c0e6932c4c11c5e8d7694ea7e332adfab42", "owner": "fractal_store::store::tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 10593, "excerpt": "UPDATE replica_records SET position=0 WHERE claim_id='record-a'"}, {"id": "lv-hbd02e2691590", "path": "crates/fractal-store/src/store/directive_notes.rs", "kind": "sql-template", "fingerprint": "f439a6bb27016c148358ff8c7764258adfa714a95ed1433b1c23be72742801b6", "owner": "fractal_store::store::directive_notes", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 175, "excerpt": "DELETE FROM person_directive_notes WHERE person=?1"}, {"id": "lv-hbd09a1c36932", "path": "crates/fractal-store/src/store/backup.rs", "kind": "sql-template", "fingerprint": "b6bfc1df536126466dd5634f1d548532b4b7ac16da8cb9a1377e77dccdf2040a", "owner": "fractal_store::store::backup", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 514, "excerpt": "INSERT OR IGNORE INTO replica_restore_quarantine(writer,sequence,envelope_hash) SELECT writer,sequence,envelope_hash FROM replica_envelopes WHERE batch_id IS NULL"}, @@ -3965,7 +4000,6 @@ {"id": "lv-hc1a7495dab62", "path": "crates/fractal-missions/src/store/mission_list.rs", "kind": "unresolved-sql-sink", "fingerprint": "be824f83b40fb6e1bfa945556ae9be449d492a6e6edd8c5fec6f70c7ce2522da", "owner": "fractal_missions::store::mission_list", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 192, "excerpt": "published_list : : CLAIMS_SINCE"}, {"id": "lv-hc1ac3d35bbf4", "path": "crates/fractal-store/src/store/client_messages.rs", "kind": "sql-template", "fingerprint": "b00efd86cc227528fbfa988943c50c7bc8f88c73ef6908072ddf7ed7cac1bc74", "owner": "fractal_store::store::client_messages", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1253, "excerpt": "DELETE FROM meta WHERE key=?1"}, {"id": "lv-hc1b4b7df7d60", "path": "crates/smallclaims/src/sqlite.rs", "kind": "unresolved-sql-sink", "fingerprint": "ce922519a3c3ecaf9b0986c2449c7680895c15f4b0e9818e994e14a4d28b6aaf", "owner": "smallclaims::sqlite", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 929, "excerpt": "transaction"}, - {"id": "lv-hc1c46de6a890", "path": "crates/fractal-api-core/src/api/client_v0/external_grants.rs", "kind": "unresolved-sql-sink", "fingerprint": "b7eafcbb01a79e6feb02839905b41bafc8a5be2f355d21ab6b4b392a34092eac", "owner": "fractal_api_core::api::client_v0::external_grants", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 139, "excerpt": "& QUERY"}, {"id": "lv-hc1c6ea0cb228", "path": "crates/fractal-store/src/store/terminal_gate_evidence/native_source_tests_shared.rs", "kind": "sql-template", "fingerprint": "740d295c2a21b85f7e9f3cfc6e07c1cddb61c6d0698f1d79e9cb732ef1e0c259", "owner": "fractal_store::store::terminal_gate_evidence::native_source_tests_shared", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 87, "excerpt": "WITH RECURSIVE pages(n) AS (SELECT 0 UNION ALL SELECT n+1 FROM pages WHERE n<(?1-1)/64) INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) SELECT 'foreign-page/'||n,'node',1000+n"}, {"id": "lv-hc1db65df6dce", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "f364d8ca6168ffa8cad7d686c9cbe491d919c3fcdda7ba967af6912aaffb62ae", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 5612, "excerpt": "& format ! ( \"{} LIMIT 1\" , newest_claims_of_kind_query ( \"claims.origin\" , \"runtime.observed\" ) )"}, {"id": "lv-hc1e68820d94d", "path": "crates/smallclaims/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "789b44b9990c7d88da3542aa5c6b25148409a57d64b88f00362513cda78a031f", "owner": "smallclaims::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1084, "excerpt": "\"COMMIT\""}, @@ -4205,6 +4239,7 @@ {"id": "lv-hd0fb382d248c", "path": "crates/smallclaims/src/store/inventory_generation.rs", "kind": "sql-template", "fingerprint": "38f157a103e70a321714005616154c97da0299a4e79af3f5c7272ecc69175f7a", "owner": "smallclaims::store::inventory_generation", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 39, "excerpt": "DROP TRIGGER IF EXISTS replica_envelopes_inventory_DELETE; DROP TRIGGER IF EXISTS retired_envelopes_inventory_INSERT;"}, {"id": "lv-hd107c49c5ec5", "path": "crates/smallclaims/src/store/checkpoint.rs", "kind": "unresolved-sql-sink", "fingerprint": "d4bcd0e8289806d29ea3468fbf684a0ea3ecfafbb50f43dac8391654ec79994a", "owner": "smallclaims::store::checkpoint", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 659, "excerpt": "& format ! ( \"PRAGMA foreign_keys = ON; PRAGMA journal_mode = DELETE; PRAGMA synchronous = OFF; PRAGMA cache_size = -{}; PRAGMA temp_store = FILE; PRAGMA mmap_size = 0;\" , crate : : sqlite : : READ_CA"}, {"id": "lv-hd1113350febe", "path": "crates/fractal-seats/src/store/runtime_starts.rs", "kind": "unresolved-sql-sink", "fingerprint": "8a0796eb8b3f4bcf14acf21104e92a39ba18db72dd5ac1da36227c90570fa780", "owner": "fractal_seats::store::runtime_starts", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 127, "excerpt": "& format ! ( \"SELECT EXISTS(SELECT 1 FROM claims WHERE subject=?1 AND store_index>?2 AND {UNREPAIRED_CLAIM} AND (kind IN ('intent.desired','agent.retired') OR (kind='runtime.action.requested' AND json"}, + {"id": "lv-hd11f3b7cf006", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "a0c1c2bdea18e42c2b40753672c0f672b89b2f55ac137f39f90ff6421e334a22", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 319, "excerpt": "DELETE FROM assistant_grant_membership_windows"}, {"id": "lv-hd12f188a255d", "path": "crates/fractal-store/src/store/wake_lookup.rs", "kind": "sql-template", "fingerprint": "259fce15c3099ff88b6e0a4a2ae93c3f2ff0f31eb80ae972b6c95bd0f94a12e0", "owner": "fractal_store::store::wake_lookup", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 96, "excerpt": "INSERT OR IGNORE INTO local_work_wake_tags "}, {"id": "lv-hd12fc35f6d00", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "afaccaf8ae10f01b753133c980c7791ff8e2e88a493ff536a5613027a2689744", "owner": "fractal_store::store::resources_preparation_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1507, "excerpt": "INSERT OR IGNORE INTO local_resource_preparation_deferred(subject) SELECT DISTINCT subject FROM local_resource_preparation_claims"}, {"id": "lv-hd14808d55e0c", "path": "crates/fractal-store/src/store/run_eta_tests.rs", "kind": "sql-template", "fingerprint": "53afe3fff8e50a5f9ebbff8644450b5f113ca6f5a2ad7dce9e4eda0795eb62e2", "owner": "fractal_store::store::run_eta_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 324, "excerpt": "INSERT INTO meta VALUES('run_eta_samples_v3','1')"}, @@ -4329,9 +4364,7 @@ {"id": "lv-hd7cd14b1d0a5", "path": "crates/fractal-store/src/store/message_send_tests.rs", "kind": "sql-template", "fingerprint": "5f2be0ab50a9c7514f427efb36cc8f4cab6feabfe7dc0f4ad8664f1ce605e815", "owner": "fractal_store::store::message_send_tests", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "line_hint": 31, "excerpt": "INSERT INTO checkpoint_claims(id,writer,sequence,envelope_hash,subject,kind, actor,predecessors,operation_id,request_digest,accepted_at_unix_ms,checkpoint) VALUES (?1,'invented-peer',1,'invented-envel"}, {"id": "lv-hd7d92523e785", "path": "crates/smallclaims/src/store/saved_inventory_tests.rs", "kind": "sql-template", "fingerprint": "c7ccec23366bfe885531ec8fdde089ce526c3d76ef218b6d0afc93adef29effd", "owner": "smallclaims::store::saved_inventory_tests", "todo": "stage-generation-and-keyed-reclamation", "disposition": "allow-for-now", "line_hint": 332, "excerpt": "INSERT OR IGNORE INTO checkpoint_envelopes(writer, sequence, envelope_hash, accepted_at_unix_ms, checkpoint) SELECT writer, sequence, envelope_hash, 0, 'invented-checkpoint' FROM replica_envelopes WHE"}, {"id": "lv-hd7dc4a36d272", "path": "crates/fractal-store/src/store/observer_actuals_tests.rs", "kind": "sql-template", "fingerprint": "7919957e727355f6fb0d09b92990cdf4ea28b80a15928f645c46e77cfb73c16f", "owner": "fractal_store::store::observer_actuals_tests", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 149, "excerpt": "DROP TABLE projection_digest_repaired_claims; CREATE TABLE projection_digest_repaired_claims(id TEXT PRIMARY KEY) WITHOUT ROWID;"}, - {"id": "lv-hd7de403d2fec", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "4d8a6bbe014853cbe11e445c1907fe84a96a76af631ac6f2514b435e746f324b", "owner": "fractal_store::store", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 788, "excerpt": " -- An unmanaged member's staging check needs tagged claims, not its runtime history. CREATE INDEX IF NOT EXISTS claims_owned_set_subject_index ON claims(subject) WHERE json_extract(body,'$.owned_set'"}, {"id": "lv-hd81a35b60f28", "path": "crates/fractal-api-core/src/api/client_messages_selector_tests.rs", "kind": "sql-template", "fingerprint": "9c1fd01759a0c066cfad05fc874a449588b618537e42c1dea36b70408ae95d56", "owner": "fractal_api_core::api::client_messages_selector_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 661, "excerpt": "UPDATE claims SET accepted_at_unix_ms=?2 WHERE subject=?1"}, - {"id": "lv-hd82c937baff5", "path": "crates/fractal-store/src/store/assistant_write.rs", "kind": "unresolved-sql-sink", "fingerprint": "874d4bf9cc46459a8b33435bb94abd6e2ae2362af60e84eacd179a1e2df2e8c6", "owner": "fractal_store::store::assistant_write", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 23, "excerpt": "& latest_claim_of_kind_query ( ) , params ! [ authorization . grant_subject , kind ] , claim_from_row"}, {"id": "lv-hd82cb2e4adf3", "path": "crates/fractal-api-core/src/api/legacy_handler_guard_tests.rs", "kind": "included-source", "fingerprint": "4e162be3f4be5a1bddabf31677419af51c1d5244c05521c685b551bcc21c0f36", "owner": "fractal_api_core::api::legacy_handler_guard_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 12, "excerpt": "include_str ! ( \"fleet.rs\" )"}, {"id": "lv-hd836545d0082", "path": "crates/fractal-delivery/src/store/tests.rs", "kind": "included-source", "fingerprint": "cd041a3f61b0baccaae454bd37e1d75fb0baddc785bc2992956f46a2b7d36015", "owner": "fractal_delivery::store::tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 648, "excerpt": "include ! ( \"projection_divergence_tests.rs\" )"}, {"id": "lv-hd8377ae3baea", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "505b9c4be459d6167de2e61b0d907f0fa29386577c5b21d8fc7f763faf0a4b28", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 3935, "excerpt": "DELETE FROM client_diagnostic_receipts WHERE accepted_at_unix_ms < ?1"}, @@ -4350,6 +4383,7 @@ {"id": "lv-hd90855b784ec", "path": "crates/fractal-seats/src/store/person_work.rs", "kind": "sql-template", "fingerprint": "eb207d596ec59bc493d0c0f7a9ca5d5de2a1af27479241c11d1986b43149fb18", "owner": "fractal_seats::store::person_work", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 443, "excerpt": "UPDATE mission_runs SET parent_step_run=?1 WHERE id=?2"}, {"id": "lv-hd90aa6430548", "path": "crates/fractal-store/src/store/slo_breaches.rs", "kind": "sql-template", "fingerprint": "70fe1777cd6c7e0e27218378e26f3923783edaa8c769e19186fd8903f1ddabc1", "owner": "fractal_store::store::slo_breaches", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 102, "excerpt": "UPDATE slo_episode_events SET conflict=1 WHERE episode=?1"}, {"id": "lv-hd90d9bade9c2", "path": "crates/fractal-store/src/store/runtime_starts.rs", "kind": "sql-template", "fingerprint": "22605d1e8cf77972d57b472c576fdb06dbcadb71c45d7187e03ed889def646a4", "owner": "fractal_store::store::runtime_starts", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 18, "excerpt": "DROP TRIGGER IF EXISTS local_runtime_starts_observation_insert; DROP TRIGGER IF EXISTS local_runtime_starts_observation_update; DROP TRIGGER IF EXISTS local_runtime_starts_observation_delete;"}, + {"id": "lv-hd91341d01a91", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "76c974fbbff4b942b7f7c3ccbeecca6927f4ea15b252083fddd6622385ad1d34", "owner": "smallclaims::store::assistant_grant_authority", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 376, "excerpt": "DELETE FROM assistant_grant_dirty WHERE claim_id=?1"}, {"id": "lv-hd925b5785834", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "49a38fe3d64b04fd70ffc23d73e15302912dc466a2598a132eb8872d6db08c08", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 16236, "excerpt": "& canonical_sql ( & format ! ( \"SELECT claims.id FROM claims JOIN batches ON batches.id=claims.batch_id WHERE {filter} ORDER BY CANONICAL_ASC(claims)\" ) )"}, {"id": "lv-hd92c67f5da38", "path": "crates/smallclaims/src/store/checkpoint_staging.rs", "kind": "unresolved-sql-sink", "fingerprint": "c32b884bb11aa9d33ad9fa5b6cbd7b18be6b5eec40e5397aa0319a5e4069ab0d", "owner": "smallclaims::store::checkpoint_staging", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 694, "excerpt": "& sql"}, {"id": "lv-hd930b07a6e79", "path": "crates/fractal-reconcile/src/reconcile/tests/incremental_deadlines.rs", "kind": "sql-template", "fingerprint": "048587c14ce8e3a7ab847e1da009c98675c1f0808dde80d4d3c80c75c76375d6", "owner": "fractal_reconcile::reconcile::tests::incremental_deadlines", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 802, "excerpt": "UPDATE claims SET origin='other' WHERE id=?1"}, @@ -4574,6 +4608,7 @@ {"id": "lv-he6dafe2f904c", "path": "crates/smallclaims/src/ivm.rs", "kind": "sql-template", "fingerprint": "43a2a96ce900b14f48d3932a6f247c6171e534fbc991c429d380e7d66c1f29e8", "owner": "smallclaims::ivm", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 984, "excerpt": "UPDATE ivm_views SET generation=generation+1 WHERE name=?1"}, {"id": "lv-he6e3040252e3", "path": "crates/fractal-api-client-v0/src/api/client_v0/observer_subscription_detail_tests.rs", "kind": "sql-template", "fingerprint": "b41394c6c4f6b2c1747aeaa99b81f93fb2a537c86162ddb3d360dab2d95dd496", "owner": "fractal_api_client_v0::api::client_v0::observer_subscription_detail_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 668, "excerpt": "UPDATE desired SET kind={value} WHERE subject=?1"}, {"id": "lv-he7052689cff7", "path": "crates/smallclaims/src/store/checkpoint_staging.rs", "kind": "sql-template", "fingerprint": "3821719cd9da9c7336b0bc4df86f909befb861c0beebc5f63ddb5497dd3a5579", "owner": "smallclaims::store::checkpoint_staging", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1119, "excerpt": "UPDATE meta SET plan=NULL WHERE id=1"}, + {"id": "lv-he7097c5f9f00", "path": "crates/smallclaims/src/store/assistant_grant_authority_bench.rs", "kind": "unresolved-sql-sink", "fingerprint": "8f1648973b28ab5e33a7254240167db3677700efe789c003da0e7c71932e4dab", "owner": "smallclaims::store::assistant_grant_authority_bench", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 203, "excerpt": "params ! [ format ! ( \"batch/{writer}/{sequence:064x}\" ) , writer , sequence , format ! ( \"{sequence:064x}\" ) ]"}, {"id": "lv-he71c6d4b5146", "path": "crates/fractal-store/src/store/publication.rs", "kind": "unresolved-sql-sink", "fingerprint": "3f8cb55af03d968c76e4e14012a507b40064cf016cc1c8cf24e587130b4a566a", "owner": "fractal_store::store::publication", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 59, "excerpt": "params ! [ subject , incarnation , at . min ( i64 : : MAX as u64 ) ] , | row | Ok ( ( row . get ( 0 ) ? , row . get ( 1 ) ? ) ) ,"}, {"id": "lv-he72846cf8338", "path": "crates/fractal-store/src/store/client_messages_version_benchmark.rs", "kind": "sql-template", "fingerprint": "c1764ab7a9266fda9025a5f79f04b789a5656be1d484ab50ab1550523ea467fc", "owner": "fractal_store::store::client_messages_version_benchmark", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 71, "excerpt": "INSERT OR IGNORE INTO meta VALUES('client_message_versions_v1','1')"}, {"id": "lv-he73f474f2f5d", "path": "crates/fractal-missions/src/store/mission_list.rs", "kind": "unresolved-sql-sink", "fingerprint": "297dc9bb78c36c199b4f862e8ebe262a51188b956f146a24aca3866d0fd445d3", "owner": "fractal_missions::store::mission_list", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 308, "excerpt": "[ now . min ( i64 : : MAX as u128 ) as i64 ] , | row | row . get : : < _ , Option < i64 > > ( 0 )"}, @@ -4613,6 +4648,7 @@ {"id": "lv-he971517b6456", "path": "crates/fractal-seats/src/store/resource_preparation/tests.rs", "kind": "sql-template", "fingerprint": "7e53d4e6c6feeda8ad76e8845caf105faef898a062d3cfadd100195493502042", "owner": "fractal_seats::store::resource_preparation::tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 245, "excerpt": "DROP VIEW temp.claims; CREATE TEMP TRIGGER invented_replay_trigger AFTER INSERT ON heal_replay_base_order BEGIN SELECT 1; END;"}, {"id": "lv-he9754fb25c5a", "path": "crates/fractal-attention/src/store/alert_action_controls.rs", "kind": "sql-template", "fingerprint": "f7eee9a8920111e3326b09d284281d362715dc916c127be5d139b2a4d2e65433", "owner": "fractal_attention::store::alert_action_controls", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 125, "excerpt": "UPDATE claims SET body=?1 WHERE id=?2"}, {"id": "lv-he97b2ef96bf2", "path": "crates/fractal-store/src/store.rs", "kind": "sql-template", "fingerprint": "8a75efb30a29d6d965390a9710b9293ecbf73f5b42e853194b830da1fd893cc3", "owner": "fractal_store::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 19963, "excerpt": "UPDATE run_generations SET status='cancelled', updated_at_unix_ms=?2 WHERE id=?1"}, + {"id": "lv-he990dace4c7d", "path": "crates/smallclaims/src/store/assistant_grant_authority_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "c4079dd19e8cdd2eee55384e6338bacdceca260b06f63e10f9236d2d584f9b55", "owner": "smallclaims::store::assistant_grant_authority_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 391, "excerpt": "authority : : CANDIDATES_QUERY"}, {"id": "lv-he9952e40d06d", "path": "crates/fractal-store/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "c7dfdc3363384623a8282c520234206912bac531669ec4c535c72628eaa50d12", "owner": "fractal_store::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 10984, "excerpt": "& canonical_sql ( \"SELECT id FROM claims WHERE actor=?1 AND kind IN ('work.claimed','work.progress') AND json_extract(body, '$.fields.claim_incarnation')=?2 ORDER BY CANONICAL_DESC(claims) LIMIT 1\" , "}, {"id": "lv-he996de9029f4", "path": "crates/smallclaims/src/ivm/asynchronous.rs", "kind": "sql-template", "fingerprint": "56eada200b8be71674b5473350faea1367170c05f744f19743f8a9d9343480bb", "owner": "smallclaims::ivm::asynchronous", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 217, "excerpt": "INSERT INTO ivm_async_views(view,fingerprint,epoch,through) VALUES(?1,?2,?3,0)"}, {"id": "lv-he9a920ead8a9", "path": "crates/fractal-missions/src/store/missions.rs", "kind": "sql-template", "fingerprint": "ad698369cc3b79c3e7633a3b21b63ac7fb277e328a1207caf2dc4c4f8a963291", "owner": "fractal_missions::store::missions", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 3859, "excerpt": "UPDATE mission_runs SET status=?2, updated_at_unix_ms=?3 WHERE id=?1"}, @@ -4706,6 +4742,7 @@ {"id": "lv-heed36338c56e", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "sql-template", "fingerprint": "cb38c898cec3b14bce43b8bf47c7542985d1ff9eb881fdd6c785e1cabc42cecf", "owner": "fractal_store::store::resources_preparation_tests", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 174, "excerpt": "UPDATE claims SET body=?2 WHERE id=?1"}, {"id": "lv-hef0985e2aacf", "path": "crates/fractal-store/src/store/custom.rs", "kind": "unresolved-sql-sink", "fingerprint": "a8b771920b8319e47251d1360f5e880bc18e8d329b0f0d003ea3c7e615558947", "owner": "fractal_store::store::custom", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 840, "excerpt": "query"}, {"id": "lv-hef1ca5e8b2ef", "path": "crates/smallclaims/src/store.rs", "kind": "sql-template", "fingerprint": "9c328854313763122be0eab82207bdcddc4676deda0f6ac59cad2fb5aa414ec0", "owner": "smallclaims::store", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 6340, "excerpt": "INSERT INTO meta(key, value) VALUES ('shard_id', ?1)"}, + {"id": "lv-hef28dd74e68f", "path": "crates/smallclaims/src/store/assistant_grant_authority_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "112e4c9f0297f565a39caeb58f8e58ced46a719665c4e419f19d5c53c4e89d26", "owner": "smallclaims::store::assistant_grant_authority_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 101, "excerpt": "& format ! ( \"SELECT {CLAIM_COLUMNS} FROM claims ORDER BY store_index\" )"}, {"id": "lv-hef32a1c268dd", "path": "crates/fractal-store/src/store/actual_state_sorter_tests.rs", "kind": "sql-template", "fingerprint": "991c69e9f205f5b48c60cf3231678ac04e9a4e0dc8c97c3e4bc3ca0509917727", "owner": "fractal_store::store::actual_state_sorter_tests", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 322, "excerpt": "INSERT INTO batches(id,origin,replica_sequence,previous_hash,hash,accepted_at_unix_ms) VALUES ('batch/alder/sorter','alder',1,NULL,'sorter','1')"}, {"id": "lv-hef3380e725e2", "path": "crates/fractal-store/src/store/observation_trim_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "ee866b77fcb9d08f8feb50959f83986d62bb9ee9d66a71f884e33517f9f86d89", "owner": "fractal_store::store::observation_trim_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 139, "excerpt": "DELETE_BEFORE , params ! [ cutoff , 5 _000 ]"}, {"id": "lv-hef35bc5b6b76", "path": "crates/fractal-drivers/src/harness_events.rs", "kind": "sql-template", "fingerprint": "fcfda00e5be3718e3eeab3867141a16142b75f49bf2c7ca7ec8034a111cdca3e", "owner": "fractal_drivers::harness_events", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 510, "excerpt": "INSERT INTO metadata VALUES ('expired-state',?1) ON CONFLICT(key) DO UPDATE SET value=excluded.value"}, @@ -4783,7 +4820,6 @@ {"id": "lv-hf3fb4eeb2031", "path": "crates/fractal-store/src/store/reconcile_work_context.rs", "kind": "unresolved-sql-sink", "fingerprint": "4b39b2329c698b4987e15023a3bbd523e95d4058dbbeb479d074f26ff0ac694f", "owner": "fractal_store::store::reconcile_work_context", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 227, "excerpt": "DEFINITIONS"}, {"id": "lv-hf3fd5d1f383c", "path": "crates/smallclaims/src/store/repair_operation_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "fec187433c4f392fddb9c0d1400a095648f252e10b441a3cf1058bac6f7d78d9", "owner": "smallclaims::store::repair_operation_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1096, "excerpt": "SCHEMA"}, {"id": "lv-hf41fabef76b6", "path": "crates/smallclaims/src/store/checkpoint_agreement.rs", "kind": "sql-template", "fingerprint": "0ffd6f6cf65077624de24ce755a746fb82c2b9795a1ab03ab03a0d385e43add2", "owner": "smallclaims::store::checkpoint_agreement", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1264, "excerpt": "INSERT INTO temp.write_clock(offset_ms, at_ms) VALUES (0, ?1)"}, - {"id": "lv-hf4201606586b", "path": "crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "412c0c2f9ba50d78b84d6a1f379e285a435a7c6c05e777851130e01716e85c3c", "owner": "fractal_api_core::api::client_v0::external_grants::conflict_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 384, "excerpt": "& format ! ( \"EXPLAIN QUERY PLAN {ADMISSION_QUERY}\" )"}, {"id": "lv-hf42544a3dbab", "path": "crates/smallclaims/src/store.rs", "kind": "sql-template", "fingerprint": "bfd7b32544dc98049f94ab3560a41a6ff3fd8f8c43d0860fa3b32bacd21cc3b3", "owner": "smallclaims::store", "todo": "chunk-or-reference-exact-wire-values", "disposition": "allow-for-now", "line_hint": 7558, "excerpt": "UPDATE replica_envelopes SET receipt_state='pending' WHERE writer=?1 AND sequence=?2 AND envelope_hash=?3 AND receipt_state='degraded' AND EXISTS ( SELECT 1 FROM replica_records WHERE writer=?1 AND se"}, {"id": "lv-hf429bed1b7cd", "path": "crates/fractal-store/src/store/seat_status.rs", "kind": "unresolved-sql-sink", "fingerprint": "03690a9ed280bcc837c991cbfcca346b27fb18298a276e132f904122346ea0f4", "owner": "fractal_store::store::seat_status", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 148, "excerpt": "& harness_observations_of_incarnation_query ( )"}, {"id": "lv-hf43488f16b99", "path": "crates/smallclaims/src/store/receive_writer_tests.rs", "kind": "sql-template", "fingerprint": "27579faa3260cd55b8a974a9017d0de1fa3307902d7876de85599b139e50d72e", "owner": "smallclaims::store::receive_writer_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 1011, "excerpt": "UPDATE batches SET rowid=1 WHERE id=?1"}, diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 6ab4eda7c8d..6730cc276a4 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -3,31 +3,31 @@ "summary": "Suspend external-grant authentication when replicated grants assign opposite profiles to one principal", "replay": { "status": "changed", - "detail": "Existing append-only grant and revocation claims are read without rewriting history. Active opposite-profile grants conflict regardless of replication arrival order; revoked and expired grants do not contribute to the conflict." + "detail": "Existing append-only grant, policy and revocation claims are preserved without rewriting history. Additive external-grant authority projection version 1 is populated by a resumable background backfill. Active opposite-profile grants conflict regardless of replication arrival order; revoked and expired grants do not contribute to the conflict." }, "schema": { "status": "changed", - "detail": "Adds the typed client error grant-profile-conflict (GrantProfileConflict in Rust), returned as HTTP 409. Bearer authentication and pairing disclose only this code and the fixed message principal has active grants of opposite profiles; revoke one to clear the conflict, without witness details. Only daemon-configured-owner inspection with ?witness=1 exposes conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients. Adds a principal/expiry expression index at store open without rewriting grant claims." + "detail": "Adds external-grant authority projection version 1 as additive store state; older builds can still open an upgraded store. Adds typed client error assistant-grant-authority-not-ready with retryable=true (HTTP 503) while assistant authorization fails closed during background backfill. Also adds grant-profile-conflict (HTTP 409). Bearer authentication and pairing disclose only the conflict code and fixed message principal has active grants of opposite profiles; revoke one to clear the conflict, without witness details. Only daemon-configured-owner inspection with ?witness=1 exposes conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients." }, "rules": { "status": "changed", - "detail": "If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view; service issuance remains disabled. Inspect computes active witnesses and cleared_conflicts witnesses with revoked or expired causes; no conflict state is persisted." + "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." }, "compatibility": { "status": "changed", - "detail": "Conflict admission counts only well-formed owner grants; foreign grants require authenticated envelope provenance from a keyed, admitted fleet writer, including valid records in degraded envelopes. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. Foreign transitions require both a keyed membership window and a valid signature; a newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Candidate claims and latest transitions are fetched together, foreign provenance is checked in one membership snapshot with deduplicated envelope signature verification, and same-profile candidates can be skipped during authentication because they cannot conflict. No provenance result is cached by fleet generation alone. Tokens remain issuer-local. Older members do not enforce suspension, so upgrade all serving members before relying on it." + "detail": "Conflict admission counts only well-formed owner grants; foreign grants require authenticated envelope provenance from a keyed, admitted fleet writer, including valid records in degraded envelopes. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. Foreign transitions require both a keyed membership window and a valid signature; a newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Projection version 1 is additive and raw append-only evidence remains authoritative and intact. Tokens remain issuer-local. Rollback to an older build is supported, but older members do not enforce the new projection readiness gate or conflict suspension, so upgrade all serving members before relying on them." }, "downtime": { "status": "changed", - "detail": "No migration downtime is required, but the first store open builds the additive principal/expiry index over existing claims; its duration depends on retained history. Affected people cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend this interruption until revocations replicate. Unaffected people retain existing authentication behavior." + "detail": "No offline migration window is planned: startup work is bounded with an approximately two-second budget planned, and retained history is backfilled in the background. Startup and total backfill durations have not been measured. Assistant authorization is temporarily unavailable with retryable assistant-grant-authority-not-ready until the local projection is ready; this is an authorization interruption, not a requirement to stop the daemon for the entire backfill. Affected people also cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend that interruption until revocations replicate." }, "manual": { "status": "changed", - "detail": "For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer; do not delete claims or replace tokens to resolve the conflict." + "detail": "Allow the resumable background backfill to finish before retrying assistant authorization after assistant-grant-authority-not-ready. For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer. Do not delete raw claims, clear append-only evidence, or replace tokens to resolve a conflict or restart the backfill." }, "recovery": { "status": "changed", - "detail": "After revocations replicate, remaining otherwise-valid grants in the intended profile can authenticate again without reissuance. Expiry of every remaining active opposite-profile grant also clears the conflict; expired and revoked grants remain unusable. If authentication is still suspended on an issuer after revocation, restore replication so it receives the revocations; restarting or changing claim arrival order does not resolve the conflict." + "detail": "Restarting resumes the background backfill idempotently from retained progress; no raw claim deletion or manual data rewrite is required. Rollback to an older build is supported because projection version 1 is additive and preserves raw evidence, but the older build does not provide the new authorization guarantees. After revocations replicate, remaining otherwise-valid grants in the intended profile can authenticate again without reissuance. Expiry of every remaining active opposite-profile grant also clears the conflict; expired and revoked grants remain unusable. If a ready issuer still reports a conflict after revocation, restore replication so it receives the revocations; restarting or changing claim arrival order does not resolve the conflict." }, "commits": [] } From b679e8875c54a47f23eebda9d725deac3916099b Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 07:30:35 +0100 Subject: [PATCH 23/52] Exercise authority projection rollback compatibility and bounded admission queries agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../tests/daemon_cost/assistant_admission.rs | 123 +++++++++-------- crates/fractal/tests/fleet.rs | 7 + crates/fractal/tests/fleet/service_grants.rs | 126 ++++++++++++++++++ scripts/ci-linux | 5 +- 4 files changed, 201 insertions(+), 60 deletions(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index 58568e84052..d58fe48e100 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -65,7 +65,7 @@ //! Each expired grant has three still-expired POLICY renewals. Each active session has //! ST_ADMISSION_WRONG_ORIGIN_OVERLAYS (default 1000; 0 allowed) authenticated wrong-origin //! overlays, alternating POLICY and REVOKED; every measured read must still succeed. -//! ST_ADMISSION_READ_COUNTS_ONLY=1 measures only read counts: it skips the index probe, +//! ST_ADMISSION_READ_COUNTS_ONLY=1 measures only read counts: it skips the //! candidate SQL, latency pairs, the q39 gate and the release-build requirement. //! Read counts require a fresh ST3_PROFILE_DIR and ST3_PROFILE_SLOW_MS=0. The existing //! profile `read_acquisitions` counts pooled read-connection/snapshot acquisitions per @@ -73,9 +73,10 @@ //! SQL work uses existing smallclaims sqlite::work trace counters (statements/VM steps). //! Authentication work is thread-scoped; standalone GET work is process-global through the //! receipt flush and can include background daemon SQL. No production code changes. -//! The index DDL timing is a synthetic startup migration probe on the populated disposable -//! real store, not total daemon startup or cold-disk startup. Latencies use the real daemon's -//! bound sockets, bearer middleware, grant lookup, projection and durable approval consumption. +//! Current-head candidate diagnostics read the effective authority projection only; +//! the separate historical index DDL probe is not a current admission measurement. +//! Latencies use the real daemon's bound sockets, bearer middleware, grant lookup, +//! projection and durable approval consumption. use std::{collections::BTreeMap, path::PathBuf, sync::Arc, time::{Instant, SystemTime, UNIX_EPOCH}}; @@ -96,7 +97,7 @@ const POLICY_RENEWALS: usize = 3; const INDEX: &str = "claims_assistant_v1_principal_expiry_index"; const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms'))"; const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; -const INDEXED_QUERY: &str = revision_api::ADMISSION_QUERY; +const PROJECTION_INDEX: &str = "assistant_grant_effective_active_index"; const PATH: &str = "/v1/client/assistant/summary"; fn number(name: &str, default: usize) -> usize { @@ -209,20 +210,9 @@ fn proof(paired: &Value, signer: &Ed25519KeyPair, sequence: usize) -> String { URL_SAFE_NO_PAD.encode(serde_json::to_vec(&json!({"payload":payload,"signature":signature})).unwrap()) } -fn explain(connection: &rusqlite::Connection, query: &str) -> Vec { - // The production query names its indexes (INDEXED BY); before the probe recreates - // one, SQLite refuses to plan it. Record that instead of a plan. - let mut statement = match connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")) { - Ok(statement) => statement, - Err(error) => return vec![format!("not plannable: {error}")], - }; - let mut rows = if query == A_QUERY { - statement.query(rusqlite::params![GRANTED, "assistant/chatgpt"]).unwrap() - } else { - statement.query(rusqlite::params![GRANTED, "assistant/chatgpt", "custom.client.assistant.v1.revoked", - "custom.client.assistant.v1.policy", - u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(), NODE]).unwrap() - }; +fn explain(connection: &rusqlite::Connection, query: &str, parameters: &[&dyn rusqlite::ToSql]) -> Vec { + let mut statement = connection.prepare(&format!("EXPLAIN QUERY PLAN {query}")).unwrap(); + let mut rows = statement.query(parameters).unwrap(); let mut plan = Vec::new(); while let Some(row) = rows.next().unwrap() { plan.push(row.get::<_, String>(3).unwrap()); } plan @@ -440,22 +430,19 @@ async fn authenticated_get_during_pairing() { } }).await.unwrap(); let connection = rusqlite::Connection::open(&database).unwrap(); - let query = if indexed { INDEXED_QUERY } else { A_QUERY }; - let (before, after, build_ms) = if counts_only { - (Vec::new(), Vec::new(), None) + let candidate_query = revision_api::candidate_query(); + let query = candidate_query.as_ref().map_or(A_QUERY, |(query, _)| *query); + let after = if counts_only { + Vec::new() + } else if let Some((query, expiry)) = &candidate_query { + let plan = explain(&connection, query, rusqlite::params![ + "assistant/chatgpt", OWNER, expiry, Option::::None, Option::::None + ]); + assert!(plan.iter().any(|line| line.contains(PROJECTION_INDEX)), "{plan:?}"); + assert!(!plan.iter().any(|line| line.contains("claims")), "{plan:?}"); + plan } else { - let index_exists: bool = connection.query_row("SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", [INDEX], |r| r.get(0)).unwrap(); - assert_eq!(index_exists, indexed, "build baseline on 98e550cb; indexed on PR3-B"); - if indexed { - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_expiry_index").unwrap(); - let before = explain(&connection, query); - let started = Instant::now(); - connection.execute_batch(CREATE_INDEX).unwrap(); - let elapsed = started.elapsed().as_secs_f64() * 1000.0; - let after = explain(&connection, query); - assert!(after.iter().any(|line| line.contains(INDEX)), "{after:?}"); - (before, after, Some(elapsed)) - } else { (explain(&connection, query), Vec::new(), None) } + explain(&connection, A_QUERY, rusqlite::params![GRANTED, "assistant/chatgpt"]) }; let total_rows: u64 = connection.query_row("SELECT count(*) FROM claims", [], |r| r.get(0)).unwrap(); let mut principal_rows = BTreeMap::new(); @@ -463,17 +450,34 @@ async fn authenticated_get_during_pairing() { let count: u64 = connection.query_row("SELECT count(*) FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2", rusqlite::params![GRANTED,principal], |r| r.get(0)).unwrap(); principal_rows.insert(principal, count); } - // Isolate indexed SQL from claim/policy loading, provenance and locks. - // Diagnostic work stays outside HTTP samples; no request-path cache. + // Isolate the production effective-authority query from provenance and locks. + // Diagnostic work stays outside HTTP samples; no raw-history admission alias. let mut diagnostics = Vec::new(); for _ in 0..8 { - let candidate = (indexed && !counts_only).then(|| { + let candidate = candidate_query.as_ref().filter(|_| !counts_only).map(|(query, expiry)| { let started = Instant::now(); - let candidate_ids = connection.prepare(query).unwrap().query_map(rusqlite::params![ - GRANTED,"assistant/chatgpt","custom.client.assistant.v1.revoked","custom.client.assistant.v1.policy", - u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(),NODE + let mut statement = connection.prepare(query).unwrap(); + let grant_records = statement.query_map(rusqlite::params![ + "assistant/chatgpt", OWNER, expiry, Option::::None, Option::::None ], |row| row.get::<_, String>(0)).unwrap().collect::, _>>().unwrap(); - (candidate_ids.len(), started.elapsed().as_secs_f64() * 1000.0) + // This independent diagnostic connection is not a traced Store connection. + let status = |counter| u64::try_from(statement.get_status(counter)).unwrap(); + let work = smallclaims::sqlite::work::SqliteWork { + statements: 1, + vm_steps: status(rusqlite::StatementStatus::VmStep), + fullscan_steps: status(rusqlite::StatementStatus::FullscanStep), + sorts: status(rusqlite::StatementStatus::Sort), + autoindex_rows: status(rusqlite::StatementStatus::AutoIndex), + }; + assert_eq!(grant_records.len(), local_active + foreign_active, + "expired history and wrong-origin overlays must not change active N"); + assert_eq!(work.fullscan_steps, 0, "candidate reads must not scan history"); + assert!(work.vm_steps <= 512 + 128 * u64::try_from(local_active + foreign_active).unwrap(), + "candidate VM work must scale with active N, not expired history or overlay floods: {work:?}"); + for record in &grant_records { + let _: fractal_daemon::model::ClaimRecord = serde_json::from_str(record).unwrap(); + } + (grant_records.len(), started.elapsed().as_secs_f64() * 1000.0, sql_work(work)) }); let credential = sessions[0].1["credential"].as_str().unwrap(); let digest = hex::encode(ring::digest::digest(&ring::digest::SHA256, credential.as_bytes()).as_ref()); @@ -488,8 +492,9 @@ async fn authenticated_get_during_pairing() { authentication_profile.finish(); let direct_auth_ms = started.elapsed().as_secs_f64()*1000.0; let authentication_read_acquisitions = profile_reads(&profile_log, profile_from, "admission-bench/authenticate"); - diagnostics.push(json!({"candidate_count":candidate.map(|(count, _)| count), - "candidate_sql_ms":candidate.map(|(_, ms)| ms), + diagnostics.push(json!({"candidate_count":candidate.as_ref().map(|(count, _, _)| count), + "candidate_sql_ms":candidate.as_ref().map(|(_, ms, _)| ms), + "candidate_sql_work":candidate.as_ref().map(|(_, _, work)| work), "direct_auth_ms":direct_auth_ms,"authentication_sql_work":authentication_sql_work, "authentication_read_acquisitions":authentication_read_acquisitions})); } @@ -498,7 +503,7 @@ async fn authenticated_get_during_pairing() { api::client_v0::external_grants::projection(&state, &inspected).unwrap(); let legacy_projection_ms = started.elapsed().as_secs_f64()*1000.0; let witness_projection_ms = revision_api::witness_projection_ms(&state, &inspected); - let plan = if counts_only { Vec::new() } else { explain(&connection, query) }; + let plan = after.clone(); println!("ADMISSION_DIAGNOSTICS {}", json!({"plan":plan,"samples":diagnostics, "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms})); drop(connection); @@ -592,7 +597,7 @@ async fn authenticated_get_during_pairing() { "final_total_claim_rows":final_rows,"admission_query":query, "conflict_fold_diagnostics":diagnostics, "legacy_projection_ms":legacy_projection_ms,"witness_projection_ms":witness_projection_ms, - "explain_without_index":before,"explain_with_index":after,"synthetic_startup_index_build_ms":build_ms, + "explain_with_index":after, "measurements":measurements}); println!("ADMISSION_MEASUREMENT {}", serde_json::to_string_pretty(&report).unwrap()); if let Some(path) = std::env::var_os("ST_ADMISSION_REPORT") { std::fs::write(path, serde_json::to_vec_pretty(&report).unwrap()).unwrap(); } @@ -608,8 +613,9 @@ async fn authenticated_get_during_pairing() { /// ST_ADMISSION_INDEX_BUILD=1 "$ST_ADMISSION_BINARY" daemon_cost::assistant_admission::synthetic_large_store_index_build --exact --nocapture --test-threads=1 /// ``` /// ST_ADMISSION_INDEX_ROWS defaults to 1,000,000 total claims. ST_ADMISSION_INDEX_REPORT -/// optionally saves JSON. Run on the indexed branch. This measures the exact startup index -/// CREATE DDL, not full Store::open, cold-disk startup, admission, or signature verification. +/// optionally saves JSON. This explicitly historical claims-index measurement is +/// independent of the current effective-authority query. It measures CREATE DDL, +/// not full Store::open, cold-disk startup, admission, or signature verification. /// Use the same identity-bound build/export commands above (including SOURCE_ROOT, /// EXPECT_REVISION and BINARY). Every index report carries the same execution identity. #[test] @@ -636,12 +642,7 @@ fn synthetic_large_store_index_build() { // Native claims triggers retain their real digest implementation during the // synthetic population, just as on production/checkpoint writer connections. smallclaims::store::configure_projection_writer(&connection).unwrap(); - let installed: bool = connection.query_row( - "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='index' AND name=?1)", - [INDEX], |row| row.get(0), - ).unwrap(); - assert!(installed, "run the large-store index probe on the indexed branch"); - connection.execute_batch("DROP INDEX claims_assistant_v1_principal_expiry_index").unwrap(); + connection.execute_batch("DROP INDEX IF EXISTS claims_assistant_v1_principal_expiry_index").unwrap(); // Copy every native required column rather than depending on a second claims schema. // The native autoincrement store_index, claim ID and subject must remain unique. let columns = { @@ -673,12 +674,13 @@ fn synthetic_large_store_index_build() { let actual_rows: u64 = connection.query_row("SELECT count(*) FROM claims", [], |row| row.get(0)).unwrap(); assert_eq!(actual_rows, u64::try_from(rows).unwrap()); connection.execute_batch("PRAGMA wal_checkpoint(TRUNCATE)").unwrap(); - let before = explain(&connection, INDEXED_QUERY); + // Independent historical A-query evidence, not the current authority query. + let before = explain(&connection, A_QUERY, rusqlite::params![GRANTED, "assistant/chatgpt"]); let main_bytes_before = std::fs::metadata(&database).unwrap().len(); let started = Instant::now(); connection.execute_batch(CREATE_INDEX).unwrap(); let elapsed_ms = started.elapsed().as_secs_f64() * 1000.0; - let after = explain(&connection, INDEXED_QUERY); + let after = explain(&connection, A_QUERY, rusqlite::params![GRANTED, "assistant/chatgpt"]); assert!(after.iter().any(|line| line.contains(INDEX)), "{after:?}"); let pages: u64 = connection.query_row("PRAGMA page_count", [], |row| row.get(0)).unwrap(); let page_size: u64 = connection.query_row("PRAGMA page_size", [], |row| row.get(0)).unwrap(); @@ -690,11 +692,12 @@ fn synthetic_large_store_index_build() { String::from_utf8(output.stdout).unwrap() }; let report = json!({ - "measurement":"synthetic startup index CREATE DDL only; not full startup", + "measurement":"historical claims principal/expiry index CREATE DDL only; not current admission or full startup", "execution_identity":identity, "claims_rows":actual_rows,"synthetic_copied_rows":rows - 1, "fixture_authority":"one native template; SQL copies are not signature-authoritative", "index_name":INDEX,"index_create_sql":CREATE_INDEX,"index_build_ms":elapsed_ms, + "historical_query":A_QUERY, "main_db_bytes_before":main_bytes_before, "main_db_bytes_after":std::fs::metadata(&database).unwrap().len(), "wal_bytes_after":wal_bytes,"logical_db_bytes_after":pages * page_size, @@ -717,7 +720,7 @@ fn synthetic_large_store_index_build() { /// pub const REVISION: &str = "origin/main"; /// pub const VARIANT: &str = "baseline"; /// // origin/main admission is a credential-hash lookup with no candidate query. -/// pub const ADMISSION_QUERY: &str = A_QUERY; +/// pub fn candidate_query() -> Option<(&'static str, String)> { None } /// pub fn verified_writer(_: &Store, _: &str) -> bool { /// panic!("origin/main has no provenance check; use FOREIGN_ACTIVE=0 and WRONG_ORIGIN_OVERLAYS=0") /// } @@ -727,7 +730,11 @@ mod revision_api { use super::*; pub const REVISION: &str = "fixed-head"; pub const VARIANT: &str = "indexed"; - pub const ADMISSION_QUERY: &str = api::client_v0::external_grants::admission_query_for_test(); + pub fn candidate_query() -> Option<(&'static str, String)> { + let now = u64::try_from(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()).unwrap(); + Some((smallclaims::store::assistant_grant_authority::CANDIDATES_QUERY, + smallclaims::store::assistant_grant_authority::expiry_key(now))) + } pub fn verified_writer(store: &Store, id: &str) -> bool { store.claim_has_authenticated_member_writer(id).unwrap() } diff --git a/crates/fractal/tests/fleet.rs b/crates/fractal/tests/fleet.rs index 52cc5529ce0..11461e9b7de 100644 --- a/crates/fractal/tests/fleet.rs +++ b/crates/fractal/tests/fleet.rs @@ -3634,6 +3634,13 @@ fn fleet_workflows_have_no_path_filter() { "previous_release_replicates_with_new_members_and_preserves_history_on_upgrade" ) ); + assert!( + stages.contains( + "fleet::service_grants::previous_release_authorizes_and_revokes_after_authority_projection_rollback" + ), + "fleet compatibility must exercise baseline rollback after authority projection backfill" + ); + assert!(stages.contains("test result: ok. 10 passed")); // The optional macOS job lives in macos.yml so label events cannot restart this gate. assert!( !compat.to_ascii_lowercase().contains("macos-"), diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index 8c4ce1f58b2..d1c015edb16 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -214,6 +214,132 @@ async fn previous_release_refuses_plugin_service_grants_on_same_database_rollbac assert_retained(&node, &grants).await; } +// Use the release's real issuance and policy routes: this history must predate the +// candidate's first Store::open, rather than being seeded by candidate store code. +async fn issue_with_policy(node: &Node, key: u8) -> Grant { + use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD}; + + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let policy = json!({ + "api_version":"st3.client.v0", + "scopes":["read.assistant.summary", "read.assistant.attention", + "read.assistant.missions", "read.assistant.agents"], + "expires_in_seconds":3600, "minimal_read_mode":"approval-once", + "disclosure_consent":true, "consent_evidence":"Disposable rollback fixture owner consent" + }); + let mut begin = policy.clone(); + begin["assistant_id"] = json!("assistant/chatgpt"); + begin["device_name"] = json!(format!("rollback fixture {key}")); + let challenge: Value = owner.post("/v1/client/pairings", &begin).await.unwrap(); + let challenge = challenge.get("value").unwrap_or(&challenge); + let pairing = challenge["pairing_id"].as_str().unwrap().trim_start_matches("pairing/"); + let response = reqwest::Client::builder().unix_socket(node.socket()).build().unwrap() + .post(format!("http://localhost/v1/client/pairings/{pairing}/complete")) + .json(&json!({"api_version":"st3.client.v0", "code":challenge["code"], + "device_public_key":URL_SAFE_NO_PAD.encode([key; 32]), "key_storage":"software"})) + .send().await.unwrap(); + let status = response.status(); + let paired: Value = response.json().await.unwrap(); + assert_eq!(status.as_u16(), 200, "baseline assistant issuance: {paired}"); + let paired = paired.get("value").unwrap_or(&paired); + let id = paired["grant"]["id"].as_str().unwrap().trim_start_matches("assistant-grant/").to_owned(); + let changed: Value = owner.post( + &format!("/v1/client/assistant/grants/{id}/policy"), &policy, + ).await.unwrap(); + let changed = changed.get("value").unwrap_or(&changed); + assert_eq!(changed["policy_revision"], 2, "{changed}"); + let subject = format!("custom/client/assistant-v1-{id}"); + let claims = node.claims().await.into_iter() + .filter(|claim| claim["subject"] == subject) + .map(|claim| claim["id"].as_str().unwrap().to_owned()).collect(); + Grant { id, credential: paired["credential"].as_str().unwrap().to_owned(), claims } +} + +fn authority_history(node: &Node) -> Vec<(String, String)> { + let connection = rusqlite::Connection::open_with_flags( + node.state_dir().join("claims.sqlite3"), rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap(); + connection.prepare( + "SELECT id, body FROM claims WHERE kind IN (?1, ?2, ?3) ORDER BY id", + ).unwrap().query_map([GRANTED, POLICY, REVOKED], |row| { + Ok((row.get(0)?, row.get(1)?)) + }).unwrap().collect::>().unwrap() +} + +fn assert_authority_projection_ready(node: &Node) { + let version: String = rusqlite::Connection::open_with_flags( + node.state_dir().join("claims.sqlite3"), rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap().query_row( + "SELECT value FROM meta WHERE key='assistant_grant_authority_version'", + [], |row| row.get(0), + ).unwrap(); + assert_eq!(version, "1", "candidate must complete authority backfill before rollback"); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore = "needs ST3_COMPAT_BIN: the pinned previous published release"] +async fn previous_release_authorizes_and_revokes_after_authority_projection_rollback() { + if fractal_daemon::test_support::supervise_test() { return; } + let root = tempfile::tempdir().unwrap(); + let mut node = Node::new(root.path(), "issuer"); + node.binary = compat_binary(); + node.start().await; + let active = issue_with_policy(&node, 7).await; + let revoked = issue_with_policy(&node, 8).await; + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let _: Value = owner.post( + &format!("/v1/client/assistant/grants/{}/revoke", revoked.id), &json!({}), + ).await.unwrap(); + assert_auth(&node, &active, true).await; + assert_auth(&node, &revoked, false).await; + let history = authority_history(&node); + assert_eq!(history.len(), 5, "two grants, two policy renewals and one revocation"); + let projection_exists: bool = rusqlite::Connection::open_with_flags( + node.state_dir().join("claims.sqlite3"), rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap().query_row( + "SELECT EXISTS(SELECT 1 FROM sqlite_schema WHERE type='table' AND name='assistant_grant_authority')", + [], |row| row.get(0), + ).unwrap(); + assert!(!projection_exists, "baseline history must predate authority projection initialization"); + let state = node.state_dir(); + + node.stop(); + node.binary = PathBuf::from(st3()); + node.start().await; + assert_eq!(node.state_dir(), state); + assert_authority_projection_ready(&node); + assert_auth(&node, &active, true).await; + assert_auth(&node, &revoked, false).await; + assert_eq!(authority_history(&node), history, "backfill must not rewrite raw evidence"); + + node.stop(); + node.binary = compat_binary(); + node.start().await; + assert_eq!(node.state_dir(), state); + assert_auth(&node, &active, true).await; + assert_auth(&node, &revoked, false).await; + assert_eq!(authority_history(&node), history, "baseline must retain the backfilled history"); + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let _: Value = owner.post( + &format!("/v1/client/assistant/grants/{}/revoke", active.id), &json!({}), + ).await.unwrap(); + assert_auth(&node, &active, false).await; + let after_revoke = authority_history(&node); + assert_eq!(after_revoke.len(), history.len() + 1); + for claim in &history { + assert!(after_revoke.contains(claim), "baseline revoke changed prior evidence"); + } + + node.stop(); + node.binary = PathBuf::from(st3()); + node.start().await; + assert_authority_projection_ready(&node); + assert_auth(&node, &active, false).await; + assert_auth(&node, &revoked, false).await; + assert_retained(&node, &[active, revoked]).await; + assert_eq!(authority_history(&node), after_revoke, "reopen must retain the baseline revoke"); +} + fn compat_binary() -> PathBuf { PathBuf::from(std::env::var("ST3_COMPAT_BIN").expect("ST3_COMPAT_BIN names the pinned baseline")) } diff --git a/scripts/ci-linux b/scripts/ci-linux index 83a74ba3d44..ea00b35a128 100755 --- a/scripts/ci-linux +++ b/scripts/ci-linux @@ -45,8 +45,9 @@ fleet_compat() { fleet::previous_release_and_this_build_restore_each_others_archives_until_the_shard_holds_items \ fleet::service_grants::previous_release_refuses_service_grants_from_a_candidate_issuer \ fleet::service_grants::previous_release_refuses_offline_seeded_service_grants_with_its_own_origin \ - fleet::service_grants::previous_release_refuses_plugin_service_grants_on_same_database_rollback 2>&1 | tee "$logs/compat-result.log" || return - grep -q "test result: ok. 9 passed" "$logs/compat-result.log" || return + fleet::service_grants::previous_release_refuses_plugin_service_grants_on_same_database_rollback \ + fleet::service_grants::previous_release_authorizes_and_revokes_after_authority_projection_rollback 2>&1 | tee "$logs/compat-result.log" || return + grep -q "test result: ok. 10 passed" "$logs/compat-result.log" || return # The GitHub plugin store beside an older poller, and that poller upgraded in place. cargo test -p fractal --locked --test integration -- --ignored --exact \ fleet::previous_release_poller_beside_a_github_plugin_member_and_its_upgrade 2>&1 | tee "$logs/compat-plugin-result.log" || return From e638ad420aae59a51c62506077ecc00a1421a241 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 07:38:00 +0100 Subject: [PATCH 24/52] Preserve complete reserved fixture identity in SQLite inventory excerpt agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- docs/st3/large-value-sites.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index 3290067baab..0799d8cbc9d 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -2247,7 +2247,7 @@ {"id": "lv-h5807a1101987", "path": "crates/fractal-store/src/store/completion_state.rs", "kind": "sql-template", "fingerprint": "6fbf81728b4e78bfb022ed799c80fd7cfdbfe883d04304f7ef9d6cf20ed6f3ab", "owner": "fractal_store::store::completion_state", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 227, "excerpt": "DELETE FROM local_completion_health_v1_claims WHERE claim_id=?1"}, {"id": "lv-h580eec954622", "path": "crates/fractal-store/src/store/tests.rs", "kind": "sql-template", "fingerprint": "ca00bf71e63d7a44fcc9d8aa75ce4f583d9c760665a19ab32e0ffe0b2945c035", "owner": "fractal_store::store::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 7172, "excerpt": "UPDATE mission_runs SET status='completed' WHERE id='run-example'"}, {"id": "lv-h581d2d15b664", "path": "crates/fractal-store/src/store/idle_mail.rs", "kind": "sql-template", "fingerprint": "f04f1cbf586659252f3d0a49923faed45656a176d5e31210a9e3ba31a598ab46", "owner": "fractal_store::store::idle_mail", "todo": "prepare-body-and-predecessor-values", "disposition": "allow-for-now", "line_hint": 171, "excerpt": "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) VALUES(?1,?2,?3,?4,'fixture',NULL,?5,'[]',?6)"}, - {"id": "lv-h5820156720c0", "path": "crates/smallclaims/src/store/assistant_grant_authority_bench.rs", "kind": "unresolved-sql-sink", "fingerprint": "59b4dbf78175f7e6e792032a53e966a89a0afa9d605487128e54573600011c83", "owner": "smallclaims::store::assistant_grant_authority_bench", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 238, "excerpt": "params ! [ id , format ! ( \"batch/{LOCAL}/{sequence:064x}\" ) , format ! ( \"conversation/synthetic/{:08x}\" , row % 1 0 0 _000 ) , format ! ( \"synthetic.message.kind{}\" , row % 1 6 ) , LOCAL , \"person/p"}, + {"id": "lv-h5820156720c0", "path": "crates/smallclaims/src/store/assistant_grant_authority_bench.rs", "kind": "unresolved-sql-sink", "fingerprint": "59b4dbf78175f7e6e792032a53e966a89a0afa9d605487128e54573600011c83", "owner": "smallclaims::store::assistant_grant_authority_bench", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 238, "excerpt": "params ! [ id , format ! ( \"batch/{LOCAL}/{sequence:064x}\" ) , format ! ( \"conversation/synthetic/{:08x}\" , row % 1 0 0 _000 ) , format ! ( \"synthetic.message.kind{}\" , row % 1 6 ) , LOCAL , \"person/perf-operator\""}, {"id": "lv-h582a34b5ce55", "path": "crates/fractal-store/src/store/ordered_membership.rs", "kind": "sql-template", "fingerprint": "00588d4f2313b213bcf242af52810c444d9e1479f3b8ff9884fde92ac7118037", "owner": "fractal_store::store::ordered_membership", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 265, "excerpt": "INSERT OR IGNORE INTO declared_resource_edges(owner,relation,name,target) VALUES(?1,'ordered-membership',?2,?2)"}, {"id": "lv-h582aabe243d0", "path": "crates/fractal-missions/src/store/person_work.rs", "kind": "unresolved-sql-sink", "fingerprint": "8612167e28c162a2fee1c63ec4be5673bd9fd8221b3cf742ed8f17fa613dcd17", "owner": "fractal_missions::store::person_work", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 569, "excerpt": "\"SAVEPOINT tell_ask_ended\""}, {"id": "lv-h582e5366bbee", "path": "crates/smallclaims/src/store/principals.rs", "kind": "unresolved-sql-sink", "fingerprint": "b9583a3b1a1be6db59892cb754cd0fcfb1ec702b7fe72b60bdd18505b2bab00a", "owner": "smallclaims::store::principals", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 1054, "excerpt": "[ REQUEUE , REQUEUE_END ] , | row | { Ok ( ( row . get : : < _ , String > ( 0 ) ? , row . get : : < _ , String > ( 1 ) ? ) ) }"}, From 3c82349e8a5c84f30dcdc6cca1a1348bec1e483d Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 09:51:06 +0100 Subject: [PATCH 25/52] Bound authority maintenance memory and avoid completed-history rescans agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/store/assistant_grant_authority.rs | 108 +++++++++++------- docs/st3/large-value-sites.json | 28 ++--- 2 files changed, 83 insertions(+), 53 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index 9cfafc5d746..e2a2a036cb6 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -81,7 +81,7 @@ pub fn expiry_key(value: u64) -> String { format!("{value:020}") } pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { connection.execute_batch( - /* sqlite-large-value: allow-for-now lv-h19226e0dde9c owner=smallclaims::store::assistant_grant_authority TODO=chunk-or-reference-variable-columns */ + /* sqlite-large-value: allow-for-now lv-hd3babb5b6b9a owner=smallclaims::store::assistant_grant_authority TODO=chunk-or-reference-variable-columns */ "CREATE TABLE IF NOT EXISTS assistant_grant_authority ( claim_id TEXT NOT NULL, base_claim_id TEXT NOT NULL, grant_subject TEXT NOT NULL, kind TEXT NOT NULL, origin TEXT NOT NULL, @@ -105,12 +105,12 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { ON assistant_grant_effective(grant_subject); CREATE TABLE IF NOT EXISTS assistant_grant_pending ( claim_id TEXT PRIMARY KEY, grant_subject TEXT NOT NULL, kind TEXT NOT NULL, - origin TEXT NOT NULL, sequence INTEGER NOT NULL, authenticated INTEGER NOT NULL, - record TEXT NOT NULL); + origin TEXT NOT NULL, actor TEXT NOT NULL, sequence INTEGER NOT NULL, + authenticated INTEGER NOT NULL, record TEXT NOT NULL); CREATE INDEX IF NOT EXISTS assistant_grant_pending_subject_index - ON assistant_grant_pending(grant_subject,authenticated); + ON assistant_grant_pending(grant_subject,authenticated,origin,actor,kind); CREATE INDEX IF NOT EXISTS assistant_grant_pending_writer_index - ON assistant_grant_pending(origin,sequence,authenticated); + ON assistant_grant_pending(origin,authenticated,sequence,claim_id); CREATE TABLE IF NOT EXISTS assistant_grant_dirty (claim_id TEXT PRIMARY KEY); CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') @@ -124,13 +124,12 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { } pub fn ready(connection: &Connection) -> Result<(), FractalError> { - let version: Option = connection.query_row( - "SELECT value FROM meta WHERE key='assistant_grant_authority_version'", [], |row| row.get(0), - ).optional().map_err(internal)?; - let dirty: bool = connection.query_row( - "SELECT EXISTS(SELECT 1 FROM assistant_grant_dirty)", [], |row| row.get(0), + let complete: bool = connection.query_row( + "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')=?1 + AND NOT EXISTS(SELECT 1 FROM assistant_grant_dirty)", + [VERSION], |row| row.get(0), ).map_err(internal)?; - if version.as_deref() != Some(VERSION) || dirty { + if !complete { return Err(FractalError::new("assistant-grant-authority-not-ready", "external-grant authority backfill is in progress; retry after it completes")); } Ok(()) @@ -168,8 +167,8 @@ pub fn candidates(connection: &Connection, principal: &str, owner: &str, expiry_ ready(connection)?; let mut statement = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h556bdadaf8cd owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ CANDIDATES_QUERY).map_err(internal)?; let records = statement.query_map(params![principal,owner,expiry_cut.map(expiry_key),excluded,ignored_profile], |row| row.get::<_,String>(0)) - .map_err(internal)?.collect::>>().map_err(internal)?; - records.into_iter().map(decode).collect() + .map_err(internal)?; + records.map(|record| decode(record.map_err(internal)?)).collect() } pub fn by_credential(connection: &Connection, digest: &str) -> Result, FractalError> { ready(connection)?; @@ -200,11 +199,13 @@ fn insert_authority(connection: &Connection, claim: &ClaimRecord, base: &ClaimRe pub fn rebuild_subject(connection: &Connection, subject: &str) -> Result<()> { connection.execute(/* sqlite-large-value: allow-for-now lv-h47619972ac92 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_effective WHERE grant_subject=?1", [subject])?; let mut statement = connection.prepare_cached("SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2")?; - let records = statement.query_map(params![subject,GRANTED], |row| row.get::<_,String>(0))?.collect::>>()?; + let records = statement.query_map(params![subject,GRANTED], |row| row.get::<_,String>(0))?; for record in records { + let record = record?; let grant: ClaimRecord = serde_json::from_str(&record)?; - let policy = transition_unchecked(connection,&grant,POLICY)?.unwrap_or_else(|| grant.clone()); - if !structurally_valid(&grant,&policy) { continue; } + let policy_claim = transition_unchecked(connection,&grant,POLICY)?; + let policy = policy_claim.as_ref().unwrap_or(&grant); + if !structurally_valid(&grant,policy) { continue; } let fields = &policy.body["fields"]; connection.execute(/* sqlite-large-value: allow-for-now lv-h2909dd1a0b9c owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_effective(claim_id,grant_subject,principal,owner,profile,expires_at,revoked,grant_record) VALUES(?1,?2,?3,?4,?5,?6,?7,?8)", @@ -214,20 +215,35 @@ pub fn rebuild_subject(connection: &Connection, subject: &str) -> Result<()> { } Ok(()) } -fn attach_subject(connection: &Connection, subject: &str) -> Result<()> { - let records = { - let mut statement = connection.prepare_cached("SELECT record FROM assistant_grant_pending WHERE grant_subject=?1 AND authenticated=1")?; - statement.query_map([subject], |row| row.get::<_,String>(0))?.collect::>>()? - }; - let claims: Vec = records.into_iter().map(|record| serde_json::from_str(&record)).collect::>()?; +fn attach_claim(connection: &Connection, claim: &ClaimRecord) -> Result<()> { let mut changed = false; - for grant in claims.iter().filter(|claim| claim.kind==GRANTED) { - changed |= insert_authority(connection,grant,grant)?; - for transition in claims.iter().filter(|claim| claim.kind!=GRANTED) { - if transition_valid(grant,transition) { changed |= insert_authority(connection,transition,grant)?; } + if claim.kind == GRANTED { + changed |= insert_authority(connection,claim,claim)?; + // Only this base's issuer prefix can attach to it. In particular, an + // authenticated wrong-actor history cannot enlarge later admission work. + let mut statement = connection.prepare_cached( + "SELECT record FROM assistant_grant_pending WHERE grant_subject=?1 + AND authenticated=1 AND origin=?2 AND actor=?3 AND kind<>?4")?; + let records = statement.query_map(params![claim.subject,claim.origin,claim.actor,GRANTED], |row| row.get::<_,String>(0))?; + for record in records { + let transition: ClaimRecord = serde_json::from_str(&record?)?; + if transition_valid(claim,&transition) { + changed |= insert_authority(connection,&transition,claim)?; + } + } + } else { + let mut statement = connection.prepare_cached( + "SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 + AND kind=?2 AND origin=?3 AND actor=?4")?; + let records = statement.query_map(params![claim.subject,GRANTED,claim.origin,claim.actor], |row| row.get::<_,String>(0))?; + for record in records { + let grant: ClaimRecord = serde_json::from_str(&record?)?; + if transition_valid(&grant,claim) { + changed |= insert_authority(connection,claim,&grant)?; + } } } - if changed { rebuild_subject(connection,subject)?; } + if changed { rebuild_subject(connection,&claim.subject)?; } Ok(()) } fn local_origin(connection: &Connection) -> Result { @@ -247,10 +263,11 @@ pub fn refresh_claim(connection: &Connection, id: &str, trusted_local: bool) -> let sequence: u64 = connection.query_row("SELECT replica_sequence FROM batches WHERE id=?1", [&claim.batch_id], |row| row.get(0))?; let authenticated = (trusted_local && claim.origin == local_origin(connection)?) || authenticated_claim(connection,&claim.id)?; - connection.execute(/* sqlite-large-value: allow-for-now lv-h4276e804ce28 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,sequence,authenticated,record) - VALUES(?1,?2,?3,?4,?5,?6,?7) ON CONFLICT(claim_id) DO UPDATE SET authenticated=MAX(authenticated,excluded.authenticated)", - params![claim.id,claim.subject,claim.kind,claim.origin,sequence,authenticated,serde_json::to_string(&claim)?])?; - if authenticated { attach_subject(connection,&claim.subject)?; } + let changed = connection.execute(/* sqlite-large-value: allow-for-now lv-h9cf86ad98d1e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8) ON CONFLICT(claim_id) DO UPDATE SET authenticated=excluded.authenticated + WHERE assistant_grant_pending.authenticated=?2 AND (?3 IS NULL OR sequence<=?3) AND authenticated=0")?; - statement.query_map(params![writer,start,end], |row| row.get::<_,String>(0))?.collect::>>()? - }; - for id in ids { refresh_claim(connection,&id,false)?; } + let mut cursor = (0_u64, String::new()); + loop { + let ids = { + let mut statement = connection.prepare_cached( + "SELECT sequence,claim_id FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index + WHERE origin=?1 AND authenticated=0 AND sequence>=?2 + AND (?3 IS NULL OR sequence<=?3) AND (sequence,claim_id)>(?4,?5) + ORDER BY sequence,claim_id LIMIT 64")?; + statement.query_map(params![writer,start,end,cursor.0,cursor.1], + |row| Ok((row.get::<_,u64>(0)?,row.get::<_,String>(1)?)))? + .collect::>>()? + }; + if ids.is_empty() { break; } + for (sequence,id) in ids { + refresh_claim(connection,&id,false)?; + cursor = (sequence,id); + } + } } Ok(()) } @@ -345,8 +374,9 @@ pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result let started = Instant::now(); let origin = local_origin(connection)?; refresh_membership(connection)?; - let complete = ready(connection).is_ok(); - if !complete { + // A completed version only drains the old-build dirty queue. Readiness also + // includes that queue, but must never cause a completed history rescan. + if fleet_meta(connection,"assistant_grant_authority_version")?.as_deref() != Some(VERSION) { for kind in KINDS { let key = format!("assistant_grant_authority_cursor/{kind}"); loop { diff --git a/docs/st3/large-value-sites.json b/docs/st3/large-value-sites.json index 0799d8cbc9d..afe0cb50209 100644 --- a/docs/st3/large-value-sites.json +++ b/docs/st3/large-value-sites.json @@ -585,18 +585,18 @@ {"site": "lv-h3f7d4d7d63f4", "path": "crates/smallclaims/src/sqlite/read_lifetime/tests.rs", "table_pattern": "payload", "columns": [{"name": "value", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h1ba817f95aef", "path": "crates/smallclaims/src/sqlite/writer_queue/tests.rs", "table_pattern": "claims", "columns": [{"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY AUTOINCREMENT", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h1ba817f95aef", "path": "crates/smallclaims/src/sqlite/writer_queue/tests.rs", "table_pattern": "values_", "columns": [{"name": "id", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_authority", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "base_claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "principal", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "profile", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "expires_at", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "credential_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_effective", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "principal", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "profile", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "expires_at", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "grant_record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_pending", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "authenticated", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_dirty", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_membership_windows", "columns": [{"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member_key", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "start", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "end", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_transition_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(grant_subject,kind,origin,actor,base_claim_id,store_index DESC)", "value_size_proven": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_latest_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(grant_subject,kind,store_index DESC)", "value_size_proven": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_credential_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(credential_hash,store_index DESC) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_effective_active_index", "table_pattern": "assistant_grant_effective", "key_expression_and_predicate": "(principal,owner,revoked,expires_at,profile)", "value_size_proven": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_effective_subject_index", "table_pattern": "assistant_grant_effective", "key_expression_and_predicate": "(grant_subject)", "value_size_proven": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_pending_subject_index", "table_pattern": "assistant_grant_pending", "key_expression_and_predicate": "(grant_subject,authenticated)", "value_size_proven": false}, - {"site": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_pending_writer_index", "table_pattern": "assistant_grant_pending", "key_expression_and_predicate": "(origin,sequence,authenticated)", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_authority", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "base_claim_id", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "principal", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "profile", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "expires_at", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "store_index", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "credential_hash", "declared_type": "TEXT", "declaration": "TEXT", "value_size_proven": false}, {"name": "record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_effective", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "principal", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "owner", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "profile", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "expires_at", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "revoked", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "grant_record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_pending", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "grant_subject", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "kind", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "origin", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "actor", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "sequence", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "authenticated", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "record", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_dirty", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "table_pattern": "assistant_grant_membership_windows", "columns": [{"name": "writer", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "member_key", "declared_type": "TEXT", "declaration": "TEXT NOT NULL", "value_size_proven": false}, {"name": "start", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}, {"name": "end", "declared_type": "INTEGER", "declaration": "INTEGER", "value_size_proven": false}], "unresolved_template": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_transition_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(grant_subject,kind,origin,actor,base_claim_id,store_index DESC)", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_latest_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(grant_subject,kind,store_index DESC)", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_authority_credential_index", "table_pattern": "assistant_grant_authority", "key_expression_and_predicate": "(credential_hash,store_index DESC) WHERE kind='custom.client.assistant.v1.granted'", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_effective_active_index", "table_pattern": "assistant_grant_effective", "key_expression_and_predicate": "(principal,owner,revoked,expires_at,profile)", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_effective_subject_index", "table_pattern": "assistant_grant_effective", "key_expression_and_predicate": "(grant_subject)", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_pending_subject_index", "table_pattern": "assistant_grant_pending", "key_expression_and_predicate": "(grant_subject,authenticated,origin,actor,kind)", "value_size_proven": false}, + {"site": "lv-hd3babb5b6b9a", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "index_pattern": "assistant_grant_pending_writer_index", "table_pattern": "assistant_grant_pending", "key_expression_and_predicate": "(origin,authenticated,sequence,claim_id)", "value_size_proven": false}, {"site": "lv-ha962eb0285cf", "path": "crates/smallclaims/src/store/canonical.rs", "table_pattern": "claim_positions", "columns": [{"name": "claim_id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}, {"name": "position", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h315c8b6f5aa8", "path": "crates/smallclaims/src/store/checkpoint.rs", "table_pattern": "canonical_index", "columns": [{"name": "old", "declared_type": "INTEGER", "declaration": "INTEGER PRIMARY KEY", "value_size_proven": false}, {"name": "new", "declared_type": "INTEGER", "declaration": "INTEGER NOT NULL", "value_size_proven": false}], "unresolved_template": false}, {"site": "lv-h298c5b9a94f9", "path": "crates/smallclaims/src/store/checkpoint.rs", "table_pattern": "sealed_claims", "columns": [{"name": "id", "declared_type": "TEXT", "declaration": "TEXT PRIMARY KEY", "value_size_proven": false}], "unresolved_template": false}, @@ -1193,7 +1193,6 @@ {"id": "lv-h18dd79b21618", "path": "crates/fractal-store/src/store/notice_authority_tests.rs", "kind": "sql-template", "fingerprint": "1d306ca6f8d0ac404bd039bda5b4330f1befc3c5af2cbb683b0ea08b3b3a7a25", "owner": "fractal_store::store::notice_authority_tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 185, "excerpt": "DELETE FROM documents WHERE name=?1 AND hash=?2"}, {"id": "lv-h18e23473abaf", "path": "crates/fractal-delivery/src/store/terminal_gate_evidence/native_source/tests.rs", "kind": "sql-template", "fingerprint": "5a66247d8f7ecaea9d55cd03b41096c4c0175a3572cf61790f6930987c671751", "owner": "fractal_delivery::store::terminal_gate_evidence::native_source::tests", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 312, "excerpt": "UPDATE test_native_terminal_guard SET pending=0 WHERE id=1"}, {"id": "lv-h18f468b699f4", "path": "crates/fractal-store/src/store/resources_preparation_tests.rs", "kind": "unresolved-sql-sink", "fingerprint": "4ec7c53222c8a758c722e2111541035ce700d5ae7bd0898c5f1b1a743e6450fd", "owner": "fractal_store::store::resources_preparation_tests", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 820, "excerpt": "sql"}, - {"id": "lv-h19226e0dde9c", "path": "crates/smallclaims/src/store/assistant_grant_authority.rs", "kind": "sql-template", "fingerprint": "c8bd40e012fde548f016ce2eeebd726b14a096f3b40b6c056a2994b0d05e3f67", "owner": "smallclaims::store::assistant_grant_authority", "todo": "chunk-or-reference-variable-columns", "disposition": "allow-for-now", "line_hint": 85, "excerpt": "CREATE TABLE IF NOT EXISTS assistant_grant_authority ( claim_id TEXT NOT NULL, base_claim_id TEXT NOT NULL, grant_subject TEXT NOT NULL, kind TEXT NOT NULL, origin TEXT NOT NULL, actor TEXT NOT NULL, "}, {"id": "lv-h1923419271b7", "path": "crates/smallclaims/src/store.rs", "kind": "unresolved-sql-sink", "fingerprint": "19f6c92406524d4f1e21d93717491852ee29c50077d9a6ff1384164a75a51579", "owner": "smallclaims::store", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 5760, "excerpt": "& canonical_sql ( LATEST_CLAIM_QUERY )"}, {"id": "lv-h193645d36e0f", "path": "crates/fractal-reconcile/src/reconcile.rs", "kind": "included-source", "fingerprint": "23bef6856b048e52b60b69a713a07339768128a512d6487d2388a7ffaba34a1c", "owner": "fractal_reconcile::reconcile", "todo": "trace-statement-and-value-representation", "disposition": "allow-for-now", "line_hint": 42048, "excerpt": "include_str ! ( \"../../fractal-drivers/tests/fixtures/blocking-screens/claude-login.txt\" )"}, {"id": "lv-h1939f319556d", "path": "crates/fractal-store/src/store/arrangements.rs", "kind": "sql-template", "fingerprint": "8326b0def65d092d55ca567201f98deb44744f6078e4566c7df9423c49a602e4", "owner": "fractal_store::store::arrangements", "todo": "bound-or-reference-values-and-reclamation", "disposition": "allow-for-now", "line_hint": 59, "excerpt": "DELETE FROM meta WHERE key>=?1 AND key Date: Mon, 9 Nov 2026 09:51:11 +0100 Subject: [PATCH 26/52] Verify resumable authority migration across abrupt daemon death agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal/tests/fleet.rs | 8 +- crates/fractal/tests/fleet/service_grants.rs | 117 +++++++++++++++++++ scripts/ci-linux | 5 +- 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/crates/fractal/tests/fleet.rs b/crates/fractal/tests/fleet.rs index d2cfa39f6bb..ab6e5f74378 100644 --- a/crates/fractal/tests/fleet.rs +++ b/crates/fractal/tests/fleet.rs @@ -3640,7 +3640,13 @@ fn fleet_workflows_have_no_path_filter() { ), "fleet compatibility must exercise baseline rollback after authority projection backfill" ); - assert!(stages.contains("test result: ok. 10 passed")); + assert!( + stages.contains( + "fleet::service_grants::authority_projection_resumes_after_daemon_is_killed_with_committed_partial_backfill" + ), + "fleet compatibility must exercise abrupt daemon death with an incomplete authority projection" + ); + assert!(stages.contains("test result: ok. 11 passed")); // The optional macOS job lives in macos.yml so label events cannot restart this gate. assert!( !compat.to_ascii_lowercase().contains("macos-"), diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index 127afe5f0ec..ba0893b5afa 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -321,6 +321,123 @@ fn assert_authority_projection_ready(node: &Node) { assert_eq!(version, "1", "candidate must complete authority backfill before rollback"); } +fn authority_projection_snapshot(connection: &rusqlite::Connection) -> (Vec, Vec) { + let authority = connection.prepare( + "SELECT json_array(claim_id,base_claim_id,grant_subject,kind,origin,actor,principal,profile, + expires_at,store_index,credential_hash,record) + FROM assistant_grant_authority ORDER BY claim_id,base_claim_id", + ).unwrap().query_map([], |row| row.get(0)).unwrap() + .collect::>>().unwrap(); + let effective = connection.prepare( + "SELECT json_array(claim_id,grant_subject,principal,owner,profile,expires_at,revoked,grant_record) + FROM assistant_grant_effective ORDER BY claim_id", + ).unwrap().query_map([], |row| row.get(0)).unwrap() + .collect::>>().unwrap(); + (authority, effective) +} + +fn authority_backfill_progress(connection: &rusqlite::Connection) -> (u64, bool) { + connection.query_row( + "SELECT COALESCE((SELECT CAST(value AS INTEGER) FROM meta WHERE key=?1),0), + EXISTS(SELECT 1 FROM meta WHERE key='assistant_grant_authority_version')", + [format!("assistant_grant_authority_cursor/{GRANTED}")], + |row| Ok((row.get(0)?, row.get(1)?)), + ).unwrap() +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore = "needs ST3_COMPAT_BIN: the pinned previous published release"] +async fn authority_projection_resumes_after_daemon_is_killed_with_committed_partial_backfill() { + use smallclaims::store::assistant_grant_authority as authority; + + if fractal_daemon::test_support::supervise_test() { return; } + let root = tempfile::tempdir().unwrap(); + let mut node = Node::new(root.path(), "issuer"); + node.binary = compat_binary(); + node.start().await; + let active = issue_with_policy(&node, 7).await; + let revoked = issue_with_policy(&node, 8).await; + let owner = Client::unix_as(node.socket(), PERSON).unwrap(); + let _: Value = owner.post( + &format!("/v1/client/assistant/grants/{}/revoke", revoked.id), &json!({}), + ).await.unwrap(); + let history = authority_history(&node); + assert_eq!(history.len(), 5); + node.stop(); + + let database = node.state_dir().join("claims.sqlite3"); + let mut connection = rusqlite::Connection::open(&database).unwrap(); + fractal_daemon::store::configure_projection_writer(&connection).unwrap(); + authority::install(&connection, &node.name).unwrap(); + let reference_path = root.path().join("uninterrupted.sqlite3"); + connection.execute("VACUUM INTO ?1", [reference_path.to_str().unwrap()]).unwrap(); + let mut reference = rusqlite::Connection::open(&reference_path).unwrap(); + fractal_daemon::store::configure_projection_writer(&reference).unwrap(); + loop { + let transaction = reference.transaction().unwrap(); + let done = authority::backfill_slice(&transaction, Duration::from_secs(2)).unwrap(); + transaction.commit().unwrap(); + if done { break; } + } + let expected = authority_projection_snapshot(&reference); + assert_eq!(expected.0.len(), 5); + assert_eq!(expected.1.len(), 2); + drop(reference); + + // Commit one real backfill step rather than making the fixture's size depend on + // machine speed. The writer fence holds startup at this incomplete migration, + // so an actual process kill cannot race a fast daemon finishing all five rows. + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction, Duration::ZERO).unwrap()); + transaction.commit().unwrap(); + let partial = authority_backfill_progress(&connection); + assert!(partial.0 > 0, "must kill with durable forward progress"); + assert!(!partial.1, "the committed projection must still be incomplete"); + assert_eq!(authority_projection_snapshot(&connection).0.len(), 1); + let blocker = connection.transaction_with_behavior(rusqlite::TransactionBehavior::Immediate).unwrap(); + node.binary = PathBuf::from(st3()); + let pty = node.root.join("bin/pty"); + let mut daemon = DaemonProcess::spawn_isolated( + node.command(&["up", "--pty-binary", pty.to_str().unwrap(), "--web-listen", "off"]), + fs::File::create(node.root.join("daemon.log")).unwrap(), + fs::File::create(node.root.join("daemon.stderr.log")).unwrap(), + ).unwrap(); + let deadline = Instant::now() + Duration::from_secs(30); + loop { + assert!(daemon.try_wait().unwrap().is_none(), "candidate exited before interrupted startup:\n{}", node.logs()); + // Startup owns the directory fence before opening/migrating the store. + if fractal_daemon::node_identity::lock_directory(&node.state_dir()).is_err() { + break; + } + assert!(Instant::now() < deadline, "candidate did not acquire its startup state fence:\n{}", node.logs()); + tokio::time::sleep(Duration::from_millis(10)).await; + } + assert_eq!(authority_backfill_progress(&blocker), partial); + daemon.kill().unwrap(); + assert!(!daemon.wait().unwrap().success(), "the interrupted daemon must not exit gracefully"); + assert_eq!(authority_backfill_progress(&blocker), partial, "kill must retain the committed cursor"); + blocker.rollback().unwrap(); + drop(connection); + assert_eq!(authority_history(&node), history, "process kill must not alter raw evidence"); + + node.start().await; + wait_until("authority backfill becomes ready after daemon restart", 30, || async { + let reader = rusqlite::Connection::open_with_flags( + &database, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap(); + authority_backfill_progress(&reader).1 + }).await; + assert_authority_projection_ready(&node); + let reader = rusqlite::Connection::open_with_flags( + &database, rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY, + ).unwrap(); + assert_eq!(authority_projection_snapshot(&reader), expected, + "restart must converge exactly to uninterrupted authority and effective rows"); + assert_auth(&node, &active, true).await; + assert_auth(&node, &revoked, false).await; + assert_eq!(authority_history(&node), history, "restart must preserve every raw claim body"); +} + #[tokio::test(flavor = "multi_thread")] #[ignore = "needs ST3_COMPAT_BIN: the pinned previous published release"] async fn previous_release_authorizes_and_revokes_after_authority_projection_rollback() { diff --git a/scripts/ci-linux b/scripts/ci-linux index acb95178685..c26601b8bb9 100755 --- a/scripts/ci-linux +++ b/scripts/ci-linux @@ -46,8 +46,9 @@ fleet_compat() { fleet::service_grants::previous_release_refuses_service_grants_from_a_candidate_issuer \ fleet::service_grants::previous_release_refuses_offline_seeded_service_grants_with_its_own_origin \ fleet::service_grants::previous_release_refuses_plugin_service_grants_on_same_database_rollback \ - fleet::service_grants::previous_release_authorizes_and_revokes_after_authority_projection_rollback 2>&1 | tee "$logs/compat-result.log" || return - grep -q "test result: ok. 10 passed" "$logs/compat-result.log" || return + fleet::service_grants::previous_release_authorizes_and_revokes_after_authority_projection_rollback \ + fleet::service_grants::authority_projection_resumes_after_daemon_is_killed_with_committed_partial_backfill 2>&1 | tee "$logs/compat-result.log" || return + grep -q "test result: ok. 11 passed" "$logs/compat-result.log" || return # The GitHub plugin store beside an older poller, and that poller upgraded in place. cargo test -p fractal --locked --test integration -- --ignored --exact \ fleet::previous_release_poller_beside_a_github_plugin_member_and_its_upgrade 2>&1 | tee "$logs/compat-plugin-result.log" || return From c8716c89b1cc721d80392fc185077775c71e5166 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 09:56:26 +0100 Subject: [PATCH 27/52] Keep malformed grant bases out of indexed bearer authority until repaired agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/store/assistant_grant_authority.rs | 16 +++++++++++++--- .../store/assistant_grant_authority_tests.rs | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index e2a2a036cb6..2626be1d7ad 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -218,7 +218,11 @@ pub fn rebuild_subject(connection: &Connection, subject: &str) -> Result<()> { fn attach_claim(connection: &Connection, claim: &ClaimRecord) -> Result<()> { let mut changed = false; if claim.kind == GRANTED { - changed |= insert_authority(connection,claim,claim)?; + // A malformed base stays pending until a valid issuer policy repairs it. + // Otherwise a newer malformed copy could mask a valid bearer lookup. + if structurally_valid(claim,claim) { + changed |= insert_authority(connection,claim,claim)?; + } // Only this base's issuer prefix can attach to it. In particular, an // authenticated wrong-actor history cannot enlarge later admission work. let mut statement = connection.prepare_cached( @@ -228,17 +232,23 @@ fn attach_claim(connection: &Connection, claim: &ClaimRecord) -> Result<()> { for record in records { let transition: ClaimRecord = serde_json::from_str(&record?)?; if transition_valid(claim,&transition) { + if transition.kind == POLICY { + changed |= insert_authority(connection,claim,claim)?; + } changed |= insert_authority(connection,&transition,claim)?; } } } else { let mut statement = connection.prepare_cached( - "SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 - AND kind=?2 AND origin=?3 AND actor=?4")?; + "SELECT record FROM assistant_grant_pending WHERE grant_subject=?1 + AND authenticated=1 AND kind=?2 AND origin=?3 AND actor=?4")?; let records = statement.query_map(params![claim.subject,GRANTED,claim.origin,claim.actor], |row| row.get::<_,String>(0))?; for record in records { let grant: ClaimRecord = serde_json::from_str(&record?)?; if transition_valid(&grant,claim) { + if claim.kind == POLICY { + changed |= insert_authority(connection,&grant,&grant)?; + } changed |= insert_authority(connection,claim,&grant)?; } } diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index 2db037b426a..0c04a14be18 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -166,6 +166,25 @@ fn decisions(store: &Store, now: u64) -> Vec { .unwrap().into_iter().map(|claim| claim.id).collect() } +#[test] +fn malformed_base_cannot_mask_a_valid_credential_but_valid_policy_can_repair_it() { + let store = node("issuer", None); + let granted = append(&store, SUBJECT, GRANTED, fields()); + let digest = fields()["credential_hash"].as_str().unwrap().to_owned(); + let mut malformed = fields(); + malformed["expires_at_unix_ms"] = Value::Null; + let pending = append(&store, SUBJECT, GRANTED, malformed); + assert!(!authority::contains(&store.readers.get(), &pending.id).unwrap()); + assert_eq!(authority::by_credential(&store.readers.get(), &digest).unwrap().unwrap().id, granted.id); + assert_eq!(authority::latest(&store.readers.get(), SUBJECT, GRANTED).unwrap().unwrap().id, granted.id); + let mut renewal = fields(); + renewal["expires_at_unix_ms"] = json!(20000); + append(&store, SUBJECT, POLICY, renewal); + assert!(authority::contains(&store.readers.get(), &pending.id).unwrap()); + assert_eq!(authority::by_credential(&store.readers.get(), &digest).unwrap().unwrap().id, pending.id); + assert_reference_and_rebuild(&store); +} + #[test] fn late_envelope_signature_promotes_previously_admitted_grant() { let (source, key) = source(); From ffc6dc73b7d99f89e61e719e2fb43fca76ffc22a Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 10:59:20 +0100 Subject: [PATCH 28/52] Regenerate retryable authority-backfill client error classification agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-client/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/fractal-client/src/lib.rs b/crates/fractal-client/src/lib.rs index 97db3cd5445..6c381addde3 100644 --- a/crates/fractal-client/src/lib.rs +++ b/crates/fractal-client/src/lib.rs @@ -1281,6 +1281,7 @@ fn render_message(code: Option<&ErrorCode>, message: &str, human: bool) -> Strin | ErrorCode::RuntimeNotLocal | ErrorCode::PrivateNotesCarrierConflict | ErrorCode::GrantProfileConflict + | ErrorCode::AssistantGrantAuthorityNotReady | ErrorCode::PrivateNotesUnreachable | ErrorCode::PrivateNotesIndeterminate | ErrorCode::ArrangementExists From 03b2f4e6e65f90012ae09a093219e8143df3ec6d Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 11:11:35 +0100 Subject: [PATCH 29/52] Use structurally valid expired grant IDs in q39 comparisons agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../tests/daemon_cost/assistant_admission.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index d58fe48e100..ecdbef63b87 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -93,7 +93,6 @@ const NODE: &str = "benchmark-member"; const GRANTED: &str = "custom.client.assistant.v1.granted"; const POLICY: &str = "custom.client.assistant.v1.policy"; const REVOKED: &str = "custom.client.assistant.v1.revoked"; -const POLICY_RENEWALS: usize = 3; const INDEX: &str = "claims_assistant_v1_principal_expiry_index"; const CREATE_INDEX: &str = "CREATE INDEX claims_assistant_v1_principal_expiry_index ON claims(kind,COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt'),json_extract(body,'$.fields.expires_at_unix_ms'))"; const A_QUERY: &str = "SELECT id FROM claims WHERE kind=?1 AND COALESCE(json_extract(body,'$.fields.principal'),'assistant/chatgpt')=?2"; @@ -322,6 +321,8 @@ async fn authenticated_get_during_pairing() { assert!(smallclaims::profile::enabled(), "profiling must initialize before Store::open"); let indexed = variant == "indexed"; let history = number("ST_ADMISSION_HISTORY", 10_000); + let policy_renewals = count("ST_ADMISSION_RENEWALS", 3); + let invalid_history_ids = std::env::var_os("ST_ADMISSION_INVALID_HISTORY_IDS").is_some(); let samples = if counts_only { 0 } else { number("ST_ADMISSION_SAMPLES", 200) }; let foreign_active = count("ST_ADMISSION_FOREIGN_ACTIVE", 0); let overlays = count("ST_ADMISSION_WRONG_ORIGIN_OVERLAYS", 1000); @@ -409,7 +410,11 @@ async fn authenticated_get_during_pairing() { tokio::task::spawn_blocking(move || { for principal in ["assistant/chatgpt", "assistant/mcp"] { for row in 0..history { - let id = format!("history-{}-{row}", principal.trim_start_matches("assistant/")); + let id = if invalid_history_ids { + format!("history-{}-{row}", principal.trim_start_matches("assistant/")) + } else { + format!("{:024x}", row * 2 + usize::from(principal == "assistant/mcp")) + }; let mut fields = template.body["fields"].clone(); fields["principal"] = json!(principal); fields["grant_id"] = json!(format!("assistant-grant/{id}")); @@ -419,7 +424,7 @@ async fn authenticated_get_during_pairing() { let subject = format!("custom/client/assistant-v1-{id}"); fixture_store.append_claim(&ClaimInput { subject:subject.clone(), kind:GRANTED.into(), actor:Some(OWNER.into()), fields:serde_json::from_value(fields.clone()).unwrap(), evidence:vec![], expected_subject:None, idempotency_key:None }).unwrap(); - for revision in 0..POLICY_RENEWALS { + for revision in 0..policy_renewals { fields["policy_revision"] = json!(revision + 2); fields["expires_at_unix_ms"] = json!(revision + 2); fixture_store.append_claim(&ClaimInput { subject:subject.clone(), kind:POLICY.into(), @@ -587,7 +592,8 @@ async fn authenticated_get_during_pairing() { "host_description":"Observed local benchmark host; no prescribed hardware identity", "fixture_person_ids":[OWNER],"verified_foreign_same_profile_active_grants":foreign_active, "history_grants_per_principal":history,"initial_total_claim_rows":total_rows,"initial_granted_rows_by_principal":principal_rows, - "policy_renewals_per_expired_grant":POLICY_RENEWALS, + "policy_renewals_per_expired_grant":policy_renewals, + "invalid_expired_history_ids":invalid_history_ids, "wrong_origin_overlays_per_active_grant":overlays, "wrong_origin_overlay_active_grants":active.len(), "sql_work_scope":{"authentication":"current-thread completed traced SQL statements", From 7dd7b75c040a4324871bccf316fdcf0df55700ca Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 11:13:02 +0100 Subject: [PATCH 30/52] Adapt admission harness to current Unix socket readiness API agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal/tests/daemon_cost/assistant_admission.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fractal/tests/daemon_cost/assistant_admission.rs b/crates/fractal/tests/daemon_cost/assistant_admission.rs index ecdbef63b87..44fc088633b 100644 --- a/crates/fractal/tests/daemon_cost/assistant_admission.rs +++ b/crates/fractal/tests/daemon_cost/assistant_admission.rs @@ -364,7 +364,7 @@ async fn authenticated_get_during_pairing() { let (ready_tx, ready_rx) = tokio::sync::oneshot::channel(); let local_app = api::router(state.clone()); let local = tokio::spawn(async move { - api::serve_reserved_unix_with_ready(reserved, local_app, None, || { ready_tx.send(()).unwrap(); }).await.unwrap(); + api::serve_reserved_unix_with_ready(reserved, local_app, None, None, || { ready_tx.send(()).unwrap(); }).await.unwrap(); }); ready_rx.await.unwrap(); let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); From 36ecca321676f09da71a9bff7972be1befcb5018 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 11:21:43 +0100 Subject: [PATCH 31/52] Remove unused seccomp opcode without relaxing the clippy ratchet agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-daemon/src/tiles/seccomp.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/fractal-daemon/src/tiles/seccomp.rs b/crates/fractal-daemon/src/tiles/seccomp.rs index 68083e6852b..62aea9bfa3b 100644 --- a/crates/fractal-daemon/src/tiles/seccomp.rs +++ b/crates/fractal-daemon/src/tiles/seccomp.rs @@ -92,7 +92,6 @@ fn jump(code: u32, k: u32, jt: u8, jf: u8) -> libc::sock_filter { const LOAD: u32 = libc::BPF_LD | libc::BPF_W | libc::BPF_ABS; const EQUAL: u32 = libc::BPF_JMP | libc::BPF_JEQ | libc::BPF_K; -const AT_LEAST: u32 = libc::BPF_JMP | libc::BPF_JGE | libc::BPF_K; const ANY_BIT: u32 = libc::BPF_JMP | libc::BPF_JSET | libc::BPF_K; const RETURN: u32 = libc::BPF_RET | libc::BPF_K; From 405eda4efdb3bf2a7393bb647beb5aa1c0dc0a09 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 11:25:45 +0100 Subject: [PATCH 32/52] Scope x32 comparison opcode to x86 and seccomp interpreter tests agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-daemon/src/tiles/seccomp.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/fractal-daemon/src/tiles/seccomp.rs b/crates/fractal-daemon/src/tiles/seccomp.rs index 62aea9bfa3b..4d7b6ebeba8 100644 --- a/crates/fractal-daemon/src/tiles/seccomp.rs +++ b/crates/fractal-daemon/src/tiles/seccomp.rs @@ -92,6 +92,8 @@ fn jump(code: u32, k: u32, jt: u8, jf: u8) -> libc::sock_filter { const LOAD: u32 = libc::BPF_LD | libc::BPF_W | libc::BPF_ABS; const EQUAL: u32 = libc::BPF_JMP | libc::BPF_JEQ | libc::BPF_K; +#[cfg(any(target_arch = "x86_64", test))] +const AT_LEAST: u32 = libc::BPF_JMP | libc::BPF_JGE | libc::BPF_K; const ANY_BIT: u32 = libc::BPF_JMP | libc::BPF_JSET | libc::BPF_K; const RETURN: u32 = libc::BPF_RET | libc::BPF_K; From b456376f8853844cb1ae29c6c1823e3d033753a3 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 12:40:01 +0100 Subject: [PATCH 33/52] Correct raw-history repair oracle and late-signature admission fixture agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/store/assistant_grant_authority_tests.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index 0c04a14be18..c8d775cfad8 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -127,10 +127,16 @@ fn reference(store: &Store) -> Vec<(String, String, bool)> { && f["credential_hash"].as_str().is_some_and(|s| s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit())) }; let mut expected = Vec::new(); - for grant in claims.iter().filter(|claim| claim.kind == GRANTED && trusted(claim) && policy(claim)) { + let base = |claim: &ClaimRecord| { + let f = &claim.body["fields"]; + identity(claim) && f.get("credential").is_none() && f.get("code").is_none() + && f["credential_hash"].as_str().is_some_and(|s| s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit())) + }; + for grant in claims.iter().filter(|claim| claim.kind == GRANTED && trusted(claim) && base(claim)) { let selected = claims.iter().rev().find(|claim| { claim.kind == POLICY && claim.origin == grant.origin && trusted(claim) && policy(claim) }).unwrap_or(grant); + if !policy(selected) { continue; } let revoked = claims.iter().any(|claim| { claim.kind == REVOKED && claim.origin == grant.origin && trusted(claim) && identity(claim) }); @@ -189,7 +195,6 @@ fn malformed_base_cannot_mask_a_valid_credential_but_valid_policy_can_repair_it( fn late_envelope_signature_promotes_previously_admitted_grant() { let (source, key) = source(); let target = node("reader", Some(key.public())); - receive(&target, &export(&source, &target)); let grant = append(&source, SUBJECT, GRANTED, fields()); let exchange = export(&source, &target); receive(&target, &unsigned(&exchange)); From 1273a3511c8db9176f311aaca07717375526d1fd Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 12:52:23 +0100 Subject: [PATCH 34/52] Maintain authority in legacy test import and distinguish evidence from credentials agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/assistant/authorization_tests.rs | 3 ++- .../src/api/client_v0/external_grants/conflict_tests.rs | 4 ++-- crates/fractal-store/src/store/shared.rs | 9 +++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs index b29a73ab0b9..41a3f8d9d07 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs @@ -121,7 +121,8 @@ async fn p1_owner_transitions_ignore_wrong_origin_overlays_but_fence_the_subject expected_subject: None, idempotency_key: None, }).unwrap(); fixture.state.store.import_replication("wrong-origin", &peer.export_replication(0).unwrap()).unwrap(); - assert_eq!(latest(&fixture.state, &subject, kind).unwrap().unwrap().id, claim.id); + assert!(fixture.state.store.claim_by_id(&claim.id).unwrap().is_some(), + "wrong-origin evidence must remain in raw history without becoming authority"); assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").unwrap().is_some()); }; diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index a9375858b34..f997665b0e3 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -271,8 +271,8 @@ fn compat_counterexample_suspends_the_valid_pair_and_refuses_the_malformed_servi for id in [assistant, service] { assert_conflict(&authenticate_id(&state, id).expect_err("the valid opposite pair is suspended")); } - let refused = authenticate_id(&state, malformed).expect_err("service grants never authenticate"); - assert_eq!((refused.status, refused.code.as_str()), (StatusCode::FORBIDDEN, "forbidden")); + assert!(authenticate_id(&state, malformed).unwrap().is_none(), + "malformed service evidence must not enter bearer authority"); } #[test] diff --git a/crates/fractal-store/src/store/shared.rs b/crates/fractal-store/src/store/shared.rs index d796a6ecc65..f8a6e6e53d2 100644 --- a/crates/fractal-store/src/store/shared.rs +++ b/crates/fractal-store/src/store/shared.rs @@ -259,6 +259,15 @@ impl Store { .map_err(internal)?; if inserted != 0 { let index = transaction.last_insert_rowid() as u64; + if matches!(claim.kind.as_str(), + smallclaims::store::assistant_grant_authority::GRANTED + | smallclaims::store::assistant_grant_authority::POLICY + | smallclaims::store::assistant_grant_authority::REVOKED) + { + smallclaims::store::assistant_grant_authority::refresh_claim( + &transaction, &claim.id, false, + ).map_err(internal)?; + } let effective = register_operation_tx(&transaction, claim).map_err(internal)?; if effective { insert_event( From c774424a6dcb8494a572146657efa693ef218166 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:00:48 +0100 Subject: [PATCH 35/52] Record synthetic authority backfill timing and qualified 50GB extrapolation agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- release-notes/external-grant-profile-conflict.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 6730cc276a4..f53e4a86006 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -19,7 +19,7 @@ }, "downtime": { "status": "changed", - "detail": "No offline migration window is planned: startup work is bounded with an approximately two-second budget planned, and retained history is backfilled in the background. Startup and total backfill durations have not been measured. Assistant authorization is temporarily unavailable with retryable assistant-grant-authority-not-ready until the local projection is ready; this is an authorization interruption, not a requirement to stop the daemon for the entire backfill. Affected people also cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend that interruption until revocations replicate." + "detail": "No offline migration window is planned: startup backfill has an approximately two-second budget, then continues in bounded background slices. A synthetic 3.73 GB store with one million claims and 1% grant-kind rows measured a 1.892-second startup slice and 1.919-second total backfill, with 54,940 KiB process peak RSS; linear same-mix throughput extrapolation to 50 GB is 25.750 seconds, not a production or cold-cache guarantee. The startup slice excludes Store::open and does not predict total daemon startup time. Assistant authorization is temporarily unavailable with retryable assistant-grant-authority-not-ready until the local projection is ready; this is an authorization interruption, not a requirement to stop the daemon for the entire backfill. Affected people also cannot authenticate with any external grant while a profile conflict remains visible; a partition can extend that interruption until revocations replicate." }, "manual": { "status": "changed", From c12b224f5d3cd25267ba356a523560ed259347e6 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:13:05 +0100 Subject: [PATCH 36/52] fix: keep assistant authority maintenance reactive after backfill agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../assistant_grant_authority_wake_tests.rs | 31 +++++++++++++++++++ crates/fractal/src/main.rs | 30 +++++++++++++++--- docs/st3/client-v0/schemas/operations.json | 1 + 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 crates/fractal/src/assistant_grant_authority_wake_tests.rs diff --git a/crates/fractal/src/assistant_grant_authority_wake_tests.rs b/crates/fractal/src/assistant_grant_authority_wake_tests.rs new file mode 100644 index 00000000000..c8e44a237d8 --- /dev/null +++ b/crates/fractal/src/assistant_grant_authority_wake_tests.rs @@ -0,0 +1,31 @@ +use super::*; +use smallclaims::store::assistant_grant_authority as authority; + +#[tokio::test] +async fn completed_authority_reconciles_older_build_appends_without_reopen() { + let store = Arc::new(Store::open_memory("node").unwrap()); + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + assert!(authority::ready(&store.readers.get()).is_ok()); + let task = tokio::spawn(build_assistant_grant_authority(store.clone())); + // The old writer bypasses projection hooks. Only the persistent insert + // trigger and the store's commit notification connect it to maintenance. + // An invalid grant is still durable dirty work and must be reconciled. + store.connection.write().execute_batch( + "BEGIN; + INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch/old-writer','node',1,'old-writer','1'); + INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES('claim/old-writer','batch/old-writer','custom/client/assistant-v1-invalid', + 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1'); + COMMIT;" + ).unwrap(); + assert!(authority::ready(&store.readers.get()).is_err()); + tokio::time::timeout(Duration::from_secs(5), async { + loop { + if authority::ready(&store.readers.get()).is_ok() { break; } + tokio::task::yield_now().await; + } + }).await.expect("a completed projection wakes and drains compatibility work"); + assert!(!authority::contains(&store.readers.get(), "claim/old-writer").unwrap()); + task.abort(); +} diff --git a/crates/fractal/src/main.rs b/crates/fractal/src/main.rs index cd2be3b4e5e..1dbd6702855 100644 --- a/crates/fractal/src/main.rs +++ b/crates/fractal/src/main.rs @@ -20817,15 +20817,32 @@ async fn build_transport_observation_index(store: Arc) { } } -/// Continue the persisted authority cursor after serving begins. Authorization -/// fails closed until the final page commits; requests never advance the cursor. +/// Continue the persisted authority cursor after serving begins, then reconcile +/// compatibility-trigger work on commits. Subscribe before checking readiness so +/// an older-build append between the check and the wait cannot be lost. async fn build_assistant_grant_authority(store: Arc) { + let (changed, mut receiver) = tokio::sync::watch::channel(()); + let _observer = store.observe_commits(move |connection| { + if connection.is_autocommit() { + changed.send_replace(()); + } + }); loop { + receiver.borrow_and_update(); let worker = store.clone(); - let result = tokio::task::spawn_blocking(move || - worker.advance_assistant_grant_authority_backfill()).await; + let result = tokio::task::spawn_blocking(move || { + if smallclaims::store::assistant_grant_authority::ready(&worker.readers.get()).is_ok() { + return Ok(true); + } + worker.advance_assistant_grant_authority_backfill() + }).await; match result { - Ok(Ok(true)) => return, + Ok(Ok(true)) => { + if receiver.changed().await.is_err() { + return; + } + continue; + } Ok(Ok(false)) => {} Ok(Err(error)) if maintenance_contention(&error) => {} error => { @@ -20838,6 +20855,9 @@ async fn build_assistant_grant_authority(store: Arc) { } } +#[cfg(test)] +mod assistant_grant_authority_wake_tests; + /// This starts only after both APIs serve. Each page reads up to 32 operation claims on a /// reader, then joins the managed background writer queue only to insert their keys, and /// yields for 100 ms. The operation audit reads bodies until the last page marks it ready. diff --git a/docs/st3/client-v0/schemas/operations.json b/docs/st3/client-v0/schemas/operations.json index 9411a43148f..59666b3f49f 100644 --- a/docs/st3/client-v0/schemas/operations.json +++ b/docs/st3/client-v0/schemas/operations.json @@ -20,6 +20,7 @@ "assistant_grant_authority_contract": { "projection_version": 1, "backfill": "resumable-background", + "compatibility_reconciliation": "commit-notification-driven-background-dirty-drain", "authorization_during_backfill": "fail-closed", "not_ready_error": { "code": "assistant-grant-authority-not-ready", From 0cc74fa880dbf005837c3b6d876cb2a116ce0764 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:13:42 +0100 Subject: [PATCH 37/52] fix: reconcile late assistant grant envelope signatures agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/store/assistant_grant_authority.rs | 14 ++- .../store/assistant_grant_authority_tests.rs | 118 ++++++++++++++++++ docs/st3/external-assistants.md | 1 + 3 files changed, 131 insertions(+), 2 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index 2626be1d7ad..d8581884d61 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -115,6 +115,16 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') BEGIN INSERT OR IGNORE INTO assistant_grant_dirty VALUES(NEW.id); END; + CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_signature_insert + AFTER INSERT ON replica_envelope_signatures + BEGIN + INSERT OR IGNORE INTO assistant_grant_dirty(claim_id) + SELECT records.claim_id FROM replica_records AS records + JOIN claims ON claims.id=records.claim_id + WHERE records.writer=NEW.writer AND records.sequence=NEW.sequence + AND records.envelope_hash=NEW.envelope_hash + AND claims.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked'); + END; CREATE TABLE IF NOT EXISTS assistant_grant_membership_windows ( writer TEXT NOT NULL, member_key TEXT NOT NULL, start INTEGER NOT NULL, end INTEGER, PRIMARY KEY(writer,member_key));" @@ -378,8 +388,8 @@ fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::M } /// Resumable, idempotent versioned backfill. Each page uses claims_kind_index; /// unrelated claims are never visited. Cursor and projection changes commit -/// together in the caller's transaction. Old-build appends are captured by the -/// additive dirty trigger even after the version has completed. +/// together in the caller's transaction. Old-build appends and signature-only +/// arrivals are captured by persistent dirty triggers even after completion. pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result { let started = Instant::now(); let origin = local_origin(connection)?; diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index c8d775cfad8..b27d1027c08 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -208,6 +208,124 @@ fn late_envelope_signature_promotes_previously_admitted_grant() { assert_reference_and_rebuild(&target); } +fn backfill_markers(connection: &Connection) -> Vec<(String, String)> { + connection.prepare( + "SELECT key,value FROM meta WHERE key='assistant_grant_authority_version' + OR key='assistant_grant_authority_membership_generation' + OR key LIKE 'assistant_grant_authority_cursor/%' ORDER BY key" + ).unwrap().query_map([], |row| Ok((row.get(0)?, row.get(1)?))) + .unwrap().collect::>().unwrap() +} + +fn insert_raw_signature(connection: &Connection, signature: &ReplicaEnvelopeSignature) { + connection.execute( + "INSERT OR IGNORE INTO replica_envelope_signatures + (writer,sequence,envelope_hash,member_key,signature,stored_at_unix_ms) + VALUES(?1,?2,?3,?4,?5,'0')", + params![signature.writer,signature.sequence,signature.hash,signature.member_key,signature.signature], + ).unwrap(); +} + +#[test] +fn raw_signature_only_insert_survives_reopen_and_promotes_grant_policy_and_revoke_without_rescan() { + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("late-signature.sqlite3"); + let (source, key) = source(); + let mut target = Store::open(&path, "reader", Arc::new(Plain)).unwrap(); + target.bind_fleet(FLEET).unwrap(); + target.pin_fleet_anchor(key.public()).unwrap(); + // Establish membership first: no membership change may drive these promotions. + receive(&target, &export(&source, &target)); + let mut grant_id = String::new(); + for kind in [GRANTED, POLICY, REVOKED] { + let mut value = fields(); + if kind == POLICY { value["expires_at_unix_ms"] = json!(20000); } + let claim = append(&source, SUBJECT, kind, value); + if kind == GRANTED { grant_id.clone_from(&claim.id); } + let exchange = export(&source, &target); + receive(&target, &unsigned(&exchange)); + assert!(raw_claims(&target).iter().any(|record| record.id == claim.id)); + assert!(!authority::contains(&target.readers.get(), &claim.id).unwrap()); + while !target.advance_assistant_grant_authority_backfill().unwrap() {} + let markers = backfill_markers(&target.readers.get()); + authority::ready(&target.readers.get()).unwrap(); + drop(target); + + // Simulate an older writer, bypassing every Store admission/refresh hook. + { + let connection = Connection::open(&path).unwrap(); + for signature in signatures(&exchange).signatures { + insert_raw_signature(&connection, &signature); + } + let dirty: Vec = connection.prepare( + "SELECT claim_id FROM assistant_grant_dirty ORDER BY claim_id" + ).unwrap().query_map([], |row| row.get(0)).unwrap() + .collect::>().unwrap(); + assert_eq!(dirty, vec![claim.id.clone()]); + assert!(authority::ready(&connection).is_err()); + assert_eq!(backfill_markers(&connection), markers); + } + // Reopen before Store startup can drain the durable queue automatically. + { + let mut connection = Connection::open(&path).unwrap(); + assert!(authority::ready(&connection).is_err()); + let transaction = connection.transaction().unwrap(); + assert!(authority::backfill_slice(&transaction, Duration::from_secs(60)).unwrap()); + authority::ready(&transaction).unwrap(); + assert!(authority::contains(&transaction, &claim.id).unwrap()); + assert_eq!(backfill_markers(&transaction), markers, "completed history or membership was rescanned"); + transaction.commit().unwrap(); + } + target = Store::open(&path, "reader", Arc::new(Plain)).unwrap(); + assert_reference_and_rebuild(&target); + if kind == REVOKED { + assert!(decisions(&target, 0).is_empty()); + let revoked: bool = target.readers.get().query_row( + "SELECT revoked FROM assistant_grant_effective WHERE claim_id=?1", + [&grant_id], |row| row.get(0), + ).unwrap(); + assert!(revoked); + } else { + assert_eq!(decisions(&target, 0), vec![grant_id.clone()]); + assert_eq!(decisions(&target, 15000).is_empty(), kind == GRANTED); + } + } +} + +#[test] +fn malformed_raw_signature_row_is_drained_without_authenticating_a_pending_revoke() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let grant = append(&source, SUBJECT, GRANTED, fields()); + receive(&target, &export(&source, &target)); + let revoke = append(&source, SUBJECT, REVOKED, fields()); + let exchange = export(&source, &target); + receive(&target, &unsigned(&exchange)); + while !target.advance_assistant_grant_authority_backfill().unwrap() {} + let markers = backfill_markers(&target.readers.get()); + { + let mut connection = target.connection.write(); + for mut signature in signatures(&exchange).signatures { + signature.signature = "not-an-ed25519-signature".into(); + insert_raw_signature(&connection, &signature); + } + assert!(authority::ready(&connection).is_err()); + let transaction = connection.transaction().unwrap(); + assert!(authority::backfill_slice(&transaction, Duration::from_secs(60)).unwrap()); + authority::ready(&transaction).unwrap(); + assert!(!authority::contains(&transaction, &revoke.id).unwrap()); + let authenticated: bool = transaction.query_row( + "SELECT authenticated FROM assistant_grant_pending WHERE claim_id=?1", + [&revoke.id], |row| row.get(0), + ).unwrap(); + assert!(!authenticated); + assert_eq!(backfill_markers(&transaction), markers); + transaction.commit().unwrap(); + } + assert_eq!(decisions(&target, 0), vec![grant.id]); + assert_reference_and_rebuild(&target); +} + #[test] fn membership_sealed_after_grant_admission_promotes_pending_authority() { let (source, key) = source(); diff --git a/docs/st3/external-assistants.md b/docs/st3/external-assistants.md index a9cebb9bf09..9fb654d3788 100644 --- a/docs/st3/external-assistants.md +++ b/docs/st3/external-assistants.md @@ -208,6 +208,7 @@ Approved reads disclose data to the external model provider. A compromised execu - Each request rechecks the authoritative grant, revocation, expiry, and current policy. Revocation targets the exact grant, not a shared device actor. Restart must not revive a revoked or expired grant. - Completion, authenticated assistant requests, renewal/policy changes, and revocation must reach the authoritative grant-issuer member. Replicated grants cannot establish current revocation/policy authority or enable cross-member proof replay. - Versioned assistant grant/revocation claims are separate from historical person claims. Credentials are stored authoritatively as digests, never bearers. Public projections must not expose credential digests. Rebuildable projections are not sole authorization authority. +- Replicated grant, policy, and revocation claims acquire projection authority only after their envelope signatures verify against the keyed membership window. A persistent SQLite trigger queues affected grant-kind records when a signature is inserted, including by older writers without projection hooks. Background draining survives reopen and reruns cryptographic authentication without rescanning completed claim history or requiring a membership change; signature-row presence alone never grants authority. - Creation, completion, renewal, policy change, and revocation outcomes must retain issuer, actor, transport, timestamps, and claim references for audit. Logs and public CLI output must not expose bearer credentials or private keys. ### Pairing verifier and recovery From 2631056d5239091dfc73332b1e6b2f52d6018f1c Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:21:08 +0100 Subject: [PATCH 38/52] fix: persist local grant append provenance and reject ambiguous history agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-api-core/src/api.rs | 35 +++++ crates/fractal-api-core/src/api/tests.rs | 39 ++++++ crates/fractal-store/src/store/runtime.rs | 16 ++- crates/fractal-store/src/store/shared.rs | 2 +- .../assistant_grant_authority_wake_tests.rs | 35 ++--- crates/fractal/tests/fleet/service_grants.rs | 13 +- crates/smallclaims/src/store.rs | 7 +- .../src/store/assistant_grant_authority.rs | 28 ++-- .../store/assistant_grant_authority_bench.rs | 12 ++ .../store/assistant_grant_authority_tests.rs | 122 ++++++++++++++++++ docs/st3/external-assistants.md | 38 ++++++ .../external-grant-profile-conflict.json | 6 +- 12 files changed, 314 insertions(+), 39 deletions(-) diff --git a/crates/fractal-api-core/src/api.rs b/crates/fractal-api-core/src/api.rs index 024721fc38d..71ad6e6a7b5 100644 --- a/crates/fractal-api-core/src/api.rs +++ b/crates/fractal-api-core/src/api.rs @@ -9482,6 +9482,38 @@ pub(crate) fn fleet_admission_check( } } +fn pending_assistant_grant_checks( + connection: &rusqlite::Connection, + local_origin: &str, +) -> anyhow::Result> { + let mut statement = connection.prepare_cached( + "SELECT pending.claim_id,pending.kind,pending.origin,pending.actor + FROM assistant_grant_pending pending + WHERE pending.authenticated=0 + AND pending.kind='custom.client.assistant.v1.granted' + AND NOT EXISTS(SELECT 1 FROM assistant_grant_local_appends local + WHERE local.claim_id=pending.claim_id) + ORDER BY pending.claim_id", + )?; + let rows = statement.query_map([], |row| { + Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?, + row.get::<_, String>(2)?, row.get::<_, String>(3)?)) + })?; + rows.map(|row| { + let (id, kind, origin, actor) = row?; + let reason = if origin == local_origin { + "grant predates local-append provenance; re-issue" + } else { + "grant lacks local-append provenance and verified member signature/membership; issuance age unknown" + }; + Ok(DoctorCheck { + name: "assistant-grant-provenance".into(), + status: "warn".into(), + message: format!("{id}: {reason}; kind={kind}; origin={origin}; actor={actor}"), + }) + }).collect() +} + fn doctor_report_within( state: &AppState, clock: &DoctorClock, @@ -9525,6 +9557,9 @@ fn doctor_report_within( message: error.to_string(), }), } + checks.extend(pending_assistant_grant_checks( + &state.store.readers.get(), state.store.origin(), + ).map_err(ApiError::internal)?); Ok(checks) }); checks.check("claim-signatures", || { diff --git a/crates/fractal-api-core/src/api/tests.rs b/crates/fractal-api-core/src/api/tests.rs index 066bb3f51d1..76a987e2b30 100644 --- a/crates/fractal-api-core/src/api/tests.rs +++ b/crates/fractal-api-core/src/api/tests.rs @@ -1044,6 +1044,45 @@ async fn native_session_reports_cannot_replace_a_successor_binding() { assert_eq!(state.store.claims_for(subject, Some("harness.session-file")).unwrap().len(), 2); } +#[test] +fn doctor_lists_unmarked_pending_grants_without_dating_remote_history() { + let store = Store::open_memory("amber").unwrap(); + let connection = store.connection.lock().expect("fixture writer"); + for (id, kind, origin, authenticated) in [ + ("claim/local-a", "custom.client.assistant.v1.granted", "amber", 0), + ("claim/local-b", "custom.client.assistant.v1.granted", "amber", 0), + ("claim/remote", "custom.client.assistant.v1.granted", "birch", 0), + ("claim/verified", "custom.client.assistant.v1.granted", "amber", 1), + ("claim/marked", "custom.client.assistant.v1.granted", "amber", 0), + ("claim/policy", "custom.client.assistant.v1.policy", "amber", 0), + ("claim/revoked", "custom.client.assistant.v1.revoked", "amber", 0), + ] { + connection.execute( + "INSERT INTO assistant_grant_pending + (claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) + VALUES(?1,?1,?2,?3,'person/operator',1,?4,'{}')", + rusqlite::params![id, kind, origin, authenticated], + ).unwrap(); + } + connection.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES('claim/marked')", [], + ).unwrap(); + let checks = pending_assistant_grant_checks(&connection, "amber").unwrap(); + assert_eq!(checks.len(), 3); + for (check, id) in checks[..2].iter().zip(["claim/local-a", "claim/local-b"]) { + assert_eq!(check.name, "assistant-grant-provenance"); + assert_eq!(check.status, "warn"); + assert_eq!(check.message, format!( + "{id}: grant predates local-append provenance; re-issue; kind=custom.client.assistant.v1.granted; origin=amber; actor=person/operator" + )); + } + assert!(checks[2].message.starts_with("claim/remote: grant lacks local-append provenance")); + assert!(checks[2].message.contains("issuance age unknown")); + assert!(!checks[2].message.contains("predates")); + connection.execute("UPDATE assistant_grant_pending SET authenticated=1", []).unwrap(); + assert!(pending_assistant_grant_checks(&connection, "amber").unwrap().is_empty()); +} + #[test] fn doctor_flags_low_descriptor_limits_and_high_usage() { let low = descriptor_usage_check(256, 8192, Some(92)); diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index d187a326d64..e82e30401b8 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -937,6 +937,13 @@ mod schema_install_tests { append(&connection, "revoke", 3, authority::REVOKED, "assistant/chatgpt", 200); append(&connection, "mcp", 4, authority::GRANTED, "assistant/mcp", 200); append(&connection, "unrelated", 5, "custom.test.recorded", "assistant/chatgpt", 200); + // These fixture rows model durable local appends. Truly old, + // unmarked raw evidence is ambiguous and must remain pending. + for id in ["active", "extended", "expired", "revoked", "revoke", "mcp"] { + connection.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES(?1)", [id], + ).unwrap(); + } let before = snapshot(&connection); let indexes_before = claims_indexes(&connection); drop(connection); @@ -977,12 +984,15 @@ mod schema_install_tests { && step.contains("principal=? AND owner=? AND revoked=? AND expires_at>?")), "{plan:?}"); assert!(plan.iter().all(|step| !step.contains("SCAN claims") && !step.contains("SEARCH claims")), "{plan:?}"); - // An older build can append raw evidence after backfill. The additive - // trigger closes admission until that evidence has been projected. + // An older build can append raw evidence after backfill. The + // trigger closes admission until reconciliation, but origin + // text alone cannot authenticate this unmarked late revoke. append(&connection, "late-revoke", 1, authority::REVOKED, "assistant/chatgpt", 200); assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).is_err()); while !authority::backfill_slice(&connection, Duration::from_secs(1)).unwrap() {} - assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).unwrap().is_empty()); + assert_eq!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None) + .unwrap().iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert!(!authority::contains(&connection, "late-revoke").unwrap()); let after = snapshot(&connection); let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); drop(connection); diff --git a/crates/fractal-store/src/store/shared.rs b/crates/fractal-store/src/store/shared.rs index f8a6e6e53d2..5cd56982aec 100644 --- a/crates/fractal-store/src/store/shared.rs +++ b/crates/fractal-store/src/store/shared.rs @@ -265,7 +265,7 @@ impl Store { | smallclaims::store::assistant_grant_authority::REVOKED) { smallclaims::store::assistant_grant_authority::refresh_claim( - &transaction, &claim.id, false, + &transaction, &claim.id, ).map_err(internal)?; } let effective = register_operation_tx(&transaction, claim).map_err(internal)?; diff --git a/crates/fractal/src/assistant_grant_authority_wake_tests.rs b/crates/fractal/src/assistant_grant_authority_wake_tests.rs index c8e44a237d8..e538075d6ea 100644 --- a/crates/fractal/src/assistant_grant_authority_wake_tests.rs +++ b/crates/fractal/src/assistant_grant_authority_wake_tests.rs @@ -11,21 +11,26 @@ async fn completed_authority_reconciles_older_build_appends_without_reopen() { // trigger and the store's commit notification connect it to maintenance. // An invalid grant is still durable dirty work and must be reconciled. store.connection.write().execute_batch( - "BEGIN; - INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) - VALUES('batch/old-writer','node',1,'old-writer','1'); - INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) - VALUES('claim/old-writer','batch/old-writer','custom/client/assistant-v1-invalid', - 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1'); - COMMIT;" + "INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch/old-writer','node',1,'old-writer','1');" ).unwrap(); - assert!(authority::ready(&store.readers.get()).is_err()); - tokio::time::timeout(Duration::from_secs(5), async { - loop { - if authority::ready(&store.readers.get()).is_ok() { break; } - tokio::task::yield_now().await; - } - }).await.expect("a completed projection wakes and drains compatibility work"); - assert!(!authority::contains(&store.readers.get(), "claim/old-writer").unwrap()); + // Two independently committed appends ensure this exercises an already + // completed worker, even if its first poll races the initial raw append. + for id in ["claim/old-writer/first", "claim/old-writer/second"] { + store.connection.write().execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,'batch/old-writer','custom/client/assistant-v1-invalid', + 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1')", + [id], + ).unwrap(); + assert!(authority::ready(&store.readers.get()).is_err()); + tokio::time::timeout(Duration::from_secs(5), async { + loop { + if authority::ready(&store.readers.get()).is_ok() { break; } + tokio::task::yield_now().await; + } + }).await.expect("a completed projection wakes and drains compatibility work"); + assert!(!authority::contains(&store.readers.get(), id).unwrap()); + } task.abort(); } diff --git a/crates/fractal/tests/fleet/service_grants.rs b/crates/fractal/tests/fleet/service_grants.rs index ba0893b5afa..94b4a97a0f9 100644 --- a/crates/fractal/tests/fleet/service_grants.rs +++ b/crates/fractal/tests/fleet/service_grants.rs @@ -380,8 +380,8 @@ async fn authority_projection_resumes_after_daemon_is_killed_with_committed_part if done { break; } } let expected = authority_projection_snapshot(&reference); - assert_eq!(expected.0.len(), 5); - assert_eq!(expected.1.len(), 2); + assert!(expected.0.is_empty(), "pre-marker Legacy grants lack authenticated writer provenance"); + assert!(expected.1.is_empty()); drop(reference); // Commit one real backfill step rather than making the fixture's size depend on @@ -393,7 +393,8 @@ async fn authority_projection_resumes_after_daemon_is_killed_with_committed_part let partial = authority_backfill_progress(&connection); assert!(partial.0 > 0, "must kill with durable forward progress"); assert!(!partial.1, "the committed projection must still be incomplete"); - assert_eq!(authority_projection_snapshot(&connection).0.len(), 1); + assert!(authority_projection_snapshot(&connection).0.is_empty(), + "a partial cursor must not turn ambiguous Legacy evidence into authority"); let blocker = connection.transaction_with_behavior(rusqlite::TransactionBehavior::Immediate).unwrap(); node.binary = PathBuf::from(st3()); let pty = node.root.join("bin/pty"); @@ -433,7 +434,7 @@ async fn authority_projection_resumes_after_daemon_is_killed_with_committed_part ).unwrap(); assert_eq!(authority_projection_snapshot(&reader), expected, "restart must converge exactly to uninterrupted authority and effective rows"); - assert_auth(&node, &active, true).await; + assert_auth(&node, &active, false).await; assert_auth(&node, &revoked, false).await; assert_eq!(authority_history(&node), history, "restart must preserve every raw claim body"); } @@ -470,7 +471,9 @@ async fn previous_release_authorizes_and_revokes_after_authority_projection_roll node.start().await; assert_eq!(node.state_dir(), state); assert_authority_projection_ready(&node); - assert_auth(&node, &active, true).await; + // The old standalone issuer had no member signature or local-append marker. + // The upgrade preserves evidence but requires its owner to re-issue. + assert_auth(&node, &active, false).await; assert_auth(&node, &revoked, false).await; assert_eq!(authority_history(&node), history, "backfill must not rewrite raw evidence"); diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 6f5cb318c40..b26ecdd8cd7 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -2194,7 +2194,12 @@ pub /* sqlite-large-value-flow: allow-for-now flow-h8ff255a3c271 owner=smallclai ])?; let store_index = transaction.last_insert_rowid() as u64; if matches!(kind, assistant_grant_authority::GRANTED | assistant_grant_authority::POLICY | assistant_grant_authority::REVOKED) { - assistant_grant_authority::refresh_claim(transaction, id, true)?; + // This function is the local append boundary; replicated admission uses + // its own insert path and must never write this marker. + transaction.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES(?1)", [id], + )?; + assistant_grant_authority::refresh_claim(transaction, id)?; } Ok(store_index) } diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index d8581884d61..32be958bb21 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -112,6 +112,7 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { CREATE INDEX IF NOT EXISTS assistant_grant_pending_writer_index ON assistant_grant_pending(origin,authenticated,sequence,claim_id); CREATE TABLE IF NOT EXISTS assistant_grant_dirty (claim_id TEXT PRIMARY KEY); + CREATE TABLE IF NOT EXISTS assistant_grant_local_appends (claim_id TEXT PRIMARY KEY); CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') BEGIN INSERT OR IGNORE INTO assistant_grant_dirty VALUES(NEW.id); END; @@ -271,7 +272,7 @@ fn local_origin(connection: &Connection) -> Result { } /// Admission pays structural/authentication cost once. Invalid rows never enter /// the authority or the pending-authentication writer/window index. -pub fn refresh_claim(connection: &Connection, id: &str, trusted_local: bool) -> Result<()> { +pub fn refresh_claim(connection: &Connection, id: &str) -> Result<()> { static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| format!("SELECT {CLAIM_COLUMNS} FROM claims WHERE id=?1")); let claim = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h1665a4a8cfdf owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ &QUERY)?.query_row(/* sqlite-large-value: allow-for-now lv-h5520ddeb5d20 owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ [id], claim_from_row).optional()?; @@ -281,7 +282,14 @@ pub fn refresh_claim(connection: &Connection, id: &str, trusted_local: bool) -> else if claim.kind==POLICY { policy_fields(&claim) } else { identity(&claim) }; if valid { let sequence: u64 = connection.query_row("SELECT replica_sequence FROM batches WHERE id=?1", [&claim.batch_id], |row| row.get(0))?; - let authenticated = (trusted_local && claim.origin == local_origin(connection)?) + // Only the local append transaction can create this durable admission + // fact. Origin text and the absence of a receipt prove nothing: legacy + // imports can also have neither envelopes nor replica records. + let local_append: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_local_appends WHERE claim_id=?1)", + [&claim.id], |row| row.get(0), + )?; + let authenticated = (local_append && claim.origin == local_origin(connection)?) || authenticated_claim(connection,&claim.id)?; let changed = connection.execute(/* sqlite-large-value: allow-for-now lv-h9cf86ad98d1e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) VALUES(?1,?2,?3,?4,?5,?6,?7,?8) ON CONFLICT(claim_id) DO UPDATE SET authenticated=excluded.authenticated @@ -323,7 +331,7 @@ pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, ha statement.query_map(params![writer,sequence,hash], |row| row.get::<_,String>(0))?.collect::>>()? }; // A replicated same-origin claim does NOT acquire the local-write exception. - for id in ids { refresh_claim(connection,&id,false)?; } + for id in ids { refresh_claim(connection,&id)?; } Ok(()) } /// Membership changes promote pending rows only in newly changed keyed windows. @@ -379,7 +387,7 @@ fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::M }; if ids.is_empty() { break; } for (sequence,id) in ids { - refresh_claim(connection,&id,false)?; + refresh_claim(connection,&id)?; cursor = (sequence,id); } } @@ -392,7 +400,6 @@ fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::M /// arrivals are captured by persistent dirty triggers even after completion. pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result { let started = Instant::now(); - let origin = local_origin(connection)?; refresh_membership(connection)?; // A completed version only drains the old-build dirty queue. Readiness also // includes that queue, but must never cause a completed history rescan. @@ -402,12 +409,12 @@ pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result loop { let cursor: u64 = connection.query_row("SELECT CAST(value AS INTEGER) FROM meta WHERE key=?1",[&key],|row|row.get(0)).optional()?.unwrap_or(0); let rows = { - let mut statement = connection.prepare_cached("SELECT id,store_index,origin FROM claims INDEXED BY claims_kind_index WHERE kind=?1 AND store_index>?2 ORDER BY store_index LIMIT 64")?; - statement.query_map(params![kind,cursor],|row|Ok((row.get::<_,String>(0)?,row.get::<_,u64>(1)?,row.get::<_,String>(2)?)))?.collect::>>()? + let mut statement = connection.prepare_cached("SELECT id,store_index FROM claims INDEXED BY claims_kind_index WHERE kind=?1 AND store_index>?2 ORDER BY store_index LIMIT 64")?; + statement.query_map(params![kind,cursor],|row|Ok((row.get::<_,String>(0)?,row.get::<_,u64>(1)?)))?.collect::>>()? }; if rows.is_empty() { break; } - for (id,index,writer) in rows { - refresh_claim(connection,&id,writer==origin)?; + for (id,index) in rows { + refresh_claim(connection,&id)?; connection.execute(/* sqlite-large-value: allow-for-now lv-h3f49c0e579cd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES(?1,?2)",params![key,index.to_string()])?; if started.elapsed()>=budget { return Ok(false); } } @@ -421,8 +428,7 @@ pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result }; if rows.is_empty() { break; } for id in rows { - let writer: Option = connection.query_row("SELECT origin FROM claims WHERE id=?1",[&id],|row|row.get(0)).optional()?; - refresh_claim(connection,&id,writer.as_deref()==Some(origin.as_str()))?; + refresh_claim(connection,&id)?; connection.execute(/* sqlite-large-value: allow-for-now lv-hd91341d01a91 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_dirty WHERE claim_id=?1",[&id])?; if started.elapsed()>=budget { return Ok(false); } } diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs index 8d4be66e2ee..91e6263187d 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -231,6 +231,13 @@ fn assistant_grant_authority_measure_realistic_backfill() { claim.execute(/* sqlite-large-value: allow-for-now lv-hb16dbad8dff5 owner=smallclaims::store::assistant_grant_authority_bench TODO=trace-statement-and-value-representation */ params![id, format!("batch/{writer}/{sequence:064x}"), format!("custom/client/assistant-v1-{group:024x}"), kind, writer, "person/perf-operator", body]).unwrap(); + if writer == LOCAL { + // Model a genuine local append, not origin-based trust + // during upgrade of ambiguous historical raw rows. + transaction.execute( + "INSERT INTO assistant_grant_local_appends(claim_id) VALUES(?1)", [&id], + ).unwrap(); + } } else { let bucket = match row % 100 { 0..=69 => 0, 70..=94 => 1, _ => 2 }; let body = &unrelated_bodies[bucket]; @@ -293,6 +300,10 @@ fn assistant_grant_authority_measure_realistic_backfill() { let revoked: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_effective WHERE revoked=1", [], |row| row.get(0)).unwrap(); let authority: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_authority", [], |row| row.get(0)).unwrap(); let unauthenticated: u64 = connection.query_row("SELECT COUNT(*) FROM assistant_grant_pending WHERE authenticated=0", [], |row| row.get(0)).unwrap(); + let pending_unauthenticated_grants: u64 = connection.query_row( + "SELECT COUNT(*) FROM assistant_grant_pending WHERE authenticated=0 AND kind=?1", + [assistant_grant_authority::GRANTED], |row| row.get(0), + ).unwrap(); assert_eq!(effective, expected_effective); assert!(effective > 0, "sample must include authenticated valid groups"); assert_eq!(revoked, expected_revoked); @@ -306,6 +317,7 @@ fn assistant_grant_authority_measure_realistic_backfill() { transaction.commit().unwrap(); assert_eq!(connection.query_row("SELECT COUNT(*) FROM assistant_grant_authority", [], |row| row.get::<_, u64>(0)).unwrap(), authority); + println!("authority_backfill_compatibility pending_unauthenticated_grant_claims={pending_unauthenticated_grants}"); let scale = config.target_bytes as f64 / fixture_db_bytes as f64; println!("authority_backfill_fixture raw_claims={raw_rows} grant_kind_claims={raw_authority_rows} granted={} policies={} revocations={raw_revocations} malformed_rows={expected_malformed_rows} unauthenticated_rows={expected_unauthenticated_rows} effective_grants={effective} authority_rows={authority} authority_bps={} malformed_group_bps={} unauthenticated_group_bps={} revoked_group_bps={} unrelated_json_bytes={unrelated_body_bytes} authority_json_bytes={authority_body_bytes} fixture_db_bytes={fixture_db_bytes} fixture_wal_bytes={fixture_wal_bytes} final_db_bytes={final_db_bytes} final_wal_bytes={final_wal_bytes} transaction_rows={}", raw_authority_rows / EVENTS, raw_authority_rows - raw_authority_rows / EVENTS - raw_revocations, diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index b27d1027c08..f417174f92a 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -460,6 +460,128 @@ fn reset_projection(connection: &Connection) { ).unwrap(); } +fn drain_authority(store: &Store) { + while !store.advance_assistant_grant_authority_backfill().unwrap() {} +} + +fn assert_bearer_rejected(store: &Store, grant: &ClaimRecord) { + let digest = grant.body["fields"]["credential_hash"].as_str().unwrap(); + assert!(!authority::contains(&store.readers.get(), &grant.id).unwrap()); + assert!(authority::by_credential(&store.readers.get(), digest).unwrap().is_none()); + assert!(!decisions(store, 0).contains(&grant.id)); +} + +fn attacker_fork() -> (Store, ClaimRecord) { + // An admitted Legacy sender invents a fork of the victim's writer history. + // No member key or signature authenticates the claimed local origin. + let sender = node("victim", None); + let mut forged = fields(); + forged["credential_hash"] = json!("b".repeat(64)); + let grant = append(&sender, SUBJECT, GRANTED, forged); + (sender, grant) +} + +#[test] +fn unsigned_victim_origin_legacy_fork_is_rejected_on_receive_and_upgrade_backfill() { + let (sender, grant) = attacker_fork(); + let victim = node("victim", None); + receive(&victim, &unsigned(&export(&sender, &victim))); + assert!(victim.claim_by_id(&grant.id).unwrap().is_some(), "Legacy evidence was admitted"); + assert_bearer_rejected(&victim, &grant); + reset_projection(&victim.connection.write()); + drain_authority(&victim); + assert_bearer_rejected(&victim, &grant); +} + +#[test] +fn victim_origin_legacy_fork_injected_after_partial_cursor_cannot_authenticate() { + let victim = node("victim", None); + let local = append(&victim, SUBJECT, GRANTED, fields()); + { + let mut connection = victim.connection.write(); + reset_projection(&connection); + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction, Duration::ZERO).unwrap()); + transaction.commit().unwrap(); + } + let (sender, grant) = attacker_fork(); + receive(&victim, &unsigned(&export(&sender, &victim))); + drain_authority(&victim); + assert_bearer_rejected(&victim, &grant); + assert!(authority::contains(&victim.readers.get(), &local.id).unwrap()); +} + +#[test] +fn older_build_raw_legacy_replication_cannot_authenticate_on_new_build_reopen() { + let directory = tempfile::tempdir().unwrap(); + let path = directory.path().join("victim.sqlite3"); + let (sender, grant) = attacker_fork(); + { + let victim = Store::open(&path, "victim", Arc::new(Plain)).unwrap(); + drain_authority(&victim); + // The pre-envelope import path wrote raw batches and claims without + // receipt records. Reproduce that older-build transaction, deliberately + // bypassing all new admission hooks and the local append marker. + let (sequence, previous, hash): (u64, Option, String) = sender.readers.get() + .query_row("SELECT replica_sequence,previous_hash,hash FROM batches WHERE id=?1", + [&grant.batch_id], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?))).unwrap(); + let mut connection = victim.connection.write(); + let transaction = connection.transaction().unwrap(); + transaction.execute( + "INSERT INTO batches(id,origin,replica_sequence,previous_hash,hash,accepted_at_unix_ms) + VALUES(?1,?2,?3,?4,?5,?6)", + params![grant.batch_id,grant.origin,sequence,previous,hash,grant.accepted_at_unix_ms.to_string()], + ).unwrap(); + transaction.execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9)", + params![grant.id,grant.batch_id,grant.subject,grant.kind,grant.origin,grant.actor, + canonical_json_text(&grant.body).unwrap(),serde_json::to_string(&grant.predecessors).unwrap(), + grant.accepted_at_unix_ms.to_string()], + ).unwrap(); + transaction.commit().unwrap(); + assert!(authority::ready(&connection).is_err()); + } + let reopened = Store::open(&path, "victim", Arc::new(Plain)).unwrap(); + drain_authority(&reopened); + assert_bearer_rejected(&reopened, &grant); +} + +#[test] +fn local_append_authenticates_immediately_and_local_unsealed_and_signed_history_survive_backfill() { + let (store, _) = source(); + let sealed = append(&store, SUBJECT, GRANTED, fields()); + store.seal_local_batches().unwrap(); + // A pre-marker sealed claim must stand on its real signature, not its + // origin. A post-upgrade unsealed claim stands on durable local admission. + store.connection.write().execute( + "DELETE FROM assistant_grant_local_appends WHERE claim_id=?1", [&sealed.id], + ).unwrap(); + let mut changed = fields(); + changed["credential_hash"] = json!("c".repeat(64)); + let unsealed = append(&store, SUBJECT, GRANTED, changed); + assert!(authority::by_credential(&store.readers.get(), &"c".repeat(64)).unwrap().is_some()); + let has_envelope: bool = store.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1)", + [&unsealed.id], |row| row.get(0), + ).unwrap(); + assert!(!has_envelope, "local authority has no signature/sealing delay"); + reset_projection(&store.connection.write()); + drain_authority(&store); + assert!(authority::contains(&store.readers.get(), &sealed.id).unwrap()); + assert!(authority::contains(&store.readers.get(), &unsealed.id).unwrap()); +} + +#[test] +fn ambiguous_pre_marker_local_unsealed_history_fails_closed() { + let store = node("victim", None); + let grant = append(&store, SUBJECT, GRANTED, fields()); + store.connection.write().execute("DELETE FROM assistant_grant_local_appends", []).unwrap(); + reset_projection(&store.connection.write()); + drain_authority(&store); + assert_bearer_rejected(&store, &grant); +} + #[test] fn committed_backfill_slice_resumes_after_reopen_and_is_idempotent() { let directory = tempfile::tempdir().unwrap(); diff --git a/docs/st3/external-assistants.md b/docs/st3/external-assistants.md index 9fb654d3788..6c8a47cc9b0 100644 --- a/docs/st3/external-assistants.md +++ b/docs/st3/external-assistants.md @@ -157,6 +157,44 @@ requests still require independent owning-person confirmation. Older daemons reject the new principal rather than accepting it as ChatGPT or a person; do not work around rejection by switching credentials. +### Upgrade: reissue grants without authenticated historical provenance + +The authority projection remains version 1 (unreleased). A durable local-append +marker is written only when this member appends a new grant, policy, or revocation +claim locally. Upgrade does not manufacture markers for existing claims. An +unmarked historical claim needs a verified member envelope signature and matching +admitted membership window, even when its origin names this member. Unsigned or +unsealed Legacy history fails closed; merely retaining the old bearer is not +sufficient. Grants issued before upgrade without a verifiable member signature +stay unusable and the configured owner must reissue them. + +After the authority backfill completes, `fractal doctor` lists every pending +unauthenticated, unmarked local grant claim ID under the claim-store check with +reason `grant predates local-append provenance; re-issue`. It also lists remote +unmarked grants, but reports missing verified provenance and unknown issuance age: +the absence of this member's local marker does not prove remote history predates +upgrade. A verified historical signature removes the unauthenticated warning. +These diagnostics do not change generic bearer authorization error messages. + +Reissue means **a new explicit pairing**, not renewal of the old grant or a SQL +edit. On the daemon host, use the configured owner and original assistant +principal with only explicitly approved scopes and recorded disclosure consent: + +```sh +fractal devices --as person/OWNER pair --assistant assistant/mcp \ + --scope read.assistant.summary \ + --disclose-to-openai --consent-evidence '' +fractal devices complete MEMBER_URL PAIRING_ID --assistant \ + --profile /absolute/path/to/new-profile.json +``` + +Use `assistant/chatgpt` instead when replacing a ChatGPT grant; never switch +principals to work around rejection. Complete the printed challenge using stdin, +then provision the newly issued credential in a protected token file as described +above and remove the old adapter credential. Service-profile issuance remains +disabled; this procedure does not enable it. Do not insert provenance markers, +rewrite signed history, or delete claims to make old grants authenticate. + ## Adapter call diagnostics `fractal-chatgpt` emits one structured `tracing` completion event per dispatched tool diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index f53e4a86006..f98601c405f 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -7,7 +7,7 @@ }, "schema": { "status": "changed", - "detail": "Adds external-grant authority projection version 1 as additive store state; older builds can still open an upgraded store. Adds typed client error assistant-grant-authority-not-ready with retryable=true (HTTP 503) while assistant authorization fails closed during background backfill. Also adds grant-profile-conflict (HTTP 409). Bearer authentication and pairing disclose only the conflict code and fixed message principal has active grants of opposite profiles; revoke one to clear the conflict, without witness details. Only daemon-configured-owner inspection with ?witness=1 exposes conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients." + "detail": "Adds external-grant authority projection version 1 as additive store state; older builds can still open an upgraded store. The durable assistant_grant_local_appends(claim_id PRIMARY KEY) table records only new local insert_claim appends, never inferred historical or replicated provenance. Projection version remains 1 (unreleased). Adds typed client error assistant-grant-authority-not-ready with retryable=true (HTTP 503) while assistant authorization fails closed during background backfill. Also adds grant-profile-conflict (HTTP 409). Bearer authentication and pairing disclose only the conflict code and fixed message principal has active grants of opposite profiles; revoke one to clear the conflict, without witness details. Only daemon-configured-owner inspection with ?witness=1 exposes conflict and cleared_conflicts witnesses with typed assistant/service profiles and revoked/expired causes. Default grant responses retain their previous shape for old strict clients." }, "rules": { "status": "changed", @@ -15,7 +15,7 @@ }, "compatibility": { "status": "changed", - "detail": "Conflict admission counts only well-formed owner grants; foreign grants require authenticated envelope provenance from a keyed, admitted fleet writer, including valid records in degraded envelopes. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. Foreign transitions require both a keyed membership window and a valid signature; a newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Projection version 1 is additive and raw append-only evidence remains authoritative and intact. Tokens remain issuer-local. Rollback to an older build is supported, but older members do not enforce the new projection readiness gate or conflict suspension, so upgrade all serving members before relying on them." + "detail": "Conflict admission counts only well-formed owner grants. New local appends require durable local-append provenance; unmarked historical claims, including claims naming this local origin, require a verified member envelope signature and matching admitted membership window. Unsigned or unsealed Legacy history is not grandfathered into authority. Grants issued before upgrade without a verifiable member signature stay unusable and must be reissued by the configured owner. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. A newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Projection version 1 is additive and raw append-only evidence remains authoritative and intact. Tokens remain issuer-local. Rollback to an older build is supported, but older members do not enforce these provenance checks, the new projection readiness gate or conflict suspension, so upgrade all serving members before relying on them." }, "downtime": { "status": "changed", @@ -23,7 +23,7 @@ }, "manual": { "status": "changed", - "detail": "Allow the resumable background backfill to finish before retrying assistant authorization after assistant-grant-authority-not-ready. For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer. Do not delete raw claims, clear append-only evidence, or replace tokens to resolve a conflict or restart the backfill." + "detail": "Allow the resumable background backfill to finish before retrying assistant authorization after assistant-grant-authority-not-ready. Run fractal doctor: the claim-store section lists each unauthenticated unmarked local grant claim ID with reason grant predates local-append provenance; re-issue. Remote unmarked grants are separately reported as lacking verified provenance with issuance age unknown, not definitively pre-upgrade. For unusable pre-upgrade grants, the configured owner reissues through trusted-local Unix with fractal devices --as person/OWNER pair --assistant assistant/mcp --scope read.assistant.summary --disclose-to-openai --consent-evidence '' (select the original principal and explicitly approved scopes), then completes the new challenge with fractal devices complete MEMBER_URL PAIRING_ID --assistant --profile /absolute/path/to/new-profile.json and replaces the protected adapter credential. There is no in-place reissue command or SQL provenance repair. Service issuance remains disabled. For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer. Do not delete raw claims, clear append-only evidence, or replace tokens to resolve a conflict or restart the backfill." }, "recovery": { "status": "changed", From 32cfa40041cea47195555270b33deaf2f0b2a4e5 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:35:38 +0100 Subject: [PATCH 39/52] fix: yield authority pages and fence maintenance lifecycle races agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../assistant_grant_authority_wake_tests.rs | 47 +++++++++++++ crates/fractal/src/main.rs | 70 +++++++++++++------ 2 files changed, 94 insertions(+), 23 deletions(-) diff --git a/crates/fractal/src/assistant_grant_authority_wake_tests.rs b/crates/fractal/src/assistant_grant_authority_wake_tests.rs index e538075d6ea..410c76039c4 100644 --- a/crates/fractal/src/assistant_grant_authority_wake_tests.rs +++ b/crates/fractal/src/assistant_grant_authority_wake_tests.rs @@ -34,3 +34,50 @@ async fn completed_authority_reconciles_older_build_appends_without_reopen() { } task.abort(); } + +#[tokio::test] +async fn authority_commit_between_completed_drain_and_wait_is_not_lost() { + let store = Arc::new(Store::open_memory("node").unwrap()); + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + let mut maintenance = AssistantGrantAuthorityMaintenance::new(store.clone()); + assert!(maintenance.advance().await.unwrap(), "the drain completed"); + // Deterministically place this commit after the completed drain and before + // waiting. No scheduler timing or sleep is needed to hit the race boundary. + store.connection.write().execute_batch( + "BEGIN; + INSERT INTO batches(id,origin,replica_sequence,hash,accepted_at_unix_ms) + VALUES('batch/race','node',1,'race','1'); + INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES('claim/race','batch/race','custom/client/assistant-v1-invalid', + 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1'); + COMMIT;" + ).unwrap(); + assert!(authority::ready(&store.readers.get()).is_err()); + tokio::time::timeout(Duration::from_secs(5), maintenance.changes.changed()) + .await.expect("the intervening commit stays visible") + .expect("the observer remains registered"); + assert!(maintenance.advance().await.unwrap()); + assert!(authority::ready(&store.readers.get()).is_ok()); +} + +#[tokio::test] +async fn authority_maintenance_shutdown_exits_and_unregisters_its_observer() { + let store = Arc::new(Store::open_memory("node").unwrap()); + while !store.advance_assistant_grant_authority_backfill().unwrap() {} + let mut maintenance = AssistantGrantAuthorityMaintenance::new(store.clone()); + assert!(maintenance.advance().await.unwrap()); + let mut changes = maintenance.changes.clone(); + let task = tokio::spawn(maintenance.run()); + tokio::task::yield_now().await; + task.abort(); + assert!(task.await.unwrap_err().is_cancelled(), "shutdown exits the loop"); + // Only the registered observer owns the sender. A closed receiver proves + // cancellation dropped the observer callback, not just the task's receiver. + tokio::time::timeout(Duration::from_secs(5), changes.changed()).await + .expect("shutdown drops the observer without waiting for another commit") + .expect_err("no observer sender remains registered"); + store.connection.write().execute( + "INSERT INTO meta(key,value) VALUES('authority-after-shutdown','1')", [], + ).unwrap(); + assert!(changes.has_changed().is_err(), "later commits cannot invoke the removed observer"); +} diff --git a/crates/fractal/src/main.rs b/crates/fractal/src/main.rs index 1dbd6702855..086c52f22fd 100644 --- a/crates/fractal/src/main.rs +++ b/crates/fractal/src/main.rs @@ -20821,37 +20821,61 @@ async fn build_transport_observation_index(store: Arc) { /// compatibility-trigger work on commits. Subscribe before checking readiness so /// an older-build append between the check and the wait cannot be lost. async fn build_assistant_grant_authority(store: Arc) { - let (changed, mut receiver) = tokio::sync::watch::channel(()); - let _observer = store.observe_commits(move |connection| { - if connection.is_autocommit() { - changed.send_replace(()); - } - }); - loop { - receiver.borrow_and_update(); - let worker = store.clone(); - let result = tokio::task::spawn_blocking(move || { + AssistantGrantAuthorityMaintenance::new(store).run().await; +} + +/// Own the subscription for exactly the maintenance task's lifetime. Splitting +/// one page from the wait also makes the drain-to-wait boundary explicit. +struct AssistantGrantAuthorityMaintenance { + store: Arc, + changes: tokio::sync::watch::Receiver<()>, + _observer: smallclaims::sqlite::CommitObserver, +} + +impl AssistantGrantAuthorityMaintenance { + fn new(store: Arc) -> Self { + let (changed, changes) = tokio::sync::watch::channel(()); + let observer = store.observe_commits(move |connection| { + if connection.is_autocommit() { + changed.send_replace(()); + } + }); + Self { store, changes, _observer: observer } + } + + async fn advance(&mut self) -> Result { + // Consume before the read, not after draining: a commit between the + // read/drain and changed().await must remain an unseen generation. + self.changes.borrow_and_update(); + let worker = self.store.clone(); + tokio::task::spawn_blocking(move || { if smallclaims::store::assistant_grant_authority::ready(&worker.readers.get()).is_ok() { return Ok(true); } worker.advance_assistant_grant_authority_backfill() - }).await; - match result { - Ok(Ok(true)) => { - if receiver.changed().await.is_err() { + }).await? + } + + async fn run(mut self) { + loop { + match self.advance().await { + Ok(true) => { + if self.changes.changed().await.is_err() { + return; + } + continue; + } + Ok(false) => {} + Err(error) if maintenance_contention(&error) => {} + error => { + stderr_message("st", format_args!("assistant grant authority backfill stopped: {error:?}; restart resumes its committed cursor")); return; } - continue; - } - Ok(Ok(false)) => {} - Ok(Err(error)) if maintenance_contention(&error) => {} - error => { - stderr_message("st", format_args!("assistant grant authority backfill stopped: {error:?}; restart resumes its committed cursor")); - return; } + // Each page releases the writer. Yield scheduling, never time-based + // pacing: persisted work resumes immediately in another transaction. + tokio::task::yield_now().await; } - // Finite, persisted cursor work; yield the writer between pages. - tokio::time::sleep(Duration::from_millis(100)).await; } } From 160f60c7531e135228c9f33bf1d166e1ae6889a2 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:37:31 +0100 Subject: [PATCH 40/52] fix: keep grant provenance diagnostics local and document restore reissue agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0.rs | 66 +++++++++++++++++++ docs/st3/backups.md | 7 ++ docs/st3/external-assistants.md | 24 ++++++- .../external-grant-profile-conflict.json | 4 +- 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/crates/fractal-api-client-v0/src/api/client_v0.rs b/crates/fractal-api-client-v0/src/api/client_v0.rs index 0e38688024a..3a00515957b 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0.rs @@ -3934,6 +3934,9 @@ fn operation_resources(state: &AppState, at: &str) -> Result, ApiErro }; let mut values = checks .iter() + // Grant IDs and issuing identities are trusted-local doctor diagnostics, not + // projection data for paired clients. Both collection and detail use this list. + .filter(|check| check.name != "assistant-grant-provenance") .map(|check| { let digest = hex::encode(Sha256::digest(check.name.as_bytes())); json!({ @@ -13751,6 +13754,69 @@ mission "differential" state="ready" { } } + #[tokio::test] + async fn paired_operations_do_not_disclose_local_doctor_grant_provenance() { + let root = tempfile::tempdir().unwrap(); + let state = test_state(root.path()); + let credential = "operations-provenance-reader"; + state.store.append_client_operation_claim(&ClaimInput { + subject: "custom/client/operations-provenance-reader".into(), + kind: "custom.client.pairing-completed".into(), + actor: Some("person/ada".into()), + fields: BTreeMap::from([ + ("credential_hash".into(), json!(credential_digest(credential))), + ("session_actor".into(), json!("client/operations-provenance-reader")), + ("person_id".into(), json!("person/ada")), + ("scopes".into(), json!(["read.projections"])), + ("expires_at_unix_ms".into(), json!(client_now_ms() as u64 + 60_000)), + ]), + evidence: Vec::new(), expected_subject: None, idempotency_key: None, + }).unwrap(); + let grant_id = "claim/private-doctor-grant"; + let origin = "private-doctor-origin"; + let issuer = "person/private-doctor-issuer"; + state.store.connection.write().execute( + "INSERT INTO assistant_grant_pending + (claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) + VALUES(?1,?1,'custom.client.assistant.v1.granted',?2,?3,1,0,'{}')", + rusqlite::params![grant_id, origin, issuer], + ).unwrap(); + let checks = doctor_report(&state).unwrap().0.checks; + let provenance = checks.iter() + .find(|check| check.name == "assistant-grant-provenance").unwrap(); + for private in [grant_id, origin, issuer] { + assert!(provenance.message.contains(private), "{provenance:?}"); + } + // Serve exactly the detailed local report through the remote projection paths. + operation_reports().insert( + Arc::as_ptr(&state.store) as usize, + OperationReport { + store: Arc::downgrade(&state.store), checks: Some(Arc::new(checks)), + at: Instant::now(), refreshing: false, + }, + ); + let digest = hex::encode(Sha256::digest(b"assistant-grant-provenance")); + let app = super::super::fabric_router(state.clone()); + for (uri, expected) in [ + ("/v1/client/operations".to_owned(), StatusCode::OK), + (format!("/v1/client/operations/diagnostic-{}", &digest[..16]), StatusCode::NOT_FOUND), + ] { + let request = Request::builder().uri(uri) + .header(AUTHORIZATION, format!("Bearer {credential}")) + .body(Body::empty()).unwrap(); + let session = authenticate(&state, &request, "fabric-loopback").unwrap(); + assert!(session.allows("read.projections")); + assert!(!session.local_peer); + let response = app.clone().oneshot(request).await.unwrap(); + assert_eq!(response.status(), expected); + let bytes = to_bytes(response.into_body(), CLIENT_MAX_RESPONSE_BYTES).await.unwrap(); + let body = std::str::from_utf8(&bytes).unwrap(); + for private in [grant_id, origin, issuer, "assistant-grant-provenance"] { + assert!(!body.contains(private), "{body}"); + } + } + } + #[tokio::test] async fn fleet_operational_commands_are_bounded_and_report_slow_queries() { use crate::OperationsFixtureStore; diff --git a/docs/st3/backups.md b/docs/st3/backups.md index 11a74a0a696..bc4027eb6b3 100644 --- a/docs/st3/backups.md +++ b/docs/st3/backups.md @@ -32,6 +32,13 @@ Without `--database`, restore selects `claims.sqlite3` in the configured `store_ `state_dir` when `store_dir` is unset. Stop the daemon before restoring there. Neither command installs services or starts a daemon. +Logical restore assigns a new writer and does not carry the source member's local +append markers for external grants. Unsigned pre-restore grants fail closed rather +than inheriting local authority. The configured owner must explicitly reissue them +using the same [grant reissue procedure](external-assistants.md#upgrade-reissue-grants-without-authenticated-historical-provenance) +as unsigned pre-upgrade grants; retaining an old bearer or editing provenance +markers is not recovery. + A backup of a member also holds the whole text of the [long messages](long-messages.md) that member owns, which are files outside the database; restore checks each against its hash and its claim and returns them to the product state root. Moving the database with `store_dir` does not diff --git a/docs/st3/external-assistants.md b/docs/st3/external-assistants.md index 6c8a47cc9b0..a8d81403084 100644 --- a/docs/st3/external-assistants.md +++ b/docs/st3/external-assistants.md @@ -168,13 +168,35 @@ unsealed Legacy history fails closed; merely retaining the old bearer is not sufficient. Grants issued before upgrade without a verifiable member signature stay unusable and the configured owner must reissue them. +A logical backup restore assigns a new writer and does not carry this member's +local-append markers. Unsigned pre-restore grants therefore fail closed, even if +they authenticated before backup. The same configured-owner reissue procedure +below applies; a restore is not a way to manufacture historical provenance. + +Authority maintenance is lifecycle-owned. While work remains, pages execute +back-to-back as bounded transactions, releasing the writer between pages and +yielding to the runtime rather than using sleep-based pacing. +Each transaction shares a 64-unit budget across history, dirty-signature claims, +and membership retries; empty membership-writer tasks also consume one unit. +Each authentication refresh visits one indexed replica record and at most 16 +writer membership keys, looking up signatures by their full +`(writer, sequence, envelope_hash, member_key)` key rather than enumerating +nonmember signatures. Durable record/key cursors continue across units so later +eligible evidence is eventually checked; new signature or membership retries +reset that progress. Membership promotion is queued for maintenance, and +authorization readiness fails closed while it is queued. Storing an identical +signature again is a no-op: it neither refreshes authority nor dirties a claim. + After the authority backfill completes, `fractal doctor` lists every pending unauthenticated, unmarked local grant claim ID under the claim-store check with reason `grant predates local-append provenance; re-issue`. It also lists remote unmarked grants, but reports missing verified provenance and unknown issuance age: the absence of this member's local marker does not prove remote history predates upgrade. A verified historical signature removes the unauthenticated warning. -These diagnostics do not change generic bearer authorization error messages. +These details remain on trusted-local doctor only: paired clients with +`read.projections` cannot retrieve the provenance check through either the +operations collection or operation detail. Generic bearer authorization error +messages are unchanged. Reissue means **a new explicit pairing**, not renewal of the old grant or a SQL edit. On the daemon host, use the configured owner and original assistant diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index f98601c405f..3d9a2d5c945 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -15,7 +15,7 @@ }, "compatibility": { "status": "changed", - "detail": "Conflict admission counts only well-formed owner grants. New local appends require durable local-append provenance; unmarked historical claims, including claims naming this local origin, require a verified member envelope signature and matching admitted membership window. Unsigned or unsealed Legacy history is not grandfathered into authority. Grants issued before upgrade without a verifiable member signature stay unusable and must be reissued by the configured owner. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. A newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Projection version 1 is additive and raw append-only evidence remains authoritative and intact. Tokens remain issuer-local. Rollback to an older build is supported, but older members do not enforce these provenance checks, the new projection readiness gate or conflict suspension, so upgrade all serving members before relying on them." + "detail": "Conflict admission counts only well-formed owner grants. New local appends require durable local-append provenance; unmarked historical claims, including claims naming this local origin, require a verified member envelope signature and matching admitted membership window. Unsigned or unsealed Legacy history is not grandfathered into authority. Grants issued before upgrade without a verifiable member signature stay unusable and must be reissued by the configured owner. Logical backup restore assigns a new writer and does not carry local-append markers; unsigned pre-restore grants fail closed and require the same configured-owner reissue procedure. Policies and revocations count only from the grant's own origin and owner with consistent immutable identity. A newer unauthenticated transition cannot hide an older authenticated renewal. Invalid overlays are ignored, retaining the last valid policy. Projection version 1 is additive and raw append-only evidence remains authoritative and intact. Tokens remain issuer-local. Rollback to an older build is supported, but older members do not enforce these provenance checks, the new projection readiness gate or conflict suspension, so upgrade all serving members before relying on them." }, "downtime": { "status": "changed", @@ -23,7 +23,7 @@ }, "manual": { "status": "changed", - "detail": "Allow the resumable background backfill to finish before retrying assistant authorization after assistant-grant-authority-not-ready. Run fractal doctor: the claim-store section lists each unauthenticated unmarked local grant claim ID with reason grant predates local-append provenance; re-issue. Remote unmarked grants are separately reported as lacking verified provenance with issuance age unknown, not definitively pre-upgrade. For unusable pre-upgrade grants, the configured owner reissues through trusted-local Unix with fractal devices --as person/OWNER pair --assistant assistant/mcp --scope read.assistant.summary --disclose-to-openai --consent-evidence '' (select the original principal and explicitly approved scopes), then completes the new challenge with fractal devices complete MEMBER_URL PAIRING_ID --assistant --profile /absolute/path/to/new-profile.json and replaces the protected adapter credential. There is no in-place reissue command or SQL provenance repair. Service issuance remains disabled. For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer. Do not delete raw claims, clear append-only evidence, or replace tokens to resolve a conflict or restart the backfill." + "detail": "Allow the resumable background backfill to finish before retrying assistant authorization after assistant-grant-authority-not-ready. Run fractal doctor: the claim-store section lists each unauthenticated unmarked local grant claim ID with reason grant predates local-append provenance; re-issue. Remote unmarked grants are separately reported as lacking verified provenance with issuance age unknown, not definitively pre-upgrade. Detailed grant IDs, origin and actor remain trusted-local doctor diagnostics and are excluded from paired-client operations collection and detail reads, including read.projections clients. For unusable pre-upgrade or unsigned pre-restore grants, the configured owner reissues through trusted-local Unix with fractal devices --as person/OWNER pair --assistant assistant/mcp --scope read.assistant.summary --disclose-to-openai --consent-evidence '' (select the original principal and explicitly approved scopes), then completes the new challenge with fractal devices complete MEMBER_URL PAIRING_ID --assistant --profile /absolute/path/to/new-profile.json and replaces the protected adapter credential. There is no in-place reissue command or SQL provenance repair. Service issuance remains disabled. For a conflicted principal, choose the intended profile and append revocations for every active grant in the opposite profile. Let those revocations replicate to each serving issuer. Do not delete raw claims, clear append-only evidence, or replace tokens to resolve a conflict or restart the backfill." }, "recovery": { "status": "changed", From 05ab7c9665363975ce2eb104c48956ae8452eec7 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 15:45:35 +0100 Subject: [PATCH 41/52] fix: bound grant authentication and skip duplicate signature refreshes agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/smallclaims/src/store.rs | 8 +- .../src/store/assistant_grant_authority.rs | 212 +++++++++---- .../store/assistant_grant_authority_bench.rs | 2 + .../store/assistant_grant_authority_tests.rs | 292 ++++++++++++++++++ 4 files changed, 457 insertions(+), 57 deletions(-) diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index b26ecdd8cd7..0df3958abe0 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -3738,9 +3738,11 @@ impl<'a> VerifiedEnvelopeSignature<'a> { self.signature, now ])?; - assistant_grant_authority::refresh_envelope( - transaction, self.writer, self.sequence, self.envelope_hash, - )?; + if inserted != 0 { + assistant_grant_authority::refresh_envelope( + transaction, self.writer, self.sequence, self.envelope_hash, + )?; + } Ok(inserted) } } diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index 32be958bb21..5ae0d7a9ed4 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -7,6 +7,8 @@ pub const POLICY: &str = "custom.client.assistant.v1.policy"; pub const REVOKED: &str = "custom.client.assistant.v1.revoked"; const VERSION: &str = "1"; const KINDS: [&str; 3] = [GRANTED, POLICY, REVOKED]; +pub const CLAIMS_PER_SLICE: usize = 64; +pub const MEMBERSHIP_KEYS_PER_REFRESH: usize = 16; const SCOPES: &[&str] = &[ "read.assistant.summary", "read.assistant.attention", "read.assistant.missions", "read.assistant.agents", "read.assistant.conversation", "read.assistant.terminal", @@ -112,11 +114,16 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { CREATE INDEX IF NOT EXISTS assistant_grant_pending_writer_index ON assistant_grant_pending(origin,authenticated,sequence,claim_id); CREATE TABLE IF NOT EXISTS assistant_grant_dirty (claim_id TEXT PRIMARY KEY); + CREATE TABLE IF NOT EXISTS assistant_grant_auth_cursor ( + claim_id TEXT PRIMARY KEY, position INTEGER NOT NULL, record_rowid INTEGER NOT NULL, member_key TEXT NOT NULL); + CREATE TABLE IF NOT EXISTS assistant_grant_membership_dirty ( + writer TEXT PRIMARY KEY, sequence INTEGER NOT NULL, claim_id TEXT NOT NULL); CREATE TABLE IF NOT EXISTS assistant_grant_local_appends (claim_id TEXT PRIMARY KEY); CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') BEGIN INSERT OR IGNORE INTO assistant_grant_dirty VALUES(NEW.id); END; - CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_signature_insert + DROP TRIGGER IF EXISTS assistant_grant_dirty_signature_insert; + CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_signature_insert_v2 AFTER INSERT ON replica_envelope_signatures BEGIN INSERT OR IGNORE INTO assistant_grant_dirty(claim_id) @@ -125,6 +132,9 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { WHERE records.writer=NEW.writer AND records.sequence=NEW.sequence AND records.envelope_hash=NEW.envelope_hash AND claims.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked'); + DELETE FROM assistant_grant_auth_cursor WHERE claim_id IN ( + SELECT claim_id FROM replica_records + WHERE writer=NEW.writer AND sequence=NEW.sequence AND envelope_hash=NEW.envelope_hash); END; CREATE TABLE IF NOT EXISTS assistant_grant_membership_windows ( writer TEXT NOT NULL, member_key TEXT NOT NULL, start INTEGER NOT NULL, end INTEGER, @@ -137,7 +147,8 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { pub fn ready(connection: &Connection) -> Result<(), FractalError> { let complete: bool = connection.query_row( "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')=?1 - AND NOT EXISTS(SELECT 1 FROM assistant_grant_dirty)", + AND NOT EXISTS(SELECT 1 FROM assistant_grant_dirty) + AND NOT EXISTS(SELECT 1 FROM assistant_grant_membership_dirty)", [VERSION], |row| row.get(0), ).map_err(internal)?; if !complete { @@ -289,37 +300,107 @@ pub fn refresh_claim(connection: &Connection, id: &str) -> Result<()> { "SELECT EXISTS(SELECT 1 FROM assistant_grant_local_appends WHERE claim_id=?1)", [&claim.id], |row| row.get(0), )?; - let authenticated = (local_append && claim.origin == local_origin(connection)?) - || authenticated_claim(connection,&claim.id)?; + let admitted: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_pending WHERE claim_id=?1 AND authenticated=1)", + [&claim.id], |row| row.get(0), + )?; + let authentication = if admitted || (local_append && claim.origin == local_origin(connection)?) { + Some(true) + } else { + authenticated_claim(connection,&claim.id)? + }; + let authenticated = authentication == Some(true); let changed = connection.execute(/* sqlite-large-value: allow-for-now lv-h9cf86ad98d1e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) VALUES(?1,?2,?3,?4,?5,?6,?7,?8) ON CONFLICT(claim_id) DO UPDATE SET authenticated=excluded.authenticated WHERE assistant_grant_pending.authenticated Result { - let fleet_id = fleet_meta(connection,"assistant_grant_authority_fleet_id")?; - let Some(fleet_id) = fleet_id else { return Ok(false); }; +/// One record and at most sixteen membership keys per refresh. Nonmember +/// signatures are never enumerated: every signature lookup supplies its full PK. +/// Persist progress even through missing/invalid evidence, so a later valid key +/// or record cannot be hidden behind an arbitrary number of earlier candidates. +fn authenticated_claim(connection: &Connection, id: &str) -> Result> { + let Some(fleet_id) = fleet_meta(connection,"assistant_grant_authority_fleet_id")? else { + return Ok(Some(false)); + }; let shard = fleet_meta(connection,"shard_id")?; - let mut statement = connection.prepare_cached( - "SELECT records.writer,records.sequence,records.envelope_hash,signatures.member_key,signatures.signature - FROM replica_records AS records JOIN claims ON claims.id=records.claim_id AND claims.origin=records.writer - JOIN replica_envelopes AS envelopes USING(writer,sequence,envelope_hash) - JOIN replica_envelope_signatures AS signatures USING(writer,sequence,envelope_hash) - JOIN assistant_grant_membership_windows AS windows - ON windows.writer=records.writer AND windows.member_key=signatures.member_key - AND records.sequence>=windows.start AND (windows.end IS NULL OR records.sequence<=windows.end) - WHERE records.claim_id=?1 AND records.state='valid' AND envelopes.receipt_state IN ('validated','degraded')")?; - let rows = statement.query_map([id], |row| Ok((row.get::<_,String>(0)?,row.get::<_,u64>(1)?,row.get::<_,String>(2)?,row.get::<_,String>(3)?,row.get::<_,String>(4)?)))?; - for row in rows { - let (writer,sequence,hash,key,signature) = row?; - if VerifiedEnvelopeSignature::verify(shard.as_deref(),&fleet_id,&writer,sequence,&hash,&key,&signature).is_some() { return Ok(true); } + let cursor: Option<(i64,i64,String)> = connection.query_row( + "SELECT position,record_rowid,member_key FROM assistant_grant_auth_cursor WHERE claim_id=?1", + [id], |row| Ok((row.get(0)?,row.get(1)?,row.get(2)?))).optional()?; + let initial = cursor.is_none(); + let (position_cursor,rowid_cursor,key_cursor) = cursor.unwrap_or((i64::MIN,i64::MIN,String::new())); + let record: Option<(i64,i64,String,u64,String,bool)> = connection.query_row( + "SELECT records.position,records.rowid,records.writer,records.sequence,records.envelope_hash, + records.state='valid' AND claims.origin=records.writer + AND EXISTS(SELECT 1 FROM replica_envelopes AS envelopes + WHERE envelopes.writer=records.writer AND envelopes.sequence=records.sequence + AND envelopes.envelope_hash=records.envelope_hash + AND envelopes.receipt_state IN ('validated','degraded')) + FROM replica_records AS records INDEXED BY replica_records_claim + JOIN claims ON claims.id=records.claim_id + WHERE records.claim_id=?1 AND (records.position,records.rowid)>=(?2,?3) + AND (?5 OR (records.position,records.rowid)<>(?2,?3) OR ?4<>'') + ORDER BY records.position,records.rowid LIMIT 1", + params![id,position_cursor,rowid_cursor,key_cursor,initial], + |row| Ok((row.get(0)?,row.get(1)?,row.get(2)?,row.get(3)?,row.get(4)?,row.get(5)?))).optional()?; + let Some((position,record_rowid,writer,sequence,hash,eligible)) = record else { + connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [id])?; + return Ok(Some(false)); + }; + // A nonempty key resumes this record; an empty key advances past it. + // The index seek skips at most the one completed record at the cursor. + let mut next_key = String::new(); + if eligible { + let mut statement = connection.prepare_cached(AUTHENTICATION_KEYS_QUERY)?; + let keys = statement.query_map( + params![writer,sequence,hash,if (position,record_rowid)==(position_cursor,rowid_cursor) { key_cursor.as_str() } else { "" },MEMBERSHIP_KEYS_PER_REFRESH], + |row| Ok((row.get::<_,String>(0)?,row.get::<_,Option>(1)?)))? + .collect::>>()?; + for (key,signature) in &keys { + if signature.as_deref().is_some_and(|signature| + VerifiedEnvelopeSignature::verify(shard.as_deref(),&fleet_id,&writer,sequence,&hash,key,signature).is_some()) { + connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [id])?; + return Ok(Some(true)); + } + } + if keys.len()==MEMBERSHIP_KEYS_PER_REFRESH { + next_key = keys.into_iter().last().expect("full key page").0; + } + } + if next_key.is_empty() { + let more: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records INDEXED BY replica_records_claim + WHERE claim_id=?1 AND (position,rowid)>(?2,?3))", + params![id,position,record_rowid], |row| row.get(0))?; + if !more { + connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [id])?; + return Ok(Some(false)); + } } - Ok(false) + connection.execute( + "INSERT INTO assistant_grant_auth_cursor VALUES(?1,?2,?3,?4) + ON CONFLICT(claim_id) DO UPDATE SET position=excluded.position, + record_rowid=excluded.record_rowid,member_key=excluded.member_key", + params![id,position,record_rowid,next_key])?; + Ok(None) } +pub const AUTHENTICATION_KEYS_QUERY: &str = + "SELECT windows.member_key,signatures.signature + FROM assistant_grant_membership_windows AS windows + LEFT JOIN replica_envelope_signatures AS signatures + ON signatures.writer=windows.writer AND signatures.sequence=?2 + AND signatures.envelope_hash=?3 AND signatures.member_key=windows.member_key + AND ?2>=windows.start AND (windows.end IS NULL OR ?2<=windows.end) + WHERE windows.writer=?1 AND windows.member_key>?4 + ORDER BY windows.member_key LIMIT ?5"; /// Refresh only this envelope's grant records, after receipt/signature state has /// been written, and before its transaction is committed. pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, hash: &str) -> Result<()> { @@ -331,7 +412,13 @@ pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, ha statement.query_map(params![writer,sequence,hash], |row| row.get::<_,String>(0))?.collect::>>()? }; // A replicated same-origin claim does NOT acquire the local-write exception. - for id in ids { refresh_claim(connection,&id)?; } + for id in ids { + // Signatures may predate their replica record and therefore could not + // invalidate a claim cursor when inserted. New evidence must restart + // its claim even when its indexed position precedes that cursor. + connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [&id])?; + refresh_claim(connection,&id)?; + } Ok(()) } /// Membership changes promote pending rows only in newly changed keyed windows. @@ -372,25 +459,14 @@ fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::M connection.execute(/* sqlite-large-value: allow-for-now lv-ha3bce0201694 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM meta WHERE key='assistant_grant_authority_fleet_id'", [])?; } connection.execute(/* sqlite-large-value: allow-for-now lv-hbcecffaa18c4 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_membership_generation',?1)",[generation.to_string()])?; - for (writer,start,end) in changed { - let mut cursor = (0_u64, String::new()); - loop { - let ids = { - let mut statement = connection.prepare_cached( - "SELECT sequence,claim_id FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index - WHERE origin=?1 AND authenticated=0 AND sequence>=?2 - AND (?3 IS NULL OR sequence<=?3) AND (sequence,claim_id)>(?4,?5) - ORDER BY sequence,claim_id LIMIT 64")?; - statement.query_map(params![writer,start,end,cursor.0,cursor.1], - |row| Ok((row.get::<_,u64>(0)?,row.get::<_,String>(1)?)))? - .collect::>>()? - }; - if ids.is_empty() { break; } - for (sequence,id) in ids { - refresh_claim(connection,&id)?; - cursor = (sequence,id); - } - } + for (writer,_,_) in changed { + // A durable writer cursor admits at most CLAIMS_PER_SLICE pending rows + // per maintenance unit, rather than draining a changed window here. + connection.execute( + "INSERT OR REPLACE INTO assistant_grant_membership_dirty + SELECT ?1,0,'' WHERE EXISTS( + SELECT 1 FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index + WHERE origin=?1 AND authenticated=0)", [writer])?; } Ok(()) } @@ -400,7 +476,32 @@ fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::M /// arrivals are captured by persistent dirty triggers even after completion. pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result { let started = Instant::now(); + let mut remaining = CLAIMS_PER_SLICE; refresh_membership(connection)?; + // Include membership-driven retries in the same fixed item budget. Each + // empty writer task also consumes a unit, bounding sparse writer queues. + while remaining>0 { + let task: Option<(String,u64,String)> = connection.query_row( + "SELECT writer,sequence,claim_id FROM assistant_grant_membership_dirty ORDER BY writer LIMIT 1", + [], |row| Ok((row.get(0)?,row.get(1)?,row.get(2)?))).optional()?; + let Some((writer,sequence,id)) = task else { break; }; + let pending: Option<(u64,String)> = connection.query_row( + "SELECT sequence,claim_id FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index + WHERE origin=?1 AND authenticated=0 AND (sequence,claim_id)>(?2,?3) + ORDER BY sequence,claim_id LIMIT 1", params![writer,sequence,id], + |row| Ok((row.get(0)?,row.get(1)?))).optional()?; + if let Some((sequence,id)) = pending { + connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [&id])?; + refresh_claim(connection,&id)?; + connection.execute( + "UPDATE assistant_grant_membership_dirty SET sequence=?2,claim_id=?3 WHERE writer=?1", + params![writer,sequence,id])?; + } else { + connection.execute("DELETE FROM assistant_grant_membership_dirty WHERE writer=?1", [writer])?; + } + remaining -= 1; + if remaining==0 || started.elapsed()>=budget { return Ok(false); } + } // A completed version only drains the old-build dirty queue. Readiness also // includes that queue, but must never cause a completed history rescan. if fleet_meta(connection,"assistant_grant_authority_version")?.as_deref() != Some(VERSION) { @@ -415,25 +516,28 @@ pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result if rows.is_empty() { break; } for (id,index) in rows { refresh_claim(connection,&id)?; + remaining -= 1; connection.execute(/* sqlite-large-value: allow-for-now lv-h3f49c0e579cd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES(?1,?2)",params![key,index.to_string()])?; - if started.elapsed()>=budget { return Ok(false); } + if remaining==0 || started.elapsed()>=budget { return Ok(false); } } } } } - loop { - let rows = { - let mut statement = connection.prepare_cached("SELECT claim_id FROM assistant_grant_dirty ORDER BY claim_id LIMIT 64")?; - statement.query_map([],|row|row.get::<_,String>(0))?.collect::>>()? - }; - if rows.is_empty() { break; } - for id in rows { - refresh_claim(connection,&id)?; - connection.execute(/* sqlite-large-value: allow-for-now lv-hd91341d01a91 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_dirty WHERE claim_id=?1",[&id])?; - if started.elapsed()>=budget { return Ok(false); } - } + // Visit each selected dirty claim once. An unfinished authentication page + // keeps its dirty row for a later transaction, not a loop in this one. + let rows = { + let mut statement = connection.prepare_cached("SELECT claim_id FROM assistant_grant_dirty ORDER BY claim_id LIMIT ?1")?; + statement.query_map([remaining],|row|row.get::<_,String>(0))?.collect::>>()? + }; + for id in rows { + refresh_claim(connection,&id)?; + remaining -= 1; + if remaining==0 || started.elapsed()>=budget { break; } } - refresh_membership(connection)?; + let dirty: bool = connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_dirty) + OR EXISTS(SELECT 1 FROM assistant_grant_membership_dirty)", [], |row| row.get(0))?; + if dirty { return Ok(false); } connection.execute(/* sqlite-large-value: allow-for-now lv-h9b70e51e754e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_version',?1)",[VERSION])?; Ok(true) } diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs index 91e6263187d..1190a677834 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -172,6 +172,8 @@ fn assistant_grant_authority_measure_realistic_backfill() { DELETE FROM assistant_grant_effective; DELETE FROM assistant_grant_pending; DELETE FROM assistant_grant_dirty; + DELETE FROM assistant_grant_auth_cursor; + DELETE FROM assistant_grant_membership_dirty; DELETE FROM assistant_grant_membership_windows; DELETE FROM meta WHERE key='assistant_grant_authority_version' OR key LIKE 'assistant_grant_authority_cursor/%' diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index f417174f92a..cfe78ddbbf3 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -63,6 +63,7 @@ fn receive(target: &Store, exchange: &ReplicationExchange) { target.receive_replication_exchange(&exchange.peer, FLEET, exchange).unwrap(); target.validate_replication_backlog().unwrap(); target.project_replication_backlog().unwrap(); + drain_authority(target); } fn unsigned(exchange: &ReplicationExchange) -> ReplicationExchange { @@ -379,6 +380,7 @@ fn sealing_local_membership_promotes_an_already_received_peer_grant() { assert!(!target.claim_has_authenticated_member_writer(&grant.id).unwrap()); assert!(decisions(&target, 0).is_empty()); target.seal_local_batches().unwrap(); + drain_authority(&target); assert!(target.claim_has_authenticated_member_writer(&grant.id).unwrap()); assert_eq!(decisions(&target, 0), vec![grant.id]); assert_reference_and_rebuild(&target); @@ -439,6 +441,7 @@ fn deterministic_event_permutations_match_raw_history_and_subject_rebuilds() { // Drain predecessors that an out-of-order envelope initially held. target.validate_replication_backlog().unwrap(); target.project_replication_backlog().unwrap(); + drain_authority(&target); assert_reference_and_rebuild(&target); assert!(authority::contains(&target.readers.get(), &grant.id).unwrap()); assert_eq!(reference(&target), vec![(grant.id, format!("{:020}", 20000), true)]); @@ -454,6 +457,8 @@ fn reset_projection(connection: &Connection) { DELETE FROM assistant_grant_pending; DELETE FROM assistant_grant_membership_windows; DELETE FROM assistant_grant_dirty; + DELETE FROM assistant_grant_auth_cursor; + DELETE FROM assistant_grant_membership_dirty; DELETE FROM meta WHERE key='assistant_grant_authority_version' OR key='assistant_grant_authority_membership_generation' OR key LIKE 'assistant_grant_authority_cursor/%';" @@ -710,3 +715,290 @@ fn malformed_and_unsigned_same_origin_flood_preserves_previous_authority_and_con assert_reference_and_rebuild(&target); } } + +#[test] +fn duplicate_verified_signature_does_not_refresh_or_dirty_claims() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let grant = append(&source, SUBJECT, GRANTED, fields()); + let exchange = export(&source, &target); + receive(&target, &exchange); + let signature = signatures(&exchange).signatures.into_iter().find(|signature| { + target.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", + params![grant.id,signature.sequence], |row| row.get::<_,bool>(0)).unwrap() + }).unwrap(); + let mut connection = target.connection.write(); + // Any refresh would delete this sentinel. Abort that attempted write rather + // than merely checking the final projection, which might be unchanged. + connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&grant.id]).unwrap(); + connection.execute_batch( + "CREATE TEMP TRIGGER reject_duplicate_refresh BEFORE DELETE ON assistant_grant_dirty + BEGIN SELECT RAISE(ABORT,'duplicate refreshed authority'); END;", + ).unwrap(); + let transaction = connection.transaction().unwrap(); + assert_eq!(store_envelope_signature_tx( + &transaction,None,FLEET,&signature.writer,signature.sequence,&signature.hash, + &signature.member_key,&signature.signature,"1", + ).unwrap(), 0); + let dirty: usize = transaction.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get(0)).unwrap(); + assert_eq!(dirty,1); + transaction.commit().unwrap(); + connection.execute_batch("DROP TRIGGER reject_duplicate_refresh; DELETE FROM assistant_grant_dirty;").unwrap(); + drop(connection); + assert_reference_and_rebuild(&target); +} + +#[test] +fn dirty_claim_flood_is_limited_to_sixty_four_refreshes_per_transaction() { + let store = node("issuer", None); + for index in 0..(authority::CLAIMS_PER_SLICE * 3 + 7) { + let mut invalid = fields(); + invalid["issuer"] = json!(format!("invalid/{index}")); + append(&store,SUBJECT,GRANTED,invalid); + } + drain_authority(&store); + let mut connection = store.connection.write(); + let markers = backfill_markers(&connection); + connection.execute("INSERT INTO assistant_grant_dirty SELECT id FROM claims WHERE kind=?1", [GRANTED]).unwrap(); + let mut remaining = authority::CLAIMS_PER_SLICE * 3 + 7; + loop { + let transaction = connection.transaction().unwrap(); + let done = authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap(); + let after: usize = transaction.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get(0)).unwrap(); + assert_eq!(remaining-after, remaining.min(authority::CLAIMS_PER_SLICE)); + assert_eq!(backfill_markers(&transaction),markers,"completed history was rescanned"); + transaction.commit().unwrap(); + remaining = after; + if done { break; } + } + assert_eq!(remaining,0); +} + +fn authentication_key_cost(connection: &Connection, signature: &ReplicaEnvelopeSignature) -> (usize,i32,i32) { + let mut statement = connection.prepare(authority::AUTHENTICATION_KEYS_QUERY).unwrap(); + let rows = statement.query_map( + params![signature.writer,signature.sequence,signature.hash,"",authority::MEMBERSHIP_KEYS_PER_REFRESH], + |row| Ok((row.get::<_,String>(0)?,row.get::<_,Option>(1)?)), + ).unwrap().collect::>>().unwrap(); + (rows.len(),statement.get_status(StatementStatus::VmStep),statement.get_status(StatementStatus::FullscanStep)) +} + +#[test] +fn nonmember_signature_flood_has_constant_membership_first_vm_cost() { + let (source,key) = source(); + let target = node("reader",Some(key.public())); + receive(&target,&export(&source,&target)); + let grant = append(&source,SUBJECT,GRANTED,fields()); + let exchange = export(&source,&target); + receive(&target,&unsigned(&exchange)); + let signature = signatures(&exchange).signatures.into_iter().find(|signature| { + target.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", + params![grant.id,signature.sequence], |row| row.get::<_,bool>(0)).unwrap() + }).unwrap(); + let mut connection = target.connection.write(); + let before = authentication_key_cost(&connection,&signature); + assert_eq!(before.0,1); + assert_eq!(before.2,0); + for count in [128,4096] { + for index in 0..count { + let mut nonmember = signature.clone(); + nonmember.member_key = format!("nonmember/{count}/{index:08}"); + nonmember.signature = "invalid".into(); + insert_raw_signature(&connection,&nonmember); + } + assert_eq!(authentication_key_cost(&connection,&signature),before, + "nonmember signature rows increased authentication VM work"); + let transaction = connection.transaction().unwrap(); + assert!(authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap()); + assert!(!authority::contains(&transaction,&grant.id).unwrap()); + transaction.commit().unwrap(); + } + // Real late evidence still verifies after the arbitrary-signature flood. + insert_raw_signature(&connection,&signature); + let transaction = connection.transaction().unwrap(); + assert!(authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap()); + assert!(authority::contains(&transaction,&grant.id).unwrap()); + transaction.commit().unwrap(); +} + +#[test] +fn eligible_evidence_beyond_first_key_page_resumes_and_cryptographically_verifies() { + let (source,key) = source(); + let target = node("reader",Some(key.public())); + receive(&target,&export(&source,&target)); + let grant = append(&source,SUBJECT,GRANTED,fields()); + let exchange = export(&source,&target); + receive(&target,&unsigned(&exchange)); + let signature = signatures(&exchange).signatures.into_iter().find(|signature| { + target.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", + params![grant.id,signature.sequence], |row| row.get::<_,bool>(0)).unwrap() + }).unwrap(); + let mut connection = target.connection.write(); + let markers = backfill_markers(&connection); + // These deliberately malformed persisted proofs must not authenticate. + // Their eligible windows sort before the real member's key. + for index in 0..(authority::MEMBERSHIP_KEYS_PER_REFRESH*3+1) { + let mut invalid = signature.clone(); + invalid.member_key = format!("!{index:08}"); + invalid.signature = "invalid".into(); + connection.execute( + "INSERT INTO assistant_grant_membership_windows VALUES(?1,?2,0,NULL)", + params![invalid.writer,invalid.member_key]).unwrap(); + insert_raw_signature(&connection,&invalid); + } + insert_raw_signature(&connection,&signature); + let cost = authentication_key_cost(&connection,&signature); + assert_eq!(cost.0,authority::MEMBERSHIP_KEYS_PER_REFRESH); + assert_eq!(cost.2,0); + let mut previous_key = String::new(); + for page in 0..4 { + let transaction = connection.transaction().unwrap(); + let done = authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap(); + assert_eq!(backfill_markers(&transaction),markers); + if page<3 { + assert!(!done,"invalid earlier evidence authenticated the claim"); + assert!(authority::ready(&transaction).is_err()); + let cursor: String = transaction.query_row( + "SELECT member_key FROM assistant_grant_auth_cursor WHERE claim_id=?1", + [&grant.id], |row| row.get(0)).unwrap(); + assert!(cursor>previous_key,"authentication did not advance durably"); + previous_key = cursor; + let admitted: bool = transaction.query_row( + "SELECT authenticated FROM assistant_grant_pending WHERE claim_id=?1", [&grant.id], |row| row.get(0)).unwrap(); + assert!(!admitted); + } else { + assert!(done); + assert!(authority::contains(&transaction,&grant.id).unwrap()); + } + transaction.commit().unwrap(); + } +} + +#[test] +fn changed_membership_writer_flood_uses_the_same_fixed_refresh_budget() { + let (source,key) = source(); + let target = node("reader",Some(key.public())); + receive(&target,&export(&source,&target)); + for _ in 0..(authority::CLAIMS_PER_SLICE*2+7) { + append(&source,SUBJECT,GRANTED,fields()); + } + receive(&target,&unsigned(&export(&source,&target))); + let mut connection = target.connection.write(); + let markers = backfill_markers(&connection); + connection.execute( + "INSERT INTO assistant_grant_membership_dirty VALUES('anchor',0,'')", [], + ).unwrap(); + connection.execute_batch( + "CREATE TEMP TABLE refreshed_items (claim_id TEXT); + CREATE TEMP TRIGGER count_membership_refresh AFTER UPDATE ON assistant_grant_membership_dirty + BEGIN INSERT INTO refreshed_items VALUES(NEW.claim_id); END;", + ).unwrap(); + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap()); + let refreshed: usize = transaction.query_row( + "SELECT COUNT(*) FROM refreshed_items", [], |row| row.get(0)).unwrap(); + assert_eq!(refreshed,authority::CLAIMS_PER_SLICE); + assert!(authority::ready(&transaction).is_err()); + assert_eq!(backfill_markers(&transaction),markers); + transaction.commit().unwrap(); + drop(connection); + drain_authority(&target); + assert!(decisions(&target,0).is_empty(),"unsigned pending grants acquired authority"); +} + +#[test] +fn late_signature_restarts_an_in_progress_key_cursor_before_its_old_position() { + let (source,key) = source(); + let target = node("reader",Some(key.public())); + receive(&target,&export(&source,&target)); + let grant = append(&source,SUBJECT,GRANTED,fields()); + let exchange = export(&source,&target); + receive(&target,&unsigned(&exchange)); + let signature = signatures(&exchange).signatures.into_iter().find(|signature| { + target.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", + params![grant.id,signature.sequence], |row| row.get::<_,bool>(0)).unwrap() + }).unwrap(); + let mut connection = target.connection.write(); + for index in 0..(authority::MEMBERSHIP_KEYS_PER_REFRESH*2) { + connection.execute( + "INSERT INTO assistant_grant_membership_windows VALUES(?1,?2,0,NULL)", + params![signature.writer,format!("~{index:08}")]).unwrap(); + } + connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&grant.id]).unwrap(); + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap()); + let cursor: String = transaction.query_row( + "SELECT member_key FROM assistant_grant_auth_cursor WHERE claim_id=?1", + [&grant.id], |row| row.get(0)).unwrap(); + assert!(cursor>signature.member_key); + transaction.commit().unwrap(); + insert_raw_signature(&connection,&signature); + let cursors: usize = connection.query_row( + "SELECT COUNT(*) FROM assistant_grant_auth_cursor WHERE claim_id=?1", + [&grant.id], |row| row.get(0)).unwrap(); + assert_eq!(cursors,0,"new evidence did not invalidate the earlier search position"); + let transaction = connection.transaction().unwrap(); + assert!(authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap()); + assert!(authority::contains(&transaction,&grant.id).unwrap()); + transaction.commit().unwrap(); +} + +#[test] +fn envelope_record_arriving_before_auth_cursor_restarts_preexisting_signature_search() { + let (source,key) = source(); + let target = node("reader",Some(key.public())); + receive(&target,&export(&source,&target)); + let grant = append(&source,SUBJECT,GRANTED,fields()); + let exchange = export(&source,&target); + receive(&target,&unsigned(&exchange)); + let signature = signatures(&exchange).signatures.into_iter().find(|signature| { + target.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", + params![grant.id,signature.sequence], |row| row.get::<_,bool>(0)).unwrap() + }).unwrap(); + let mut connection = target.connection.write(); + // Keep an unsigned later-position copy, leaving the signed envelope with + // no attached claim record when its signature arrives. + connection.execute( + "INSERT INTO replica_envelopes + SELECT writer,sequence,'decoy-envelope',previous_hash,accepted_at_unix_ms, + payload,batch_id,relay,receipt_state,validation_error,received_at_unix_ms + FROM replica_envelopes WHERE writer=?1 AND sequence=?2 AND envelope_hash=?3", + params![signature.writer,signature.sequence,signature.hash]).unwrap(); + connection.execute( + "UPDATE replica_records SET envelope_hash='decoy-envelope',position=1 WHERE claim_id=?1", + [&grant.id]).unwrap(); + for index in 0..(authority::MEMBERSHIP_KEYS_PER_REFRESH*2) { + connection.execute( + "INSERT INTO assistant_grant_membership_windows VALUES(?1,?2,0,NULL)", + params![signature.writer,format!("~{index:08}")]).unwrap(); + } + connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&grant.id]).unwrap(); + let transaction = connection.transaction().unwrap(); + assert!(!authority::backfill_slice(&transaction,Duration::from_secs(60)).unwrap()); + let position: i64 = transaction.query_row( + "SELECT position FROM assistant_grant_auth_cursor WHERE claim_id=?1", + [&grant.id], |row| row.get(0)).unwrap(); + assert_eq!(position,1); + transaction.commit().unwrap(); + insert_raw_signature(&connection,&signature); + let cursors: usize = connection.query_row( + "SELECT COUNT(*) FROM assistant_grant_auth_cursor WHERE claim_id=?1", + [&grant.id], |row| row.get(0)).unwrap(); + assert_eq!(cursors,1,"signature unexpectedly had a linked claim record"); + let transaction = connection.transaction().unwrap(); + transaction.execute( + "INSERT INTO replica_records + (record_ref,writer,sequence,envelope_hash,position,raw,state,claim_id,updated_at_unix_ms) + SELECT 'earlier-signed-record',writer,sequence,?2,0,raw,'valid',claim_id,'0' + FROM replica_records WHERE claim_id=?1", + params![grant.id,signature.hash]).unwrap(); + authority::refresh_envelope(&transaction,&signature.writer,signature.sequence,&signature.hash).unwrap(); + assert!(authority::contains(&transaction,&grant.id).unwrap(), + "the earlier signed record was hidden behind the old position/key cursor"); + transaction.commit().unwrap(); +} From dc771be11d99fde4566aa251c830a4be059712a9 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 16:13:37 +0100 Subject: [PATCH 42/52] fix: isolate grant membership maintenance and subject readiness agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 22 +- .../external_grants/conflict_tests.rs | 54 +++ .../src/store/assistant_write.rs | 33 +- .../fractal-store/src/store/messages_shard.rs | 4 + crates/fractal-store/src/store/runtime.rs | 12 +- .../assistant_grant_authority_wake_tests.rs | 8 +- crates/fractal/src/main.rs | 2 +- crates/smallclaims/src/store.rs | 11 +- .../src/store/assistant_grant_authority.rs | 313 ++++++++++++++---- .../store/assistant_grant_authority_bench.rs | 4 +- .../store/assistant_grant_authority_tests.rs | 120 ++++++- .../assistant_grant_receipt_cost_tests.rs | 174 ++++++++++ crates/smallclaims/src/store/prepared_seal.rs | 1 - docs/st3/external-assistants.md | 24 +- .../external-grant-profile-conflict.json | 2 +- 15 files changed, 669 insertions(+), 115 deletions(-) create mode 100644 crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index 5685061bbda..4f29727f8bc 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -17,6 +17,14 @@ pub const ROUTES: &[(&str, &str)] = &[ pub const PRINCIPAL: &str = "assistant/chatgpt"; pub const MCP_PRINCIPAL: &str = "assistant/mcp"; +fn authority_error(error: FractalError) -> ApiError { + if error.code == "assistant-grant-authority-not-ready" { + credential_rejected("the client credential is unknown or expired") + } else { + ApiError::bad(error) + } +} + /// Closed authority profiles: callers cannot register a profile or mix its rights. /// Service is reserved and cannot issue credentials or authorize any request. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -85,7 +93,7 @@ fn candidate_grants_except(state: &AppState, principal: &str, expiry_cut: Option Profile::Assistant => "assistant", Profile::Service => "service", }); authority::candidates(&state.store.readers.get(), principal, owning_person(state)?, - expiry_cut, excluded, ignored_profile).map_err(ApiError::bad)? + expiry_cut, excluded, ignored_profile).map_err(authority_error)? .into_iter().map(|grant| { let profile = Profile::stored(fields(&grant)?)?; Ok((grant, profile)) @@ -179,7 +187,7 @@ pub fn fields(claim: &ClaimRecord) -> Result<&Value, ApiError> { } pub fn latest(state: &AppState, subject: &str, kind: &str) -> Result, ApiError> { if matches!(kind, GRANTED | POLICY | REVOKED) { - return authority::latest(&state.store.readers.get(), subject, kind).map_err(ApiError::bad); + return authority::latest(&state.store.readers.get(), subject, kind).map_err(authority_error); } Ok(state.store.claims_for_subject_kind_at(subject, kind, None, true, 1) .map_err(ApiError::internal)?.claims.into_iter().next()) @@ -197,7 +205,7 @@ pub fn append(state: &AppState, subject: String, kind: &str, actor: &str, if kind == REVOKED { Profile::stored(&value)?; let granted = authority::latest(&state.store.readers.get(), &subject, GRANTED) - .map_err(ApiError::bad)?.ok_or_else(|| forbidden("assistant grant is absent"))?; + .map_err(authority_error)?.ok_or_else(|| forbidden("assistant grant is absent"))?; if actor != owning_person(state)? || granted.actor.as_deref() != Some(actor) || granted.origin != state.store.origin() || previous.is_none() @@ -264,7 +272,7 @@ pub fn audit(state: &AppState, operation: &str, actor: &str, transport: &str, } fn transition(state: &AppState, granted: &ClaimRecord, kind: &str) -> Result, ApiError> { - authority::transition(&state.store.readers.get(), granted, kind).map_err(ApiError::bad) + authority::transition(&state.store.readers.get(), granted, kind).map_err(authority_error) } pub fn revoked(state: &AppState, granted: &ClaimRecord) -> Result { @@ -317,13 +325,13 @@ pub fn projection_with_witness(state: &AppState, granted: &ClaimRecord) -> Resul pub fn authenticate(state: &AppState, digest: &str, transport: &'static str) -> Result, ApiError> { let Some(granted) = authority::by_credential(&state.store.readers.get(), digest) - .map_err(ApiError::bad)? else { return Ok(None); }; + .map_err(authority_error)? else { return Ok(None); }; session(state, &granted, transport).map(Some) } pub fn session(state: &AppState, granted: &ClaimRecord, transport: &'static str) -> Result { - if !authority::contains(&state.store.readers.get(), &granted.id).map_err(ApiError::bad)? { - return Err(forbidden("assistant grant is absent or unauthenticated")); + if !authority::contains(&state.store.readers.get(), &granted.id).map_err(authority_error)? { + return Err(credential_rejected("the client credential is unknown or expired")); } let now = client_now_ms() as u64; let policy = effective(state, granted)?; diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index f997665b0e3..b8b9f15a385 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -1,6 +1,7 @@ use super::*; use fractal_client::ErrorCode; use smallclaims::fleet::MemberKey; +use std::collections::BTreeSet; use std::sync::Arc; const FLEET: &str = "86700000-0000-4000-8000-000000000001"; @@ -41,6 +42,7 @@ fn replicate(from: &AppState, to: &AppState) { to.store.receive_replication_exchange(from.store.origin(), FLEET, &exchange).unwrap(); to.store.validate_replication_backlog().unwrap(); to.store.project_replication_backlog().unwrap(); + while !to.store.advance_assistant_grant_authority_backfill().unwrap() {} } fn admitted_pair(root: &std::path::Path) -> (AppState, AppState) { @@ -587,3 +589,55 @@ fn p1_policy_candidates_keep_read_acquisitions_bounded_with_expired_history() { operation.finish(); } } + +#[test] +fn dirty_grant_reads_and_bearers_fail_closed_without_blocking_an_unrelated_credential() { + let root = tempfile::tempdir().unwrap(); + let state = member(root.path(), "issuer"); + let grant = issue(&state, ASSISTANT_ID, "assistant").unwrap(); + let independent = issue(&state, SERVICE_ID, "assistant").unwrap(); + while !state.store.advance_assistant_grant_authority_backfill().unwrap() {} + authenticate_id(&state, ASSISTANT_ID).unwrap().unwrap(); + authenticate_id(&state, SERVICE_ID).unwrap().unwrap(); + state.store.connection.write().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&grant.id], + ).unwrap(); + assert!(authenticate_id(&state, ASSISTANT_ID).unwrap().is_none()); + authenticate_id(&state, SERVICE_ID).unwrap().unwrap(); + let denied = credential_rejected("the client credential is unknown or expired"); + for error in [ + session(&state, &grant, "http").unwrap_err(), + effective(&state, &grant).unwrap_err(), + revoked(&state, &grant).unwrap_err(), + projection(&state, &grant).unwrap_err(), + latest(&state, &grant.subject, GRANTED).unwrap_err(), + ] { + assert_eq!(error.status, denied.status); + assert_eq!(error.code, denied.code); + assert_eq!(error.message, denied.message); + assert_eq!(error.details, denied.details); + } + assert_eq!(candidate_grants(&state, PRINCIPAL, Some(0)).unwrap() + .iter().map(|(claim, _)| claim.id.as_str()).collect::>(), + BTreeSet::from([grant.id.as_str(), independent.id.as_str()])); +} + +#[test] +fn dirty_opposite_profile_witness_does_not_clear_an_established_conflict() { + let _service = ServiceFixture::enable(); + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + replicate(&a, &b); + replicate(&b, &a); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).unwrap_err()); + a.store.connection.write().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&service.id], + ).unwrap(); + assert!(authenticate_id(&a, SERVICE_ID).unwrap().is_none(), + "the dirty subject's own credential is fenced"); + assert_conflict(&authenticate_id(&a, ASSISTANT_ID).unwrap_err()); + assert_eq!(candidate_grants(&a, PRINCIPAL, Some(0)).unwrap().len(), 2, + "pending work cannot erase the last authenticated opposite-profile snapshot"); +} diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 10b9fd5e07c..0f67f358174 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -27,13 +27,16 @@ pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &As pub fn authorized_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let denied = || FractalError::new("forbidden", "assistant write authorization changed or expired before commit"); - let granted = authority::latest(connection, &authorization.grant_subject, authority::GRANTED)? + let authority_error = |error: FractalError| { + if error.code == "assistant-grant-authority-not-ready" { denied() } else { error } + }; + let granted = authority::latest(connection, &authorization.grant_subject, authority::GRANTED).map_err(authority_error)? .ok_or_else(denied)?; - let policy_claim = authority::transition(connection, &granted, authority::POLICY)?; + let policy_claim = authority::transition(connection, &granted, authority::POLICY).map_err(authority_error)?; let policy = policy_claim.as_ref().unwrap_or(&granted); if granted.origin != origin || policy.origin != origin || !authority::structurally_valid(&granted, policy) - || authority::transition(connection, &granted, authority::REVOKED)?.is_some() { + || authority::transition(connection, &granted, authority::REVOKED).map_err(authority_error)?.is_some() { return Err(denied()); } let fields = &policy.body["fields"]; @@ -229,4 +232,28 @@ mod tests { assert!(refuse_unverified("message.sent", Some(principal), Some(principal), false).is_err()); } } + + #[test] + fn writer_recheck_fences_dirty_subject_without_exposing_projection_state() { + let (store, subject, mut body) = transition_fixture(); + body["fields"]["policy_revision"] = json!(1); + body["fields"]["scopes"] = json!(["write.assistant.answers"]); + let policy = insert_transition(&store, &subject, authority::POLICY, "person/owner", &body); + let authorization = AssistantWriteAuthorization { + grant_subject: subject, + actor: body["fields"]["session_actor"].as_str().unwrap().into(), + owner: "person/owner".into(), policy_revision: 1, + scope: "write.assistant.answers".into(), recipient: None, + }; + let connection = store.connection.write(); + authorize_grant(&connection, "local", &authorization).unwrap(); + connection.execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES('unrelated-claim')", [], + ).unwrap(); + authorize_grant(&connection, "local", &authorization).unwrap(); + connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&policy.id]).unwrap(); + let error = authorize_grant(&connection, "local", &authorization).unwrap_err(); + assert_eq!(error.code, "forbidden"); + assert_eq!(error.message, "assistant write authorization changed or expired before commit"); + } } diff --git a/crates/fractal-store/src/store/messages_shard.rs b/crates/fractal-store/src/store/messages_shard.rs index 32b016d9b35..a1a354703e4 100644 --- a/crates/fractal-store/src/store/messages_shard.rs +++ b/crates/fractal-store/src/store/messages_shard.rs @@ -463,6 +463,10 @@ impl FleetAuthority for GraphAuthority { FleetAuthority::fleet_generation(&self.graph()?.graph) } + fn assistant_grant_membership_revision(&self) -> anyhow::Result { + FleetAuthority::assistant_grant_membership_revision(&self.graph()?.graph) + } + fn fleet_membership(&self) -> anyhow::Result { FleetAuthority::fleet_membership(&self.graph()?.graph) } diff --git a/crates/fractal-store/src/store/runtime.rs b/crates/fractal-store/src/store/runtime.rs index e82e30401b8..dc3b9a2fbd9 100644 --- a/crates/fractal-store/src/store/runtime.rs +++ b/crates/fractal-store/src/store/runtime.rs @@ -984,14 +984,18 @@ mod schema_install_tests { && step.contains("principal=? AND owner=? AND revoked=? AND expires_at>?")), "{plan:?}"); assert!(plan.iter().all(|step| !step.contains("SCAN claims") && !step.contains("SEARCH claims")), "{plan:?}"); - // An older build can append raw evidence after backfill. The - // trigger closes admission until reconciliation, but origin - // text alone cannot authenticate this unmarked late revoke. + // An older build's raw revoke fences its subject before and + // after reconciliation: origin text cannot authenticate it, + // but pending revocation must not authorize a stale grant. append(&connection, "late-revoke", 1, authority::REVOKED, "assistant/chatgpt", 200); - assert!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None).is_err()); + authority::ready(&connection).unwrap(); + assert_eq!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None) + .unwrap().iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert!(!authority::contains(&connection, "active").unwrap()); while !authority::backfill_slice(&connection, Duration::from_secs(1)).unwrap() {} assert_eq!(authority::candidates(&connection, "assistant/chatgpt", "person/owner", Some(100), None, None) .unwrap().iter().map(|claim| claim.id.as_str()).collect::>(), vec!["active"]); + assert!(!authority::contains(&connection, "active").unwrap()); assert!(!authority::contains(&connection, "late-revoke").unwrap()); let after = snapshot(&connection); let cookie: u32 = connection.pragma_query_value(None, "schema_version", |row| row.get(0)).unwrap(); diff --git a/crates/fractal/src/assistant_grant_authority_wake_tests.rs b/crates/fractal/src/assistant_grant_authority_wake_tests.rs index 410c76039c4..f42a9b6c7b1 100644 --- a/crates/fractal/src/assistant_grant_authority_wake_tests.rs +++ b/crates/fractal/src/assistant_grant_authority_wake_tests.rs @@ -23,10 +23,10 @@ async fn completed_authority_reconciles_older_build_appends_without_reopen() { 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1')", [id], ).unwrap(); - assert!(authority::ready(&store.readers.get()).is_err()); + authority::ready(&store.readers.get()).unwrap(); tokio::time::timeout(Duration::from_secs(5), async { loop { - if authority::ready(&store.readers.get()).is_ok() { break; } + if !authority::maintenance_pending(&store.readers.get()).unwrap() { break; } tokio::task::yield_now().await; } }).await.expect("a completed projection wakes and drains compatibility work"); @@ -52,12 +52,14 @@ async fn authority_commit_between_completed_drain_and_wait_is_not_lost() { 'custom.client.assistant.v1.granted','node','person/owner','{}','[]','1'); COMMIT;" ).unwrap(); - assert!(authority::ready(&store.readers.get()).is_err()); + authority::ready(&store.readers.get()).unwrap(); + assert!(authority::maintenance_pending(&store.readers.get()).unwrap()); tokio::time::timeout(Duration::from_secs(5), maintenance.changes.changed()) .await.expect("the intervening commit stays visible") .expect("the observer remains registered"); assert!(maintenance.advance().await.unwrap()); assert!(authority::ready(&store.readers.get()).is_ok()); + assert!(!authority::maintenance_pending(&store.readers.get()).unwrap()); } #[tokio::test] diff --git a/crates/fractal/src/main.rs b/crates/fractal/src/main.rs index 086c52f22fd..9cc8bdf5723 100644 --- a/crates/fractal/src/main.rs +++ b/crates/fractal/src/main.rs @@ -20849,7 +20849,7 @@ impl AssistantGrantAuthorityMaintenance { self.changes.borrow_and_update(); let worker = self.store.clone(); tokio::task::spawn_blocking(move || { - if smallclaims::store::assistant_grant_authority::ready(&worker.readers.get()).is_ok() { + if !smallclaims::store::assistant_grant_authority::maintenance_pending(&worker.readers.get())? { return Ok(true); } worker.advance_assistant_grant_authority_backfill() diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index 0df3958abe0..e04341c5d74 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -3738,11 +3738,6 @@ impl<'a> VerifiedEnvelopeSignature<'a> { self.signature, now ])?; - if inserted != 0 { - assistant_grant_authority::refresh_envelope( - transaction, self.writer, self.sequence, self.envelope_hash, - )?; - } Ok(inserted) } } @@ -3754,6 +3749,8 @@ pub trait FleetAuthority: Send + Sync { fn fleet_id(&self) -> Result>; /// Advances whenever the default store's membership may have changed. fn fleet_generation(&self) -> Result; + /// Projection-relevant evidence only; unrelated signatures do not advance it. + fn assistant_grant_membership_revision(&self) -> Result; fn fleet_membership(&self) -> Result; fn fleet_membership_sealed(&self) -> Result; /// Whether this is a default store that takes its fleet from no other store. @@ -3769,6 +3766,10 @@ impl FleetAuthority for Store { fleet_generation(&self.readers.get()) } + fn assistant_grant_membership_revision(&self) -> Result { + Store::assistant_grant_membership_revision(self) + } + fn fleet_membership(&self) -> Result { Store::fleet_membership(self) } diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index 5ae0d7a9ed4..1c90ebb2c6a 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -118,13 +118,20 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { claim_id TEXT PRIMARY KEY, position INTEGER NOT NULL, record_rowid INTEGER NOT NULL, member_key TEXT NOT NULL); CREATE TABLE IF NOT EXISTS assistant_grant_membership_dirty ( writer TEXT PRIMARY KEY, sequence INTEGER NOT NULL, claim_id TEXT NOT NULL); + CREATE TABLE IF NOT EXISTS assistant_grant_membership_state ( + id INTEGER PRIMARY KEY CHECK(id=1), revision INTEGER NOT NULL, applied_revision INTEGER NOT NULL); + INSERT OR IGNORE INTO assistant_grant_membership_state VALUES(1,1,0); CREATE TABLE IF NOT EXISTS assistant_grant_local_appends (claim_id TEXT PRIMARY KEY); CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') BEGIN INSERT OR IGNORE INTO assistant_grant_dirty VALUES(NEW.id); END; DROP TRIGGER IF EXISTS assistant_grant_dirty_signature_insert; - CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_signature_insert_v2 + DROP TRIGGER IF EXISTS assistant_grant_dirty_signature_insert_v2; + CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_signature_insert_v3 AFTER INSERT ON replica_envelope_signatures + WHEN EXISTS(SELECT 1 FROM assistant_grant_membership_windows + WHERE writer=NEW.writer AND member_key=NEW.member_key + AND NEW.sequence>=start AND (end IS NULL OR NEW.sequence<=end)) BEGIN INSERT OR IGNORE INTO assistant_grant_dirty(claim_id) SELECT records.claim_id FROM replica_records AS records @@ -140,15 +147,62 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { writer TEXT NOT NULL, member_key TEXT NOT NULL, start INTEGER NOT NULL, end INTEGER, PRIMARY KEY(writer,member_key));" )?; + install_membership_evidence_triggers(connection)?; connection.execute(/* sqlite-large-value: allow-for-now lv-h3f117dab1bdd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_local_origin',?1)", [local_origin])?; Ok(()) } +/// Independent from the inherited fleet-generation counter: an irrelevant +/// signature may invalidate that legacy cache, but never this projection. +fn install_membership_evidence_triggers(connection: &Connection) -> Result<()> { + let bump = "UPDATE assistant_grant_membership_state SET revision=revision+1 WHERE id=1;"; + for (event, row) in [("INSERT", "NEW"), ("DELETE", "OLD")] { + connection.execute_batch(&format!( + "CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_claim_{event} + AFTER {event} ON claims WHEN {row}.kind IN ({FLEET_CLAIM_KINDS}) + BEGIN {bump} END; + CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_envelope_{event} + AFTER {event} ON replica_envelopes + WHEN EXISTS(SELECT 1 FROM claims WHERE batch_id={row}.batch_id + AND kind IN ({FLEET_CLAIM_KINDS})) + BEGIN {bump} END; + CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_anchor_{event} + AFTER {event} ON meta WHEN {row}.key IN ('fleet_anchor_key','fleet_id') + BEGIN {bump} END;" + ))?; + } + connection.execute_batch(&format!( + "CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_claim_update + AFTER UPDATE OF kind,body,subject,batch_id ON claims + WHEN OLD.kind IN ({FLEET_CLAIM_KINDS}) OR NEW.kind IN ({FLEET_CLAIM_KINDS}) + BEGIN {bump} END; + CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_envelope_update + AFTER UPDATE OF writer,sequence,batch_id,envelope_hash,receipt_state ON replica_envelopes + WHEN EXISTS(SELECT 1 FROM claims WHERE batch_id IN (OLD.batch_id,NEW.batch_id) + AND kind IN ({FLEET_CLAIM_KINDS})) + BEGIN {bump} END; + CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_anchor_update + AFTER UPDATE OF value ON meta + WHEN NEW.key IN ('fleet_anchor_key','fleet_id') AND NEW.value IS NOT OLD.value + BEGIN {bump} END; + CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_signature_insert + AFTER INSERT ON replica_envelope_signatures + WHEN EXISTS(SELECT 1 FROM assistant_grant_membership_windows + WHERE writer=NEW.writer AND member_key=NEW.member_key + AND NEW.sequence>=start AND (end IS NULL OR NEW.sequence<=end)) + AND EXISTS(SELECT 1 FROM replica_envelopes AS envelopes + JOIN claims ON claims.batch_id=envelopes.batch_id + WHERE envelopes.writer=NEW.writer AND envelopes.sequence=NEW.sequence + AND envelopes.envelope_hash=NEW.envelope_hash + AND claims.kind IN ({FLEET_CLAIM_KINDS})) + BEGIN {bump} END;" + ))?; + Ok(()) +} + pub fn ready(connection: &Connection) -> Result<(), FractalError> { let complete: bool = connection.query_row( - "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')=?1 - AND NOT EXISTS(SELECT 1 FROM assistant_grant_dirty) - AND NOT EXISTS(SELECT 1 FROM assistant_grant_membership_dirty)", + "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')=?1", [VERSION], |row| row.get(0), ).map_err(internal)?; if !complete { @@ -156,6 +210,36 @@ pub fn ready(connection: &Connection) -> Result<(), FractalError> { } Ok(()) } +/// Durable maintenance work is independent of initial-backfill readiness. +pub fn maintenance_pending(connection: &Connection) -> Result { + let pending: bool = connection.query_row( + "SELECT COALESCE((SELECT value FROM meta WHERE key='assistant_grant_authority_version'),'')<>?1 + OR EXISTS(SELECT 1 FROM assistant_grant_dirty) + OR EXISTS(SELECT 1 FROM assistant_grant_membership_dirty) + OR EXISTS(SELECT 1 FROM assistant_grant_membership_state WHERE revision<>applied_revision)", + [VERSION], |row| row.get(0), + ).map_err(internal)?; + Ok(pending) +} +fn subject_pending(connection: &Connection, subject: &str) -> Result { + connection.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_dirty AS dirty + JOIN claims ON claims.id=dirty.claim_id WHERE claims.subject=?1) + OR EXISTS(SELECT 1 FROM assistant_grant_auth_cursor AS cursor + JOIN claims ON claims.id=cursor.claim_id WHERE claims.subject=?1) + OR EXISTS(SELECT 1 FROM assistant_grant_pending + WHERE grant_subject=?1 AND authenticated=0)", + [subject], |row| row.get(0), + ).map_err(internal) +} +/// A pending proof or unauthenticated revoke fences only its grant subject. +pub fn subject_ready(connection: &Connection, subject: &str) -> Result<(), FractalError> { + ready(connection)?; + if subject_pending(connection, subject)? { + return Err(FractalError::new("assistant-grant-authority-not-ready", "external-grant subject authentication is in progress")); + } + Ok(()) +} fn decode(record: String) -> Result { serde_json::from_str(&record).map_err(internal) } @@ -163,7 +247,7 @@ pub const TRANSITION_QUERY: &str = "SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2 AND origin=?3 AND actor=?4 AND base_claim_id=?5 ORDER BY store_index DESC LIMIT 1"; pub fn transition(connection: &Connection, granted: &ClaimRecord, kind: &str) -> Result, FractalError> { - ready(connection)?; + subject_ready(connection, &granted.subject)?; transition_unchecked(connection, granted, kind).map_err(internal) } fn transition_unchecked(connection: &Connection, granted: &ClaimRecord, kind: &str) -> Result> { @@ -172,7 +256,7 @@ fn transition_unchecked(connection: &Connection, granted: &ClaimRecord, kind: &s record.map(|record| serde_json::from_str(&record).map_err(Into::into)).transpose() } pub fn latest(connection: &Connection, subject: &str, kind: &str) -> Result, FractalError> { - ready(connection)?; + subject_ready(connection, subject)?; let record: Option = connection.query_row( "SELECT record FROM assistant_grant_authority WHERE grant_subject=?1 AND kind=?2 ORDER BY store_index DESC LIMIT 1", params![subject,kind], |row| row.get(0)).optional().map_err(internal)?; @@ -185,6 +269,9 @@ pub const CANDIDATES_QUERY: &str = "SELECT grant_record FROM assistant_grant_eff SELECT grant_record FROM assistant_grant_effective WHERE ?3 IS NULL AND principal=?1 AND owner=?2 AND (?4 IS NULL OR claim_id<>?4) AND (?5 IS NULL OR profile<>?5)"; +/// Authenticated effective snapshots for conflict admission, not bearer access. +/// A pending revoke must not erase an opposite-profile conflict witness before +/// it authenticates. Bearer and transition readers independently fence subjects. pub fn candidates(connection: &Connection, principal: &str, owner: &str, expiry_cut: Option, excluded: Option<&str>, ignored_profile: Option<&str>) -> Result, FractalError> { ready(connection)?; let mut statement = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h556bdadaf8cd owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ CANDIDATES_QUERY).map_err(internal)?; @@ -197,11 +284,22 @@ pub fn by_credential(connection: &Connection, digest: &str) -> Result = connection.query_row( "SELECT record FROM assistant_grant_authority WHERE credential_hash=?1 AND kind='custom.client.assistant.v1.granted' ORDER BY store_index DESC LIMIT 1", [digest], |row| row.get(0)).optional().map_err(internal)?; - record.map(decode).transpose() + let grant = record.map(decode).transpose()?; + match grant { + Some(grant) if !subject_pending(connection, &grant.subject)? => Ok(Some(grant)), + _ => Ok(None), + } } pub fn contains(connection: &Connection, claim_id: &str) -> Result { ready(connection)?; - connection.query_row("SELECT EXISTS(SELECT 1 FROM assistant_grant_authority WHERE claim_id=?1)", [claim_id], |row| row.get(0)).map_err(internal) + let subject: Option = connection.query_row( + "SELECT grant_subject FROM assistant_grant_authority WHERE claim_id=?1 LIMIT 1", + [claim_id], |row| row.get(0), + ).optional().map_err(internal)?; + match subject { + Some(subject) => Ok(!subject_pending(connection, &subject)?), + None => Ok(false), + } } fn insert_authority(connection: &Connection, claim: &ClaimRecord, base: &ClaimRecord) -> Result { @@ -331,6 +429,14 @@ fn authenticated_claim(connection: &Connection, id: &str) -> Result let Some(fleet_id) = fleet_meta(connection,"assistant_grant_authority_fleet_id")? else { return Ok(Some(false)); }; + // Never first-authenticate against a partially applied or stale membership + // snapshot. Already admitted claims and durable local appends bypass this + // path; only this pending subject remains fenced until maintenance catches up. + let membership_ready: bool = connection.query_row( + "SELECT revision=applied_revision FROM assistant_grant_membership_state WHERE id=1", + [], |row| row.get(0), + )?; + if !membership_ready { return Ok(None); } let shard = fleet_meta(connection,"shard_id")?; let cursor: Option<(i64,i64,String)> = connection.query_row( "SELECT position,record_rowid,member_key FROM assistant_grant_auth_cursor WHERE claim_id=?1", @@ -404,7 +510,6 @@ pub const AUTHENTICATION_KEYS_QUERY: &str = /// Refresh only this envelope's grant records, after receipt/signature state has /// been written, and before its transaction is committed. pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, hash: &str) -> Result<()> { - refresh_membership(connection)?; let ids = { let mut statement = connection.prepare_cached("SELECT records.claim_id FROM replica_records AS records JOIN claims ON claims.id=records.claim_id WHERE records.writer=?1 AND records.sequence=?2 AND records.envelope_hash=?3 @@ -421,63 +526,70 @@ pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, ha } Ok(()) } -/// Membership changes promote pending rows only in newly changed keyed windows. -/// Authentication is an admission fact, not a live membership predicate: a later -/// removal/fence cannot retract authentication already established for a past -/// sequence. It can only prevent a pending row from first acquiring it. -pub fn refresh_membership(connection: &Connection) -> Result<()> { - if fleet_meta(connection,"assistant_grant_authority_shared_fleet")?.is_some() { - return Ok(()); - } - let generation = fleet_generation(connection)?; - let previous: Option = connection.query_row("SELECT CAST(value AS INTEGER) FROM meta WHERE key='assistant_grant_authority_membership_generation'",[],|row| row.get(0)).optional()?; - if previous==Some(generation) { return Ok(()); } - refresh_membership_from(connection, &fleet_membership_tx(connection)?, generation, fleet_meta(connection,"fleet_id")?.as_deref())?; - Ok(()) +fn membership_revision(connection: &Connection) -> Result { + Ok(connection.query_row( + "SELECT revision FROM assistant_grant_membership_state WHERE id=1", [], |row| row.get(0), + )?) +} + +struct MembershipUpdate { + revision: i64, + fleet_id: Option, + // Only changed/deleted keys, never a replacement of the complete snapshot. + windows: Vec<(String, String, Option<(u64, Option)>)>, + complete: bool, } -fn refresh_membership_from(connection: &Connection, membership: &crate::fleet::Membership, generation: i64, fleet_id: Option<&str>) -> Result<()> { - let mut changed = Vec::new(); - for incarnation in membership.incarnations() { - let prior: Option<(u64,Option)> = connection.query_row( - "SELECT start,end FROM assistant_grant_membership_windows WHERE writer=?1 AND member_key=?2", - params![incarnation.name,incarnation.member_key], |row| Ok((row.get(0)?,row.get(1)?))).optional()?; - if prior!=Some((incarnation.start,incarnation.end)) { - changed.push((incarnation.name.clone(),incarnation.start,incarnation.end)); +impl MembershipUpdate { + fn apply(&self, connection: &Connection) -> Result { + for (writer,key,window) in &self.windows { + if let Some((start,end)) = window { + connection.execute( + "INSERT INTO assistant_grant_membership_windows VALUES(?1,?2,?3,?4) + ON CONFLICT(writer,member_key) DO UPDATE SET start=excluded.start,end=excluded.end", + params![writer,key,start,end], + )?; + } else { + connection.execute( + "DELETE FROM assistant_grant_membership_windows WHERE writer=?1 AND member_key=?2", + params![writer,key], + )?; + } + connection.execute( + "INSERT OR REPLACE INTO assistant_grant_membership_dirty + SELECT ?1,0,'' WHERE EXISTS( + SELECT 1 FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index + WHERE origin=?1 AND authenticated=0)", [writer], + )?; } + if self.complete { + if let Some(fleet_id) = &self.fleet_id { + connection.execute( + "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_fleet_id',?1)", + [fleet_id], + )?; + } else { + connection.execute("DELETE FROM meta WHERE key='assistant_grant_authority_fleet_id'", [])?; + } + connection.execute( + "UPDATE assistant_grant_membership_state SET applied_revision=?1 WHERE id=1", + [self.revision], + )?; + } + Ok(self.windows.len()) } - // Replace the window snapshot before promotions, including removal of keys - // no longer present in a conflicted membership fold. - connection.execute(/* sqlite-large-value: allow-for-now lv-hd11f3b7cf006 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM assistant_grant_membership_windows", [])?; - for incarnation in membership.incarnations() { - connection.execute(/* sqlite-large-value: allow-for-now lv-h679dd6776599 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_membership_windows(writer,member_key,start,end) VALUES(?1,?2,?3,?4)", - params![incarnation.name,incarnation.member_key,incarnation.start,incarnation.end])?; - } - if let Some(fleet_id) = fleet_id { - connection.execute(/* sqlite-large-value: allow-for-now lv-h0ce05c43b4a2 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_fleet_id',?1)",[fleet_id])?; - } else { - connection.execute(/* sqlite-large-value: allow-for-now lv-ha3bce0201694 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "DELETE FROM meta WHERE key='assistant_grant_authority_fleet_id'", [])?; - } - connection.execute(/* sqlite-large-value: allow-for-now lv-hbcecffaa18c4 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_membership_generation',?1)",[generation.to_string()])?; - for (writer,_,_) in changed { - // A durable writer cursor admits at most CLAIMS_PER_SLICE pending rows - // per maintenance unit, rather than draining a changed window here. - connection.execute( - "INSERT OR REPLACE INTO assistant_grant_membership_dirty - SELECT ?1,0,'' WHERE EXISTS( - SELECT 1 FROM assistant_grant_pending INDEXED BY assistant_grant_pending_writer_index - WHERE origin=?1 AND authenticated=0)", [writer])?; - } - Ok(()) } /// Resumable, idempotent versioned backfill. Each page uses claims_kind_index; /// unrelated claims are never visited. Cursor and projection changes commit /// together in the caller's transaction. Old-build appends and signature-only /// arrivals are captured by persistent dirty triggers even after completion. pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result { + backfill_slice_with_limit(connection, budget, CLAIMS_PER_SLICE) +} + +fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut remaining: usize) -> Result { let started = Instant::now(); - let mut remaining = CLAIMS_PER_SLICE; - refresh_membership(connection)?; + if remaining==0 { return Ok(false); } // Include membership-driven retries in the same fixed item budget. Each // empty writer task also consumes a unit, bounding sparse writer queues. while remaining>0 { @@ -543,29 +655,90 @@ pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result } impl Store { - /// Background work only; request handlers never call this method. + /// Relevant membership evidence only; unlike fleet_generation, arbitrary + /// nonmember signatures do not advance this projection-owned revision. + pub fn assistant_grant_membership_revision(&self) -> Result { + if let Some(authority) = self.fleet_authority.get() { + return authority.assistant_grant_membership_revision(); + } + membership_revision(&self.readers.get()) + } + + // The membership fold and snapshot comparison run on readers, before the + // writer is acquired. A writer transaction applies at most 64 changed keys. + fn prepare_assistant_grant_membership(&self) -> Result> { + let revision = self.assistant_grant_membership_revision()?; + let connection = self.readers.get(); + let applied: i64 = connection.query_row( + "SELECT applied_revision FROM assistant_grant_membership_state WHERE id=1", + [], |row| row.get(0), + )?; + if revision==applied { return Ok(None); } + let membership = self.fleet_membership_sealed()?; + let fleet_id = if let Some(authority) = self.fleet_authority.get() { + authority.fleet_id()? + } else { + fleet_meta(&connection, "fleet_id")? + }; + let desired: BTreeMap<_,_> = membership.incarnations().map(|incarnation| ( + (incarnation.name.clone(),incarnation.member_key.clone()), + (incarnation.start,incarnation.end), + )).collect(); + let current: BTreeMap<_,_> = connection.prepare( + "SELECT writer,member_key,start,end FROM assistant_grant_membership_windows", + )?.query_map([], |row| Ok(((row.get::<_,String>(0)?,row.get::<_,String>(1)?), + (row.get::<_,u64>(2)?,row.get::<_,Option>(3)?))))? + .collect::>()?; + let mut windows = Vec::with_capacity(CLAIMS_PER_SLICE); + let mut complete = true; + for (identity,window) in &desired { + if current.get(identity)==Some(window) { continue; } + if windows.len()==CLAIMS_PER_SLICE { complete=false; break; } + windows.push((identity.0.clone(),identity.1.clone(),Some(*window))); + } + if complete { + for identity in current.keys() { + if desired.contains_key(identity) { continue; } + if windows.len()==CLAIMS_PER_SLICE { complete=false; break; } + windows.push((identity.0.clone(),identity.1.clone(),None)); + } + } + Ok(Some(MembershipUpdate { revision, fleet_id, windows, complete })) + } + + /// Background work only; receipt transactions never fold fleet history. pub fn advance_assistant_grant_authority_backfill(&self) -> Result { + let prepared = self.prepare_assistant_grant_membership()?; let mut connection = self.connection.write_background(); let transaction = connection.transaction()?; self.sync_assistant_grant_membership(&transaction)?; - let done = backfill_slice(&transaction,Duration::from_millis(100))?; + let used = if let Some(update) = &prepared { + if membership_revision(&transaction)? != update.revision { + return Ok(false); + } + update.apply(&transaction)? + } else { 0 }; + let done = backfill_slice_with_limit( + &transaction, Duration::from_millis(100), CLAIMS_PER_SLICE-used, + )?; + let membership_ready: bool = transaction.query_row( + "SELECT revision=applied_revision FROM assistant_grant_membership_state WHERE id=1", + [], |row| row.get(0), + )?; transaction.commit()?; - Ok(done) + Ok(done && membership_ready) } + /// Shards copy only the authoritative relevant-evidence counter here. This + /// constant-size synchronization is safe in a receipt transaction; the + /// membership snapshot itself is prepared off-writer by maintenance. pub(super) fn sync_assistant_grant_membership(&self, connection: &Connection) -> Result<()> { - let Some(authority) = self.fleet_authority.get() else { - return refresh_membership(connection); - }; - let generation = authority.fleet_generation()?; - let previous: Option = connection.query_row( - "SELECT CAST(value AS INTEGER) FROM meta WHERE key='assistant_grant_authority_membership_generation'", [], |row| row.get(0), - ).optional()?; - if previous==Some(generation) && fleet_meta(connection,"assistant_grant_authority_shared_fleet")?.is_some() { - return Ok(()); + if let Some(authority) = self.fleet_authority.get() { + connection.execute( + "UPDATE assistant_grant_membership_state SET revision=?1 WHERE id=1", + [authority.assistant_grant_membership_revision()?], + )?; } - let membership = authority.fleet_membership_sealed()?; - connection.execute(/* sqlite-large-value: allow-for-now lv-h437f9d145151 owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_shared_fleet','1')", [])?; - refresh_membership_from(connection,&membership,generation,authority.fleet_id()?.as_deref()) + Ok(()) } } diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs index 1190a677834..f859097933c 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -176,8 +176,8 @@ fn assistant_grant_authority_measure_realistic_backfill() { DELETE FROM assistant_grant_membership_dirty; DELETE FROM assistant_grant_membership_windows; DELETE FROM meta WHERE key='assistant_grant_authority_version' - OR key LIKE 'assistant_grant_authority_cursor/%' - OR key='assistant_grant_authority_membership_generation';", + OR key LIKE 'assistant_grant_authority_cursor/%'; + UPDATE assistant_grant_membership_state SET applied_revision=-1 WHERE id=1;", ).unwrap(); // Fixed small pool of representative unrelated JSON sizes, not a history. let unrelated_bodies = [ diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index cfe78ddbbf3..dfbc55e5912 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -170,7 +170,9 @@ fn assert_reference_and_rebuild(store: &Store) { fn decisions(store: &Store, now: u64) -> Vec { authority::candidates(&store.readers.get(), "assistant/chatgpt", OWNER, Some(now), None, None) - .unwrap().into_iter().map(|claim| claim.id).collect() + .unwrap().into_iter() + .filter(|claim| authority::contains(&store.readers.get(), &claim.id).unwrap()) + .map(|claim| claim.id).collect() } #[test] @@ -212,7 +214,6 @@ fn late_envelope_signature_promotes_previously_admitted_grant() { fn backfill_markers(connection: &Connection) -> Vec<(String, String)> { connection.prepare( "SELECT key,value FROM meta WHERE key='assistant_grant_authority_version' - OR key='assistant_grant_authority_membership_generation' OR key LIKE 'assistant_grant_authority_cursor/%' ORDER BY key" ).unwrap().query_map([], |row| Ok((row.get(0)?, row.get(1)?))) .unwrap().collect::>().unwrap() @@ -263,13 +264,16 @@ fn raw_signature_only_insert_survives_reopen_and_promotes_grant_policy_and_revok ).unwrap().query_map([], |row| row.get(0)).unwrap() .collect::>().unwrap(); assert_eq!(dirty, vec![claim.id.clone()]); - assert!(authority::ready(&connection).is_err()); + authority::ready(&connection).unwrap(); + assert!(authority::maintenance_pending(&connection).unwrap()); + assert!(authority::subject_ready(&connection, SUBJECT).is_err()); assert_eq!(backfill_markers(&connection), markers); } // Reopen before Store startup can drain the durable queue automatically. { let mut connection = Connection::open(&path).unwrap(); - assert!(authority::ready(&connection).is_err()); + authority::ready(&connection).unwrap(); + assert!(authority::maintenance_pending(&connection).unwrap()); let transaction = connection.transaction().unwrap(); assert!(authority::backfill_slice(&transaction, Duration::from_secs(60)).unwrap()); authority::ready(&transaction).unwrap(); @@ -310,7 +314,8 @@ fn malformed_raw_signature_row_is_drained_without_authenticating_a_pending_revok signature.signature = "not-an-ed25519-signature".into(); insert_raw_signature(&connection, &signature); } - assert!(authority::ready(&connection).is_err()); + authority::ready(&connection).unwrap(); + assert!(authority::subject_ready(&connection, SUBJECT).is_err()); let transaction = connection.transaction().unwrap(); assert!(authority::backfill_slice(&transaction, Duration::from_secs(60)).unwrap()); authority::ready(&transaction).unwrap(); @@ -323,7 +328,8 @@ fn malformed_raw_signature_row_is_drained_without_authenticating_a_pending_revok assert_eq!(backfill_markers(&transaction), markers); transaction.commit().unwrap(); } - assert_eq!(decisions(&target, 0), vec![grant.id]); + assert!(decisions(&target, 0).is_empty()); + assert_bearer_rejected(&target, &grant); assert_reference_and_rebuild(&target); } @@ -459,8 +465,8 @@ fn reset_projection(connection: &Connection) { DELETE FROM assistant_grant_dirty; DELETE FROM assistant_grant_auth_cursor; DELETE FROM assistant_grant_membership_dirty; + UPDATE assistant_grant_membership_state SET applied_revision=-1 WHERE id=1; DELETE FROM meta WHERE key='assistant_grant_authority_version' - OR key='assistant_grant_authority_membership_generation' OR key LIKE 'assistant_grant_authority_cursor/%';" ).unwrap(); } @@ -513,7 +519,7 @@ fn victim_origin_legacy_fork_injected_after_partial_cursor_cannot_authenticate() receive(&victim, &unsigned(&export(&sender, &victim))); drain_authority(&victim); assert_bearer_rejected(&victim, &grant); - assert!(authority::contains(&victim.readers.get(), &local.id).unwrap()); + assert_bearer_rejected(&victim, &local); } #[test] @@ -545,7 +551,8 @@ fn older_build_raw_legacy_replication_cannot_authenticate_on_new_build_reopen() grant.accepted_at_unix_ms.to_string()], ).unwrap(); transaction.commit().unwrap(); - assert!(authority::ready(&connection).is_err()); + authority::ready(&connection).unwrap(); + assert!(authority::maintenance_pending(&connection).unwrap()); } let reopened = Store::open(&path, "victim", Arc::new(Plain)).unwrap(); drain_authority(&reopened); @@ -711,7 +718,8 @@ fn malformed_and_unsigned_same_origin_flood_preserves_previous_authority_and_con let after = transition_cost(&target, &grant); assert_eq!(after, before, "same-origin flood changed selected authority or request VM/read cost at {count}"); assert_eq!(candidate_cost(&target), candidate_before, "candidate request cost grew at {count}"); - assert_eq!(decisions(&target, 15000), vec![grant.id.clone()]); + assert!(decisions(&target, 15000).is_empty(), "pending revokes fence only this subject"); + assert_bearer_rejected(&target, &grant); assert_reference_and_rebuild(&target); } } @@ -860,7 +868,9 @@ fn eligible_evidence_beyond_first_key_page_resumes_and_cryptographically_verifie assert_eq!(backfill_markers(&transaction),markers); if page<3 { assert!(!done,"invalid earlier evidence authenticated the claim"); - assert!(authority::ready(&transaction).is_err()); + assert!(authority::ready(&transaction).is_ok()); + assert!(authority::subject_ready(&transaction, SUBJECT).is_err()); + assert!(authority::maintenance_pending(&transaction).unwrap()); let cursor: String = transaction.query_row( "SELECT member_key FROM assistant_grant_auth_cursor WHERE claim_id=?1", [&grant.id], |row| row.get(0)).unwrap(); @@ -901,7 +911,9 @@ fn changed_membership_writer_flood_uses_the_same_fixed_refresh_budget() { let refreshed: usize = transaction.query_row( "SELECT COUNT(*) FROM refreshed_items", [], |row| row.get(0)).unwrap(); assert_eq!(refreshed,authority::CLAIMS_PER_SLICE); - assert!(authority::ready(&transaction).is_err()); + assert!(authority::ready(&transaction).is_ok()); + assert!(authority::subject_ready(&transaction, SUBJECT).is_err()); + assert!(authority::maintenance_pending(&transaction).unwrap()); assert_eq!(backfill_markers(&transaction),markers); transaction.commit().unwrap(); drop(connection); @@ -1002,3 +1014,87 @@ fn envelope_record_arriving_before_auth_cursor_restarts_preexisting_signature_se "the earlier signed record was hidden behind the old position/key cursor"); transaction.commit().unwrap(); } + +fn independent_grant(store: &Store) -> ClaimRecord { + let suffix = "fedcba9876543210fedcba98"; + let mut independent = fields(); + independent["grant_id"] = json!(format!("assistant-grant/{suffix}")); + independent["session_actor"] = json!(format!("assistant/chatgpt/session/assistant-grant/{suffix}")); + independent["credential_hash"] = json!("b".repeat(64)); + append(store, &format!("custom/client/assistant-v1-{suffix}"), GRANTED, independent) +} + +fn assert_subject_fenced(connection: &Connection, grant: &ClaimRecord, independent: &ClaimRecord) { + authority::ready(connection).unwrap(); + assert!(authority::subject_ready(connection, &grant.subject).is_err()); + assert!(!authority::contains(connection, &grant.id).unwrap()); + assert!(authority::by_credential(connection, grant.body["fields"]["credential_hash"].as_str().unwrap()).unwrap().is_none()); + assert!(authority::latest(connection, &grant.subject, GRANTED).is_err()); + for kind in [POLICY, REVOKED] { + assert!(authority::transition(connection, grant, kind).is_err()); + } + authority::subject_ready(connection, &independent.subject).unwrap(); + assert!(authority::contains(connection, &independent.id).unwrap()); + assert_eq!(authority::by_credential(connection, independent.body["fields"]["credential_hash"].as_str().unwrap()).unwrap().unwrap().id, independent.id); + assert_eq!(authority::latest(connection, &independent.subject, GRANTED).unwrap().unwrap().id, independent.id); + for kind in [POLICY, REVOKED] { + assert!(authority::transition(connection, independent, kind).unwrap().is_none()); + } + for cutoff in [Some(0), None] { + let candidates = authority::candidates(connection, "assistant/chatgpt", OWNER, cutoff, None, None).unwrap(); + // Conflict snapshots retain this authenticated witness even while its + // own credential is fenced; a pending revoke cannot clear a conflict. + assert_eq!(candidates.iter().map(|claim| claim.id.as_str()).collect::>(), + BTreeSet::from([grant.id.as_str(), independent.id.as_str()])); + } +} + +#[test] +fn dirty_and_auth_cursor_work_fence_only_their_subject_on_every_read_path() { + let store = node("issuer", None); + let grant = append(&store, SUBJECT, GRANTED, fields()); + let independent = independent_grant(&store); + drain_authority(&store); + let connection = store.connection.write(); + connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&grant.id]).unwrap(); + assert!(authority::maintenance_pending(&connection).unwrap()); + assert_subject_fenced(&connection, &grant, &independent); + connection.execute("DELETE FROM assistant_grant_dirty WHERE claim_id=?1", [&grant.id]).unwrap(); + connection.execute( + "INSERT INTO assistant_grant_auth_cursor(claim_id,position,record_rowid,member_key) VALUES(?1,0,0,'')", + [&grant.id], + ).unwrap(); + assert_subject_fenced(&connection, &grant, &independent); + connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [&grant.id]).unwrap(); + assert!(authority::contains(&connection, &grant.id).unwrap()); +} + +#[test] +fn unsigned_pending_revoke_fences_only_its_established_subject_after_dirty_work_drains() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let grant = append(&source, SUBJECT, GRANTED, fields()); + receive(&target, &export(&source, &target)); + let independent = independent_grant(&target); + let revoke = append(&source, SUBJECT, REVOKED, fields()); + let exchange = export(&source, &target); + receive(&target, &unsigned(&exchange)); + drain_authority(&target); + { + let connection = target.readers.get(); + assert!(!authority::maintenance_pending(&connection).unwrap()); + let authenticated: bool = connection.query_row( + "SELECT authenticated FROM assistant_grant_pending WHERE claim_id=?1", + [&revoke.id], |row| row.get(0), + ).unwrap(); + assert!(!authenticated); + assert_subject_fenced(&connection, &grant, &independent); + } + receive(&target, &signatures(&exchange)); + let connection = target.readers.get(); + authority::subject_ready(&connection, SUBJECT).unwrap(); + assert_eq!(authority::transition(&connection, &grant, REVOKED).unwrap().unwrap().id, revoke.id); + assert_eq!(decisions(&target, 0), vec![independent.id]); +} + +include!("assistant_grant_receipt_cost_tests.rs"); diff --git a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs new file mode 100644 index 00000000000..4fe94e51036 --- /dev/null +++ b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs @@ -0,0 +1,174 @@ +// Included by assistant_grant_authority_tests to share its real replication fixtures. + +fn receipt_signature_for_claim(store: &Store, exchange: &ReplicationExchange, claim: &ClaimRecord) -> ReplicaEnvelopeSignature { + signatures(exchange).signatures.into_iter().find(|signature| { + store.readers.get().query_row( + "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND writer=?2 AND sequence=?3 AND envelope_hash=?4)", + params![claim.id, signature.writer, signature.sequence, signature.hash], + |row| row.get::<_, bool>(0), + ).unwrap() + }).unwrap() +} + +fn fresh_nonmember_proof(envelope: &ReplicaEnvelopeSignature) -> ReplicaEnvelopeSignature { + let key = MemberKey::generate().unwrap().0; + let message = crate::fleet::envelope_signature_message_in( + None, FLEET, &envelope.writer, envelope.sequence, &envelope.hash, + ); + ReplicaEnvelopeSignature { + writer: envelope.writer.clone(), sequence: envelope.sequence, hash: envelope.hash.clone(), + member_key: key.public().to_owned(), signature: key.sign(&message), + } +} + +fn complete_signature_receipt_cost(store: &Store, signature: &ReplicaEnvelopeSignature) -> crate::sqlite::work::SqliteWork { + // Match receipt's split: cryptographic verification precedes writer admission. + // Everything from acquiring the writer through BEGIN, store (including all + // triggers), COMMIT and returning the writer belongs to the measured scope. + let verified = VerifiedEnvelopeSignature::verify( + None, FLEET, &signature.writer, signature.sequence, &signature.hash, + &signature.member_key, &signature.signature, + ).expect("fresh proof must cryptographically verify"); + let scope = crate::sqlite::work::SqliteWorkScope::start(); + { + let mut connection = store.connection.write(); + let transaction = connection.transaction().unwrap(); + assert_eq!(verified.store(&transaction, "1").unwrap(), 1); + transaction.commit().unwrap(); + } + scope.finish() +} + +fn receipt_projection_work_state(connection: &Connection) -> Vec>> { + [ + "SELECT id,revision,applied_revision FROM assistant_grant_membership_state ORDER BY id", + "SELECT claim_id,position,record_rowid,member_key FROM assistant_grant_auth_cursor ORDER BY claim_id", + "SELECT claim_id FROM assistant_grant_dirty ORDER BY claim_id", + "SELECT writer,sequence,claim_id FROM assistant_grant_membership_dirty ORDER BY writer", + ].into_iter().map(|sql| { + let mut statement = connection.prepare(sql).unwrap(); + let columns = statement.column_count(); + statement.query_map([], |row| (0..columns).map(|column| row.get(column)).collect()) + .unwrap().collect::>>>().unwrap() + }).collect() +} + +#[test] +fn fresh_nonmember_proof_receipt_has_constant_complete_transaction_vm_cost() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + receive(&target, &export(&source, &target)); + let grant = append(&source, SUBJECT, GRANTED, fields()); + let exchange = export(&source, &target); + receive(&target, &unsigned(&exchange)); + let envelope = receipt_signature_for_claim(&target, &exchange, &grant); + { + let connection = target.connection.write(); + // Persist an interrupted authentication checkpoint and its queued claim. + // A proof from outside the writer's window must neither reset this + // checkpoint nor consume/recreate its work, even for the same envelope. + connection.execute( + "INSERT INTO assistant_grant_auth_cursor SELECT claim_id,position,rowid,?2 FROM replica_records WHERE claim_id=?1 LIMIT 1", + params![grant.id, key.public()], + ).unwrap(); + connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&grant.id]).unwrap(); + } + let before = receipt_projection_work_state(&target.readers.get()); + assert_eq!(before[1].len(), 1, "checkpoint fixture must be nonempty"); + assert_eq!(before[2].len(), 1, "dirty fixture must be nonempty"); + let baseline = complete_signature_receipt_cost(&target, &fresh_nonmember_proof(&envelope)); + assert!(baseline.statements >= 3, "must account for BEGIN, insertion and COMMIT"); + assert!(baseline.vm_steps > 0, "SQL VM instrumentation must be active"); + assert_eq!(baseline.fullscan_steps, 0); + assert_eq!(baseline.sorts, 0); + assert_eq!(baseline.autoindex_rows, 0); + let mut retained = 1; + for count in [128, 1024] { + for _ in 0..count { + let proof = fresh_nonmember_proof(&envelope); + let work = complete_signature_receipt_cost(&target, &proof); + retained += 1; + assert_eq!(work, baseline, "complete receipt work grew with {retained} retained fresh proofs"); + } + let connection = target.readers.get(); + let stored: usize = connection.query_row( + "SELECT COUNT(*) FROM replica_envelope_signatures WHERE writer=?1 AND sequence=?2 AND envelope_hash=?3", + params![envelope.writer, envelope.sequence, envelope.hash], |row| row.get(0), + ).unwrap(); + assert_eq!(stored, retained, "proofs must be new retained rows, not duplicate no-ops"); + assert_eq!(receipt_projection_work_state(&connection), before, + "irrelevant proofs changed projection revision, checkpoint or queued work"); + } +} + +#[test] +fn sustained_fresh_nonmember_proof_receipts_leave_unrelated_established_credential_live() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let established = append(&source, SUBJECT, GRANTED, fields()); + receive(&target, &export(&source, &target)); + let mut pending_fields = fields(); + pending_fields["credential_hash"] = json!("b".repeat(64)); + let pending = append(&source, "custom/client/assistant-v1-fedcba9876543210fedcba98", GRANTED, pending_fields); + let exchange = export(&source, &target); + receive(&target, &unsigned(&exchange)); + let envelope = receipt_signature_for_claim(&target, &exchange, &pending); + let before = receipt_projection_work_state(&target.readers.get()); + for arrival in 0..256 { + complete_signature_receipt_cost(&target, &fresh_nonmember_proof(&envelope)); + // Deliberately do not advance background maintenance between arrivals. + // Ongoing irrelevant evidence must not turn a completed grant into a + // globally pending projection, or authenticate the unsigned grant. + let connection = target.readers.get(); + assert_eq!(receipt_projection_work_state(&connection), before, "arrival {arrival} queued projection work"); + assert!(!authority::maintenance_pending(&connection).unwrap()); + assert!(authority::contains(&connection, &established.id).unwrap()); + assert_eq!(authority::by_credential(&connection, &"a".repeat(64)).unwrap().unwrap().id, established.id); + assert!(!authority::contains(&connection, &pending.id).unwrap()); + assert!(authority::by_credential(&connection, &"b".repeat(64)).unwrap().is_none()); + } +} + +#[test] +fn membership_window_changes_share_the_fixed_transaction_budget_without_replacing_unchanged_windows() { + let (store, key) = source(); + drain_authority(&store); + let stable_rowid: i64 = store.readers.get().query_row( + "SELECT rowid FROM assistant_grant_membership_windows WHERE writer='anchor' AND member_key=?1", + [key.public()], |row| row.get(0), + ).unwrap(); + let extra = authority::CLAIMS_PER_SLICE*2+7; + { + let mut connection = store.connection.write(); + let transaction = connection.transaction().unwrap(); + for index in 0..extra { + transaction.execute( + "INSERT INTO assistant_grant_membership_windows VALUES('obsolete',?1,0,NULL)", + [format!("obsolete-{index:08}")], + ).unwrap(); + } + transaction.execute( + "UPDATE assistant_grant_membership_state SET revision=revision+1 WHERE id=1", [], + ).unwrap(); + transaction.commit().unwrap(); + } + assert!(!store.advance_assistant_grant_authority_backfill().unwrap()); + let remaining: usize = store.readers.get().query_row( + "SELECT COUNT(*) FROM assistant_grant_membership_windows WHERE writer='obsolete'", + [], |row| row.get(0), + ).unwrap(); + assert_eq!(extra-remaining, authority::CLAIMS_PER_SLICE, + "only the fixed number of changed/deleted windows may be applied"); + let unchanged_rowid: i64 = store.readers.get().query_row( + "SELECT rowid FROM assistant_grant_membership_windows WHERE writer='anchor' AND member_key=?1", + [key.public()], |row| row.get(0), + ).unwrap(); + assert_eq!(unchanged_rowid, stable_rowid, "unchanged windows are never deleted and reinserted"); + assert!(authority::maintenance_pending(&store.readers.get()).unwrap()); + drain_authority(&store); + let remaining: usize = store.readers.get().query_row( + "SELECT COUNT(*) FROM assistant_grant_membership_windows WHERE writer='obsolete'", + [], |row| row.get(0), + ).unwrap(); + assert_eq!(remaining, 0); +} diff --git a/crates/smallclaims/src/store/prepared_seal.rs b/crates/smallclaims/src/store/prepared_seal.rs index 788500f5cd8..fd0f4358c59 100644 --- a/crates/smallclaims/src/store/prepared_seal.rs +++ b/crates/smallclaims/src/store/prepared_seal.rs @@ -627,7 +627,6 @@ impl Store { )?; } } - super::assistant_grant_authority::refresh_membership(transaction)?; Ok(true) } } diff --git a/docs/st3/external-assistants.md b/docs/st3/external-assistants.md index a8d81403084..400e51bbc29 100644 --- a/docs/st3/external-assistants.md +++ b/docs/st3/external-assistants.md @@ -176,16 +176,28 @@ below applies; a restore is not a way to manufacture historical provenance. Authority maintenance is lifecycle-owned. While work remains, pages execute back-to-back as bounded transactions, releasing the writer between pages and yielding to the runtime rather than using sleep-based pacing. -Each transaction shares a 64-unit budget across history, dirty-signature claims, -and membership retries; empty membership-writer tasks also consume one unit. +Each transaction shares a 64-unit budget across changed membership windows, +history, dirty-signature claims, and membership retries; empty membership-writer +tasks also consume one unit. Membership folding and snapshot comparison happen +on readers before writer admission; only changed keys are applied, never a full +window replacement in a receipt transaction. Each authentication refresh visits one indexed replica record and at most 16 writer membership keys, looking up signatures by their full `(writer, sequence, envelope_hash, member_key)` key rather than enumerating nonmember signatures. Durable record/key cursors continue across units so later -eligible evidence is eventually checked; new signature or membership retries -reset that progress. Membership promotion is queued for maintenance, and -authorization readiness fails closed while it is queued. Storing an identical -signature again is a no-op: it neither refreshes authority nor dirties a claim. +eligible evidence is eventually checked. Only relevant member-key evidence or +membership retries reset that progress. Fresh nonmember signatures neither +reset cursors nor enqueue projection work or invalidate its membership snapshot. +An identical signature is also a no-op. + +Global not-ready applies only during initial/version backfill. Thereafter dirty +or pending authentication fences only that grant subject, including a pending +revoke; established credentials for unrelated subjects remain usable. The last +authenticated effective snapshot remains a conflict witness until an authenticated +transition changes it: pending work cannot clear an existing opposite-profile +conflict. The inherited fleet-generation cache may still invalidate and aggregate historical +signature keys independently; that pre-existing fleet-fold amplification is +separate from this projection's receipt path and is not claimed fixed here. After the authority backfill completes, `fractal doctor` lists every pending unauthenticated, unmarked local grant claim ID under the claim-store check with diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 3d9a2d5c945..14d3082b4ef 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -11,7 +11,7 @@ }, "rules": { "status": "changed", - "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." + "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. After initial backfill, dirty or pending authentication, including a pending revoke, fences only its grant subject; unrelated established credentials remain usable. Fresh signatures from keys outside the writer's admitted window do not reset authentication cursors, queue projection work or invalidate its membership snapshot. Membership folding and comparison run on readers outside receipt transactions; only changed windows are applied within the shared 64-unit transaction budget. Inherited fleet-generation invalidation and signature aggregation are pre-existing behavior outside this projection fix. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." }, "compatibility": { "status": "changed", From e102b695a80ac2233ad1de33bc45cc7aee9cf53c Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 16:14:52 +0100 Subject: [PATCH 43/52] fix: distinguish private subject fences from initial backfill readiness agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-api-core/src/api/client_v0/external_grants.rs | 2 +- crates/smallclaims/src/store/assistant_grant_authority.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index 4f29727f8bc..9cf99151d07 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -18,7 +18,7 @@ pub const PRINCIPAL: &str = "assistant/chatgpt"; pub const MCP_PRINCIPAL: &str = "assistant/mcp"; fn authority_error(error: FractalError) -> ApiError { - if error.code == "assistant-grant-authority-not-ready" { + if error.code == "assistant-grant-subject-not-ready" { credential_rejected("the client credential is unknown or expired") } else { ApiError::bad(error) diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index 1c90ebb2c6a..300b797845c 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -236,7 +236,7 @@ fn subject_pending(connection: &Connection, subject: &str) -> Result Result<(), FractalError> { ready(connection)?; if subject_pending(connection, subject)? { - return Err(FractalError::new("assistant-grant-authority-not-ready", "external-grant subject authentication is in progress")); + return Err(FractalError::new("assistant-grant-subject-not-ready", "external-grant subject authentication is in progress")); } Ok(()) } From 47658c32a8bae642d36a47aa3efa7b894726f3ef Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 16:40:01 +0100 Subject: [PATCH 44/52] fix: reuse authoritative fleet generation for grant maintenance agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../fractal-store/src/store/messages_shard.rs | 3 - crates/fractal/src/main.rs | 2 +- crates/smallclaims/src/store.rs | 18 +- .../src/store/assistant_grant_authority.rs | 175 +++++------- .../store/assistant_grant_authority_bench.rs | 2 +- .../store/assistant_grant_authority_tests.rs | 17 +- ...sistant_grant_membership_property_tests.rs | 261 ++++++++++++++++++ .../assistant_grant_receipt_cost_tests.rs | 48 +++- crates/smallclaims/src/store/prepared_seal.rs | 1 - docs/st3/external-assistants.md | 17 +- .../external-grant-profile-conflict.json | 2 +- 11 files changed, 403 insertions(+), 143 deletions(-) create mode 100644 crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs diff --git a/crates/fractal-store/src/store/messages_shard.rs b/crates/fractal-store/src/store/messages_shard.rs index a1a354703e4..ecbe4139dff 100644 --- a/crates/fractal-store/src/store/messages_shard.rs +++ b/crates/fractal-store/src/store/messages_shard.rs @@ -463,9 +463,6 @@ impl FleetAuthority for GraphAuthority { FleetAuthority::fleet_generation(&self.graph()?.graph) } - fn assistant_grant_membership_revision(&self) -> anyhow::Result { - FleetAuthority::assistant_grant_membership_revision(&self.graph()?.graph) - } fn fleet_membership(&self) -> anyhow::Result { FleetAuthority::fleet_membership(&self.graph()?.graph) diff --git a/crates/fractal/src/main.rs b/crates/fractal/src/main.rs index 9cc8bdf5723..fc332287378 100644 --- a/crates/fractal/src/main.rs +++ b/crates/fractal/src/main.rs @@ -20849,7 +20849,7 @@ impl AssistantGrantAuthorityMaintenance { self.changes.borrow_and_update(); let worker = self.store.clone(); tokio::task::spawn_blocking(move || { - if !smallclaims::store::assistant_grant_authority::maintenance_pending(&worker.readers.get())? { + if !worker.assistant_grant_authority_maintenance_pending()? { return Ok(true); } worker.advance_assistant_grant_authority_backfill() diff --git a/crates/smallclaims/src/store.rs b/crates/smallclaims/src/store.rs index e04341c5d74..140a43cf43e 100644 --- a/crates/smallclaims/src/store.rs +++ b/crates/smallclaims/src/store.rs @@ -893,6 +893,9 @@ pub struct Store { /// Request-only sealed folds, which may omit local batches not yet sealed. /// Never used by the sealing path's `membership_cache` fast path. sealed_membership_cache: Mutex>, + /// Last inherited generation whose applied window snapshot was checked. + /// Equal snapshots advance only this memory cache, never the writer. + assistant_grant_membership_observed_generation: AtomicI64, /// Where the scan for signatures missing on admitted envelopes stands. signature_backfill: Mutex, /// Read-only sealed view; never populated with the client's local-signer fallback. @@ -1360,6 +1363,7 @@ impl Store { admission_schema_digest: std::sync::OnceLock::new(), membership_cache: Mutex::new(None), sealed_membership_cache: Mutex::new(None), + assistant_grant_membership_observed_generation: AtomicI64::new(i64::MIN), fleet_authority: std::sync::OnceLock::new(), admitted_fleet_generation: AtomicI64::new(i64::MIN), signature_backfill: Mutex::default(), @@ -3749,8 +3753,6 @@ pub trait FleetAuthority: Send + Sync { fn fleet_id(&self) -> Result>; /// Advances whenever the default store's membership may have changed. fn fleet_generation(&self) -> Result; - /// Projection-relevant evidence only; unrelated signatures do not advance it. - fn assistant_grant_membership_revision(&self) -> Result; fn fleet_membership(&self) -> Result; fn fleet_membership_sealed(&self) -> Result; /// Whether this is a default store that takes its fleet from no other store. @@ -3766,9 +3768,6 @@ impl FleetAuthority for Store { fleet_generation(&self.readers.get()) } - fn assistant_grant_membership_revision(&self) -> Result { - Store::assistant_grant_membership_revision(self) - } fn fleet_membership(&self) -> Result { Store::fleet_membership(self) @@ -7188,10 +7187,9 @@ impl Store { self.fleet_authority .set(authority) .map_err(|_| anyhow::anyhow!("this shard already has a fleet authority"))?; - let mut connection = self.connection.write_background(); - let transaction = connection.transaction()?; - self.sync_assistant_grant_membership(&transaction)?; - transaction.commit()?; + // Generation numbers belong to their authority. Recheck the inherited + // snapshot even if it happens to equal the shard's former local number. + self.assistant_grant_membership_observed_generation.store(i64::MIN, Ordering::Release); Ok(()) } @@ -7982,7 +7980,6 @@ impl Store { let transaction = connection .transaction_with_behavior(rusqlite::TransactionBehavior::Immediate) .map_err(internal)?; - self.sync_assistant_grant_membership(&transaction).map_err(internal)?; let counts = (|transaction: &Transaction<'_>| -> Result<(usize, usize, usize, u128), FractalError> { let mut received = 0; let mut duplicate = 0; @@ -8505,7 +8502,6 @@ impl Store { membership = None; continue; } - self.sync_assistant_grant_membership(&pass)?; let started = std::time::Instant::now(); let end = (next + ADMISSION_CHUNK_ENVELOPES).min(pending.len()); let first = next; diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index 300b797845c..f59c2216f76 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -119,8 +119,8 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { CREATE TABLE IF NOT EXISTS assistant_grant_membership_dirty ( writer TEXT PRIMARY KEY, sequence INTEGER NOT NULL, claim_id TEXT NOT NULL); CREATE TABLE IF NOT EXISTS assistant_grant_membership_state ( - id INTEGER PRIMARY KEY CHECK(id=1), revision INTEGER NOT NULL, applied_revision INTEGER NOT NULL); - INSERT OR IGNORE INTO assistant_grant_membership_state VALUES(1,1,0); + id INTEGER PRIMARY KEY CHECK(id=1), applied_generation INTEGER NOT NULL); + INSERT OR IGNORE INTO assistant_grant_membership_state VALUES(1,-1); CREATE TABLE IF NOT EXISTS assistant_grant_local_appends (claim_id TEXT PRIMARY KEY); CREATE TRIGGER IF NOT EXISTS assistant_grant_dirty_insert AFTER INSERT ON claims WHEN NEW.kind IN ('custom.client.assistant.v1.granted','custom.client.assistant.v1.policy','custom.client.assistant.v1.revoked') @@ -147,58 +147,10 @@ pub fn install(connection: &Connection, local_origin: &str) -> Result<()> { writer TEXT NOT NULL, member_key TEXT NOT NULL, start INTEGER NOT NULL, end INTEGER, PRIMARY KEY(writer,member_key));" )?; - install_membership_evidence_triggers(connection)?; connection.execute(/* sqlite-large-value: allow-for-now lv-h3f117dab1bdd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES('assistant_grant_authority_local_origin',?1)", [local_origin])?; Ok(()) } -/// Independent from the inherited fleet-generation counter: an irrelevant -/// signature may invalidate that legacy cache, but never this projection. -fn install_membership_evidence_triggers(connection: &Connection) -> Result<()> { - let bump = "UPDATE assistant_grant_membership_state SET revision=revision+1 WHERE id=1;"; - for (event, row) in [("INSERT", "NEW"), ("DELETE", "OLD")] { - connection.execute_batch(&format!( - "CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_claim_{event} - AFTER {event} ON claims WHEN {row}.kind IN ({FLEET_CLAIM_KINDS}) - BEGIN {bump} END; - CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_envelope_{event} - AFTER {event} ON replica_envelopes - WHEN EXISTS(SELECT 1 FROM claims WHERE batch_id={row}.batch_id - AND kind IN ({FLEET_CLAIM_KINDS})) - BEGIN {bump} END; - CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_anchor_{event} - AFTER {event} ON meta WHEN {row}.key IN ('fleet_anchor_key','fleet_id') - BEGIN {bump} END;" - ))?; - } - connection.execute_batch(&format!( - "CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_claim_update - AFTER UPDATE OF kind,body,subject,batch_id ON claims - WHEN OLD.kind IN ({FLEET_CLAIM_KINDS}) OR NEW.kind IN ({FLEET_CLAIM_KINDS}) - BEGIN {bump} END; - CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_envelope_update - AFTER UPDATE OF writer,sequence,batch_id,envelope_hash,receipt_state ON replica_envelopes - WHEN EXISTS(SELECT 1 FROM claims WHERE batch_id IN (OLD.batch_id,NEW.batch_id) - AND kind IN ({FLEET_CLAIM_KINDS})) - BEGIN {bump} END; - CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_anchor_update - AFTER UPDATE OF value ON meta - WHEN NEW.key IN ('fleet_anchor_key','fleet_id') AND NEW.value IS NOT OLD.value - BEGIN {bump} END; - CREATE TRIGGER IF NOT EXISTS assistant_grant_membership_signature_insert - AFTER INSERT ON replica_envelope_signatures - WHEN EXISTS(SELECT 1 FROM assistant_grant_membership_windows - WHERE writer=NEW.writer AND member_key=NEW.member_key - AND NEW.sequence>=start AND (end IS NULL OR NEW.sequence<=end)) - AND EXISTS(SELECT 1 FROM replica_envelopes AS envelopes - JOIN claims ON claims.batch_id=envelopes.batch_id - WHERE envelopes.writer=NEW.writer AND envelopes.sequence=NEW.sequence - AND envelopes.envelope_hash=NEW.envelope_hash - AND claims.kind IN ({FLEET_CLAIM_KINDS})) - BEGIN {bump} END;" - ))?; - Ok(()) -} pub fn ready(connection: &Connection) -> Result<(), FractalError> { let complete: bool = connection.query_row( @@ -215,8 +167,7 @@ pub fn maintenance_pending(connection: &Connection) -> Result?1 OR EXISTS(SELECT 1 FROM assistant_grant_dirty) - OR EXISTS(SELECT 1 FROM assistant_grant_membership_dirty) - OR EXISTS(SELECT 1 FROM assistant_grant_membership_state WHERE revision<>applied_revision)", + OR EXISTS(SELECT 1 FROM assistant_grant_membership_dirty)", [VERSION], |row| row.get(0), ).map_err(internal)?; Ok(pending) @@ -382,6 +333,12 @@ fn local_origin(connection: &Connection) -> Result { /// Admission pays structural/authentication cost once. Invalid rows never enter /// the authority or the pending-authentication writer/window index. pub fn refresh_claim(connection: &Connection, id: &str) -> Result<()> { + // Receipt/local append boundary: only durable local admission is immediate. + // Remote first-authentication runs in maintenance after generation validation. + refresh_claim_inner(connection, id, false) +} + +fn refresh_claim_inner(connection: &Connection, id: &str, membership_current: bool) -> Result<()> { static QUERY: std::sync::LazyLock = std::sync::LazyLock::new(|| format!("SELECT {CLAIM_COLUMNS} FROM claims WHERE id=?1")); let claim = connection.prepare_cached(/* sqlite-large-value: allow-for-now lv-h1665a4a8cfdf owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ &QUERY)?.query_row(/* sqlite-large-value: allow-for-now lv-h5520ddeb5d20 owner=smallclaims::store::assistant_grant_authority TODO=trace-statement-and-value-representation */ [id], claim_from_row).optional()?; @@ -404,8 +361,10 @@ pub fn refresh_claim(connection: &Connection, id: &str) -> Result<()> { )?; let authentication = if admitted || (local_append && claim.origin == local_origin(connection)?) { Some(true) - } else { + } else if membership_current { authenticated_claim(connection,&claim.id)? + } else { + None }; let authenticated = authentication == Some(true); let changed = connection.execute(/* sqlite-large-value: allow-for-now lv-h9cf86ad98d1e owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT INTO assistant_grant_pending(claim_id,grant_subject,kind,origin,actor,sequence,authenticated,record) @@ -429,14 +388,6 @@ fn authenticated_claim(connection: &Connection, id: &str) -> Result let Some(fleet_id) = fleet_meta(connection,"assistant_grant_authority_fleet_id")? else { return Ok(Some(false)); }; - // Never first-authenticate against a partially applied or stale membership - // snapshot. Already admitted claims and durable local appends bypass this - // path; only this pending subject remains fenced until maintenance catches up. - let membership_ready: bool = connection.query_row( - "SELECT revision=applied_revision FROM assistant_grant_membership_state WHERE id=1", - [], |row| row.get(0), - )?; - if !membership_ready { return Ok(None); } let shard = fleet_meta(connection,"shard_id")?; let cursor: Option<(i64,i64,String)> = connection.query_row( "SELECT position,record_rowid,member_key FROM assistant_grant_auth_cursor WHERE claim_id=?1", @@ -526,14 +477,9 @@ pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, ha } Ok(()) } -fn membership_revision(connection: &Connection) -> Result { - Ok(connection.query_row( - "SELECT revision FROM assistant_grant_membership_state WHERE id=1", [], |row| row.get(0), - )?) -} struct MembershipUpdate { - revision: i64, + generation: i64, fleet_id: Option, // Only changed/deleted keys, never a replacement of the complete snapshot. windows: Vec<(String, String, Option<(u64, Option)>)>, @@ -572,8 +518,8 @@ impl MembershipUpdate { connection.execute("DELETE FROM meta WHERE key='assistant_grant_authority_fleet_id'", [])?; } connection.execute( - "UPDATE assistant_grant_membership_state SET applied_revision=?1 WHERE id=1", - [self.revision], + "UPDATE assistant_grant_membership_state SET applied_generation=?1 WHERE id=1", + [self.generation], )?; } Ok(self.windows.len()) @@ -584,10 +530,13 @@ impl MembershipUpdate { /// together in the caller's transaction. Old-build appends and signature-only /// arrivals are captured by persistent dirty triggers even after completion. pub fn backfill_slice(connection: &Connection, budget: Duration) -> Result { - backfill_slice_with_limit(connection, budget, CLAIMS_PER_SLICE) + let applied: i64 = connection.query_row( + "SELECT applied_generation FROM assistant_grant_membership_state WHERE id=1", [], |row| row.get(0), + )?; + backfill_slice_with_limit(connection, budget, CLAIMS_PER_SLICE, fleet_generation(connection)?==applied) } -fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut remaining: usize) -> Result { +fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut remaining: usize, membership_current: bool) -> Result { let started = Instant::now(); if remaining==0 { return Ok(false); } // Include membership-driven retries in the same fixed item budget. Each @@ -604,7 +553,7 @@ fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut rema |row| Ok((row.get(0)?,row.get(1)?))).optional()?; if let Some((sequence,id)) = pending { connection.execute("DELETE FROM assistant_grant_auth_cursor WHERE claim_id=?1", [&id])?; - refresh_claim(connection,&id)?; + refresh_claim_inner(connection,&id,membership_current)?; connection.execute( "UPDATE assistant_grant_membership_dirty SET sequence=?2,claim_id=?3 WHERE writer=?1", params![writer,sequence,id])?; @@ -627,7 +576,7 @@ fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut rema }; if rows.is_empty() { break; } for (id,index) in rows { - refresh_claim(connection,&id)?; + refresh_claim_inner(connection,&id,membership_current)?; remaining -= 1; connection.execute(/* sqlite-large-value: allow-for-now lv-h3f49c0e579cd owner=smallclaims::store::assistant_grant_authority TODO=bound-or-reference-values-and-reclamation */ "INSERT OR REPLACE INTO meta(key,value) VALUES(?1,?2)",params![key,index.to_string()])?; if remaining==0 || started.elapsed()>=budget { return Ok(false); } @@ -642,7 +591,7 @@ fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut rema statement.query_map([remaining],|row|row.get::<_,String>(0))?.collect::>>()? }; for id in rows { - refresh_claim(connection,&id)?; + refresh_claim_inner(connection,&id,membership_current)?; remaining -= 1; if remaining==0 || started.elapsed()>=budget { break; } } @@ -655,25 +604,32 @@ fn backfill_slice_with_limit(connection: &Connection, budget: Duration, mut rema } impl Store { - /// Relevant membership evidence only; unlike fleet_generation, arbitrary - /// nonmember signatures do not advance this projection-owned revision. - pub fn assistant_grant_membership_revision(&self) -> Result { + fn assistant_grant_membership_generation(&self) -> Result { if let Some(authority) = self.fleet_authority.get() { - return authority.assistant_grant_membership_revision(); + return authority.fleet_generation(); } - membership_revision(&self.readers.get()) + fleet_generation(&self.readers.get()) } - // The membership fold and snapshot comparison run on readers, before the - // writer is acquired. A writer transaction applies at most 64 changed keys. + pub fn assistant_grant_authority_maintenance_pending(&self) -> Result { + if maintenance_pending(&self.readers.get()).map_err(anyhow::Error::new)? { + return Ok(true); + } + Ok(self.assistant_grant_membership_generation()? != + self.assistant_grant_membership_observed_generation.load(Ordering::Acquire)) + } + + // Reuse the inherited sealed-view invalidation contract, including bootstrap + // proofs and every fold-input mutation. Its reader-fold amplification is + // tracked by #6124; never mirror those inputs in another trigger/revision. + // Only actual changed windows acquire the writer; equal snapshots update an + // in-memory observation, without SQL writes or authentication cursor resets. fn prepare_assistant_grant_membership(&self) -> Result> { - let revision = self.assistant_grant_membership_revision()?; + let generation = self.assistant_grant_membership_generation()?; + if generation==self.assistant_grant_membership_observed_generation.load(Ordering::Acquire) { + return Ok(None); + } let connection = self.readers.get(); - let applied: i64 = connection.query_row( - "SELECT applied_revision FROM assistant_grant_membership_state WHERE id=1", - [], |row| row.get(0), - )?; - if revision==applied { return Ok(None); } let membership = self.fleet_membership_sealed()?; let fleet_id = if let Some(authority) = self.fleet_authority.get() { authority.fleet_id()? @@ -703,42 +659,41 @@ impl Store { windows.push((identity.0.clone(),identity.1.clone(),None)); } } - Ok(Some(MembershipUpdate { revision, fleet_id, windows, complete })) + Ok(Some(MembershipUpdate { generation, fleet_id, windows, complete })) } /// Background work only; receipt transactions never fold fleet history. pub fn advance_assistant_grant_authority_backfill(&self) -> Result { let prepared = self.prepare_assistant_grant_membership()?; + let generation = prepared.as_ref().map_or_else( + || self.assistant_grant_membership_observed_generation.load(Ordering::Acquire), + |update| update.generation, + ); + let claim_work = maintenance_pending(&self.readers.get()).map_err(anyhow::Error::new)?; + if !claim_work && prepared.as_ref().is_none_or(|update| update.windows.is_empty()) { + if self.assistant_grant_membership_generation()? != generation { return Ok(false); } + self.assistant_grant_membership_observed_generation.store(generation,Ordering::Release); + return Ok(true); + } let mut connection = self.connection.write_background(); let transaction = connection.transaction()?; - self.sync_assistant_grant_membership(&transaction)?; + let current_generation = if let Some(authority) = self.fleet_authority.get() { + authority.fleet_generation()? + } else { + fleet_generation(&transaction)? + }; + if current_generation != generation { return Ok(false); } let used = if let Some(update) = &prepared { - if membership_revision(&transaction)? != update.revision { - return Ok(false); - } update.apply(&transaction)? } else { 0 }; + let membership_current = prepared.as_ref().is_none_or(|update| update.complete); let done = backfill_slice_with_limit( - &transaction, Duration::from_millis(100), CLAIMS_PER_SLICE-used, - )?; - let membership_ready: bool = transaction.query_row( - "SELECT revision=applied_revision FROM assistant_grant_membership_state WHERE id=1", - [], |row| row.get(0), + &transaction, Duration::from_millis(100), CLAIMS_PER_SLICE-used, membership_current, )?; transaction.commit()?; - Ok(done && membership_ready) - } - - /// Shards copy only the authoritative relevant-evidence counter here. This - /// constant-size synchronization is safe in a receipt transaction; the - /// membership snapshot itself is prepared off-writer by maintenance. - pub(super) fn sync_assistant_grant_membership(&self, connection: &Connection) -> Result<()> { - if let Some(authority) = self.fleet_authority.get() { - connection.execute( - "UPDATE assistant_grant_membership_state SET revision=?1 WHERE id=1", - [authority.assistant_grant_membership_revision()?], - )?; + if membership_current { + self.assistant_grant_membership_observed_generation.store(generation,Ordering::Release); } - Ok(()) + Ok(done && membership_current) } } diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs index f859097933c..1d9cfc96a74 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -177,7 +177,7 @@ fn assistant_grant_authority_measure_realistic_backfill() { DELETE FROM assistant_grant_membership_windows; DELETE FROM meta WHERE key='assistant_grant_authority_version' OR key LIKE 'assistant_grant_authority_cursor/%'; - UPDATE assistant_grant_membership_state SET applied_revision=-1 WHERE id=1;", + UPDATE assistant_grant_membership_state SET applied_generation=-1 WHERE id=1;", ).unwrap(); // Fixed small pool of representative unrelated JSON sizes, not a history. let unrelated_bodies = [ diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index dfbc55e5912..10071a280e6 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -465,7 +465,8 @@ fn reset_projection(connection: &Connection) { DELETE FROM assistant_grant_dirty; DELETE FROM assistant_grant_auth_cursor; DELETE FROM assistant_grant_membership_dirty; - UPDATE assistant_grant_membership_state SET applied_revision=-1 WHERE id=1; + UPDATE assistant_grant_membership_state SET applied_generation=-1 WHERE id=1; + UPDATE meta SET value=value WHERE key='fleet_anchor_key'; DELETE FROM meta WHERE key='assistant_grant_authority_version' OR key LIKE 'assistant_grant_authority_cursor/%';" ).unwrap(); @@ -1010,9 +1011,16 @@ fn envelope_record_arriving_before_auth_cursor_restarts_preexisting_signature_se FROM replica_records WHERE claim_id=?1", params![grant.id,signature.hash]).unwrap(); authority::refresh_envelope(&transaction,&signature.writer,signature.sequence,&signature.hash).unwrap(); - assert!(authority::contains(&transaction,&grant.id).unwrap(), - "the earlier signed record was hidden behind the old position/key cursor"); + let cursor_exists: bool = transaction.query_row( + "SELECT EXISTS(SELECT 1 FROM assistant_grant_auth_cursor WHERE claim_id=?1)", + [&grant.id], |row| row.get(0), + ).unwrap(); + assert!(!cursor_exists, "new earlier evidence must restart its authentication cursor"); transaction.commit().unwrap(); + drop(connection); + drain_authority(&target); + assert!(authority::contains(&target.readers.get(),&grant.id).unwrap(), + "the earlier signed record was hidden behind the old position/key cursor"); } fn independent_grant(store: &Store) -> ClaimRecord { @@ -1098,3 +1106,6 @@ fn unsigned_pending_revoke_fences_only_its_established_subject_after_dirty_work_ } include!("assistant_grant_receipt_cost_tests.rs"); + +#[path = "assistant_grant_membership_property_tests.rs"] +mod membership_property_tests; diff --git a/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs b/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs new file mode 100644 index 00000000000..ba40857c446 --- /dev/null +++ b/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs @@ -0,0 +1,261 @@ +//! Real-envelope event properties. Expected windows always come from a fresh raw fleet fold. +use super::*; + +type Windows = BTreeMap<(String, String), (u64, Option)>; + +fn windows(membership: &crate::fleet::Membership) -> Windows { + membership.incarnations().map(|member| ( + (member.name.clone(), member.member_key.clone()), (member.start, member.end), + )).collect() +} + +fn assert_windows(store: &Store, authority_store: &Store, context: &str) { + drain_authority(store); + // Do not reuse the projection's preparation/diff helper, nor its membership cache. + let expected = windows(&fleet_membership_tx(&authority_store.readers.get()).unwrap()); + assert_eq!(windows(&authority_store.fleet_membership_sealed().unwrap()), expected, "sealed fold: {context}"); + let actual: Windows = store.readers.get().prepare( + "SELECT writer,member_key,start,end FROM assistant_grant_membership_windows ORDER BY writer,member_key", + ).unwrap().query_map([], |row| Ok(((row.get(0)?, row.get(1)?), (row.get(2)?, row.get(3)?)))) + .unwrap().collect::>().unwrap(); + assert_eq!(actual, expected, "persisted membership: {context}"); +} + +// Same deterministic xorshift generator as the existing event-permutation regression. +// Fixed seeds make every failing mutation/order reproducible without external RNG state. +fn next(state: &mut u64) -> u64 { + *state ^= *state << 13; + *state ^= *state >> 7; + *state ^= *state << 17; + *state +} + +fn shuffle(values: &mut [T], state: &mut u64) { + for index in (1..values.len()).rev() { + let selected = (next(state) % (index as u64 + 1)) as usize; + values.swap(index, selected); + } +} + +#[test] +fn seeded_membership_events_match_fresh_fleet_fold_after_every_event() { + for seed in 1..=8_u64 { + let (source, anchor) = source(); + let target = node("reader", Some(anchor.public())); + for index in 0..6 { + let member = MemberKey::generate().unwrap().0; + append(&source, &format!("host/member-{index}"), "fleet.member-admitted", json!({ + "member_key": member.public(), "via": "member", "sponsor": "anchor", + "writer_floor": index, "mode": "listening" + })); + source.seal_local_batches().unwrap(); + } + append(&source, SUBJECT, GRANTED, fields()); + let exchange = export(&source, &target); + let proofs = signatures(&exchange).signatures; + let mut events = Vec::new(); + for envelope in &exchange.envelopes { + let mut single = exchange.clone(); + single.envelopes = vec![envelope.clone()]; + single.signatures.clear(); + events.push(unsigned(&single)); + events.push(signatures(&single)); + } + let mut state = seed; + shuffle(&mut events, &mut state); + // On alternating seeds force anchor authentication after every admission/grant. + // Other seeds freely allow signatures before envelopes and admission records. + if seed % 2 == 0 { + let anchor_sequence = exchange.envelopes.iter().map(|e| e.sequence).min().unwrap(); + let position = events.iter().position(|event| + event.envelopes.is_empty() && event.signatures.iter().any(|proof| proof.sequence == anchor_sequence) + ).unwrap(); + let delayed = events.remove(position); + events.push(delayed); + } + for (index, event) in events.iter().enumerate() { + receive(&target, event); + assert_windows(&target, &target, &format!("seed={seed} receipt={index}")); + } + // Ensure out-of-order held records have all become admissible before mutating history. + receive(&target, &exchange); + assert_windows(&target, &target, "complete signed history"); + assert!(!windows(&fleet_membership_tx(&target.readers.get()).unwrap()).is_empty()); + + // Every seed exercises every category, then a random suffix repeats mutations on + // random membership batches/signatures. Each mutation and restoration is an event. + let mut mutations: Vec = (0..4).collect(); + mutations.extend((0..20).map(|_| next(&mut state) % 4)); + for (index, mutation) in mutations.into_iter().enumerate() { + let proof = &proofs[(next(&mut state) as usize) % proofs.len()]; + let batch: (String, String, u64) = target.readers.get().query_row( + "SELECT batches.id,batches.origin,batches.replica_sequence FROM batches JOIN claims ON claims.batch_id=batches.id + WHERE claims.kind='fleet.member-admitted' ORDER BY claims.store_index LIMIT 1 OFFSET ?1", + [next(&mut state) % 7], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)), + ).unwrap(); + { + let connection = target.connection.write(); + match mutation { + 0 => { connection.execute("DELETE FROM replica_envelope_signatures WHERE writer=?1 AND sequence=?2 AND envelope_hash=?3 AND member_key=?4", + params![proof.writer,proof.sequence,proof.hash,proof.member_key]).unwrap(); } + 1 => { connection.execute("UPDATE replica_envelope_signatures SET member_key=?5 WHERE writer=?1 AND sequence=?2 AND envelope_hash=?3 AND member_key=?4", + params![proof.writer,proof.sequence,proof.hash,proof.member_key,format!("untrusted-{seed}-{index}")]).unwrap(); } + 2 => { connection.execute("UPDATE batches SET origin=?2 WHERE id=?1", params![batch.0,format!("unrelated-{seed}-{index}")]).unwrap(); } + _ => { connection.execute("UPDATE batches SET replica_sequence=?2 WHERE id=?1", params![batch.0,batch.2+10000]).unwrap(); } + } + } + assert_windows(&target, &target, &format!("seed={seed} mutation={index} kind={mutation}")); + { + let connection = target.connection.write(); + if mutation == 1 { + connection.execute("DELETE FROM replica_envelope_signatures WHERE member_key=?1", [format!("untrusted-{seed}-{index}")]).unwrap(); + } + if mutation < 2 { insert_raw_signature(&connection, proof); } + else { + connection.execute("UPDATE batches SET origin=?2,replica_sequence=?3 WHERE id=?1", params![batch.0,batch.1,batch.2]).unwrap(); + } + } + assert_windows(&target, &target, &format!("seed={seed} restored={index}")); + } + } +} + +#[test] +fn inherited_generation_membership_events_match_authoritative_raw_fold() { + let (source, anchor) = source(); + let authority_store = Arc::new(node("reader", Some(anchor.public()))); + let shard = Store::open_memory("shard-reader", Arc::new(Plain)).unwrap(); + shard.bind_shard(&crate::shards::ShardId::parse("membership-property").unwrap()).unwrap(); + shard.bind_fleet_authority(authority_store.clone()).unwrap(); + assert_windows(&shard, &authority_store, "initial inherited snapshot"); + let own_generation = fleet_generation(&shard.readers.get()).unwrap(); + for index in 0..5 { + let member = MemberKey::generate().unwrap().0; + append(&source, &format!("host/inherited-{index}"), "fleet.member-admitted", json!({ + "member_key": member.public(), "via": "member", "sponsor": "anchor", + "writer_floor": index, "mode": "listening" + })); + let exchange = export(&source, &authority_store); + receive(&authority_store, &unsigned(&exchange)); + assert_windows(&shard, &authority_store, "inherited unsigned admission"); + let mut proofs = signatures(&exchange); + proofs.signatures.reverse(); + for proof in proofs.signatures.clone() { + proofs.signatures = vec![proof]; + receive(&authority_store, &proofs); + assert_windows(&shard, &authority_store, "inherited late signature"); + } + // No local fleet event can be the trigger for any of these snapshot changes. + assert_eq!(fleet_generation(&shard.readers.get()).unwrap(), own_generation); + } + assert_eq!(windows(&fleet_membership_tx(&authority_store.readers.get()).unwrap()).len(), 6); +} + +fn fixture_fields(suffix: &str, profile: &str, digest: char) -> Value { + let mut value = fields(); + value["grant_id"] = json!(format!("assistant-grant/{suffix}")); + value["session_actor"] = json!(format!("assistant/chatgpt/session/assistant-grant/{suffix}")); + value["profile"] = json!(profile); + value["credential_hash"] = json!(digest.to_string().repeat(64)); + value +} + +// Independent raw-history oracle for this closed fixture contract. In particular this +// does not call structurally_valid, transition_valid, rebuild_subject or candidates, +// and never reads assistant_grant_* tables. Pending and dirty state is not authority. +fn raw_conflict_witnesses(store: &Store, ignored_profile: &str, now: u64) -> Vec { + let claims = raw_claims(store); + let trusted = |claim: &ClaimRecord| store.claim_has_authenticated_member_writer(&claim.id).unwrap(); + let matches = |grant: &ClaimRecord, claim: &ClaimRecord| { + claim.subject == grant.subject && claim.origin == grant.origin && claim.actor == grant.actor + && ["issuer", "grant_id", "principal", "profile"].iter().all(|field| + claim.body["fields"][*field] == grant.body["fields"][*field]) + }; + let mut result = Vec::new(); + for grant in claims.iter().filter(|claim| claim.kind == GRANTED && trusted(claim)) { + let fields = &grant.body["fields"]; + let suffix = fields["grant_id"].as_str().unwrap().strip_prefix("assistant-grant/").unwrap(); + assert_eq!(grant.subject, format!("custom/client/assistant-v1-{suffix}")); + assert_eq!(grant.actor.as_deref(), Some(OWNER)); + assert_eq!(fields["issuer"], OWNER); + assert_eq!(fields["principal"], "assistant/chatgpt"); + let selected = claims.iter().rev().find(|claim| + claim.kind == POLICY && matches(grant, claim) && trusted(claim) + ).unwrap_or(grant); + let policy = &selected.body["fields"]; + assert_eq!(policy["session_actor"], fields["session_actor"]); + assert_eq!(policy["disclosure_consent"], true); + assert_eq!(policy["scopes"], json!(["read.assistant.summary"])); + let revoked = claims.iter().any(|claim| + claim.kind == REVOKED && matches(grant, claim) && trusted(claim)); + if !revoked && policy["expires_at_unix_ms"].as_u64().unwrap() > now + && fields["profile"] != ignored_profile { + result.push(grant.id.clone()); + } + } + result.sort(); + result +} + +fn assert_conflict_oracle(store: &Store, own: &ClaimRecord, witness: &ClaimRecord, expected_witness: bool) { + let expected = raw_conflict_witnesses(store, "assistant", 0); + assert_eq!(expected.contains(&witness.id), expected_witness); + let mut actual: Vec<_> = authority::candidates(&store.readers.get(), "assistant/chatgpt", OWNER, + Some(0), Some(&own.id), Some("assistant")).unwrap().into_iter().map(|claim| claim.id).collect(); + actual.sort(); + assert_eq!(actual, expected, "conflict witnesses differ from authenticated raw history"); + assert!(authority::contains(&store.readers.get(), &own.id).unwrap(), "unrelated subject fence denied own bearer"); + assert_eq!(authority::by_credential(&store.readers.get(), &"a".repeat(64)).unwrap().unwrap().id, own.id); +} + +#[test] +fn fenced_opposite_profile_witness_matches_independent_raw_history_oracle() { + for seed in 1..=8_u64 { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let own = append(&source, SUBJECT, GRANTED, fields()); + let suffix = "abcdef0123456789abcdef01"; + let subject = format!("custom/client/assistant-v1-{suffix}"); + let service_fields = fixture_fields(suffix, "service", 'b'); + let witness = append(&source, &subject, GRANTED, service_fields.clone()); + receive(&target, &export(&source, &target)); + assert_conflict_oracle(&target, &own, &witness, true); + // A valid, genuinely signed policy remains the effective snapshot until a + // later revoke authenticates, even when that subject is dirty/fenced. + let mut renewal = service_fields.clone(); + renewal["expires_at_unix_ms"] = json!(20000); + append(&source, &subject, POLICY, renewal); + receive(&target, &export(&source, &target)); + append(&source, &subject, REVOKED, service_fields); + let revoke_exchange = export(&source, &target); + receive(&target, &unsigned(&revoke_exchange)); + assert_conflict_oracle(&target, &own, &witness, true); + assert!(!authority::contains(&target.readers.get(), &witness.id).unwrap()); + { + target.connection.write().execute("INSERT OR IGNORE INTO assistant_grant_dirty VALUES(?1)", [&witness.id]).unwrap(); + } + assert_conflict_oracle(&target, &own, &witness, true); + drain_authority(&target); + assert_conflict_oracle(&target, &own, &witness, true); + let mut proofs = signatures(&revoke_exchange); + let mut state = seed; + shuffle(&mut proofs.signatures, &mut state); + for proof in proofs.signatures.clone() { + proofs.signatures = vec![proof]; + receive(&target, &proofs); + let expected = raw_conflict_witnesses(&target, "assistant", 0).contains(&witness.id); + assert_conflict_oracle(&target, &own, &witness, expected); + } + assert_conflict_oracle(&target, &own, &witness, false); + // Conversely, pending work on the bearer's own subject must deny that + // bearer, without changing the independent conflict-history answer. + append(&source, SUBJECT, POLICY, fields()); + receive(&target, &unsigned(&export(&source, &target))); + assert!(!authority::contains(&target.readers.get(), &own.id).unwrap()); + assert!(authority::by_credential(&target.readers.get(), &"a".repeat(64)).unwrap().is_none()); + assert!(authority::subject_ready(&target.readers.get(), SUBJECT).is_err()); + assert!(raw_conflict_witnesses(&target, "assistant", 0).is_empty()); + assert!(authority::candidates(&target.readers.get(), "assistant/chatgpt", OWNER, + Some(0), Some(&own.id), Some("assistant")).unwrap().is_empty()); + } +} diff --git a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs index 4fe94e51036..52f676c2b0d 100644 --- a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs @@ -41,7 +41,7 @@ fn complete_signature_receipt_cost(store: &Store, signature: &ReplicaEnvelopeSig fn receipt_projection_work_state(connection: &Connection) -> Vec>> { [ - "SELECT id,revision,applied_revision FROM assistant_grant_membership_state ORDER BY id", + "SELECT id,applied_generation FROM assistant_grant_membership_state ORDER BY id", "SELECT claim_id,position,record_rowid,member_key FROM assistant_grant_auth_cursor ORDER BY claim_id", "SELECT claim_id FROM assistant_grant_dirty ORDER BY claim_id", "SELECT writer,sequence,claim_id FROM assistant_grant_membership_dirty ORDER BY writer", @@ -57,11 +57,13 @@ fn receipt_projection_work_state(connection: &Connection) -> Vec= 3, "must account for BEGIN, insertion and COMMIT"); assert!(baseline.vm_steps > 0, "SQL VM instrumentation must be active"); assert_eq!(baseline.fullscan_steps, 0); assert_eq!(baseline.sorts, 0); assert_eq!(baseline.autoindex_rows, 0); - let mut retained = 1; + let mut retained = initial_signatures+1; for count in [128, 1024] { for _ in 0..count { let proof = fresh_nonmember_proof(&envelope); @@ -106,13 +112,17 @@ fn sustained_fresh_nonmember_proof_receipts_leave_unrelated_established_credenti let (source, key) = source(); let target = node("reader", Some(key.public())); let established = append(&source, SUBJECT, GRANTED, fields()); - receive(&target, &export(&source, &target)); + let fleet_exchange = export(&source, &target); + receive(&target, &fleet_exchange); + let anchor = raw_claims(&source).into_iter().find(|claim| claim.kind=="fleet.member-admitted").unwrap(); let mut pending_fields = fields(); pending_fields["credential_hash"] = json!("b".repeat(64)); + pending_fields["grant_id"] = json!("assistant-grant/fedcba9876543210fedcba98"); + pending_fields["session_actor"] = json!("assistant/chatgpt/session/assistant-grant/fedcba9876543210fedcba98"); let pending = append(&source, "custom/client/assistant-v1-fedcba9876543210fedcba98", GRANTED, pending_fields); let exchange = export(&source, &target); receive(&target, &unsigned(&exchange)); - let envelope = receipt_signature_for_claim(&target, &exchange, &pending); + let envelope = receipt_signature_for_claim(&target, &fleet_exchange, &anchor); let before = receipt_projection_work_state(&target.readers.get()); for arrival in 0..256 { complete_signature_receipt_cost(&target, &fresh_nonmember_proof(&envelope)); @@ -148,7 +158,7 @@ fn membership_window_changes_share_the_fixed_transaction_budget_without_replacin ).unwrap(); } transaction.execute( - "UPDATE assistant_grant_membership_state SET revision=revision+1 WHERE id=1", [], + "UPDATE meta SET value=value WHERE key='fleet_anchor_key'", [], ).unwrap(); transaction.commit().unwrap(); } @@ -172,3 +182,27 @@ fn membership_window_changes_share_the_fixed_transaction_budget_without_replacin ).unwrap(); assert_eq!(remaining, 0); } + +#[test] +fn unchanged_membership_generation_fold_does_not_enter_the_writer_or_reset_work() { + let (source, key) = source(); + let target = node("reader", Some(key.public())); + let exchange = export(&source, &target); + receive(&target, &exchange); + let anchor = raw_claims(&source).into_iter() + .find(|claim| claim.kind == "fleet.member-admitted").unwrap(); + let envelope = receipt_signature_for_claim(&target, &exchange, &anchor); + let before = receipt_projection_work_state(&target.readers.get()); + complete_signature_receipt_cost(&target, &fresh_nonmember_proof(&envelope)); + assert!(target.assistant_grant_authority_maintenance_pending().unwrap()); + let commits = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0)); + let observed = commits.clone(); + let _observer = target.observe_commits(move |_| { + observed.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + }); + assert!(target.advance_assistant_grant_authority_backfill().unwrap()); + assert_eq!(commits.load(std::sync::atomic::Ordering::SeqCst), 0, + "an unchanged authoritative window snapshot must not open a writer transaction"); + assert_eq!(receipt_projection_work_state(&target.readers.get()), before); + assert!(!target.assistant_grant_authority_maintenance_pending().unwrap()); +} diff --git a/crates/smallclaims/src/store/prepared_seal.rs b/crates/smallclaims/src/store/prepared_seal.rs index fd0f4358c59..6cb550154b2 100644 --- a/crates/smallclaims/src/store/prepared_seal.rs +++ b/crates/smallclaims/src/store/prepared_seal.rs @@ -540,7 +540,6 @@ impl Store { transaction: &Transaction<'_>, prepared: &PreparedSeal, ) -> Result { - self.sync_assistant_grant_membership(transaction)?; if prepared.origin != self.origin { return Ok(false); } diff --git a/docs/st3/external-assistants.md b/docs/st3/external-assistants.md index 400e51bbc29..b8f399f60d0 100644 --- a/docs/st3/external-assistants.md +++ b/docs/st3/external-assistants.md @@ -187,17 +187,24 @@ writer membership keys, looking up signatures by their full nonmember signatures. Durable record/key cursors continue across units so later eligible evidence is eventually checked. Only relevant member-key evidence or membership retries reset that progress. Fresh nonmember signatures neither -reset cursors nor enqueue projection work or invalidate its membership snapshot. -An identical signature is also a no-op. +reset cursors nor enqueue projection work. They can invalidate the inherited +fleet-generation cache: maintenance folds the authoritative sealed view on +readers, compares windows, and observes an unchanged snapshot in memory without +opening a writer transaction or resetting authentication work. No parallel +membership-invalidation revision or trigger set is maintained. An identical +signature is also a no-op. Global not-ready applies only during initial/version backfill. Thereafter dirty or pending authentication fences only that grant subject, including a pending revoke; established credentials for unrelated subjects remain usable. The last authenticated effective snapshot remains a conflict witness until an authenticated transition changes it: pending work cannot clear an existing opposite-profile -conflict. The inherited fleet-generation cache may still invalidate and aggregate historical -signature keys independently; that pre-existing fleet-fold amplification is -separate from this projection's receipt path and is not claimed fixed here. +conflict. The inherited fleet-generation fold can still aggregate historical +signature keys on readers; that pre-existing amplification is tracked by #6124 +and is not claimed fixed here. Writer-time subject fences retain the generic +authorization denial. Clean-grant inspection omits optional cleared-conflict +explanations for other subjects whose authentication is pending, rather than +denying inspection or weakening an established conflict witness. After the authority backfill completes, `fractal doctor` lists every pending unauthenticated, unmarked local grant claim ID under the claim-store check with diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 14d3082b4ef..1f230486919 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -11,7 +11,7 @@ }, "rules": { "status": "changed", - "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. After initial backfill, dirty or pending authentication, including a pending revoke, fences only its grant subject; unrelated established credentials remain usable. Fresh signatures from keys outside the writer's admitted window do not reset authentication cursors, queue projection work or invalidate its membership snapshot. Membership folding and comparison run on readers outside receipt transactions; only changed windows are applied within the shared 64-unit transaction budget. Inherited fleet-generation invalidation and signature aggregation are pre-existing behavior outside this projection fix. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." + "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. After initial backfill, dirty or pending authentication, including a pending revoke, fences only its grant subject; unrelated established credentials remain usable. Fresh signatures from keys outside the writer's admitted window do not reset authentication cursors or queue projection work. Membership invalidation reuses the inherited fleet generation, including delayed bootstrap evidence and all fold-input mutations; there is no separate projection revision or copied trigger set. Folding and comparison run on readers outside receipt transactions; an unchanged window snapshot advances only an in-memory observation, without writer admission or cursor resets. Only changed windows are applied within the shared 64-unit transaction budget. Inherited reader-side signature aggregation remains a pre-existing cost tracked by #6124. Writer-time pending-subject checks retain generic authorization denials; clean-grant inspection omits optional explanations for other pending subjects while preserving established authenticated conflict witnesses. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." }, "compatibility": { "status": "changed", From 0592e8f8fa2a9596e663b10157228df41340a554 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 16:40:07 +0100 Subject: [PATCH 45/52] fix: isolate pending grant subjects in writes and inspection agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/api/client_v0/external_grants.rs | 16 ++++++- .../external_grants/conflict_tests.rs | 30 ++++++++++++ .../src/store/message_send_tests.rs | 46 +++++++++++++++++++ .../src/store/assistant_write.rs | 27 ++--------- crates/fractal/tests/assistant_native.rs | 24 ++++++++-- 5 files changed, 113 insertions(+), 30 deletions(-) diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants.rs b/crates/fractal-api-core/src/api/client_v0/external_grants.rs index 9cf99151d07..f609cfea37d 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants.rs @@ -310,8 +310,20 @@ pub fn projection_with_witness(state: &AppState, granted: &ClaimRecord) -> Resul let mut cleared = Vec::new(); for (other, other_profile) in candidate_grants(state, principal(source)?, None)? { if profile == other_profile { continue; } - let policy = effective(state, &other)?; - let cause = if revoked(state, &other)? || revoked(state, granted)? { Some("revoked") } + // Historical explanations are optional: another subject's pending proof + // must not turn inspection of this clean grant into a bearer denial. + let explanation = (|| { + let connection = state.store.readers.get(); + let policy = authority::transition(&connection, &other, POLICY)? + .unwrap_or_else(|| other.clone()); + let revoked = authority::transition(&connection, &other, REVOKED)?.is_some(); + Ok::<_, FractalError>((policy, revoked)) + })(); + let (policy, other_revoked) = match explanation { + Err(error) if error.code == "assistant-grant-subject-not-ready" => continue, + result => result.map_err(authority_error)?, + }; + let cause = if other_revoked || value["revoked"] == true { Some("revoked") } else if !unexpired(fields(&policy)?, now) || !unexpired(source, now) { Some("expired") } else { None }; if let Some(cause) = cause { cleared.push(json!({"grants":[witness(granted, profile),witness(&other, other_profile)],"cause":cause})); diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index b8b9f15a385..7d260ddb532 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -641,3 +641,33 @@ fn dirty_opposite_profile_witness_does_not_clear_an_established_conflict() { assert_eq!(candidate_grants(&a, PRINCIPAL, Some(0)).unwrap().len(), 2, "pending work cannot erase the last authenticated opposite-profile snapshot"); } + +#[test] +fn clean_grant_inspection_omits_pending_expired_or_revoked_opposite_history() { + let _service = ServiceFixture::enable(); + for cause in ["expired", "revoked"] { + let root = tempfile::tempdir().unwrap(); + let (a, b) = admitted_pair(root.path()); + let assistant = issue(&a, ASSISTANT_ID, "assistant").unwrap(); + let service = issue(&b, SERVICE_ID, "service").unwrap(); + let mut source = fields(&service).unwrap().clone(); + let kind = if cause == "expired" { + source["expires_at_unix_ms"] = json!(1_u64); + POLICY + } else { REVOKED }; + append(&b, service.subject.clone(), kind, OWNER, source, Some(&service)).unwrap(); + replicate(&b, &a); + let inspected = projection_with_witness(&a, &assistant).unwrap(); + assert_eq!(inspected["cleared_conflicts"][0]["cause"], cause); + a.store.connection.write().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&service.id], + ).unwrap(); + assert!(authenticate_id(&a, SERVICE_ID).unwrap().is_none()); + assert!(authenticate_id(&a, ASSISTANT_ID).unwrap().is_some()); + let inspected = projection_with_witness(&a, &assistant).unwrap(); + assert!(inspected["conflict"].is_null()); + assert_eq!(inspected["cleared_conflicts"], json!([])); + assert_eq!(inspected["revoked"], false); + assert_eq!(inspected["id"], ASSISTANT_ID); + } +} diff --git a/crates/fractal-delivery/src/store/message_send_tests.rs b/crates/fractal-delivery/src/store/message_send_tests.rs index 3ea559bf7e1..a3ec00841a7 100644 --- a/crates/fractal-delivery/src/store/message_send_tests.rs +++ b/crates/fractal-delivery/src/store/message_send_tests.rs @@ -491,3 +491,49 @@ fn assistant_provenance_stamps_authenticated_grant_and_preserves_replica_admissi assert_eq!(store.append_assistant_claim_outcome(&wrong_actor, &authorization).unwrap_err().code, "forbidden"); } } + +#[test] +fn writer_recheck_fences_dirty_subject_without_exposing_projection_state() { + let store = Store::open_memory("node").unwrap(); + store.apply(&crate::graph::parse_test_intent( + "version 2\nagent \"example-recipient.local\" { workspace \"/tmp/st-test\"; command \"true\"; restart always; }", "node").unwrap(), + &BTreeMap::from([("agent/example-recipient.local".to_string(), Vec::new())]), "assistant-recipient").unwrap(); + let grant_subject = "custom/client/assistant-v1-native-fixture"; + let grant_id = "assistant-grant/native-fixture"; + let session_actor = format!("assistant/chatgpt/session/{grant_id}"); + let granted = store.append_claim(&ClaimInput { + subject: grant_subject.into(), kind: "custom.client.assistant.v1.granted".into(), + actor: Some("person/robin".into()), + fields: serde_json::from_value(json!({ + "principal":"assistant/chatgpt", "session_actor":session_actor, + "issuer":"person/robin", "disclosure_consent":true, "policy_revision":1, + "expires_at_unix_ms":u64::MAX, "scopes":["write.assistant.messages"], + "grant_id":grant_id + })).unwrap(), + evidence: vec![], expected_subject: None, idempotency_key: None, + }).unwrap(); + let authorization = assistant_write::AssistantWriteAuthorization { + grant_subject: grant_subject.into(), actor: session_actor, + owner: "person/robin".into(), policy_revision: 1, + scope: "write.assistant.messages".into(), + recipient: Some("agent/example-recipient.local".into()), + }; + let mut input = request(); + input.actor = Some("assistant/chatgpt".into()); + input.fields.insert("from".into(), json!("assistant/chatgpt")); + input.fields.insert("to".into(), json!("agent/example-recipient.local")); + // An unrelated pending claim must not prevent the actual mutation transaction. + store.connection.lock().unwrap().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES('unrelated-claim')", [], + ).unwrap(); + assert!(store.append_assistant_claim_outcome(&input, &authorization).unwrap().1); + input.subject = "message/assistant-dirty-subject-denied".into(); + input.idempotency_key = Some("assistant-dirty-subject-denied".into()); + store.connection.lock().unwrap().execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&granted.id], + ).unwrap(); + let error = store.append_assistant_claim_outcome(&input, &authorization).unwrap_err(); + assert_eq!(error.code, "forbidden"); + assert_eq!(error.message, "assistant write authorization changed or expired before commit"); + assert!(store.latest_claim(&input.subject, None).unwrap().is_none()); +} diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 0f67f358174..1058416fa51 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -28,7 +28,9 @@ pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &As pub fn authorized_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let denied = || FractalError::new("forbidden", "assistant write authorization changed or expired before commit"); let authority_error = |error: FractalError| { - if error.code == "assistant-grant-authority-not-ready" { denied() } else { error } + if matches!(error.code.as_str(), "assistant-grant-authority-not-ready" | "assistant-grant-subject-not-ready") { + denied() + } else { error } }; let granted = authority::latest(connection, &authorization.grant_subject, authority::GRANTED).map_err(authority_error)? .ok_or_else(denied)?; @@ -233,27 +235,4 @@ mod tests { } } - #[test] - fn writer_recheck_fences_dirty_subject_without_exposing_projection_state() { - let (store, subject, mut body) = transition_fixture(); - body["fields"]["policy_revision"] = json!(1); - body["fields"]["scopes"] = json!(["write.assistant.answers"]); - let policy = insert_transition(&store, &subject, authority::POLICY, "person/owner", &body); - let authorization = AssistantWriteAuthorization { - grant_subject: subject, - actor: body["fields"]["session_actor"].as_str().unwrap().into(), - owner: "person/owner".into(), policy_revision: 1, - scope: "write.assistant.answers".into(), recipient: None, - }; - let connection = store.connection.write(); - authorize_grant(&connection, "local", &authorization).unwrap(); - connection.execute( - "INSERT INTO assistant_grant_dirty(claim_id) VALUES('unrelated-claim')", [], - ).unwrap(); - authorize_grant(&connection, "local", &authorization).unwrap(); - connection.execute("INSERT INTO assistant_grant_dirty VALUES(?1)", [&policy.id]).unwrap(); - let error = authorize_grant(&connection, "local", &authorization).unwrap_err(); - assert_eq!(error.code, "forbidden"); - assert_eq!(error.message, "assistant write authorization changed or expired before commit"); - } } diff --git a/crates/fractal/tests/assistant_native.rs b/crates/fractal/tests/assistant_native.rs index f12a6747757..9cbce98d7ec 100644 --- a/crates/fractal/tests/assistant_native.rs +++ b/crates/fractal/tests/assistant_native.rs @@ -604,7 +604,7 @@ async fn writer_transaction_rechecks_policy_revision_actor_scope_and_revocation( } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() { +async fn synchronous_send_rechecks_pending_subject_revocation_and_scope_removal_before_commit() { let h = Arc::new(Harness::new()); let paired = h.pair().await; let gate = h.root.path().join("mutation-gate"); @@ -613,10 +613,10 @@ async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() let count_messages = || connection.query_row( "SELECT count(*) FROM claims WHERE kind='message.sent'", [], |row| row.get::<_, u64>(0), ).unwrap(); - for revoke in [false, true] { + for change in ["pending-subject", "scope", "revocation"] { h.policy(&paired, scopes()).await; let before = count_messages(); - let request = h.message(AGENT, if revoke { "held-revoke" } else { "held-scope" }).await; + let request = h.message(AGENT, &format!("held-{change}")).await; for name in ["hold", "entered", "release", "done"] { let path = gate.join(name); if path.exists() { std::fs::remove_file(path).unwrap(); } @@ -633,7 +633,14 @@ async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() tokio::time::sleep(std::time::Duration::from_millis(5)).await; } assert!(!send.is_finished(), "synchronous send must still await its mutation"); - if revoke { + if change == "pending-subject" { + let granted = h.state.store.latest_claim( + &grant_subject(&paired), Some("custom.client.assistant.v1.granted"), + ).unwrap().unwrap(); + connection.execute( + "INSERT INTO assistant_grant_dirty(claim_id) VALUES(?1)", [&granted.id], + ).unwrap(); + } else if change == "revocation" { h.owner("POST", &grant_path(&paired, "/revoke"), &json!({})).await; } else { h.owner("POST", &grant_path(&paired, "/policy"), &AssistantGrantPolicy { @@ -650,7 +657,16 @@ async fn synchronous_send_rechecks_revocation_and_scope_removal_before_commit() let (status, denial) = send.await.unwrap(); assert!(!status.is_success(), "{denial}"); assert_eq!(denial["code"], "forbidden", "{denial}"); + assert_eq!(denial["message"], "assistant write authorization changed or expired before commit"); + assert!(!denial.to_string().contains("not-ready"), "{denial}"); assert_eq!(count_messages(), before, "denied send must append no message claim"); + if change == "pending-subject" { + connection.execute( + "DELETE FROM assistant_grant_dirty WHERE claim_id IN + (SELECT id FROM claims WHERE subject=?1)", + [grant_subject(&paired)], + ).unwrap(); + } } } From 594cfabb6ad1ad6526c1c5fe51a7566badbbd02b Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 16:47:19 +0100 Subject: [PATCH 46/52] docs: scope fleet invalidation contract to projected windows agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/smallclaims/src/store/assistant_grant_authority.rs | 8 +++++--- release-notes/external-grant-profile-conflict.json | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index f59c2216f76..be6fd51bc77 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -619,9 +619,11 @@ impl Store { self.assistant_grant_membership_observed_generation.load(Ordering::Acquire)) } - // Reuse the inherited sealed-view invalidation contract, including bootstrap - // proofs and every fold-input mutation. Its reader-fold amplification is - // tracked by #6124; never mirror those inputs in another trigger/revision. + // Reuse the inherited sealed-view invalidation contract for changes to the + // projected writer/key/start/end windows, including delayed bootstrap proofs. + // Shard bounds do not affect those tuples (their generation triggers cover + // INSERT/DELETE, not UPDATE). Reader-fold amplification remains #6124; do + // not mirror membership invalidation in another trigger/revision. // Only actual changed windows acquire the writer; equal snapshots update an // in-memory observation, without SQL writes or authentication cursor resets. fn prepare_assistant_grant_membership(&self) -> Result> { diff --git a/release-notes/external-grant-profile-conflict.json b/release-notes/external-grant-profile-conflict.json index 1f230486919..c2c537c3827 100644 --- a/release-notes/external-grant-profile-conflict.json +++ b/release-notes/external-grant-profile-conflict.json @@ -11,7 +11,7 @@ }, "rules": { "status": "changed", - "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. After initial backfill, dirty or pending authentication, including a pending revoke, fences only its grant subject; unrelated established credentials remain usable. Fresh signatures from keys outside the writer's admitted window do not reset authentication cursors or queue projection work. Membership invalidation reuses the inherited fleet generation, including delayed bootstrap evidence and all fold-input mutations; there is no separate projection revision or copied trigger set. Folding and comparison run on readers outside receipt transactions; an unchanged window snapshot advances only an in-memory observation, without writer admission or cursor resets. Only changed windows are applied within the shared 64-unit transaction budget. Inherited reader-side signature aggregation remains a pre-existing cost tracked by #6124. Writer-time pending-subject checks retain generic authorization denials; clean-grant inspection omits optional explanations for other pending subjects while preserving established authenticated conflict witnesses. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." + "detail": "Assistant authorization fails closed until the local authority projection backfill is ready. After initial backfill, dirty or pending authentication, including a pending revoke, fences only its grant subject; unrelated established credentials remain usable. Fresh signatures from keys outside the writer's admitted window do not reset authentication cursors or queue projection work. Membership invalidation reuses the inherited fleet generation for changes to projected writer/key/start/end windows, including delayed bootstrap evidence; there is no separate projection revision or copied trigger set. Folding and comparison run on readers outside receipt transactions; an unchanged window snapshot advances only an in-memory observation, without writer admission or cursor resets. Only changed windows are applied within the shared 64-unit transaction budget. Inherited reader-side signature aggregation remains a pre-existing cost tracked by #6124. Writer-time pending-subject checks retain generic authorization denials; clean-grant inspection omits optional explanations for other pending subjects while preserving established authenticated conflict witnesses. If a principal has active grants in both assistant and service profiles, all of that principal's external grants are suspended, not just the losing or newest profile. Multiple same-profile grants remain allowed. Authentication resumes after replicated append-only revocations or expiry remove the opposite-profile conflict from the local view. The configured owner can revoke existing service-profile history through trusted-local Unix without changing its immutable profile; service issuance, policy updates and requests remain disabled. Owner inspection reports active witnesses and cleared_conflicts witnesses with revoked or expired causes from the authority projection and retained evidence." }, "compatibility": { "status": "changed", From 198dc27cecb26be80d18ed79dc79a6be076b5d34 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 16:47:20 +0100 Subject: [PATCH 47/52] test: materialize unsigned keyed history before projection checks agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../store/assistant_grant_authority_tests.rs | 42 +++++++++++++++---- ...sistant_grant_membership_property_tests.rs | 4 +- .../assistant_grant_receipt_cost_tests.rs | 4 +- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index 10071a280e6..01b709a6852 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -245,7 +245,7 @@ fn raw_signature_only_insert_survives_reopen_and_promotes_grant_policy_and_revok let claim = append(&source, SUBJECT, kind, value); if kind == GRANTED { grant_id.clone_from(&claim.id); } let exchange = export(&source, &target); - receive(&target, &unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); assert!(raw_claims(&target).iter().any(|record| record.id == claim.id)); assert!(!authority::contains(&target.readers.get(), &claim.id).unwrap()); while !target.advance_assistant_grant_authority_backfill().unwrap() {} @@ -305,7 +305,7 @@ fn malformed_raw_signature_row_is_drained_without_authenticating_a_pending_revok receive(&target, &export(&source, &target)); let revoke = append(&source, SUBJECT, REVOKED, fields()); let exchange = export(&source, &target); - receive(&target, &unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); while !target.advance_assistant_grant_authority_backfill().unwrap() {} let markers = backfill_markers(&target.readers.get()); { @@ -476,6 +476,30 @@ fn drain_authority(store: &Store) { while !store.advance_assistant_grant_authority_backfill().unwrap() {} } +// Build the raw, unsigned keyed-writer history an older importer could leave. +// Today's admission correctly holds unsigned keyed envelopes before raw claims +// exist, so receive(unsigned(exchange)) cannot exercise projection authentication. +// Use the real signed transport to materialize batches/receipt records, then +// discard this exchange's proofs and rebuild the projection from the remaining +// evidence before making any assertion. Existing earlier signatures survive. +fn receive_pre_projection_unsigned_history(target: &Store, exchange: &ReplicationExchange) { + receive(target, exchange); + { + let mut connection = target.connection.write(); + let transaction = connection.transaction().unwrap(); + for signature in signatures(exchange).signatures { + transaction.execute( + "DELETE FROM replica_envelope_signatures + WHERE writer=?1 AND sequence=?2 AND envelope_hash=?3 AND member_key=?4", + params![signature.writer, signature.sequence, signature.hash, signature.member_key], + ).unwrap(); + } + reset_projection(&transaction); + transaction.commit().unwrap(); + } + drain_authority(target); +} + fn assert_bearer_rejected(store: &Store, grant: &ClaimRecord) { let digest = grant.body["fields"]["credential_hash"].as_str().unwrap(); assert!(!authority::contains(&store.readers.get(), &grant.id).unwrap()); @@ -715,7 +739,7 @@ fn malformed_and_unsigned_same_origin_flood_preserves_previous_authority_and_con append(&source, SUBJECT, REVOKED, fields()); } let unsigned_rows = export(&source, &target); - receive(&target, &unsigned(&unsigned_rows)); + receive_pre_projection_unsigned_history(&target, &unsigned_rows); let after = transition_cost(&target, &grant); assert_eq!(after, before, "same-origin flood changed selected authority or request VM/read cost at {count}"); assert_eq!(candidate_cost(&target), candidate_before, "candidate request cost grew at {count}"); @@ -800,7 +824,7 @@ fn nonmember_signature_flood_has_constant_membership_first_vm_cost() { receive(&target,&export(&source,&target)); let grant = append(&source,SUBJECT,GRANTED,fields()); let exchange = export(&source,&target); - receive(&target,&unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); let signature = signatures(&exchange).signatures.into_iter().find(|signature| { target.readers.get().query_row( "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", @@ -839,7 +863,7 @@ fn eligible_evidence_beyond_first_key_page_resumes_and_cryptographically_verifie receive(&target,&export(&source,&target)); let grant = append(&source,SUBJECT,GRANTED,fields()); let exchange = export(&source,&target); - receive(&target,&unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); let signature = signatures(&exchange).signatures.into_iter().find(|signature| { target.readers.get().query_row( "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", @@ -896,7 +920,7 @@ fn changed_membership_writer_flood_uses_the_same_fixed_refresh_budget() { for _ in 0..(authority::CLAIMS_PER_SLICE*2+7) { append(&source,SUBJECT,GRANTED,fields()); } - receive(&target,&unsigned(&export(&source,&target))); + receive_pre_projection_unsigned_history(&target, &export(&source,&target)); let mut connection = target.connection.write(); let markers = backfill_markers(&connection); connection.execute( @@ -929,7 +953,7 @@ fn late_signature_restarts_an_in_progress_key_cursor_before_its_old_position() { receive(&target,&export(&source,&target)); let grant = append(&source,SUBJECT,GRANTED,fields()); let exchange = export(&source,&target); - receive(&target,&unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); let signature = signatures(&exchange).signatures.into_iter().find(|signature| { target.readers.get().query_row( "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", @@ -967,7 +991,7 @@ fn envelope_record_arriving_before_auth_cursor_restarts_preexisting_signature_se receive(&target,&export(&source,&target)); let grant = append(&source,SUBJECT,GRANTED,fields()); let exchange = export(&source,&target); - receive(&target,&unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); let signature = signatures(&exchange).signatures.into_iter().find(|signature| { target.readers.get().query_row( "SELECT EXISTS(SELECT 1 FROM replica_records WHERE claim_id=?1 AND sequence=?2)", @@ -1086,7 +1110,7 @@ fn unsigned_pending_revoke_fences_only_its_established_subject_after_dirty_work_ let independent = independent_grant(&target); let revoke = append(&source, SUBJECT, REVOKED, fields()); let exchange = export(&source, &target); - receive(&target, &unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); drain_authority(&target); { let connection = target.readers.get(); diff --git a/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs b/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs index ba40857c446..ee714bd06b1 100644 --- a/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_membership_property_tests.rs @@ -228,7 +228,7 @@ fn fenced_opposite_profile_witness_matches_independent_raw_history_oracle() { receive(&target, &export(&source, &target)); append(&source, &subject, REVOKED, service_fields); let revoke_exchange = export(&source, &target); - receive(&target, &unsigned(&revoke_exchange)); + receive_pre_projection_unsigned_history(&target, &revoke_exchange); assert_conflict_oracle(&target, &own, &witness, true); assert!(!authority::contains(&target.readers.get(), &witness.id).unwrap()); { @@ -250,7 +250,7 @@ fn fenced_opposite_profile_witness_matches_independent_raw_history_oracle() { // Conversely, pending work on the bearer's own subject must deny that // bearer, without changing the independent conflict-history answer. append(&source, SUBJECT, POLICY, fields()); - receive(&target, &unsigned(&export(&source, &target))); + receive_pre_projection_unsigned_history(&target, &export(&source, &target)); assert!(!authority::contains(&target.readers.get(), &own.id).unwrap()); assert!(authority::by_credential(&target.readers.get(), &"a".repeat(64)).unwrap().is_none()); assert!(authority::subject_ready(&target.readers.get(), SUBJECT).is_err()); diff --git a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs index 52f676c2b0d..05dec0ba914 100644 --- a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs @@ -62,7 +62,7 @@ fn fresh_nonmember_proof_receipt_has_constant_complete_transaction_vm_cost() { let anchor = raw_claims(&source).into_iter().find(|claim| claim.kind=="fleet.member-admitted").unwrap(); let grant = append(&source, SUBJECT, GRANTED, fields()); let exchange = export(&source, &target); - receive(&target, &unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); let envelope = receipt_signature_for_claim(&target, &fleet_exchange, &anchor); { let connection = target.connection.write(); @@ -121,7 +121,7 @@ fn sustained_fresh_nonmember_proof_receipts_leave_unrelated_established_credenti pending_fields["session_actor"] = json!("assistant/chatgpt/session/assistant-grant/fedcba9876543210fedcba98"); let pending = append(&source, "custom/client/assistant-v1-fedcba9876543210fedcba98", GRANTED, pending_fields); let exchange = export(&source, &target); - receive(&target, &unsigned(&exchange)); + receive_pre_projection_unsigned_history(&target, &exchange); let envelope = receipt_signature_for_claim(&target, &fleet_exchange, &anchor); let before = receipt_projection_work_state(&target.readers.get()); for arrival in 0..256 { From e127da3d5b8241326535d1bbaa78ad821cea864a Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 18:05:40 +0100 Subject: [PATCH 48/52] fix: match assistant authority error codes directly agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/fractal-store/src/store/assistant_write.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fractal-store/src/store/assistant_write.rs b/crates/fractal-store/src/store/assistant_write.rs index 1058416fa51..c0ab6fc4894 100644 --- a/crates/fractal-store/src/store/assistant_write.rs +++ b/crates/fractal-store/src/store/assistant_write.rs @@ -28,7 +28,7 @@ pub fn authorize_grant(connection: &Connection, origin: &str, authorization: &As pub fn authorized_grant(connection: &Connection, origin: &str, authorization: &AssistantWriteAuthorization) -> Result { let denied = || FractalError::new("forbidden", "assistant write authorization changed or expired before commit"); let authority_error = |error: FractalError| { - if matches!(error.code.as_str(), "assistant-grant-authority-not-ready" | "assistant-grant-subject-not-ready") { + if matches!(error.code, "assistant-grant-authority-not-ready" | "assistant-grant-subject-not-ready") { denied() } else { error } }; From 92d53380f9f31fcd8782f77b2415bb0497609271 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 21:13:50 +0100 Subject: [PATCH 49/52] fix: name assistant grant membership window bounds agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- crates/smallclaims/src/store/assistant_grant_authority.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority.rs b/crates/smallclaims/src/store/assistant_grant_authority.rs index be6fd51bc77..248163d461b 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority.rs @@ -478,11 +478,14 @@ pub fn refresh_envelope(connection: &Connection, writer: &str, sequence: u64, ha Ok(()) } +// Inclusive membership bounds; an absent end denotes a current incarnation. +type MembershipWindow = (u64, Option); + struct MembershipUpdate { generation: i64, fleet_id: Option, // Only changed/deleted keys, never a replacement of the complete snapshot. - windows: Vec<(String, String, Option<(u64, Option)>)>, + windows: Vec<(String, String, Option)>, complete: bool, } From 2c905f287231461024740560642140802f8b7f06 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Mon, 9 Nov 2026 22:26:42 +0100 Subject: [PATCH 50/52] test: align grant fixtures with authenticated authority fencing agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../assistant/authorization_tests.rs | 40 ++++++++++++++++++- .../external_grants/conflict_tests.rs | 16 +++++++- .../src/store/message_send_tests.rs | 14 +++++-- .../assistant_grant_receipt_cost_tests.rs | 4 +- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs index 41a3f8d9d07..00299ebb8ac 100644 --- a/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs +++ b/crates/fractal-api-client-v0/src/api/client_v0/assistant/authorization_tests.rs @@ -108,6 +108,39 @@ async fn p1_owner_transitions_ignore_wrong_origin_overlays_but_fence_the_subject let subject = subject(&fixture.grant).unwrap(); let granted = latest(&fixture.state, &subject, GRANTED).unwrap().unwrap(); let peer = Store::open_memory("wrong-origin").unwrap(); + // These overlays must be authenticated data from the wrong issuer. + // An unsigned import instead fences the subject until it authenticates. + const FLEET: &str = "86700000-0000-4000-8000-000000000001"; + let anchor = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + let peer_key = Arc::new(smallclaims::fleet::MemberKey::generate().unwrap().0); + for store in [&*fixture.state.store, &peer] { + store.bind_fleet(FLEET).unwrap(); + store.pin_fleet_anchor(anchor.public()).unwrap(); + } + fixture.state.store.set_member_key(Some(anchor.clone())).unwrap(); + peer.set_member_key(Some(peer_key.clone())).unwrap(); + fixture.state.store.admit_fleet_anchor(FLEET, anchor.public(), "listening").unwrap(); + fixture.state.store.append_claim(&ClaimInput { + subject: "host/wrong-origin".into(), kind: "fleet.member-admitted".into(), + actor: Some(OWNER.into()), + fields: serde_json::from_value(json!({ + "fleet_id": FLEET, "member_key": peer_key.public(), + "via": "invite", "mode": "listening", "writer_floor": 0, + })).unwrap(), + evidence: Vec::new(), expected_subject: None, idempotency_key: None, + }).unwrap(); + let replicate = |from: &Store, to: &Store| { + let exchange = from.export_replication_exchange_answering( + FLEET, &to.replication_inventory().unwrap(), + &to.replication_signature_requests().unwrap(), + ).unwrap(); + to.receive_replication_exchange(from.origin(), FLEET, &exchange).unwrap(); + to.validate_replication_backlog().unwrap(); + to.project_replication_backlog().unwrap(); + }; + replicate(&fixture.state.store, &peer); + while !peer.advance_assistant_grant_authority_backfill().unwrap() {} + while !fixture.state.store.advance_assistant_grant_authority_backfill().unwrap() {} let overlay = || { let mut value = fields(&granted).unwrap().clone(); if kind == POLICY { @@ -120,9 +153,14 @@ async fn p1_owner_transitions_ignore_wrong_origin_overlays_but_fence_the_subject fields: serde_json::from_value(value).unwrap(), evidence: Vec::new(), expected_subject: None, idempotency_key: None, }).unwrap(); - fixture.state.store.import_replication("wrong-origin", &peer.export_replication(0).unwrap()).unwrap(); + replicate(&peer, &fixture.state.store); assert!(fixture.state.store.claim_by_id(&claim.id).unwrap().is_some(), "wrong-origin evidence must remain in raw history without becoming authority"); + assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").unwrap().is_none(), + "receipt must fence the subject before background authentication"); + while !fixture.state.store.advance_assistant_grant_authority_backfill().unwrap() {} + assert!(fixture.state.store.claim_has_authenticated_member_writer(&claim.id).unwrap(), + "wrong-origin filtering must be exercised after writer authentication"); assert!(authenticate(&fixture.state, &credential_digest(&fixture.credential), "fabric-loopback").unwrap().is_some()); }; diff --git a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs index 7d260ddb532..2d76102b27a 100644 --- a/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs +++ b/crates/fractal-api-core/src/api/client_v0/external_grants/conflict_tests.rs @@ -391,6 +391,8 @@ fn unauthenticated_legacy_transitions_preserve_authenticated_lifecycle_history() if let Some(revoke) = &authentic_revoke { assert!(a.store.claim_has_authenticated_member_writer(&revoke.id).unwrap()); } + assert_eq!(effective(&a, &foreign).unwrap().id, live.id); + assert_eq!(revoked(&a, &foreign).unwrap(), scenario == "revocation"); // A different incarnation of the same writer sends a signed envelope // below the admission floor. It is visible Legacy data, not authority, @@ -419,8 +421,18 @@ fn unauthenticated_legacy_transitions_preserve_authenticated_lifecycle_history() assert_eq!(tests::reference_transition(&a, &foreign, POLICY).unwrap().unwrap().id, live.id); assert_eq!(tests::reference_transition(&a, &foreign, REVOKED).unwrap().map(|claim| claim.id), authentic_revoke.as_ref().map(|claim| claim.id.clone())); - assert_eq!(effective(&a, &foreign).unwrap().id, live.id); - assert_eq!(revoked(&a, &foreign).unwrap(), scenario == "revocation"); + // Maintenance has finished, but this below-floor incarnation cannot + // authenticate. Its retained transition still fences its own subject; + // it must neither grant bearer access nor replace the last authenticated + // snapshot used for cross-subject conflict admission. + assert!(authenticate_id(&a, SERVICE_ID).unwrap().is_none()); + for error in [ + effective(&a, &foreign).unwrap_err(), + revoked(&a, &foreign).unwrap_err(), + ] { + assert_eq!(error.code, "forbidden"); + assert_eq!(error.details["reason"], "credential-rejected"); + } let candidate = json!({"profile":"assistant","principal":PRINCIPAL}); let reference = tests::rust_only_admission(&a, &candidate).map_err(|error| error.code); let production = admit_profile(&a, &candidate).map_err(|error| error.code); diff --git a/crates/fractal-delivery/src/store/message_send_tests.rs b/crates/fractal-delivery/src/store/message_send_tests.rs index a3ec00841a7..de714062a84 100644 --- a/crates/fractal-delivery/src/store/message_send_tests.rs +++ b/crates/fractal-delivery/src/store/message_send_tests.rs @@ -445,8 +445,8 @@ fn assistant_provenance_stamps_authenticated_grant_and_preserves_replica_admissi store.apply(&crate::graph::parse_test_intent( "version 2\nagent \"example-recipient.local\" { workspace \"/tmp/st-test\"; command \"true\"; restart always; }", "node").unwrap(), &BTreeMap::from([("agent/example-recipient.local".to_string(), Vec::new())]), "assistant-recipient").unwrap(); - let grant_subject = "custom/client/assistant-v1-native-fixture"; - let grant_id = "assistant-grant/native-fixture"; + let grant_subject = "custom/client/assistant-v1-0123456789abcdef01234567"; + let grant_id = "assistant-grant/0123456789abcdef01234567"; let session_actor = format!("{principal}/session/{grant_id}"); store.append_claim(&ClaimInput { subject: grant_subject.into(), kind: "custom.client.assistant.v1.granted".into(), @@ -454,12 +454,15 @@ fn assistant_provenance_stamps_authenticated_grant_and_preserves_replica_admissi fields: serde_json::from_value(json!({ "principal":principal, "session_actor":session_actor, "issuer":"person/robin", "disclosure_consent":true, "policy_revision":1, + "credential_hash":"a".repeat(64), "minimal_read_mode":"approval-once", "expires_at_unix_ms":now_ms() as u64 + 60_000, "scopes":["write.assistant.messages"], "recipient_allowlist":["agent/example-recipient.local"], "grant_id":grant_id })).unwrap(), evidence: vec![], expected_subject: None, idempotency_key: None, }).unwrap(); + // Complete fixture authority maintenance before exercising the writer recheck. + while !store.advance_assistant_grant_authority_backfill().unwrap() {} let authorization = assistant_write::AssistantWriteAuthorization { grant_subject: grant_subject.into(), actor: session_actor.clone(), owner: "person/robin".into(), policy_revision: 1, scope: "write.assistant.messages".into(), @@ -498,8 +501,8 @@ fn writer_recheck_fences_dirty_subject_without_exposing_projection_state() { store.apply(&crate::graph::parse_test_intent( "version 2\nagent \"example-recipient.local\" { workspace \"/tmp/st-test\"; command \"true\"; restart always; }", "node").unwrap(), &BTreeMap::from([("agent/example-recipient.local".to_string(), Vec::new())]), "assistant-recipient").unwrap(); - let grant_subject = "custom/client/assistant-v1-native-fixture"; - let grant_id = "assistant-grant/native-fixture"; + let grant_subject = "custom/client/assistant-v1-0123456789abcdef01234567"; + let grant_id = "assistant-grant/0123456789abcdef01234567"; let session_actor = format!("assistant/chatgpt/session/{grant_id}"); let granted = store.append_claim(&ClaimInput { subject: grant_subject.into(), kind: "custom.client.assistant.v1.granted".into(), @@ -507,11 +510,14 @@ fn writer_recheck_fences_dirty_subject_without_exposing_projection_state() { fields: serde_json::from_value(json!({ "principal":"assistant/chatgpt", "session_actor":session_actor, "issuer":"person/robin", "disclosure_consent":true, "policy_revision":1, + "credential_hash":"a".repeat(64), "minimal_read_mode":"approval-once", "expires_at_unix_ms":u64::MAX, "scopes":["write.assistant.messages"], "grant_id":grant_id })).unwrap(), evidence: vec![], expected_subject: None, idempotency_key: None, }).unwrap(); + // Settle the valid fixture before injecting dirty state; the writer must not repair it. + while !store.advance_assistant_grant_authority_backfill().unwrap() {} let authorization = assistant_write::AssistantWriteAuthorization { grant_subject: grant_subject.into(), actor: session_actor, owner: "person/robin".into(), policy_revision: 1, diff --git a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs index 05dec0ba914..ab8080eea64 100644 --- a/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_receipt_cost_tests.rs @@ -174,7 +174,9 @@ fn membership_window_changes_share_the_fixed_transaction_budget_without_replacin [key.public()], |row| row.get(0), ).unwrap(); assert_eq!(unchanged_rowid, stable_rowid, "unchanged windows are never deleted and reinserted"); - assert!(authority::maintenance_pending(&store.readers.get()).unwrap()); + // Membership-only work is tracked by the Store's observed generation, not + // the connection-level claim/signature dirty queues. + assert!(store.assistant_grant_authority_maintenance_pending().unwrap()); drain_authority(&store); let remaining: usize = store.readers.get().query_row( "SELECT COUNT(*) FROM assistant_grant_membership_windows WHERE writer='obsolete'", From cb1be0ac8891ec7c653e74db3459e2f4ddb82ade Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Tue, 10 Nov 2026 03:05:35 +0100 Subject: [PATCH 51/52] test: prepare sealed membership before authority benchmark backfill agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../store/assistant_grant_authority_bench.rs | 31 +++++++++++-- .../store/assistant_grant_authority_tests.rs | 46 +++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs index 1d9cfc96a74..79dbb001e0e 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -152,10 +152,34 @@ fn slice(connection: &mut Connection, budget: Duration) -> (bool, Duration) { #[test] #[ignore = "opt-in disk/RSS authority backfill measurement; run alone with --ignored --nocapture"] fn assistant_grant_authority_measure_realistic_backfill() { - let config = Config::from_env(); + measure_backfill(Config::from_env()); +} + +#[test] +fn assistant_grant_authority_bench_unsigned_rows_reach_readiness() { + measure_backfill(Config { + rows: 10_000, + authority_bps: 5_000, + malformed_bps: 1_000, + unauthenticated_bps: 4_000, + revoked_bps: 2_500, + unrelated_body_bytes: 256, + authority_body_bytes: 1_024, + transaction_rows: 1_000, + slice_ms: 100, + startup_ms: 2_000, + target_bytes: 50_000_000_000, + }); +} + +fn measure_backfill(config: Config) { + let fixture_started = Instant::now(); let directory = tempfile::tempdir().unwrap(); let path = directory.path().join("claims.sqlite3"); let store = Store::open(&path, LOCAL, Arc::new(runtime::Plain)).unwrap(); + // The low-level slices below require the same sealed membership snapshot + // the production Store worker prepares before refreshing unsigned claims. + assert!(store.advance_assistant_grant_authority_backfill().unwrap()); let mut expected_effective = 0_u64; let mut expected_revoked = 0_u64; let mut raw_revocations = 0_u64; @@ -174,10 +198,8 @@ fn assistant_grant_authority_measure_realistic_backfill() { DELETE FROM assistant_grant_dirty; DELETE FROM assistant_grant_auth_cursor; DELETE FROM assistant_grant_membership_dirty; - DELETE FROM assistant_grant_membership_windows; DELETE FROM meta WHERE key='assistant_grant_authority_version' - OR key LIKE 'assistant_grant_authority_cursor/%'; - UPDATE assistant_grant_membership_state SET applied_generation=-1 WHERE id=1;", + OR key LIKE 'assistant_grant_authority_cursor/%';", ).unwrap(); // Fixed small pool of representative unrelated JSON sizes, not a history. let unrelated_bodies = [ @@ -258,6 +280,7 @@ fn assistant_grant_authority_measure_realistic_backfill() { assert_eq!(checkpoint, (0, 0, 0)); } drop(store); + println!("authority_backfill_fixture_creation elapsed_ms={:.3}", fixture_started.elapsed().as_secs_f64() * 1_000.0); let mut connection = open_connection(&path); let raw_rows: u64 = connection.query_row("SELECT COUNT(*) FROM claims", [], |row| row.get(0)).unwrap(); let raw_authority_rows: u64 = connection.query_row( diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index 01b709a6852..51434d6caeb 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -584,6 +584,52 @@ fn older_build_raw_legacy_replication_cannot_authenticate_on_new_build_reopen() assert_bearer_rejected(&reopened, &grant); } +#[test] +fn unsigned_remote_without_membership_drains_once_and_maintenance_goes_idle() { + let sender = node("unsigned-remote", None); + let grant = append(&sender, SUBJECT, GRANTED, fields()); + let target = node("reader", None); + drain_authority(&target); + { + let (sequence, previous, hash): (u64, Option, String) = sender.readers.get() + .query_row("SELECT replica_sequence,previous_hash,hash FROM batches WHERE id=?1", + [&grant.batch_id], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?))).unwrap(); + let mut connection = target.connection.write(); + let transaction = connection.transaction().unwrap(); + // Reproduce a pre-envelope remote import: no local append marker, + // replica receipt, signature, or membership window can authenticate it. + transaction.execute( + "INSERT INTO batches(id,origin,replica_sequence,previous_hash,hash,accepted_at_unix_ms) + VALUES(?1,?2,?3,?4,?5,?6)", + params![grant.batch_id,grant.origin,sequence,previous,hash,grant.accepted_at_unix_ms.to_string()], + ).unwrap(); + transaction.execute( + "INSERT INTO claims(id,batch_id,subject,kind,origin,actor,body,predecessors,accepted_at_unix_ms) + VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9)", + params![grant.id,grant.batch_id,grant.subject,grant.kind,grant.origin,grant.actor, + canonical_json_text(&grant.body).unwrap(),serde_json::to_string(&grant.predecessors).unwrap(), + grant.accepted_at_unix_ms.to_string()], + ).unwrap(); + assert!(authority::maintenance_pending(&transaction).unwrap()); + assert_eq!(transaction.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_,u64>(0)).unwrap(), 1); + assert!(authority::backfill_slice(&transaction, Duration::from_millis(100)).unwrap()); + assert_eq!(transaction.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_,u64>(0)).unwrap(), 0); + assert!(!transaction.query_row( + "SELECT authenticated FROM assistant_grant_pending WHERE claim_id=?1", + [&grant.id], |row| row.get::<_,bool>(0)).unwrap()); + assert!(!authority::maintenance_pending(&transaction).unwrap()); + transaction.commit().unwrap(); + } + assert!(!target.assistant_grant_authority_maintenance_pending().unwrap()); + let writes = target.connection.write().total_changes(); + for _ in 0..3 { + assert!(target.advance_assistant_grant_authority_backfill().unwrap()); + assert!(!target.assistant_grant_authority_maintenance_pending().unwrap()); + } + assert_eq!(target.connection.write().total_changes(), writes, "idle maintenance must not requeue or refresh unsigned evidence"); + assert_bearer_rejected(&target, &grant); +} + #[test] fn local_append_authenticates_immediately_and_local_unsealed_and_signed_history_survive_backfill() { let (store, _) = source(); From 635e3baa658cba3848d329bab184f92f96de60f5 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Tue, 10 Nov 2026 03:57:58 +0100 Subject: [PATCH 52/52] test: persist benchmark membership snapshot before seeding agent-identity: agent/dotfiles/st-delegation-2 agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.12.5 agent-runtime: OMP 18.12.5 agent-model: openai-codex/gpt-6.1-sol --- .../src/store/assistant_grant_authority_bench.rs | 14 +++++++++----- .../src/store/assistant_grant_authority_tests.rs | 13 ++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs index 79dbb001e0e..2c99625bcc3 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_bench.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_bench.rs @@ -163,7 +163,7 @@ fn assistant_grant_authority_bench_unsigned_rows_reach_readiness() { malformed_bps: 1_000, unauthenticated_bps: 4_000, revoked_bps: 2_500, - unrelated_body_bytes: 256, + unrelated_body_bytes: 1_024, authority_body_bytes: 1_024, transaction_rows: 1_000, slice_ms: 100, @@ -177,9 +177,6 @@ fn measure_backfill(config: Config) { let directory = tempfile::tempdir().unwrap(); let path = directory.path().join("claims.sqlite3"); let store = Store::open(&path, LOCAL, Arc::new(runtime::Plain)).unwrap(); - // The low-level slices below require the same sealed membership snapshot - // the production Store worker prepares before refreshing unsigned claims. - assert!(store.advance_assistant_grant_authority_backfill().unwrap()); let mut expected_effective = 0_u64; let mut expected_revoked = 0_u64; let mut raw_revocations = 0_u64; @@ -188,7 +185,7 @@ fn measure_backfill(config: Config) { let mut authority_body_bytes = 0_u64; let mut unrelated_body_bytes = 0_u64; { - let mut connection = store.connection.write(); + let connection = store.connection.write(); connection.execute_batch( /* sqlite-large-value: allow-for-now lv-h6064c7271014 owner=smallclaims::store::assistant_grant_authority_bench TODO=bound-or-reference-values-and-reclamation */ "DROP TRIGGER IF EXISTS assistant_grant_dirty_insert; @@ -201,6 +198,13 @@ fn measure_backfill(config: Config) { DELETE FROM meta WHERE key='assistant_grant_authority_version' OR key LIKE 'assistant_grant_authority_cursor/%';", ).unwrap(); + } + // Invalidating readiness above makes the production worker persist its + // sealed snapshot, rather than taking the already-idle in-memory fast path. + assert!(store.advance_assistant_grant_authority_backfill().unwrap()); + { + let mut connection = store.connection.write(); + connection.execute("DELETE FROM meta WHERE key='assistant_grant_authority_version'", []).unwrap(); // Fixed small pool of representative unrelated JSON sizes, not a history. let unrelated_bodies = [ padded_body(json!({"fields": {"text": "synthetic conversation summary"}}), config.unrelated_body_bytes / 4), diff --git a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs index 51434d6caeb..d09e5366b6c 100644 --- a/crates/smallclaims/src/store/assistant_grant_authority_tests.rs +++ b/crates/smallclaims/src/store/assistant_grant_authority_tests.rs @@ -612,13 +612,16 @@ fn unsigned_remote_without_membership_drains_once_and_maintenance_goes_idle() { ).unwrap(); assert!(authority::maintenance_pending(&transaction).unwrap()); assert_eq!(transaction.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_,u64>(0)).unwrap(), 1); - assert!(authority::backfill_slice(&transaction, Duration::from_millis(100)).unwrap()); - assert_eq!(transaction.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_,u64>(0)).unwrap(), 0); - assert!(!transaction.query_row( + transaction.commit().unwrap(); + } + assert!(target.advance_assistant_grant_authority_backfill().unwrap()); + { + let connection = target.readers.get(); + assert_eq!(connection.query_row("SELECT COUNT(*) FROM assistant_grant_dirty", [], |row| row.get::<_,u64>(0)).unwrap(), 0); + assert!(!connection.query_row( "SELECT authenticated FROM assistant_grant_pending WHERE claim_id=?1", [&grant.id], |row| row.get::<_,bool>(0)).unwrap()); - assert!(!authority::maintenance_pending(&transaction).unwrap()); - transaction.commit().unwrap(); + assert!(!authority::maintenance_pending(&connection).unwrap()); } assert!(!target.assistant_grant_authority_maintenance_pending().unwrap()); let writes = target.connection.write().total_changes();