Compliance → Licenses
Purpose
Track every license your clinic and its prescribers must hold to handle controlled substances — DEA registrations, state pharmacy permits, state veterinary licenses, technician registrations. CS Logbook surfaces them in two scopes: facility licenses (the clinic's own DEA registration, state pharmacy permit) and individual licenses (each DVM's personal DEA practitioner registration, state veterinary license).
This is general product information about CS Logbook, not legal advice. CS Logbook tracks the licenses you record; it does not issue, validate, or define which licenses are required. Verify current registration and licensing requirements with the DEA Diversion Control Division and your state veterinary/pharmacy board.
Where the requirement lives: DEA registration rules are in 21 CFR Part 1301 (covering registration and modification of registration); state licensing is governed by your state veterinary and pharmacy boards (varies by state).
When to use it
- Initial setup: enter every license held by the clinic and every prescriber at onboarding
- License renewal: when a license is renewed by the issuing authority, record the renewal so the new expiration date drives the alerts
- License retired: when a prescriber leaves the clinic or a license type is no longer applicable, soft-delete the license (the audit trail is preserved)
- Audit prep: a DEA inspector will ask for the registration certificate first; CS Logbook gives you a one-page rollup of every active license
Walkthrough
Step 1 — Open the licenses page
Navigate to /home/<your-clinic>/compliance/licenses. Three tabs:
- Facility Licenses — the clinic's own registrations
- Clinic Member Licenses — individual DVM/staff licenses (visible to the clinic but stored in each user's personal account)
- Expiring — combined view of any license expiring within 90 days, sorted by urgency

Step 2 — Add a license
Click Add License in the top-right (only visible to users with canManageCompliance — owners/admins/managers). You're taken to the New License page (/compliance/licenses/new).
The form has 6 fields. Required: license type, license scope, license number, issuing authority, issue date, expiration date, status. The status defaults to active.

License scope determines where the license is stored:
- Facility: stored on the clinic account; visible to all clinic members on the Facility Licenses tab
- Individual (DVM): stored on YOUR personal account; visible to you on the clinic's Clinic Member Licenses tab (the clinic can see it for compliance tracking)
⚠️ When you pick scope = individual while operating in a clinic workspace, the license is created on your personal account, not the clinic's. This is by design — your DEA practitioner license is yours, not the clinic's.
Click Add License. The new row appears on the appropriate tab.

Step 3 — Renew a license
When the issuing authority renews a license, click Actions → Renew License on the row. You're taken to the Renew License page (/compliance/licenses/<id>/renew) with the current license info displayed and a form for new dates + (optional) new license number (ADR-020 moved renew off the in-table dialog onto a full-page route).

Submit. Two things happen atomically:
- The
licensesrow is updated in place —issue_date,expiration_date,status='active',last_renewal_date=today. License number is updated only if you provided a different value. - A new row is inserted into
license_renewal_historycapturing the previous expiration → new expiration delta with the user who processed the renewal.
The renewal history is browsable via Actions → Renewal History on any row.
Step 4 — View license details
Click Actions → View Details to see the full license record including renewal frequency, document URL (if attached), and alert thresholds.
Step 5 — Soft-delete a license
Click Actions → Delete. The confirmation dialog explains this is a soft delete — the record is marked deleted (deleted_at set) but preserved in the audit trail. An administrator can restore it if needed.
Field reference
License form
| Field | Label | Type | Required | Validation |
|---|---|---|---|---|
licenseType |
License Type | select | ✓ | enum: dea_registration, state_pharmacy_permit, state_facility_license, dea_practitioner, state_veterinary, state_cs_registration, state_tech_registration |
licenseScope |
License Scope | select | ✓ | enum: facility, individual |
licenseNumber |
License Number | text | ✓ | 1-100 chars |
issuingAuthority |
Issuing Authority | text | ✓ | 1-255 chars (e.g., "DEA", "California Veterinary Medical Board") |
issueDate |
Issue Date | date | ✓ | YYYY-MM-DD |
expirationDate |
Expiration Date | date | ✓ | YYYY-MM-DD; must be after issue date |
status |
Status | select | optional | enum: active, pending_renewal, expired, suspended, revoked; default active |
state |
State | text | optional | 2-letter US state code (NULL for federal DEA) |
Hidden fields auto-populated by the action: account_id, created_by, created_at, updated_at, alert_thresholds (default [90, 60, 30, 14, 7] days), renewal_requirements (state-specific JSON), deleted_at (NULL until soft-delete).
Edge cases
License scope must match account type
If you try to create a facility license while operating in a personal account context, or an individual license against a clinic account, the action's validate_license_scope_trigger throws an error. The form's scope select forces a deliberate choice; the trigger is a defensive backstop.
Unique constraint on (account, type, state, number)
The licenses table has a unique constraint on (account_id, license_type, state, license_number). Attempting to add a duplicate license (same type + state + number for the same account) returns an error. Use the renewal flow instead — it preserves the same row.
Soft-delete preserves audit trail
A deleted license is still queryable for audit purposes (deleted_at IS NOT NULL). An admin or DEA inspector reviewing the records can see every license that was ever held, including the deletion timestamp. Hard delete is blocked at the database level (licenses_delete_blocked policy uses USING(false)).
Expiration alerts auto-fire
Each license has an alert_thresholds JSONB column with default [90, 60, 30, 14, 7] (days before expiration). Compliance alerts auto-generate at each threshold. The expiration alerts surface on the Expiring tab and on the Alerts page.
Common mistakes
- Recording a renewed license as a new license. When a license is renewed, use Actions → Renew License on the existing row — don't add a new row. Adding a new row creates a phantom "old" license in your records.
- Forgetting individual licenses. Each prescribing DVM needs their own DEA practitioner license recorded. Without it, the dispense flow's prescriber-filter dropdown won't surface them as eligible prescribers per DEA rules.
- Wrong issuing authority spelling. Inspectors notice. Use the canonical name: "Drug Enforcement Administration" or "DEA" for federal; the full state board name (e.g., "California Veterinary Medical Board") for state.
- Using "Other" license type without a comment. The license types enum covers most cases. If you have a license that doesn't fit, document it in the issuing authority field with a clarifying note.
Related
- Compliance → Alerts — license expiration alerts surface here
- Audits → DEA Audit Prep — license verification is the first checklist category
- Glossary § DEA Schedule classifications
- Glossary § DEA CFR citations