Audits → Discrepancies & Corrective Actions
Purpose
Track every unresolved audit finding through to documented resolution. The Discrepancies queue is the unified registry where corrective action plans (CAPAs) from internal audits and theft/loss filings come together, with assignments, due dates and verification status. Spot checks are not a source: a spot-check discrepancy is investigated and resolved on the count record itself.
This is general product information about CS Logbook, not legal advice. The discrepancies queue is a tracking aid; it does not define remediation obligations. Verify current requirements with the DEA Diversion Control Division and your state veterinary/pharmacy board.
Regulatory basis: tracking discrepancies to resolution supports keeping records complete, accurate, and current (DEA recordkeeping rules), an inspector reading "found a variance, no action recorded" sees a clinic that detected a problem but didn't document a fix. Some state boards may require remediation tracking, confirm your state's rules. (SOC 2 Trust Services Criterion CC4, Monitoring, also calls for evidence that detected issues are addressed.)
When to use it
- An audit found something: the conduct flow auto-creates CAPAs for items flagged
requires_corrective_action. Land in the queue, assign, work through resolution. - A biennial flagged a variance: file an ad-hoc CAPA from the biennial detail page.
- A theft/loss incident resolved with corrective action required: the incident's resolution flow optionally creates a CAPA.
- Manager-level reassignment: the queue surfaces every CAPA across all audit sources; managers reassign overdue items, monitor verification cadence, escalate to owner.
The discrepancies queue is the single source of truth for "what's still open." A CAPA isn't done until it's verified: not just completed. Verification is the closing-the-loop step that distinguishes "we wrote it down" from "we actually fixed it."
Walkthrough
The discrepancies queue is a single page that aggregates CAPAs across audit types:
/audits/discrepancies → unified queue of corrective_actions linked to any auditStep 1: Open the discrepancies queue
Navigate to /home/<your-clinic>/audits/discrepancies. The page lists every audit_corrective_actions row for your account.
If the queue is empty, the page renders the empty state: "No open discrepancies: There are currently no unresolved audit discrepancies or corrective actions." An empty queue means nothing is open; it does not establish regulatory compliance
Screenshot of the discrepancies queue (populated + empty state) coming in a 15d-2 follow-up: this guide ships ahead of the queue's data-test instrumentation work.
Step 2: Read the queue
Each row surfaces:
- Title: the CAPA's short label (e.g., "Investigate 5.2% variance in Hydromorphone CTR-2026-HYD-003")
- Category: what kind of finding (e.g., "Inventory", "Security", "Record-keeping")
- Severity:
low/medium/high/critical - Source audit: clickable link back to the audit that created the CAPA
- Assigned to: staff member responsible
- Due date: soft deadline; overdue rows are flagged
- Status:
open/in_progress/completed/verified - Created at: when the CAPA was filed
The queue defaults to ordering by status ASC, severity DESC, due_date ASC: open critical items at the top, verified items at the bottom.
Step 3: Open a CAPA detail
Click a row to view the CAPA detail. The detail page shows the full CAPA record + a chronological log of status transitions (when it moved from open to in_progress, when completion notes were added, when verification happened).
The detail also shows the immutable-linkage fields: these were set at CAPA creation and cannot be changed after the source audit is finalized:
audit_id: which audit raised this finding (FK)title: the original short labeldescription: the original problem statementcategory: the original categoryseverity: the original severity assessmentassigned_by: who created the CAPAassigned_date: when the CAPA was createdcreated_at: DB-managed timestamp
The Sprint B audits-finalize-lock migration (2026-05-06) added a prevent_finalized_capa_rewrite BEFORE UPDATE trigger that enforces this. Once the source audit is finalized, the CAPA's "what was originally found" is immutable; only the lifecycle fields can change.
Step 4: Work the CAPA through its lifecycle
The CAPA passes through 4 statuses:
| Status | Meaning | Who transitions |
|---|---|---|
open |
Filed, not yet started | Auto on creation |
in_progress |
Work underway | Anyone with audits.conduct |
completed |
Remediation done; awaiting verification | The assignee |
verified |
Verifier confirmed remediation is effective; CAPA closed | A user who is not the assignee (separation-of-duty) |
Lifecycle fields editable post-creation:
status: transitions through the 4 stagesassigned_to: reassign as neededdue_date: extend if scope is broader than initially expectedexpected_completion_date: your target completion (vs. soft due_date)completion_*: completion notes + completion date + completion userverification_*: verification notes + verification date + verification userbefore_photos/after_photos: photo URL arrays for visual evidencesupporting_documents: URLs of any supporting files
When the assignee marks the CAPA completed, fill:
- Completion notes: what was done, what changed, what's now in place that wasn't before
- After photos: if applicable, the visual evidence of remediation (e.g., new lock installed, repaired storage cabinet)
Step 5: Verify (separation-of-duty)
When the CAPA is completed, a different user (not the assignee) reviews the remediation and either:
- Verifies: fills
verification_notes(what was checked, what was found), setsstatus='verified', setsverification_dateandverification_by - Rejects back to
in_progress: if the remediation was incomplete or ineffective; documents why in verification notes; the assignee picks it back up
Verification by a different user is the SOC 2 / state-board principle: the person who did the work shouldn't be the person who confirms it was done. CS Logbook does NOT enforce this at the DB layer (the verification_by column accepts any user); the soft-warning prompt at verification time is the only guardrail. Verifying your own CAPA is a process flag, not a hard block.
Step 6: Close-out review
After verification, the CAPA stays in the queue (filtered by status) but no longer blocks compliance review. The audit trail is preserved per DEA record-retention rules. If the verification was rejected (returning to in_progress), the prior verification attempt is preserved as a status-log entry.
Field reference
CAPA core fields (immutable after source audit is finalized)
| Field | Description |
|---|---|
audit_id |
UUID FK to source audit (any audit type) |
title |
Short label, max 255 |
description |
Problem statement |
category |
Category label (Inventory / Security / Record-keeping / Quality / Other) |
severity |
low / medium / high / critical |
assigned_by |
UUID of user who created the CAPA |
assigned_date |
When the CAPA was filed (ISO date) |
Lifecycle fields (mutable post-creation, even after audit finalization)
| Field | Description |
|---|---|
status |
open / in_progress / completed / verified |
assigned_to |
UUID of currently-responsible user |
due_date |
Soft deadline (ISO date) |
expected_completion_date |
Target completion (ISO date) |
completion_notes |
What was done |
completion_date |
When marked completed |
completion_by |
UUID of user who marked complete |
verification_notes |
What was verified |
verification_date |
When marked verified |
verification_by |
UUID of verifier |
before_photos |
Array of URLs |
after_photos |
Array of URLs |
supporting_documents |
Array of URLs |
Resulting database rows
| Table | Lifecycle |
|---|---|
audit_corrective_actions |
Created at audit submit (auto, when requires_corrective_action=true on a checklist item) OR ad-hoc from biennial/theft-loss detail pages. A spot check does not create one: investigate the discrepancy and record whether it is resolved |
| Same | Updated through status transitions; immutable-linkage fields locked once source audit finalized |
Edge cases
CAPA created from a non-audit source
The discrepancies queue surfaces CAPAs from audit_corrective_actions where audit_id is set to one of the audit types. Some clinics may want to create ad-hoc CAPAs without a source audit; this is not currently supported: a CAPA must link back to a source audit (internal audit / theft-loss prep). For follow-up work without an audit context, create an alert on the Alerts page under Compliance.
Soft warning: severe CAPA past due
If a CAPA is severity='high' or severity='critical' AND due_date < now() AND status IN ('open', 'in_progress'), the queue row is flagged red with an overdue badge. There is no hard block; the user can leave it overdue. The visibility prompts immediate attention.
Self-verification
CS Logbook does not block a user from verifying their own CAPA. The audit trail records both completion_by and verification_by columns separately, so an inspector can detect self-verification by inspecting the row. State boards may treat this as a process violation: train your team that verification is a different user.
CAPA verification reversal
A verified CAPA cannot be moved back to completed or in_progress directly via the UI, because verification is treated as a closing transition. If the verification was incorrect (the remediation didn't actually work), the right pattern is a new CAPA referencing the original (for example, "Revisit verification of CAPA #42, remediation insufficient on re-inspection"). This preserves the audit trail per DEA record-retention rules.
Source audit deleted / cancelled
If the source audit is cancelled (rare but allowed), linked CAPAs remain in the queue and remain workable: the cancellation reason is recorded on the audit, not propagated to CAPAs. If the source audit is hard-deleted (forbidden in normal use; would require a service-role DB operation), the CAPA's audit_id FK reference may break. Do not hard-delete audits.
Hard block: rewriting linkage on a finalized audit's CAPA
Once the source audit is finalized (finalized_at IS NOT NULL), the prevent_finalized_capa_rewrite BEFORE UPDATE trigger blocks any UPDATE that touches audit_id / title / description / category / severity / assigned_by / assigned_date / created_at. The DB raises P0001. UI inputs for these fields are disabled when the source audit is finalized; the trigger is the defense-in-depth.
Common mistakes
- Marking CAPAs
completedwithout filling completion notes. The completion notes ARE the audit trail. "Done" with no detail is the same as "we lost the receipt." - Self-verifying. The verifier should be someone other than the assignee. Process the separation explicitly.
- Letting CAPAs sit at
completedwithoutverified.Verifiedis the closing step;completedwithoutverifiedis a CAPA in limbo. Track verification cadence; managers should review the queue weekly. - Editing immutable fields. The
prevent_finalized_capa_rewritetrigger blocks DB-layer; the UI disables the inputs. If you find yourself wanting to edit a finalized CAPA's title or description, the right pattern is to file a new CAPA referencing the original. - Not using before/after photos when applicable. A CAPA about a broken safe latch is harder to verify without a photo of the new latch in place. Use photos for physical-remediation CAPAs.
- Treating CAPAs as informational. The queue is a working surface. Owners + managers should review weekly; assignees should work to close. A queue with 30 open CAPAs older than 90 days is a clinic with a compliance posture problem.
- Hard-deleting audits. There is no UI path; doing it via service-role DB operations breaks the linkage to CAPAs. Don't. Soft-delete is the supported retraction pattern.
Related
- Audits, overview, the audit lifecycle and where CAPAs originate
- Biennial inventory: variance findings that auto-flag for ad-hoc CAPA creation
- Spot check: investigate a counted variance, and record whether it is resolved
- Theft/loss reporting: incident resolution can flag corrective action required
- DEA audit prep: post-visit findings flow through this queue
- Sprint 17 internal audit feature plan: the CAPA model is shared across audit types per the architecture doc
- ADR-006 enforcement philosophy: soft warnings vs hard blocks; the immutable-linkage trigger is one of the few hard blocks