Skip to content
Corex

ManagedTable

Corex\Database\Schema\ManagedTable · class · Core layer

Marks a Corex custom table as “managed” so it appears in the Corex → Data admin screen — the unprefixed table name, a human label, and the ordered columns to show ({id, label}). Pure: it carries the metadata; corex-config turns it into a DataSource (spec 038). A table may also declare what may be done to it (spec 074): which fields are writable, the CSV headers that map to them, how to validate them, what to do with a column nobody declared, and which schema migrations it ships. Everything here is opt-in and read-only by default — the Data workspace derives its capabilities from this declaration, so a table cannot end up advertising an operation it never agreed to. Audit and system tables simply say nothing and stay read-only. Migrations are declared as plain arrays rather than MigrationDefinition objects because that class lives in corex-config, and the schema layer must not depend on the admin layer. A table also says which of its columns hold personal data, and of which kind (spec 109). That one is not opt-in in its effect: a column the table says nothing about is “undeclared”, and everything that lets a record leave the site treats an undeclared column as personal data.

__construct(string $name, string $label, array $columns, ?string $textDomain, array $writableFields, string $unknownColumns, array $migrations, array $insertDefaults, array $personalData, ?string $category, ?string $ownerAbility)

Section titled “__construct(string $name, string $label, array $columns, ?string $textDomain, array $writableFields, string $unknownColumns, array $migrations, array $insertDefaults, array $personalData, ?string $category, ?string $ownerAbility)”

This is an immutable declaration record, not a service: every parameter is a piece of the same statement about one table, and they are passed by name at the single call site each table has. (Deliberate exception to the four-argument ceiling, which exists to stop collaborator lists growing — there are no collaborators here.)

Which group the Data screen lists the table in (spec 109, FR-003). Most tables say nothing and the answer follows from what they are: a table somebody can write to holds what the site works with, and one nobody can is a record of what happened. A table that is read-only and still the site’s own records says so.

personalDataClass(string $columnId): string

Section titled “personalDataClass(string $columnId): string”

The class the table declared for a column, or “undeclared” when it declared none.

The columns a create must set even though no one may import into them, and their values. A row created by import has to end up in the same shape the owning feature would have created — an imported newsletter subscriber with no status is in a state the double opt-in flow does not recognise, so it can never be confirmed and never be emailed. Defaults are the feature’s answer to “what does a new row look like”, kept separate from the writable fields precisely so an import still cannot choose them.

Import needs somewhere to put the rows, so it is exactly writability — there is no separate switch to get out of step with it.

Rollback is claimed only when at least one declaration actually provides a way back. Offering it for a one-way migration would promise an undo that does nothing; the per-run check in MigrationService still gates each individual definition.