Modules
Settings → Modules (/admin/modules) is the coarsest configuration control
in SeqDesk. A module is a named bundle of behaviour — usually a set of form field
types, sometimes a whole subsystem — that is either on or off for the entire
instance. Turning one off removes its fields from every form builder and from
every form a researcher sees, no matter what each individual field’s Visible
setting says.
Only a facility admin can reach the page. The whole /admin area redirects
RESEARCHER accounts to /orders, and PUT /api/admin/modules — the write
path — rejects anything but FACILITY_ADMIN.
Reading module state is deliberately unrestricted. The browser loads it from
GET /api/modules, which requires no session at all, because a
form cannot be rendered without knowing which modules are on. Treat the list
of enabled modules as public information about your instance — it is.
The three-part relationship
This is the part that trips people up, so it is worth stating plainly.
A module owns a set of field types
The mapping is hard-coded in src/lib/modules/form-integration.ts, not
configurable. Each module claims one or more FieldType values, plus a few
well-known field names, plus a moduleSource marker written onto fields the
app inserts itself.
The form builders offer those field types
A field type whose owning module is enabled can be added in the relevant builder. A field type whose module is disabled is filtered out before the builder ever renders it.
Enabling a module does not add the field
This is the step everyone misses. A module turns a field type on; it does not place a field on your form. Until you add a field of that type — by hand in the builder, or with the Form actions buttons on the module card — the module is active but invisible. The card shows an amber Missing field badge in exactly that state, and an emerald Field added badge once a matching field exists.
Two fields are the exception: a Sequencing Technology field on the order form and
a MIxS field on the study form are seeded automatically while the stored
configuration is still older than the shipped defaults version. funding,
billing and the ENA sample fields are never seeded for you.
Field ownership is resolved in a fixed order: the field’s
moduleSource first, then its type, then its
name. A field that matches none of them belongs to no module and
is always shown — which is why your own custom
text and select fields never disappear when you
toggle modules.
The modules
The page is split into four tabs, one per category.
Form Modules
| Module ID | Name | Default | Field types | Target form |
|---|---|---|---|---|
mixs-metadata | MIxS Metadata | On | mixs (_mixs) | Study |
funding-info | External Funding & Grants | Off | funding (_funding, study_funding) | Study |
billing-info | Cost Center & PSP | Off | billing | Sequencing Order |
ena-sample-fields | ENA Sample Fields | On | organism (_organism, sample_title, sample_alias) | Sequencing Order |
sequencing-tech | Sequencing Technology | Always on | sequencing-tech, barcode (_sequencing_tech, _barcode) | Sequencing Order |
dynamic-studies | Dynamic Study Definitions | Off | — (no field types) | Study |
Validation
| Module ID | Name | Default | Effect |
|---|---|---|---|
ai-validation | AI Field Validation | On | Enables the per-field AI validation prompt and strictness setting in the order builder, and gates POST /api/ai/validate. Contributes no field type of its own. |
Access Control
| Module ID | Name | Default | Effect |
|---|---|---|---|
account-validation | Account Validation | Off | Restricts self-registration to a list of email domains. |
Communication
| Module ID | Name | Default | Effect |
|---|---|---|---|
notifications | Email Notifications | Off | Master gate for the hosted email relay. See Email Notifications. |
sequencing-tech is in ALWAYS_ENABLED_MODULE_IDS; its switch is permanently
disabled and isModuleEnabled returns true for it even when the global kill
switch is on. Instrument and kit registration for it lives on
Sequencing Technologies.
Reading a module card
| Badge | Meaning |
|---|---|
| Active | Enabled and effective right now |
| Inactive | Switched off |
| Always active | sequencing-tech; cannot be switched off |
| Paused (Global Off) | The module’s own switch is on, but the installation-level kill switch is suppressing it |
| Coming Soon | Listed but not yet available; the switch is disabled |
| Settings available | The card expands with its own settings panel when enabled |
| Field added / Missing field | Whether a field owned by this module currently exists on the target form |
| Hidden from users when disabled | Shown on a disabled module that owns field types, as a reminder of the blast radius |
Each card also carries a Form integration block naming the target form and
the exact field types, links to the builders that can place them, and — for
sequencing-tech — an Open module settings link to /admin/sequencing-tech.
Form actions
These buttons do in one click what you would otherwise do by hand in a builder. They are disabled while the module is off, and they never duplicate a field that already exists.
| Module | Action | Writes to |
|---|---|---|
mixs-metadata | Add MIxS to Study Form | Study form config |
funding-info | Add Funding to Study Form | Study form config |
ena-sample-fields | Add ENA Fields to Sequencing Order Form | Order form config (per-sample) |
sequencing-tech | Add Sequencing Tech to Sequencing Order Form | Order form config |
sequencing-tech | Add Barcode to Sequencing Order Form | Order form config (per-sample) |
sequencing-tech | Apply ONT Run Plan Preset | Order form and the sequencing run questionnaire |
Add Barcode stays disabled until a Sequencing Technology field exists on the order form, and pressing it early answers Add Sequencing Technology first. The barcode field is populated from the kit chosen in the technology selector, so it is meaningless without one.
Modules with their own settings
Account Validation
Expanding the enabled card gives you Allowed Email Domains. Domains are
lower-cased and must contain a dot; anything else is dropped on save. The list is
stored as accountValidationSettings inside SiteSettings.extraSettings.
Two switches’ worth of behaviour, from /api/register:
| State | Result for a non-matching domain |
|---|---|
| Empty domain list | Everyone may register — the list, not the module, is what enforces anything |
| Domains listed, enforcement on | Registration is refused |
| Domains listed, enforcement off | Registration proceeds with a warning that the domain is not approved |
Matching is exact, not suffix-based. Listing
example.org does not admit
lab.example.org — add every subdomain you actually use, or you
will lock out half your institute.
Cost Center & PSP
Configures how a billing field validates input: whether the PSP element is
collected at all, its prefix range, the number of digits in the main part, its
suffix range, and the example string shown to researchers — the shipped default
describes 1-1234567-99. Cost centre collection has its own switch, an optional
regular expression, and its own example.
Where the setting lives, and who reads it
State is one JSON string in the singleton settings row,
SiteSettings.modulesConfig:
{
"modules": {
"mixs-metadata": true,
"ena-sample-fields": true,
"dynamic-studies": false
},
"globalDisabled": false
}Unknown keys are ignored and missing keys fall back to the shipped defaults, so a
partial object is safe. A bare { "module-id": true } object without the
modules wrapper is still accepted for backwards compatibility. If the column
contains invalid JSON, every module silently reverts to its default state rather
than erroring — worth remembering if you edit the database by hand.
Enforcement is not in one place. Each of these reads the same column independently:
| Consumer | What it decides |
|---|---|
GET /api/admin/form-config | Which fields the order builder may show |
GET /api/orders/[id]/samples | Which per-sample columns a researcher sees |
src/lib/studies/schema.ts | Which study fields resolve, and whether per-study questionnaires apply |
POST /api/ai/validate | Whether assisted validation answers at all |
POST /api/register | Whether domain restrictions apply |
src/lib/notifications/settings.ts | Whether hosted email is considered enabled |
| The sidebar | Study Forms versus Define Studies |
The browser copy is loaded once per page load through a React context. A module change therefore reaches other people’s open tabs only on their next navigation, not instantly.
The global kill switch
globalDisabled forces every optional module off at once. While it is set, the
page shows “Modules are globally disabled at installation level”, individual
switches are frozen, and each module that was on reports Paused (Global Off)
— its own stored state is preserved, so clearing the kill switch restores exactly
what you had.
What breaks if you get this wrong
| Change | Consequence |
|---|---|
Disabling ena-sample-fields after orders exist | Organism, Sample Title and Sample Alias stop rendering. The values already stored on samples are untouched, but ENA submission loses the fields it needs to build a sample XML |
Disabling mixs-metadata on a facility that submits to ENA | Study and sample MIxS blocks vanish from the questionnaire; existing checklist answers stay in the database, unreachable through the UI |
Enabling dynamic-studies mid-flight | Studies that already have their own StudyFormConfig switch to it; studies that do not keep using the global study form. Both states coexist, which is intended but surprising |
Disabling dynamic-studies again | Per-study questionnaires are ignored and everyone falls back to the global study form. The per-study definitions are not deleted |
Enabling account-validation with an empty list | Nothing changes. The module is on, but with no domains it admits everyone |
Enabling notifications without a relay token | Email stays off. The module is only one of three conditions the dispatcher checks |
Setting globalDisabled on a live instance | Every optional field type disappears from researchers’ forms at once, including required ones. Forms remain submittable, so you may silently stop collecting data you rely on |
Disabling a module never deletes data. Field values already written to
customFields stay exactly where they are and reappear the moment
the module is re-enabled. The risk of a module toggle is what stops being
collected, not what is lost.
Setting modules at install time
Module flags can be shipped in settings.json and merged over whatever is in the
database by Infrastructure → Import settings.json
(/admin/data-compute). The import merges rather than replaces, so a file
naming three modules leaves the rest alone:
{
"modules": {
"mixs-metadata": true,
"ena-sample-fields": true,
"billing-info": true
}
}Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Module is Active but researchers see nothing new | No field of that type exists on the form yet | Use the card’s Form actions button, or add the field in the builder |
| Card shows Missing field after you added the field | The field was added to the other form — module targets are fixed | Check the Used in line on the card and add it to the named form |
| A field is invisible even though Visible is on | Its owning module is off; the module filter runs before the visibility check | Re-enable the module |
| Every switch is greyed out | The global kill switch is set | Clear globalDisabled on this page |
The sequencing-tech switch will not move | It is in ALWAYS_ENABLED_MODULE_IDS | It cannot be disabled; hide its fields in the builder instead |
| A colleague still sees the old state | Module state is fetched once per page load | Ask them to reload |
| Add Barcode is disabled | No Sequencing Technology field on the order form | Add that first |
| Registrations refused after enabling Account Validation | Exact-match domains, subdomains excluded | Add each subdomain, or turn enforcement off to warn instead of block |
See also
- Form Builders — where the field types these modules contribute are actually placed
- Sequencing Technologies — the
registry behind
sequencing-techandbarcode - Email Notifications — the rest of the
notificationsmodule - User Management — registration, which
account-validationconstrains - Study Metadata & MIxS — what
mixs-metadatacollects