Records that are kept
Core module For: Administrator, Compliance manager Checked on 18.0.0.2.0
Which DSCSA records and files the core module keeps, for how long, what can still change on them, and what a user sees when trying to delete or change them. The rules apply to every user, the administrator included; nothing here is a setting.
Background: the modules follow the reading that DSCSA's record rule keeps transaction information and statements at least six years after the transaction (FD&C Act § 582, record-keeping provisions; see Compliance background), and they protect those records inside Odoo, with a legal hold and an off-site archive. The software describes its dates as a minimum and never deletes the records; your procedure decides how long your business keeps its records outside Odoo. For units a 3PL keeps for owners, see also 3PL records that are kept.
What is kept, and what can never be deleted or changed
Records
| Record | Kept | What can still change | Where to see it |
|---|---|---|---|
| DSCSA document (inbound and outbound), its lines and its transaction history | Never deleted. Keep At Least Until = transaction date + 6 years | After posting: only the chatter, the customer's link, the legal hold and the off-site archive fields. The hash chain proves it (Verify the integrity of the DSCSA documents) | Inventory ‣ Rx Tracking ‣ Documents, the Retention tab |
| Package (one per serialized unit) | Never deleted once received | Only the ledger's own operations (receipts, deliveries, returns, scrap, counts, quarantine) change its state and links | Inventory ‣ Rx Tracking ‣ Packages (Look up a unit in the package ledger) |
| Lot named in a posted document | Kept as a lot | The expiry date (logged); not the lot number or product (Correct a lot's number or expiry after documents were posted) | the lot form |
| Retention export and its two CSV files | Never changed or deleted | Only its off-site archive fields | Inventory ‣ Rx Tracking ‣ Retention Exports |
| Trace request, once responded, and its response zip | Never deleted; frozen after the response | Chatter and activities | Inventory ‣ Rx Tracking ‣ Trace Requests (Respond to a trace request with the response zip, and send it) |
| Done scrap's serials | Kept with the scrap | Nothing | the scrap's DSCSA Serials block (Scrap DSCSA units) |
| Verified license | Kept as verification evidence; archive it instead of deleting | Its licensed facts can't change (Renew, correct or retire a verified license) | Inventory ‣ Rx Tracking ‣ Licenses |
On a document, the Retention tab shows Keep At Least Until, the Legal Hold checkbox and, while the document is on hold, Hold Placed By, Hold Placed On and the reason (shown without a label, known issue PF-W10-03):

Files
These files can't be deleted, and their content, name and owner record can't change:
| File | Kept |
|---|---|
| Files of a DSCSA document (the frozen T3 PDF and EPCIS XML, and any file attached to it) | for good |
| The two CSV files of a retention export | for good |
| The response zip of a trace request | for good |
| The evidence of a verified license (its Evidence files and files in its chatter) | until the license's expiry date + 6 years (Keep Evidence Until on the license), or for as long as the license has no expiry date |
The evidence files of an unverified license are ordinary files. Odoo's automatic clean-up of unused files never removes the kept files. Harmless changes (a file's description) are still allowed. Only uninstalling the module removes the protection.
What a user sees
Deleting a kept file (for example with Remove on the chatter's file list, then Ok) shows an Invalid Operation dialog that names each file and why it is kept:
These files are DSCSA records that must be kept; they can't be deleted:
- T3-DSCSA-OUT-2026-00004.pdf: attached to DSCSA Transaction Document DSCSA/OUT/2026/00004
The reason line can also read "frozen file of DSCSA document DOCUMENT-NUMBER", "response to DSCSA trace request REQUEST-NUMBER" or "verification evidence of license LICENSE, kept until DATE" (or "kept for as long as the license has no expiry date"). Changing a kept file starts with "These files are DSCSA records that must be kept; their content, name and owner can't change:". Removing evidence from a verified license's Evidence field reads "FILE can't be removed from LICENSE: verification evidence of a verified license is kept (until DATE)."
The forms and lists of documents, packages and retention exports have no Delete and no Edit for kept fields. An import or an integration that tries is refused with one of these messages:
| Record | Message |
|---|---|
| DSCSA document | "DSCSA documents are records the law requires us to keep; they can't be deleted." / "DSCSA document DOCUMENT-NUMBER is posted and can't be changed (fields: FIELDS)." |
| Document lines | "The lines of a posted DSCSA document can't be changed." / "The lines of a posted DSCSA document can't be deleted." |
| Transaction history | "The transaction history of posted DSCSA document DOCUMENT-NUMBER can't be changed." / "DSCSA document DOCUMENT-NUMBER is posted: its transaction history can't be changed." |
| Retention export | "Retention exports are records that must be kept; they can't be changed (fields: FIELDS)." / "Retention exports are records that must be kept; they can't be deleted." |
| Package | "Package SERIAL is part of the DSCSA record and cannot be deleted." and the ledger messages in Error: "DSCSA packages change only through the package ledger's own operations" |
(The first message is the product's own wording, quoted as it appears.) What to do: see Error: "These files are DSCSA records that must be kept …" and Error: "… can't be changed" or "… can't be deleted" on a kept record.
The document manifest in the off-site archive
With the off-site archive on, each posted document's folder in the bucket holds its files and one JSON manifest, NUMBER.manifest.json
(the document number with each / replaced by -). The manifest ties the files to the document and carries what is needed to check the
hash chain without Odoo: Get a record back from the off-site archive and check it. It is written
once, when the document is queued, and never changes. Its fields, with the values of DSCSA/OUT/2026/00002 on the example database:
| Field | What it holds | Example |
|---|---|---|
format, format_version | what kind of file this is, and its layout version | aglow_rx_tracking/dscsa-archive-manifest, 1 |
database_uuid | the Odoo database that wrote it (Odoo's database.uuid system parameter) | b3eb0f44-… |
company.id, company.name, company.gln | the company whose document it is, and its Global Location Number (GLN) | 1, Demo Rx Distribution LLC, 0614141000012 |
document.number | the document number | DSCSA/OUT/2026/00002 |
document.direction | outbound (sent) or inbound (received) | outbound |
document.document_date, document.transaction_date | the document's Document Date and Transaction Date | 2026-09-28 |
document.posted_on | when it was posted, in UTC (the form shows your time zone) | 2026-09-28 12:28:02 |
document.chain_index | its Chain Position in the company's hash chain (inbound and outbound share one chain) | 8 |
document.previous_hash | the Hash of the document at the position before; empty for the first | $1$f1c9e50b… |
document.hash | the document's Hash | $1$efd60579… |
document.hash_rule | how the hash is computed, in words: hash = '$1$' + hex(sha256(previous_hash + hash_payload)) | |
document.hash_payload | the exact text that was hashed: compact JSON (sorted keys, ASCII, no spaces) of the number, direction, company ID, chain position, the frozen document data (seller, buyer, lines, Transaction Statement, history) and each file's SHA-256 | {"chain_index":8,"company_id":1,…} |
files[] | one entry per archived file: name (the file name in Odoo), key (its S3 key), sha256, size (bytes) and mimetype | T3-DSCSA-OUT-2026-00002.pdf, 2f3f0830…, 1170457, application/pdf |
object_lock.mode, object_lock.retain_until | the lock of the objects: COMPLIANCE (GOVERNANCE for a test-mode upload) and the retention date, in UTC | COMPLIANCE, 2032-09-29T12:00:00Z |
The sha256 of each file must also appear under files inside hash_payload, which the hash covers. The manifest itself has no manifest:
its SHA-256 is on its archive job (SHA-256) and in the object's metadata (dscsa-sha256), like every archived object's. A retention
export has no manifest; its files' SHA-256 are on the export's form.
Related procedures
- Place a legal hold on DSCSA documents
- Get the monthly retention export, or export on demand
- Verify the integrity of the DSCSA documents
- Set up the off-site archive: a write-once copy outside Odoo
- Get a record back from the off-site archive and check it