Finding
In submit_request, the auto_approve branch constructs the MediaRequest with status = RequestStatus::Approved and persists it before identity validation runs. The subsequent identity.validate(...) call can return an error (unknown title, unreachable metadata service). When it does, the function returns early via ?, leaving a row in the database with status Approved and want_id = None. No compensating delete or update_status follows. Approved → Monitoring is the only valid next transition, but want_id is null and the transition is never completed, so the row is permanently stuck in a non-terminal state.
Evidence
crates/aitesis/src/lib.rs:135 constructs the request with status = RequestStatus::Approved. crates/aitesis/src/lib.rs:155 persists it before validation:
repo::insert_request(&self.write, &request).await?;
// ...
if auto_approve {
self.identity.validate(...).await?; // failure leaves Approved row with no want_id
let want_id = self.monitor.create_want(&request).await?;
The insert is committed before identity.validate(...) (line 166) and monitor.create_want(...) run; an error from either path returns before any compensating write.
Why this matters
A flaky or adversarially-degraded metadata service silently fills the database with dead Approved rows. Because they are non-terminal they count toward the user's pending-request limit but can never be resolved — re-running approve fails with InvalidTransition since the status is already Approved, and normal cleanup ignores them. On a counter-surveillance device this is both a pending-limit denial-of-service (a degraded upstream exhausts the user's quota with phantom requests) and an uncontrolled accumulation of persistent request records that cannot be purged through the supported path — increasing the on-disk forensic footprint that the system is supposed to keep minimal.
Desired correction
Insert with Submitted status first, then perform identity validation and want creation, and only then update_status to Approved → Monitoring. Alternatively, perform the insert and all post-insert steps inside a single transaction and roll back if any step fails. Done when: an identity-validation failure during auto-approve results in no persisted row (or a Submitted-status row that can be retried), with no Approved row left lacking a want_id.
Finding
In
submit_request, theauto_approvebranch constructs theMediaRequestwithstatus = RequestStatus::Approvedand persists it before identity validation runs. The subsequentidentity.validate(...)call can return an error (unknown title, unreachable metadata service). When it does, the function returns early via?, leaving a row in the database with statusApprovedandwant_id = None. No compensating delete orupdate_statusfollows.Approved → Monitoringis the only valid next transition, butwant_idis null and the transition is never completed, so the row is permanently stuck in a non-terminal state.Evidence
crates/aitesis/src/lib.rs:135constructs the request withstatus = RequestStatus::Approved.crates/aitesis/src/lib.rs:155persists it before validation:The insert is committed before
identity.validate(...)(line 166) andmonitor.create_want(...)run; an error from either path returns before any compensating write.Why this matters
A flaky or adversarially-degraded metadata service silently fills the database with dead
Approvedrows. Because they are non-terminal they count toward the user's pending-request limit but can never be resolved — re-runningapprovefails withInvalidTransitionsince the status is alreadyApproved, and normal cleanup ignores them. On a counter-surveillance device this is both a pending-limit denial-of-service (a degraded upstream exhausts the user's quota with phantom requests) and an uncontrolled accumulation of persistent request records that cannot be purged through the supported path — increasing the on-disk forensic footprint that the system is supposed to keep minimal.Desired correction
Insert with
Submittedstatus first, then perform identity validation and want creation, and only thenupdate_statustoApproved → Monitoring. Alternatively, perform the insert and all post-insert steps inside a single transaction and roll back if any step fails. Done when: an identity-validation failure during auto-approve results in no persisted row (or aSubmitted-status row that can be retried), with noApprovedrow left lacking awant_id.