# Confirmed orders generate confirmation record or flag

- **Pattern:** `ab-001136` (`ecommerce-order-management.order-lifecycle.confirmation-record`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001136
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001136)

## Why it matters

If the only record of order confirmation is the `status` field flipping to 'confirmed', there is no queryable timestamp for 'orders confirmed in the last 7 days', no display value for 'Confirmed on March 12' in the customer order detail view, and no audit anchor distinct from subsequent status changes. CWE-841 covers workflows where the state machine advances correctly but the associated data capture is incomplete. A `confirmedAt` timestamp is a lightweight addition with disproportionate operational value — it powers fulfillment metrics, SLA tracking, and customer-facing order timelines.

## Severity rationale

Low because the order flow itself is not broken — the missing metadata only becomes a problem when querying, reporting, or displaying confirmation timing.

## Remediation

Add a nullable `confirmedAt` column to the orders table in `prisma/schema.prisma` and populate it during the confirmation transition in `lib/orders/state-machine.ts`.

```ts
// prisma/schema.prisma addition:
// confirmedAt DateTime?

// In transitionOrder (lib/orders/state-machine.ts):
const extraFields: Partial<Order> = {}
if (newStatus === 'confirmed') extraFields.confirmedAt = new Date()

await db.orders.update({
  where: { id: orderId },
  data: { status: newStatus, ...extraFields },
})
```

## Detection

- **ID:** `confirmation-record`
- **Severity:** `low`
- **What to look for:** When an order transitions to `confirmed` status, enumerate all data fields written alongside the status change. Look for additional data capture beyond just changing the status field: a `confirmedAt` timestamp column on the orders table, a dedicated confirmation record in a separate table, or a confirmation ID/code generated at confirmation time. Count the number of confirmation-specific fields written (minimum 1 required to pass). Check the order model schema in `prisma/schema.prisma` or equivalent and the confirmation transition handler.
- **Pass criteria:** When an order reaches confirmed status, at least 1 confirmation-specific field (a `confirmedAt` timestamp or equivalent confirmation metadata) is written to the order record or a related table. The confirmation timestamp exists separately from `updatedAt` so it can be queried and displayed independently. A handler that only writes `status: 'confirmed'` with no other metadata does not count as pass.
- **Fail criteria:** Order confirmation only changes the `status` field from `pending` to `confirmed` with no additional metadata captured (0 confirmation-specific fields). The only way to know when an order was confirmed is to infer it from history entries or `updatedAt`, which may have been overwritten by subsequent state changes.
- **Skip (N/A) when:** The project does not have a distinct confirmation step — for example, orders go directly from `pending` to `processing` via a payment webhook with no explicit confirmation state. No `confirmed` status value exists in the codebase.
- **Detail on fail:** `"Order status changes to 'confirmed' but no confirmedAt timestamp is captured. 0 confirmation-specific fields are written. The only record of when confirmation happened would be in the order_history table if it exists, or is lost entirely if it does not."`
- **Remediation:** Add a `confirmedAt` timestamp to your order model (in `prisma/schema.prisma`) and set it during the confirmation transition:

  ```ts
  // Add to your order schema (prisma/schema.prisma):
  // confirmedAt DateTime?

  // In transitionOrder or the confirmation handler (lib/orders/state-machine.ts):
  if (newStatus === 'confirmed') {
    await db.orders.update({
      where: { id: orderId },
      data: {
        status: 'confirmed',
        confirmedAt: new Date(),
        updatedAt: new Date(),
      },
    })
  }
  ```

  This makes it easy to display "Confirmed on [date]" in the customer order detail view and to run queries like "all orders confirmed in the past 7 days."

## External references

- cwe CWE-841
- iso-25010 functional-correctness

Taxons: data-integrity

HTML version: https://auditbuffet.com/patterns/ab-001136
