Skip to content

Commit 1da032b

Browse files
fix: stabilize sparsekernel list ordering
1 parent 99b1b0c commit 1da032b

1 file changed

Lines changed: 89 additions & 4 deletions

File tree

  • crates/sparsekernel-core/src

crates/sparsekernel-core/src/lib.rs

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ impl SparseKernelDb {
15891589
) -> Result<Vec<CapabilityRecord>> {
15901590
let mut stmt = self.conn.prepare(
15911591
"SELECT id, subject_type, subject_id, resource_type, resource_id, action, constraints_json, expires_at, created_at
1592-
FROM capabilities WHERE subject_type = ? AND subject_id = ? ORDER BY created_at DESC",
1592+
FROM capabilities WHERE subject_type = ? AND subject_id = ? ORDER BY created_at DESC, id ASC",
15931593
)?;
15941594
let rows = stmt.query_map(params![subject_type, subject_id], capability_from_row)?;
15951595
rows.collect::<std::result::Result<Vec<_>, _>>()
@@ -1675,7 +1675,7 @@ impl SparseKernelDb {
16751675
pub fn list_tool_calls(&self, limit: i64) -> Result<Vec<ToolCallRecord>> {
16761676
let mut stmt = self.conn.prepare(
16771677
"SELECT id, task_id, session_id, agent_id, tool_name, status, input_json, output_json, error, started_at, ended_at, created_at
1678-
FROM tool_calls ORDER BY created_at DESC LIMIT ?",
1678+
FROM tool_calls ORDER BY created_at DESC, id ASC LIMIT ?",
16791679
)?;
16801680
let rows = stmt.query_map(params![limit.max(0)], tool_call_from_row)?;
16811681
rows.collect::<std::result::Result<Vec<_>, _>>()
@@ -1765,7 +1765,7 @@ impl SparseKernelDb {
17651765
pub fn list_browser_contexts(&self, limit: i64) -> Result<Vec<BrowserContextRecord>> {
17661766
let mut stmt = self.conn.prepare(
17671767
"SELECT id, pool_id, agent_id, session_id, task_id, profile_mode, allowed_origins_json, status, created_at
1768-
FROM browser_contexts ORDER BY created_at DESC LIMIT ?",
1768+
FROM browser_contexts ORDER BY created_at DESC, id ASC LIMIT ?",
17691769
)?;
17701770
let rows = stmt.query_map(params![limit.max(0)], browser_context_from_row)?;
17711771
rows.collect::<std::result::Result<Vec<_>, _>>()
@@ -1775,7 +1775,7 @@ impl SparseKernelDb {
17751775
pub fn list_browser_pools(&self) -> Result<Vec<BrowserPoolRecord>> {
17761776
let mut stmt = self.conn.prepare(
17771777
"SELECT id, trust_zone_id, browser_kind, status, max_contexts, cdp_endpoint, created_at, updated_at
1778-
FROM browser_pools ORDER BY trust_zone_id ASC, browser_kind ASC",
1778+
FROM browser_pools ORDER BY trust_zone_id ASC, browser_kind ASC, id ASC",
17791779
)?;
17801780
let rows = stmt.query_map([], browser_pool_from_row)?;
17811781
rows.collect::<std::result::Result<Vec<_>, _>>()
@@ -4022,6 +4022,91 @@ mod tests {
40224022
assert!(actions.contains(&"capability.revoked".to_string()));
40234023
}
40244024

4025+
#[test]
4026+
fn ledger_list_queries_use_stable_tie_breakers() {
4027+
let (_dir, db) = temp_db();
4028+
let created_at = "2026-04-29T00:00:00Z";
4029+
for id in ["cap-b", "cap-a"] {
4030+
db.conn
4031+
.execute(
4032+
"INSERT INTO capabilities(id, subject_type, subject_id, resource_type, resource_id, action, created_at)
4033+
VALUES(?, 'agent', 'main', 'tool', ?, 'invoke', ?)",
4034+
params![id, id, created_at],
4035+
)
4036+
.unwrap();
4037+
}
4038+
let capability_ids: Vec<String> = db
4039+
.list_capabilities("agent", "main")
4040+
.unwrap()
4041+
.into_iter()
4042+
.map(|capability| capability.id)
4043+
.collect();
4044+
assert_eq!(
4045+
capability_ids,
4046+
vec!["cap-a".to_string(), "cap-b".to_string()]
4047+
);
4048+
4049+
for id in ["tool-b", "tool-a"] {
4050+
db.conn
4051+
.execute(
4052+
"INSERT INTO tool_calls(id, tool_name, status, created_at)
4053+
VALUES(?, ?, 'created', ?)",
4054+
params![id, id, created_at],
4055+
)
4056+
.unwrap();
4057+
}
4058+
let tool_call_ids: Vec<String> = db
4059+
.list_tool_calls(10)
4060+
.unwrap()
4061+
.into_iter()
4062+
.map(|call| call.id)
4063+
.collect();
4064+
assert_eq!(
4065+
tool_call_ids,
4066+
vec!["tool-a".to_string(), "tool-b".to_string()]
4067+
);
4068+
4069+
for id in ["pool-b", "pool-a"] {
4070+
db.conn
4071+
.execute(
4072+
"INSERT INTO browser_pools(id, trust_zone_id, browser_kind, status, max_contexts, created_at, updated_at)
4073+
VALUES(?, 'public_web', 'mock', 'active', 2, ?, ?)",
4074+
params![id, created_at, created_at],
4075+
)
4076+
.unwrap();
4077+
}
4078+
let browser_pool_ids: Vec<String> = db
4079+
.list_browser_pools()
4080+
.unwrap()
4081+
.into_iter()
4082+
.map(|pool| pool.id)
4083+
.collect();
4084+
assert_eq!(
4085+
browser_pool_ids,
4086+
vec!["pool-a".to_string(), "pool-b".to_string()]
4087+
);
4088+
4089+
for id in ["context-b", "context-a"] {
4090+
db.conn
4091+
.execute(
4092+
"INSERT INTO browser_contexts(id, pool_id, profile_mode, status, created_at)
4093+
VALUES(?, 'pool-a', 'ephemeral', 'active', ?)",
4094+
params![id, created_at],
4095+
)
4096+
.unwrap();
4097+
}
4098+
let browser_context_ids: Vec<String> = db
4099+
.list_browser_contexts(10)
4100+
.unwrap()
4101+
.into_iter()
4102+
.map(|context| context.id)
4103+
.collect();
4104+
assert_eq!(
4105+
browser_context_ids,
4106+
vec!["context-a".to_string(), "context-b".to_string()]
4107+
);
4108+
}
4109+
40254110
#[test]
40264111
fn tool_broker_checks_capability_tracks_artifacts_and_audits() {
40274112
let (dir, db) = temp_db();

0 commit comments

Comments
 (0)