Skip to content
ImplementedFor engineers, QA, validation staff

Environments and versioning

Last updated Oct 21, 2026

Trialion's environment model is inside the product, not in the infrastructure. There is one deployment, and UAT and Live are workspaces of a study, not separate installations: you do not stand up a second instance to validate a study. Three separate things describe where a study is, and they are kept apart on purpose.

Interactive · How a Study Comes to LifeOpen full screen →

Watch a study come to life. It advances Build → UAT → Live; roles enter as they’re needed, and every operation is marked built, partial, or not built yet — honestly.

Cast — 1 of 15 roles active
OAOrganization AdminPMProject ManagerEDeCRF DesignerDMData ManagerCRAClinical Research AssociateSTMSite MonitorMOMedical OfficerCDCClinical Data CoordinatorSMSponsor ManagerSSMSponsor Supply ManagerRMRegulatory ManagerAUDAuditorPIPrincipal InvestigatorCRCClinical Research CoordinatorPHPharmacy
BuildSetup · design
UATValidation · test data
LiveProduction
What a real trial still needs — not built yet

These clinical capabilities would live in the Live environment but aren’t built. Shown here so the picture is honest, not aspirational.

Safety submissionNot built yet
MOSM

Generating and sending expedited reports (E2B), a gateway, and automatic reconciliation with the safety database.

What is not built yet
Drug supply and accountabilityNot built yet
SSMPH

Inventory, dispensing, resupply, kits, depots and shipments.

What is not built yet
Randomization and blindingNot built yet
SMPICRC

Allocation of participants to treatment, and hiding the arm from the people who must not see it.

What is not built yet
Medical coding (MedDRA, WHODrug)Not built yet
MO

Coding of adverse events, history and medications to standard dictionaries.

What is not built yet
Central monitoring and monitoring reportsNot built yet
CRASTM

Key risk indicators, central statistical monitoring and monitoring-visit reports.

What is not built yet

1. The study's state: what the trial is doing

A study has one operational state, on the study and never on a version, which is what lets version 3.0 be built and tested while the study is Active on 2.0 (Change the state of a study).

ActionFromToPermissionTwo people
holdActiveOn holdstudy.state.changeno
resumeOn holdActivestudy.state.changeno
close enrollmentActive, On holdClosed to enrolmentstudy.state.changeno
completeClosed to enrolmentCompletedstudy.state.changeno
lockCompletedLockedstudy.lockyes
unlockLockedCompletedstudy.lockyes
archiveLockedArchivedstudy.archiveno

A study starts in Setup and becomes Active by itself when version 1.0 goes Live; nobody takes that decision. What each state allows is stated once, in studyCapabilities, and everything else asks it:

StateNew participantsClinical dataSafety reportingVersion work
SetupNoNone (no Live data yet)NoYes
ActiveYesFullYesYes
On holdNoFullYesYes
Closed to enrolmentNoFullYesYes
CompletedNoOnly to answer a queryYesNo
LockedNoNoneNoNo
ArchivedNoNone (read-only)NoNo

Each kind of write has an intent (enrol, data_entry, cleaning, safety, version_work, metadata, governance), and whether the state allows the intent is judged as the last layer of every write's decision, after membership, permission and workspace, so a person who is not allowed is never told the study's state. The first four intents apply to Live data only; UAT data follows the version and its cycle, and in UAT the state gates only version work. An unknown state allows nothing.

The same matrix is also enforced in the database: a trigger on the Live data tables (cdms_assert_live_writable) refuses a Live write the state does not allow (nothing once Locked or Archived, a new participant only when Active, a changed value of a Completed study only to answer a query), so a bug in a route cannot write what the state forbids.

2. The version: what the design is

The design is one versioned, sealed unit: forms, visits, mapping, rules and settings are compiled together. A study has at most one version in flight and one Live version, held in two pointers on the study.

StateMoves it offers
buildsubmit to uat, withdraw
uatpass cycle, fail cycle, withdraw
awaiting signoffsign, reject, withdraw
approvedgo live, withdraw
live(none: final)
superseded(none: final)
withdrawn(none: final)
  • Submitting to UAT publishes the draft forms and compiles the whole design into a snapshot (config_snapshots): immutable, hashed (SHA-256 of its canonical content), never deleted. A cycle (uat_cycles, numbered for each version) opens on it.
  • Sign-offs (version_signoffs) bind to the snapshot the passed cycle tested; the capacity (Author, QA, Approver) comes from the role; three different people; separation of duties is checked by the database. Approval is the third sign-off. A change after sign-off is a new submit, a new snapshot, a new cycle.
  • Go live, supersede, withdraw are each one database function called inside one audited command, so each is atomic: going Live supersedes the previous Live version and repoints the study in the same transaction, and takes the study from Setup to Active on the first one.
  • An amendment is the next version, cloned from the Live design in Build. Participants follow the version they were captured under and move to a new one individually, after re-consent where the amendment asks for it; a change that no longer fits data the study holds is Breaking and is refused at submit and at go-live (ADR 0016).
  • Draft revisions are append-only per save and store only what changed, so the history of a design in Build is kept.
  • Read-only is enforced in the database: once a version is submitted, its forms, visits, mapping and rules cannot be written, whatever the application asks.

The configuration cache

The runtime reads what a version runs from its snapshot (runtime-config module), indexed by the snapshot's id. Because a snapshot never changes, the cache needs no invalidation; it is bounded (RUNTIME_CONFIG_CACHE_MAX_BYTES, default 256 MiB, and RUNTIME_CONFIG_CACHE_MAX_ENTRIES, default 256). A version that should run but has no snapshot is refused loudly (409 version.snapshot_missing).

Forms inside a version

A form has its own short life, Draft, Active, Archived, and belongs to a version. Only a draft form's design can change; making it active checks it; an Active form is reopened only while the study has never released a version, and afterwards the path is a new form version. A field that holds data is deprecated, never deleted. Visit bindings capture the form version they were made against, so a new form version starts unbound (Versions, reopening and what publishing locks).

3. The workspace: where the data lives

The data of a study's execution lives in UAT or Live, and a session is in one of them or in none. The server derives the workspace from the session's own access profile on every request: nothing in a path, header or parameter names it, so nothing the browser sends can move a request between test and production data.

  • A session may carry no workspace (ADR 0019): the dashboard, the study level and the Build area belong to none. Every route declares its kind: none (reads and writes nothing a workspace owns), named (may touch workspace data and names which, or reads Live's by definition) or required (acts in the session's workspace; a session that has entered none is refused with 409 workspace.required).
  • Entering UAT or Live is an explicit act (POST /auth/workspace with a study and a workspace): the server picks the person's role on that study in that workspace, mints a new session and ends the one it replaces. The dialog names the area, the version and the role first. A person with only UAT roles lands in UAT; site staff with only Live roles land in Live.
  • The database holds the wall with a second row-level-security policy keyed to the session's workspace on the execution tables (Data and tenancy). UAT rows also carry their cycle, so a closed cycle is a read-only copy of that cycle's test data.
  • What carries over from UAT to Live: nothing but the design. Test participants, records, queries and sites stay in UAT; Live sites and people are registered fresh, which is why the first go-live needs an active Live site with an investigator.

What is deferred

  • Site-by-site activation of an amendment. A release applies to the study; participants move individually, but you cannot stage the design by site. There is no per-site ethics gate before an amendment reaches a site.
  • Participant migration modes (grandfather, migrate at the next visit, forced): a participant moves when the amendment is taken and their re-consent, if asked for, is consented.
  • Automatic team carry-forward from UAT to Live at go-live: a person's role is one on the study and is held in both workspaces, but site assignments are per workspace.

Compliance Q&A

Compliance Q&ABuiltAnnex 11 4Part 11 11.10(a)Part 11 11.10(f)ALCOA+ consistent
Can test activity ever be mistaken for, or mixed with, production data?

No. A session is in UAT or in Live and the database filters every execution table by it, so a Live session cannot read test data and a UAT session cannot read production data, whatever the application asks. Test participants are numbered with a UAT marker.

Evidence: schema: tenant_env_isolation policy on 21 tables bound to app.current_env from the sessionparticipant and record numbers carry a UAT markerserver/tests rls-environment-wallsimulation of 20 Oct 2026 (UAT and Live separate)

Compliance Q&ABuiltPart 11 11.10(a)Part 11 11.10(k)Annex 11 10
Can a released design be changed in place?

No. Once a version is submitted, its design is read-only in the database; the Live design changes only by an amendment that is built, tested in a cycle and signed by three people, and the earlier version is kept as Superseded.

Evidence: server versions (snapshot immutable and hashedread-only enforced in the databasechanges only by a new version)

Data and tenancy · Review and release a study · Sign off a version and go live · Amend a live study · GAMP 5 and CSV · Architecture decisions