# History/audit tracking

- **Pattern:** `ab-000552` (`booking-flow-lifecycle.lifecycle.history-tracking`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000552
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000552)

## Why it matters

Without a history table or audit log, a booking system cannot answer the most basic support questions: "who cancelled my appointment?", "when was this booking confirmed?", or "was the reschedule requested by the customer or the provider?". ISO 25010:2011 maintainability requires that state changes are traceable. In regulated contexts (medical scheduling, legal appointments, financial services), audit trails are legally required. Even in unregulated systems, the inability to reconstruct booking history turns routine customer disputes into unresolvable conflicts and forces manual database forensics for every support ticket.

## Severity rationale

Info because audit logging improves operational visibility and dispute resolution but does not directly cause data corruption or security exposure when absent.

## Remediation

Create a `BookingLog` table and write a transition record on every status change. Add the model in `prisma/schema.prisma` and call the log function from your booking service.

```typescript
// schema.prisma
model BookingLog {
  id          String   @id @default(cuid())
  bookingId   String
  fromStatus  String
  toStatus    String
  actorId     String
  createdAt   DateTime @default(now())
}

// booking-service.ts — call on every transition
async function logTransition(bookingId: string, from: string, to: string, actorId: string) {
  await db.bookingLog.create({
    data: { bookingId, fromStatus: from, toStatus: to, actorId }
  });
}
```

## Detection

- **ID:** `history-tracking`
- **Label:** History/audit tracking
- **Severity:** `info`
- **What to look for:** A separate table (e.g., `BookingLog`, `BookingHistory`, `AuditLog`, or embedded `history` JSON field) that records status changes with timestamps and actor information. Count all status transition points in the codebase (create, confirm, cancel, reschedule, fail) and verify each one creates a history/log record. Enumerate: "X of Y status transitions are logged with actor and timestamp."
- **Pass criteria:** Code records who changed what and when for each status transition. History entries must survive application restarts (stored in database, not just console.log or in-memory). At least 3 fields must be logged per transition: booking ID, new status, and timestamp. Actor ID (who made the change) is strongly recommended. Report: `"X of Y status transitions logged in [table/model]. Fields: [list]."`
- **Fail criteria:** Only current state is stored; no history of previous states or who made changes. Console-only logging does not count.
- **Skip (N/A) when:** Simple MVP with no audit requirements and fewer than 3 status transitions in the entire booking flow.
- **Detail on fail:** `"No audit logging found. It is impossible to debug 'who cancelled my appointment' disputes or track modification history."`
- **Cross-reference:** The cancellation-state-machine check in this category verifies the cancellation transition that should be logged.
- **Cross-reference:** The initial-booking-state check in Booking Creation verifies the initial status that is the first entry in the history.
- **Cross-reference:** The deadline-enforcement check in this category verifies time-based restrictions that should also be logged when enforced.
- **Remediation:** Create a history table and log each transition. Add the model in your schema (e.g., `prisma/schema.prisma`) and log calls in your booking service.

  ```typescript
  async function logBookingChange(
    bookingId: string,
    fromStatus: string,
    toStatus: string,
    actorId: string
  ) {
    await db.bookingLog.create({
      data: {
        bookingId,
        fromStatus,
        toStatus,
        actorId,
        timestamp: new Date(),
      }
    });
  }

  // Called on every transition
  await logBookingChange(bookingId, 'PENDING', 'CONFIRMED', userId);
  ```

## External references

- iso-25010 security.accountability

Taxons: observability

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