How modules work
A module has four states, and each one does something different to your data.
Install
The platform extracts the ZIP, checks the manifest against the schema, plans the install, creates the module's tables, runs its SQL migrations, writes its configuration row, syncs its translations, regenerates the registry, rebuilds and restarts.
The plan comes first on purpose. It expands your selection to include anything the modules depend on, orders it so prerequisites are extracted first, tells you what it added on your behalf, and refuses the whole set rather than installing half of it if there is a cycle, a conflict, an unknown id or a version it cannot satisfy.
A Postgres advisory lock stops two installs racing, and registry regeneration rolls the filesystem back if it fails, so there is no such thing as a partial install that half worked.
Enable and disable
Enabling is what makes a module visible. Disabling makes it vanish from every surface at once: its pages 404, its admin screens leave the sidebar, its navigation entries go, its hooks stop firing. Its data is untouched and its tables stay exactly as they were.
ModuleConfig.enabled in the database is the single source of truth for this.
Nothing else decides it.
Uninstall
The files go and the configuration row goes. Two things deliberately stay: the module's database tables, and any translation an administrator edited by hand.
That is so a reinstall finds its data where it left it. An uninstall is not a delete, and if you want the tables gone you drop them yourself, knowing what you are dropping.
Dependencies and versions
A manifest declares coreVersion as a semver range over the core's
module-facing API version, and may pin other modules the same way, such as
"store@^2.1.0".
Install, update and enable all check those ranges and refuse rather than failing later at runtime. A payment gateway that needs the store module will not enable without it, and will say so instead of rendering a settings page for something that is not there.
Uploading your own
Admin, then Modules, then upload a ZIP. It goes through the same checks as a marketplace module: path traversal, reserved ids, manifest schema, id matching the directory, and manifest file references that point outside the module directory. A module manifest arrives from outside the machine, so it is treated as something to be verified rather than trusted.