store: add with_audited_effect audit-before-effect combinator (#215) - #239
Conversation
Add AuditDescriptor + Store::with_audited_effect: the single effect-path entry that can write an effect row, folding the effect closure and its audit append into one Immediate transaction (via with_immediate_tx) and committing atomically. Effect-only writes cannot be expressed on this path (AD-105 ledger-before-consume, spec #208 D-002). Migrate the pilot owner_assert_identity_binding off its hand-paired Deferred transaction onto the combinator; add a rollback regression test proving a forced audit failure leaves no orphan effect row.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
Next review available in: 9 minutes Limit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?Wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What
Adds the audit-before-effect combinator so a wrong ordering stops compiling on the effect path (spec #208 D-002, expand step; blocked-by #213 which is merged).
AuditDescriptor(store/audited_effect.rs) — owned value type carrying the audit-row inputs (kind,action,decision,reason,task_grant_id,target_refs,payload_refs) as data, decoupled fromStore/rusqlite.new(kind)+with_reason(...)cover the common case; other fields are public and default toNone/empty.Store::with_audited_effect(descriptor, effect)— the ONLY effect-path entry that can write an effect row. It runs the effect closure, thenappend_audit_conn, inside oneImmediatetransaction and commits atomically. Routes through the existingwith_immediate_txcombinator (Store: add with_immediate_tx / with_deferred_read transaction combinators #213) rather than restating the D-050 write-serialization discipline. Audit-only and internal-maintenance writes keep using their separately named entries.owner_assert_identity_bindingmoves off its hand-paired transaction onto the combinator.identity.boundaudit failure (via the existinginstall_audit_append_failure_for_kindtrigger harness) leaves no orphan effect row (AD-105 ledger-before-consume).Why
The 83 hand-paired
append_audit_connsites enforce audit-before-effect by convention; a single missed pairing is invisible until an audit query comes up short. This encapsulates the discipline so an effect-only write cannot compile on the effect path. Mass migration of the remaining sites is #218 (not this ticket).Notes
conn.transaction()); routing it throughwith_audited_effect→with_immediate_txupgrades it to Immediate, aligning with spec Spec: deepened Store interface #208 D-001 / D-050. Behavior-preserving on the happy path, strictly safer under write contention.with_audited_effectonly (concurrency note: dev-214/dev-217 touch other store files in parallel).Verification
./scripts/check.shgreen — 45/45 spec items, full kernel suite including the shell-binary E2E; 7/7store::identitytests pass (incl. the new rollback test).Implementation-notes five-line summary
AuditDescriptorvalue type +Store::with_audited_effectcombinator instore/audited_effect.rs— the only effect-path entry that can write an effect row.append_audit_conninto oneImmediatetransaction (viawith_immediate_tx) and commits atomically; effect-only writes cannot be expressed on this path (AD-105 ledger-before-consume).owner_assert_identity_bindingoff its hand-paired Deferred transaction onto the combinator, upgrading it toImmediate.identity.boundaudit failure leaves no orphan effect row../scripts/check.shgreen; diff scoped towith_audited_effectonly.Closes #215
Summary by cubic
Adds
Store::with_audited_effectto enforce audit-before-effect on the effect path. Previously callers hand-paired effect writes withappend_audit_conn; now the combinator runs the effect then appends audit in one Immediate transaction, so a write with no prior audit cannot be expressed on this path and rollbacks leave no orphan effect rows.AuditDescriptor(owned inputs for audit metadata) and thewith_audited_effect(descriptor, effect)API instore/audited_effect.rs, implemented viawith_immediate_tx.owner_assert_identity_bindingfrom a Deferred transaction towith_audited_effect(Immediate); behavior is preserved, safety under write contention improves.identity.boundaudit failure and verifies no orphan identity or identifier rows remain.Written for commit 96661b7. Summary will update on new commits.