Skip to content
Updated Sep 26, 2026 by Barča Dvořáková · Owner: analysisactiveentityconfluence-migration Edit on GitHub

Entity: clientModule ​

Entity Definition ​

  • Entity Name: clientModule
  • Entity Type: Database table (join table with metadata)
  • Description: Records which add-on modules are enabled for a given client. A module that does not have a corresponding clientModule row is invisible to all users of that client.

Data Attributes Table ​

Attribute NameDescriptionData TypeDefault ValueRequired (= Nullable)UniqueFormatValidationsIndexExample
idPrimary keyUUIDGenerated in code (app layer)YesYesUUID v7-Primary Key018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2
tenantIdTenant this record belongs to.UUID-YesNoUUID v7FK → tenant; must existname: idx_client_module_tenantId, type: btree018fa51f-fda1-79f4-8461-2cb8f1cabc10
clientIdClient the module is enabled forUUID-YesNoUUID v7FK → client; must exist — see clientname: idx_client_module_clientId, type: btree018fa51f-fda1-79f4-8461-2cb8f1cabc10
moduleKeyIdentifies which module is enabled.String-YesNocamelCase stringNon-empty; must be a value from the predefined list (see "Allowed moduleKey values" below); unique per clientIdname: idx_client_module_clientId_moduleKey, type: btree (unique)remoteReadings
createdAtTimestamp of when the record was created. Immutable after insert.Timestamp with time zonenow() — set in codeYesNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZCannot be null; cannot be modified after creation-2025-03-16T18:00:00Z
updatedAtTimestamp of the last update to the record.Timestamp with time zonenow() — set in codeYesNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZCannot be null-2025-03-16T18:00:00Z
deletedAtTimestamp of soft deletion. Null means the record is active. Once set, immutable.Timestamp with time zone-NoNoISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZImmutable once set. Active records: WHERE deletedAt IS NULL-2025-06-01T09:00:00Z
createdByIdentifier of the actor who created the recordString-YesNotype:actorNon-empty-user:018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2
updatedByIdentifier of the actor who last updated the recordString-YesNotype:actorNon-empty-user:018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2

Allowed moduleKey values ​

The following module keys are currently known (the list is not exhaustive):

moduleKeyDescriptionDefault on client creation
remoteReadingsRemote meter reading collectionYes
remoteReadingsAnalysisAnalysis and reporting of remote readingsYes
buildingPassportBuilding passport and energy certificationNo
iso50001EnMS management per ISO 50001 standardNo
emissionFactorsCO₂ emission factor management per gaugeNo
energySharingEnergy community / energy sharing featuresNo
settlementFinancial settlement for energy sharingNo
consumptionMonitoringConsumption monitoring and anomaly alertsNo
tariffOptimisationElectricity tariff optimisation toolsNo

Note: moduleKey is validated against this known list but is not modeled as a closed enum on the source page (it is typed as a plain camelCase string with "the list is not exhaustive" stated explicitly). This looks like a candidate for the "open set" pattern described in the foundations doc (§7, open enum still gets a page) rather than an inline table — flagging for consideration, not changed here since the source documents it inline.

Audited fields ​

Recorded on created (in full) and deleted (in full) — a pure enable/disable join, so no field of an existing row is ever changed, only added or removed: clientId, moduleKey.

Excluded: none.

Every entry would carry subjectEntityType = client / subjectEntityId = clientId — the module being toggled is named by moduleKey on the entry itself, not as a separate subject.

Not registered for entityName resolution — renders id-only in the audit trail (architecture 61-audit-log.md §7.4 in the code repo: a valid, permanent state, not a gap). If registered, moduleKey is the natural candidate.