Search all 478 artefacts by title, document ID or content.
Printed on the standard letterhead. Page furniture, margins and repeating table headers come from the same stylesheet the PDF service uses.
Pensieve Labs
The operating system for hospitals
DIS-GL-401
v1.0.0 | 31 July 2026
DIS-GL-401 | Version 1.0.0 | Last Modified On 31 July 2026
The engineer at the hospital's next vendor, six months from now, who has been handed an export and told to load it. Not a procurement officer, not a lawyer.
Everything here is stated at the level that person needs: directory layout, file naming, encodings, column conventions, join keys, null semantics, cardinality, and what to do when something does not fit. A vendor should be able to scope a migration from this document before Pensieve is ever contacted, which is the entire point of publishing it.
WPR-GL-400 is the promise. This is the proof that the promise is specific enough to be kept.
| Deployment model | How the export is produced |
|---|---|
DM-1 Dedicated |
Pensieve generates the package from the dedicated project and delivers it |
DM-2 Shared |
Pensieve generates the package scoped to the tenant, with a documented cross-tenant leakage check |
DM-3 Customer Cloud |
Pensieve generates the package inside the hospital's own project and leaves it there |
DM-4 On-Premise |
The hospital runs the export tooling against its own instance; Pensieve supplies the tooling, the operator guide and attendance. The package layout and formats are identical |
The package is byte-for-byte the same shape in all four models. Where a section below is model-dependent it says so.
1.1 Nothing proprietary. Every format in this document is either an open standard with a published
specification, or plain delimited text. Nothing requires a Pensieve licence, a
Pensieve library, or a call to Edsol Edtech Pvt. Ltd. to read.
1.2 Three redundant representations of the same clinical fact. Every clinical record appears (a) in the relational export, (b) as a FHIR resource where the record is representable as one, and (c) inside a rendered PDF of its encounter. A migration that fails on (a) and (b) still leaves the hospital lawful, because (c) needs no software at all.
1.3 Referential integrity is preserved, not flattened. Internal identifiers are exported as they are, joins are documented, and no relationship is silently collapsed into a denormalised blob.
1.4 Everything is countable. Every table has a row count in the manifest. Every file has a size and a SHA-256. Completeness is verifiable arithmetic, not a claim.
1.5 Self-describing. The package carries its own data dictionary, its own entity-relationship description and its own load guide. Reading the export does not require reading this document. This document exists so the reader can plan before the export arrives.
1.6 Additive versioning. The package format is versioned. Within a major version, columns are added and
never removed or retyped, and a new file may appear but an existing file does not change meaning. The
version is stamped in manifest/package.json.
A single root directory named pensieve-export_<tenant>_<ISO8601-UTC-timestamp>_v<package-version>.
pensieve-export_<tenant>_20260731T041500Z_v1/
├── README.md Start here. Human-readable, 2 pages
├── manifest/
│ ├── package.json Package version, tenant, extraction window, model, counts
│ ├── files.csv Every file: path, bytes, sha256, class, part-of
│ ├── record-counts.csv Every entity: name, rows in export, rows in source, delta
│ ├── checksums.sha256 GNU coreutils format, for `sha256sum -c`
│ └── extraction-log.ndjson What ran, when, how long, and any warning raised
├── docs/
│ ├── data-dictionary.md Every table, every column, type, nullability, meaning
│ ├── data-dictionary.csv The same content, machine-readable
│ ├── entity-relationships.md ER description + Mermaid diagram + join key list
│ ├── load-guide.md Step-by-step load into PostgreSQL, with DDL
│ ├── fhir-profile-statement.md Resources, profiles, extensions, and what is not FHIR
│ ├── code-systems.md Every code system and version used
│ ├── integration-inventory.md Third-party systems, direction, payloads, credential shape
│ ├── known-limitations.md What is imperfect in THIS export, named
│ └── ddl/
│ ├── postgresql.sql CREATE TABLE for every relational file
│ └── types.csv Logical type → PostgreSQL, MySQL, SQL Server, Parquet
├── relational/
│ ├── csv/<schema>/<table>.csv RFC 4180, UTF-8, header row
│ └── parquet/<schema>/<table>.parquet
├── fhir/
│ ├── <ResourceType>/<ResourceType>-<nnnn>.ndjson
│ └── _index/ Patient→resource index, and a FHIR Bundle sample
├── imaging/
│ ├── DICOMDIR
│ └── <PatientKey>/<StudyUID>/<SeriesUID>/<SOPInstanceUID>.dcm
├── documents/
│ ├── index.csv Every file → patient, encounter, type, author, date
│ └── files/<yyyy>/<mm>/<doc_id>.<ext>
├── rendered/
│ ├── index.csv Every PDF → patient, encounter, date range
│ └── <PatientKey>/<EncounterKey>.pdf
├── configuration/
│ ├── <domain>.json Masters, tariffs, formulary, org, roles, forms, workflows
│ └── applications/<app_id>/ Customer Application definitions
├── audit/
│ └── <yyyy-mm>/audit-<yyyy-mm-dd>.ndjson
├── registers/
│ └── <register-name>/ Statutory registers in their statutory shape
└── database-dump/ Optional, on election; see Section 8
├── pensieve_<tenant>.dump PostgreSQL custom format
└── restore-guide.md
2.1 Path rules. POSIX separators. Lower-case ASCII directory names except where a standard mandates
otherwise (DICOMDIR, FHIR resource type directories, which use FHIR's own PascalCase). No spaces, no
characters outside [A-Za-z0-9._-] in any generated file name. Maximum path length 200 characters, so the
package survives extraction on Windows without a long-path setting.
2.2 Compression. Each top-level directory is delivered as a separate .tar.zst archive plus its own
checksum file, so a hospital can transfer, verify and load one class at a time. Uncompressed delivery is
available on request. zstd was chosen over gzip for speed on imaging volumes and over 7z because it
is available in every mainstream distribution's package manager.
2.3 Encryption in transit and at rest on media. Archives are encrypted with AES-256 using an
age/openssl enc-compatible envelope where the delivery method is physical media or a third-party
destination. The passphrase or recipient key is exchanged on a separate channel from the media. Electronic
delivery over TLS to a hospital-owned destination is not additionally encrypted at the file layer unless
the hospital asks.
These apply to every text-based file in the package. A loader written against this section works on every
file in relational/csv, documents/index.csv, rendered/index.csv and the manifest.
| Convention | Rule |
|---|---|
| Encoding | UTF-8, no byte-order mark. Devanagari and other Indic scripts are stored and exported as-is. Names are not transliterated, folded or stripped |
| Collation | Sort order in files is by primary key ascending, byte-wise on the UTF-8 representation. Do not assume a locale collation |
| Delimiter | Comma. RFC 4180 quoting: fields containing a comma, a double quote or a line break are enclosed in double quotes; an embedded double quote is doubled |
| Line ending | LF (0x0A). Embedded line breaks inside a quoted field are preserved as they were stored |
| Header | Row 1 is the header. Column names are lower_snake_case, stable within a major package version |
| Null | An empty, unquoted field. A quoted empty string "" is a genuine empty string. This distinction is preserved and it matters for clinical free text |
| Booleans | true / false, lower case. Never 1/0, Y/N, t/f |
| Integers | No thousands separators, no currency symbol, optional leading - |
| Decimals | . as the decimal point. Scale is fixed per column and stated in the data dictionary |
| Money | Two fields per amount: <name>_amount as a decimal with the scale in the dictionary, and <name>_currency as an ISO 4217 alphabetic code. Money is never exported as a formatted string and never carries a symbol |
| Dates | ISO 8601 YYYY-MM-DD |
| Timestamps | ISO 8601 with an explicit offset, always UTC: YYYY-MM-DDThh:mm:ss.sssZ. The tenant's civil time zone is in manifest/package.json as an IANA name so local times can be reconstructed |
| Durations | ISO 8601 duration (PT30M) |
| Identifiers | Exported exactly as stored. Treat every identifier as an opaque string, never as a number, even where it looks numeric. Leading zeros are significant |
| Enumerations | The stored code, plus a _display sibling column carrying the label at export time. Load against the code, display the label |
| Free text | Preserved verbatim, including line breaks and clinical shorthand. Not sanitised, not HTML-escaped, not truncated |
| Binary | Never inline in CSV. Referenced by a path into documents/files/ |
| File splitting | Any file above 2 GiB is split into <name>.part0001.csv, <name>.part0002.csv, … Every part repeats the header row. manifest/files.csv records the part_of group and the part ordinal |
3.1 Soft deletes. Rows deleted in the Platform are exported with is_deleted = true, deleted_at and
deleted_by populated, unless the hospital's own retention configuration purged them before the export.
A loader that wants only live data filters is_deleted = false. Clinical amendments are never physical
updates: the superseded value is retained and exported as its own row with superseded_by set, because
Indian medico-legal practice requires that corrections be visible rather than overwritten.
3.2 Audit columns. Every relational table carries created_at, created_by, updated_at,
updated_by, is_deleted, deleted_at, deleted_by, row_version. They are documented once here and
not repeated for every table in the dictionary.
3.3 Tenant column. Every table carries tenant_id. In a single-tenant export it is constant. It is
exported anyway, so that a loader can assert it.
Location: relational/csv/<schema>/<table>.csv and relational/parquet/<schema>/<table>.parquet.
4.1 Two formats, same data. CSV is the reference representation: universally loadable, diff-able, inspectable in any tool. Parquet is provided for the large tables: observations, audit, financial ledger, imaging metadata, where CSV is slow and type-lossy. The CSV is authoritative. Where they disagree, the CSV is right and it is a defect Pensieve corrects at no charge.
4.2 Schemas. Tables are grouped into schema directories. The grouping is the Platform's own domain model, and it is what the data dictionary is organised by.
| Schema | Contains |
|---|---|
identity |
Patients, patient identifiers, contacts, relationships, consent records, ABHA linkage where the hospital enabled it |
clinical |
Encounters, admissions, transfers, discharges, diagnoses, problems, allergies, procedures, clinical notes, vitals, assessments, care plans |
orders |
Orders, order sets, order status history, specimens, results, panels, report authorisation |
medication |
Prescriptions, medication orders, administrations, dispensings, formulary linkage, schedule classification |
imaging |
Studies, series, instances, modality worklist entries, radiology reports, and the join to imaging/ |
theatre |
Operation theatre bookings, procedure records, implant logs, anaesthesia records |
nursing |
Assessments, observations, intake-output, wound care, handover notes |
scheduling |
Appointments, slots, resources, queues, waitlists |
billing |
Invoices, invoice lines, tariffs, packages, payers, estimates, receipts, refunds, credit notes, write-offs |
claims |
Insurance and scheme claims, pre-authorisations, TPA correspondence, claim status history |
inventory |
Items, batches, expiry, stock movements, indents, issues, returns, consumption against encounter |
procurement |
Vendors, purchase orders, goods receipts, invoices, payments |
hr |
Staff, roles, credentials, rosters, attendance, leave |
quality |
Indicators, incidents, audits, committee records, accreditation evidence |
admin |
Organisational structure, departments, wards, beds, locations, users, permission grants |
platform |
Configuration versions, workflow instances, notification history, document templates |
4.3 The join model. Every table exposes a surrogate primary key <table>_id. Foreign keys are
<referenced_table>_id. Composite keys are documented in docs/entity-relationships.md and are never
implicit. patient_id and encounter_key are the two joins that matter and every clinical, billing and
document row carries at least one of them.
4.4 The patient key. patient_id is the Platform's internal surrogate. The hospital's own medical
record number is a separate column, mrn, in identity.patient_identifier, along with every other
identifier the hospital recorded: Aadhaar reference where captured, ABHA address, scheme identifiers,
passport for international patients. Identifiers are exported in the identity.patient_identifier table
with a system column, never as ad-hoc columns on the patient row, because a hospital typically has more
identifier types than any fixed schema anticipates.
4.5 Cardinality and orphans. The extraction takes a consistent snapshot at a single logical point in
time, so no exported foreign key points at a row that is missing from the package. If the extraction cannot
achieve a consistent snapshot for a domain, that fact is recorded in docs/known-limitations.md and in
manifest/extraction-log.ndjson, with the affected tables named. Silence about a known inconsistency is
not acceptable; naming it is.
4.6 Empty tables. A table with zero rows is still exported, as a header-only file, so a loader can
distinguish "no data" from "not delivered". manifest/record-counts.csv shows 0.
4.7 Parquet specifics. Parquet v2, ZSTD compression, one row group per 128 MiB. Logical types:
TIMESTAMP(isAdjustedToUTC=true, unit=MILLIS), DECIMAL(p,s) for money, STRING for identifiers,
BOOLEAN, DATE. Nullability matches the CSV null semantics at Section 3. Column names identical to the CSV
header.
Location: fhir/<ResourceType>/<ResourceType>-<nnnn>.ndjson
5.1 Version and shape. HL7 FHIR R4 (4.0.1). One resource per line, newline-delimited JSON, UTF-8,
LF line endings, no wrapping array, no pretty-printing. This is the shape defined by the FHIR Bulk Data
Access specification, so a receiver that has implemented bulk import already has a loader.
5.2 File splitting. Files are capped at 200,000 resources or 1 GiB, whichever comes first, and numbered
-0001, -0002, … Order within a resource type is by resource id ascending.
5.3 The resource set. Exported where the underlying record is representable as the resource.
| Domain | Resources |
|---|---|
| Administrative | Patient, RelatedPerson, Practitioner, PractitionerRole, Organization, Location, HealthcareService, Schedule, Slot, Appointment |
| Clinical core | Encounter, EpisodeOfCare, Condition, Procedure, AllergyIntolerance, ClinicalImpression, CarePlan, CareTeam, Flag |
| Observations | Observation (vitals, nursing observations, lab analytes, assessment scores), DiagnosticReport, Specimen, ServiceRequest |
| Medication | Medication, MedicationRequest, MedicationDispense, MedicationAdministration, MedicationStatement |
| Imaging | ImagingStudy, and DiagnosticReport for the radiology report |
| Documents | DocumentReference (one per file in documents/, and one per PDF in rendered/), Composition for structured discharge summaries |
| Financial | Coverage, Account, ChargeItem, Invoice, Claim, ClaimResponse, ExplanationOfBenefit where the payer workflow produced one |
| Consent & provenance | Consent, Provenance, AuditEvent (see Section 5.9) |
| Infrastructure | Bundle samples in fhir/_index/, CapabilityStatement describing what the export contains |
5.4 Identifiers and references. Resource id values are stable within the export and are derived from
the relational surrogate keys, so Patient/12345 in the FHIR export is patient_id = 12345 in
identity.patient.csv. This is the join between the two representations and it is the most useful single
fact in this document. References are relative ("reference": "Patient/12345"), never absolute URLs.
Business identifiers (MRN, ABHA address, scheme numbers) appear in Patient.identifier with a system
URI documented in docs/code-systems.md.
5.5 Profiles. Resources are exported as base R4 profiles. Pensieve does not claim conformance to
a national implementation guide, and meta.profile is populated only where the underlying record was
genuinely captured against that profile. docs/fhir-profile-statement.md states, resource by resource,
which elements are populated, which are always absent, and which extensions are used.
Read
fhir-profile-statement.mdbefore scoping a migration. A receiver that assumes every element of a national IG is present will build against something that is not there. The statement exists so that the assumption is never made.
5.6 Extensions. Where Pensieve holds a clinically meaningful value with no R4 element, it is exported as
an extension under a https://trust.pensievelabs.org-rooted URI, and every extension used is listed in the
profile statement with its data type and meaning. No undocumented extension appears in the export.
5.7 Terminology. Codes are exported with the system the hospital actually used. Where the hospital
coded in a standard system, ICD-10, ICD-11, SNOMED CT, LOINC, RxNorm, NDC, or an Indian scheme's own
package codes, the code and system are exported unchanged. Where the hospital used a local code,
system is a local URI and the code appears in docs/code-systems.md with its display text. Pensieve
does not map local codes to standard codes in the export, because a silent mapping is a clinical safety
risk. Where the hospital has configured a mapping, the mapping table is exported in
configuration/terminology-map.json so the receiver can apply it deliberately.
5.8 What is not FHIR, and where it is instead. Stated plainly rather than left for the receiver to discover.
| Not representable as an R4 resource | Where it is |
|---|---|
| Operation theatre scheduling detail, implant tracking, anaesthesia charting minutiae | relational/csv/theatre/ |
| Inventory batches, expiry, stock movement, consumption against encounter | relational/csv/inventory/ |
| Indian statutory registers in their statutory column order | registers/ and relational/csv/quality/ |
| Tariff structures, package pricing, payer rate cards | relational/csv/billing/ |
| Roster, attendance, credentialing | relational/csv/hr/ |
| Workflow instances, form layouts, report definitions | configuration/ |
| Quality indicators, incident records, committee minutes | relational/csv/quality/ |
Nothing is lost. Some of it is simply not clinical data in FHIR's sense, and forcing it into a
Basic resource would make it harder to use, not easier.
5.9 AuditEvent. A FHIR representation of the access log is exported for the current retention year
only, because the full log is very large and is already in audit/ in a documented NDJSON schema. A
hospital that wants the whole log as AuditEvent asks, and Pensieve produces it at no charge.
5.10 Validation. Every NDJSON file is validated against the R4 StructureDefinitions before delivery. The
validator output, including warnings, is included at fhir/_index/validation-report.txt. Warnings are
shipped, not suppressed. A clean report with the warnings removed would tell the receiver less.
Location: imaging/
6.1 Format. DICOM Part 10 files, one per SOP instance, unmodified from what the modality or PACS
produced. Transfer syntax is preserved as stored. Pensieve does not transcode, recompress or
re-window, because a lossy transcode of a diagnostic image is a clinical safety event. The transfer syntax
per study is recorded in imaging/study-index.csv.
6.2 Directory structure. imaging/<PatientKey>/<StudyInstanceUID>/<SeriesInstanceUID>/<SOPInstanceUID>.dcm.
UIDs are used as directory names unchanged. Where a UID exceeds the path budget at Section 2.1, which the standard
permits but practice rarely produces, the directory is a stable 16-character hash and the mapping is in
imaging/uid-map.csv.
6.3 DICOMDIR. A standard DICOMDIR index is written at imaging/DICOMDIR, so the archive opens in
any standards-compliant viewer without an import step.
6.4 Metadata sidecar. imaging/study-index.csv carries, per study: patient_id, mrn,
study_instance_uid, accession_number, study_date, study_time, modality, body_part,
referring_practitioner, performing_practitioner, series_count, instance_count, total_bytes,
transfer_syntax_uid, encounter_key, report_document_id. This is the file that lets a receiver plan
its PACS ingest before touching a single .dcm.
6.5 Identity in the DICOM headers. Patient identity in the header is exported as stored. Pensieve
does not de-identify on export. The hospital is the custodian of its own patients' identity and an
export to the hospital is not a disclosure. Where the hospital requires a de-identified copy for research
or for transfer to a third party, it is a separate deliverable, elected on FRM-GL-404, produced with a
stated de-identification profile.
6.6 Non-DICOM images. Photographs, wound images, scanned films and endoscopy stills that were never
DICOM objects are in documents/, in their original format, indexed to patient and encounter. They are
not wrapped in a synthetic DICOM object.
6.7 Volume. Imaging is typically 90 per cent or more of an export's bytes. RBK-GL-025 Section 7 covers
tranche delivery: imaging is delivered first and separately, on hospital-owned storage or media, while the
rest of the package is prepared. Do not let imaging volume delay the clinical export.
documents/Every file the hospital uploaded or the Platform generated as a file: scanned admission forms, signed consents, external reports, discharge summaries, insurance correspondence, identity documents, lab reports received as PDF, referral letters.
documents/index.csv columns: document_id, relative_path, original_filename, mime_type,
bytes, sha256, patient_id, mrn, encounter_key, document_type_code, document_type_display,
document_date, authored_by, authenticated_by, authenticated_at, is_signed,
signature_method, source_system, is_deleted.rendered/The most important directory in the package, and the one that keeps a hospital lawful on day one after a migration fails.
rendered/<PatientKey>/<EncounterKey>.pdf.rendered/index.csv records which.documents/.Page N of M, and the export
timestamp. A page separated from its bundle is still attributable.rendered/index.csv columns: patient_id, mrn, patient_name, encounter_key, encounter_type,
admission_date, discharge_date, relative_path, pages, bytes, sha256, is_mlc.is_mlc is exported because medico-legal case records carry a different retention obligation for the
hospital. See DIS-GL-406 Section 5.configuration/JSON, one file per domain, each with a $schema pointer to a schema file in the same directory.
masters.json, tariffs.json, packages.json, formulary.json, organisation.json, locations.json
, roles.json, permission-sets.json, users.json, form-layouts.json, report-definitions.json,
workflow-definitions.json, notification-templates.json, document-templates.json,
retention-policy.json, terminology-map.json, integration-config.json (endpoints, message shapes
and field mappings, never secrets), applications/<app_id>/ for each Customer Application definition.
7.3.1 Configuration is definitions, not software. These files describe what was configured. They do not execute outside the Platform. They are exported so that a receiving vendor can rebuild equivalent behaviour without re-eliciting two years of decisions from the hospital's staff, which is where most of the real cost of a migration sits.
7.3.2 users.json contains no credentials. Usernames, roles, permission grants and status. No password
hash, no MFA secret, no session token, no API key. Ever.
audit/audit/<yyyy-mm>/audit-<yyyy-mm-dd>.ndjson.docs/data-dictionary.md: event_id, event_time (UTC), event_type,
outcome, actor_user_id, actor_display, actor_role, actor_ip, actor_user_agent, session_id,
tenant_id, object_type, object_id, patient_id, encounter_key, action, field_changed,
old_value_hash, new_value_hash, reason_code, request_id, source_component.relational/. This keeps the log from becoming a second uncontrolled copy of the clinical record.READ events), because that is what a hospital
needs for a NABH assessment and for a patient's access enquiry.DIS-GL-406 Section 4.1.registers/Registers the Platform maintains for the hospital are exported in their statutory column order and labelling, not in the Platform's internal shape, so that the register survives the migration as a register.
| Register | Delivered as | Note |
|---|---|---|
| Schedule H1 supply register | CSV and print-ready PDF in the statutory column order | Rule 65(11A), D&C Rules 1945; three-year retention sits with the hospital |
| Schedule X sales register | CSV and PDF | The duplicate prescription itself is physical and is not in the Platform |
| Narcotic / Essential Narcotic Drug registers | CSV and PDF | Physical bound registers remain the inspection norm; the export supports, not replaces, them |
| PCPNDT Forms D, E, F, G and consent | PDF per form, plus a CSV index | PNDT Rules 1996 Rule 9 requires an authenticated printed copy where records are kept on computer |
| MTP Form III admission register | Confidential; access-restricted in the delivery pack | |
| Bio-medical waste records | CSV and PDF | Five-year retention sits with the hospital |
| Blood bank donor, testing and issue records | CSV and PDF | |
| Register of medical certificates | CSV and PDF | IMC Regulations 2002, Reg. 1.3.3 |
| Birth and death reporting records | CSV and PDF | The registrar's own register is the permanent record |
7.5.1 The registers are exported because the hospital's obligation to hold them does not end when the
software changes. DIS-GL-406 Section 5 is the reconciliation between what Pensieve deletes and what the
hospital must keep. Read the two together.
Elected on FRM-GL-404. Provided at no charge. Not the default.
8.1 What it is. A native PostgreSQL custom-format dump (pg_dump -Fc) of the tenant's schema and
data, plus the DDL, plus a restore guide. For DM-2 it is a dump of a restored single-tenant extract, not
of the shared cluster.
database-dump/
├── pensieve_<tenant>.dump pg_dump -Fc -Z 3
├── schema-only.sql pg_dump -s, for reading without restoring
├── restore-guide.md Version, extensions, roles, restore command, verification
└── version.txt PostgreSQL major.minor used to produce the dump
8.2 Restore. pg_restore into an empty database on the same PostgreSQL major version or later, with
the extensions listed in restore-guide.md installed first. The guide names them, gives the exact command
line and gives three verification queries whose expected results are in manifest/record-counts.csv.
8.3 Why it is not the default. A dump is the fastest route for a receiver with PostgreSQL competence and the worst route for everyone else. It carries the Platform's internal schema, which is undocumented beyond the data dictionary, contains internal working tables, and ties the hospital to one database engine. The CSV and FHIR exports are engine-neutral and documented. The dump is offered because refusing it would be a lock-in behaviour, not because it is the right choice for most hospitals.
8.4 What the dump does not contain. Files (documents, images, rendered PDFs) are on disk and object
storage, not in the database. A dump alone is not a complete export. FRM-GL-404 states this above the
election box so it cannot be missed.
8.5 Secrets are excluded. Credential vault tables are excluded from the dump entirely, not exported with
ciphertext. Their structure is documented in docs/data-dictionary.md; their contents are revoked and
deleted per ADD-GL-007 and Section 12.3.
9.1 Indicative volumes. For planning only, per year of operation. Actual volumes vary by case mix, imaging intensity and scanning practice.
| Class | 50 to 100 beds | 100 to 200 beds | 200 to 350 beds |
|---|---|---|---|
| Relational CSV | 2 to 8 GiB | 8 to 25 GiB | 25 to 60 GiB |
| FHIR NDJSON | 3 to 10 GiB | 10 to 30 GiB | 30 to 80 GiB |
| Documents | 20 to 80 GiB | 80 to 250 GiB | 250 to 600 GiB |
| Rendered PDFs | 10 to 40 GiB | 40 to 120 GiB | 120 to 300 GiB |
| Imaging (DICOM) | 0.5 to 5 TiB | 3 to 15 TiB | 10 to 40 TiB |
| Audit NDJSON | 5 to 20 GiB | 20 to 60 GiB | 60 to 150 GiB |
[ESTIMATE: modelled from record volumes and typical study sizes, not from a delivered export. Pensieve replaces these with measured figures as real exports are delivered, and will say so when it does.]
9.2 Splitting rules. Files over 2 GiB are split per Section 3. Archives are per top-level directory. Imaging is additionally split by year, then by study, so a partial transfer is resumable at study granularity.
9.3 Tranche delivery. For volumes above roughly 5 TiB the package is delivered in tranches, each with
its own manifest and its own CRT-GL-010:
manifest/, docs/, relational/, configuration/, registers/. This is everything
needed to plan the migration and is delivered first, always.fhir/, rendered/, documents/.imaging/, by year, most recent first.The verification window at WPR-GL-400 clause 9.3 runs from the delivery of the last tranche, not the
first.
9.4 Transfer. Direct to hospital-owned cloud storage is preferred above 1 TiB. Signed-URL download is the default below it. Encrypted physical media at cost, or on hospital-supplied media, where the network makes transfer impractical, with a receipted handover and the passphrase on a separate channel.
9.5 Resumability. Every delivery method supports resume. A 12-hour transfer that fails at hour 11 does not start again.
The manifest is what makes completeness provable rather than assertable. A hospital that verifies nothing else should verify this.
10.1 manifest/package.json
{
"package_format_version": "1.0",
"tenant_id": "Customer tenant ID",
"customer_legal_name": "Customer legal name",
"deployment_model": "DM-1",
"extraction_started_at": "2026-07-31T04:15:00.000Z",
"extraction_completed_at": "2026-07-31T09:42:11.000Z",
"logical_snapshot_at": "2026-07-31T04:15:00.000Z",
"tenant_timezone": "Asia/Kolkata",
"platform_version": "Deal platform version",
"fhir_version": "4.0.1",
"character_encoding": "UTF-8",
"scope_reference": "FRM-GL-404 instance reference",
"tranche": { "number": 1, "of": 3 },
"totals": { "files": 0, "bytes": 0, "entities": 0, "rows": 0 },
"exclusions": [],
"known_limitations_ref": "docs/known-limitations.md"
}
exclusions[] is populated whenever anything in scope was not exported, with the reason. An empty
array is a positive statement that nothing was excluded.
10.2 manifest/files.csv: relative_path, bytes, sha256, content_class, part_of,
part_ordinal, part_count, created_at.
10.3 manifest/record-counts.csv: schema, entity, rows_in_source, rows_in_export, delta,
delta_reason, counted_at.
delta must be zero for every entity. A non-zero delta is a defect unless delta_reason explains it,
the two legitimate reasons being a hospital-elected scope reduction and a soft-deleted class the hospital
asked to omit. Pensieve does not deliver an export with an unexplained delta.
10.4 manifest/checksums.sha256: GNU coreutils format, so the hospital runs sha256sum -c checksums.sha256 and needs nothing from Pensieve to verify integrity.
10.5 manifest/extraction-log.ndjson: every extraction step, its start and end, rows or files
produced, and any warning. Shipped whether or not it is flattering.
Everything below runs on a standard Linux or macOS workstation with no Pensieve software. The same commands
are in docs/load-guide.md and in CHK-GL-023 Part A.
11.1 Integrity
sha256sum -c manifest/checksums.sha256
Expect OK on every line. Any FAILED line is a transfer defect: re-download that file and re-check.
11.2 Completeness
# row count of a CSV, excluding the header
awk 'END {print NR-1}' relational/csv/clinical/encounter.csv
Compare against rows_in_export in manifest/record-counts.csv, and compare that against rows_in_source.
11.3 FHIR
wc -l fhir/Patient/Patient-0001.ndjson # one resource per line
head -n1 fhir/Patient/Patient-0001.ndjson | jq .resourceType
Then validate a sample against the R4 StructureDefinitions with any conformant validator, and compare
against fhir/_index/validation-report.txt.
11.4 Imaging. Open imaging/DICOMDIR in any standards-compliant viewer. Pick five studies from
imaging/study-index.csv across different modalities and confirm they open, that patient identity matches,
and that instance_count matches the file count in the series directories.
11.5 Rendered records. Pick ten encounters a clinician can independently recognise: a recent discharge, a long stay, an MLC, a day-care procedure, an outpatient visit. Open the PDFs and confirm the clinical content is complete and legible.
11.6 Load. Follow docs/load-guide.md: create the schema from docs/ddl/postgresql.sql, COPY the CSVs
in the dependency order the guide gives, then run the three verification queries. The guide is written so
that this works without asking Pensieve a question. If it does not, that is a defect Pensieve fixes at no
charge within 10 Business Days, and the fix is to the guide, not an e-mail answering the question.
Stated here rather than discovered later.
12.1 Pensieve's software. The Platform itself, its source code and its binaries are not Customer Data.
Continuity of the software is addressed by source-code escrow (ADD-GL-011) and DIS-GL-407, a different
mechanism for a different problem.
12.2 Other customers' data. Under DM-2, a documented cross-tenant leakage check runs before delivery
and its evidence is in the delivery pack.
12.3 Secrets and credentials. No password hashes, MFA secrets, session tokens, private keys, API keys or
third-party credentials supplied under ADD-GL-007. The hospital already holds its own third-party
credentials (they were supplied by the hospital under the bring-your-own-credential model) and an export
file is not a safe place for a secret. What Pensieve held is revoked and deleted on offboarding and the
deletion is certified. integration-inventory.md tells the receiving vendor which credentials it needs to
obtain and what shape each takes, which is the useful part.
12.4 Pensieve's internal operational data. Infrastructure telemetry, platform-level metrics, internal
incident records and internal cost data. Where an incident affected the hospital, the incident record and
its post-incident review are the hospital's under DPA-GL-001 clause 10 and are supplied on request.
12.5 Data the hospital's own retention policy already purged. The export is a snapshot of what exists at extraction. Records purged earlier under the hospital's configured retention are not resurrected.
12.6 Data entered after the extraction snapshot. Which is why the final delta export at RBK-GL-024 Section 5
step B9 exists, and why the scheduled export to hospital-owned storage in WPR-GL-400 clause 6.2 is the
standing recommendation.
12.7 Visual and behavioural fidelity. Screens, workflows, keyboard shortcuts and the user experience are not data and are not exported. Configuration definitions describe what was configured; they do not reproduce how it looked.
12.8 ABDM and NHCX artefacts held by the hospital. Under the boundary in DIS-GL-024, the hospital
holds its own HFR, HPR and NHCX credentials and is the registered participant. Linkage records the Platform
created (ABHA addresses recorded against patients, consent artefact references, care-context links) are
exported, in identity and as Consent resources. The credentials themselves are not, per Section 12.3.
13.1 An export is data, not a running hospital system. Loading it is a migration project with its own plan, budget and clinical validation. Pensieve supplies the data, the documentation and 40 person-hours of help; it does not perform the migration.
13.2 Pensieve does not warrant that a receiving vendor will accept these formats. They are open, standard and documented, which is the most any supplier can do. Ask your candidate vendors, in writing and early, whether they ingest FHIR R4 NDJSON and DICOM Part 10. A vendor that cannot is telling you something about itself.
13.3 FHIR coverage is partial by design. Section 5.8 lists what is not FHIR and where it is instead. A receiver that plans on FHIR alone will miss inventory, tariffs, rosters, registers and workflow.
13.4 Local codes stay local. Section 5.7. Pensieve does not silently map them.
13.5 Configuration will not execute elsewhere. Section 7.3.1.
13.6 The rendered PDFs are large. They are also the reason a hospital stays lawful when a migration slips. Do not de-scope them to save transfer time.
13.7 Under DM-4, Pensieve depends on the hospital to run the export. The tooling, the guide and
attendance are provided; the execution is the hospital's. ADD-GL-008 records the mechanics.
13.8 The volumes at Section 9.1 are estimates. They are marked as such and will be replaced with measured figures.
13.9 This specification describes the current package format. Format changes are additive within a
major version (Section 1.6). A major version change is announced under POL-GL-064 with the same notice period as
a Platform change, and the previous version remains producible for twelve (12) months.
Ask. WPR-GL-400 clause 3.5 is the commitment: where a reasonable alternative format is available, Pensieve
provides it at no charge; where it is not, Pensieve says so plainly and provides the documented mapping
instead. Requests are made on FRM-GL-404 Part C or by writing to info@pensievelabs.org.
Things hospitals have reason to ask for, and the answer:
| Request | Answer |
|---|---|
| HL7 v2 messages instead of FHIR | Available for the message types the Platform already produces. Ask at Phase B |
| A different SQL dialect's DDL | docs/ddl/types.csv gives the type mapping for PostgreSQL, MySQL, SQL Server and Parquet. A generated DDL for the others is available on request |
| De-identified copy for research | Separate deliverable, stated de-identification profile, elected on FRM-GL-404 |
| Only a date range, or only one department | Scope election on FRM-GL-404. The full export remains available at no charge afterwards |
| Export directly into the incoming vendor's staging bucket | Yes, on the hospital's written instruction naming the destination |
| A second copy months later | Yes. At no charge. However many times |
| Subject | Document that owns it |
|---|---|
| The exit and portability commitment | WPR-GL-400 |
| Export mechanics and delivery | RBK-GL-025 |
| The offboarding process end to end | RBK-GL-024 |
| Export scope election and acceptance | FRM-GL-404 |
| Delivery certificate | CRT-GL-010 |
| What Pensieve retains after termination | DIS-GL-406 |
| Third-party credential handling and revocation | ADD-GL-007 |
| ABDM/NHCX integration boundary | DIS-GL-024 |
| On-premise export mechanics | ADD-GL-008 |
| Contractual export obligation | MSA-IN-001 clause 22.5 |
| Version | Date | Author | Summary |
|---|---|---|---|
| 1.0.0 | 2026-07-31 | Data & Configuration | First published version. Full package layout; universal file conventions including null, money, identifier and encoding semantics; sixteen relational schemas with the join model; FHIR R4 NDJSON resource set with an explicit statement of what is not FHIR and where it is instead; DICOM Part 10 with no transcoding; the rendered-PDF encounter set; configuration, audit and statutory register exports; the PostgreSQL dump option with an honest statement of why it is not the default; volume estimates marked as estimates; the manifest and the verification commands; twelve categories of what is not in the export; and nine stated limitations. |
DIS-GL-401 v1.0.0 | Last Modified On 31 July 2026 | Review due
31 January 2027 | Published at https://trust.pensievelabs.org