Skip to content

fix(cli): a failed audit-record write mid-run does not stop further purchases #2103

Description

@cristim

Summary

writePurchaseAuditRecord (introduced in #1609) logs a warning and continues
when common.WriteAuditRecord fails mid-run, on both the main pipeline
(executePurchasePipeline) and the --input-csv path (processPurchaseLoop).
CheckAuditLogWritable only proves the log was writable at the start of the
run; a failure partway through (disk full, permissions changed, the file
deleted out from under the process) leaves that recommendation's purchase
attempted with no durable record, and the run continues purchasing more
recommendations regardless.

Location

  • cmd/multi_service.go, writePurchaseAuditRecord (shared helper) and its
    two callers: executePurchasePipeline and processPurchaseLoop.

Failure scenario

A --purchase run (either entry point) purchases recommendation 1 for real,
then the disk fills up or the audit-log file becomes unwritable before
recommendation 2 is processed. WriteAuditRecord for recommendation 1's
result fails; writePurchaseAuditRecord logs Warning: failed to write audit record: ... and the loop proceeds to purchase recommendation 2, 3, etc. Every
purchase after the first failure moves real money with no audit trail at all,
and the operator has no way to reconcile which recommendations were bought
without one.

Suggested fix

When common.WriteAuditRecord fails on a real purchase (not a dry run), stop
processing further recommendations in that loop rather than logging a warning
and continuing, on both executePurchasePipeline and processPurchaseLoop.
The already-attempted purchase's PurchaseResult should still be returned to
the caller so it is reflected in the CSV report, but no further purchase
should be attempted once the audit trail can no longer be trusted to capture
it. A dry run may continue (nothing is bought, so the audit log matters less
for reconciliation), matching the fail-closed-on-purchase-only pattern
already used for the duplicate check (#1941) and --target-coverage sizing
(#1942).

Found while implementing #1609 and reviewing the failure-visibility of
writePurchaseAuditRecord's two call sites.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions