History/audit tracking
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.
// 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 embeddedhistoryJSON 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);
External references
- iso-25010:2011 · security.accountability — Accountability — booking status transitions traced to actor and timestamp
Taxons
History
- 2026-04-18·v1.0.0·Initial import from booking-flow-lifecycle·automated