Skip to content

Commit f8c3575

Browse files
Merge branch 'worktree-agent-a812b4e1062c78c34' into codex/tracedecay-total-redesign-plan
2 parents 75a0ccc + 785c579 commit f8c3575

1 file changed

Lines changed: 61 additions & 6 deletions

File tree

src/daemon/context_scout_lifecycle.rs

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,52 @@ mod tests {
653653
)
654654
}
655655

656+
/// Writes durable evidence straight into the shard, bypassing the
657+
/// runtime scope gate.
658+
///
659+
/// This is only ever correct for staging state the store contract
660+
/// forbids — a row scoped to another project — so that the reader-side
661+
/// guards can be exercised against it. Everything else must go through
662+
/// [`ObservationStore::persist_observation`].
663+
async fn stage_foreign_scoped_observation(
664+
sessions: &RegisteredGlobalDb,
665+
write: &AnchoredObservationWrite,
666+
) {
667+
let observation = write.observation();
668+
let receipt = observation.receipt();
669+
let writer = sessions.writer_connection().unwrap();
670+
writer
671+
.execute(
672+
"INSERT INTO sanitization_receipts
673+
(receipt_id, sanitizer_version, payload_digest, receipt_json)
674+
VALUES (?1, ?2, ?3, ?4)",
675+
crate::db::engine::params![
676+
receipt.receipt().receipt_id().as_str(),
677+
receipt.receipt().sanitizer_version().as_str(),
678+
observation.payload_reference().digest().as_str(),
679+
serde_json::to_string(receipt).unwrap()
680+
],
681+
)
682+
.await
683+
.unwrap();
684+
writer
685+
.execute(
686+
"INSERT INTO observations
687+
(observation_id, payload_digest, receipt_id, observation_json,
688+
committed_cursor_json)
689+
VALUES (?1, ?2, ?3, ?4, ?5)",
690+
crate::db::engine::params![
691+
observation.observation_id().as_str(),
692+
observation.payload_reference().digest().as_str(),
693+
receipt.receipt().receipt_id().as_str(),
694+
serde_json::to_string(observation).unwrap(),
695+
serde_json::to_string(write.next_cursor()).unwrap()
696+
],
697+
)
698+
.await
699+
.unwrap();
700+
}
701+
656702
/// Every test below registers under hook ids unique to that test: the
657703
/// authority registry is process-global, so overlapping keys would make
658704
/// parallel tests observe each other's entries.
@@ -1165,12 +1211,21 @@ mod tests {
11651211
.unwrap();
11661212
// Durable evidence carrying a foreign project scope, stored in the
11671213
// shard that the lookup is otherwise authorized against.
1168-
observation_store(&sessions)
1169-
.persist_observation(durable_native_observation(&id::<ProjectId>(
1170-
"project.native.foreign-scope",
1171-
)))
1172-
.await
1173-
.unwrap();
1214+
let foreign = durable_native_observation(&id::<ProjectId>("project.native.foreign-scope"));
1215+
// The store contract refuses to create this state: every observation
1216+
// operation is gated on the observation scope matching the bound
1217+
// shard family, so the runtime rejects the write before it reaches
1218+
// the shard. The row can therefore only arrive by corruption or a
1219+
// pre-contract import, which is exactly what the lookup's durable
1220+
// scope check has to survive.
1221+
assert!(
1222+
observation_store(&sessions)
1223+
.persist_observation(foreign.clone())
1224+
.await
1225+
.is_err(),
1226+
"the runtime must refuse a foreign-scoped write against this shard"
1227+
);
1228+
stage_foreign_scoped_observation(&sessions, &foreign).await;
11741229
let bound_profile_id = sessions.binding().shard_id.profile_id.clone();
11751230

11761231
// Foreign-scoped evidence and no evidence at all both fail closed,

0 commit comments

Comments
 (0)