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.
Info because audit logging improves operational visibility and dispute resolution but does not directly cause data corruption or security exposure when absent.
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.
// 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 }
});
}
ID: booking-flow-lifecycle.lifecycle.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.
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);