Appearance
Entity: remoteEndPoint
Entity Type: Database table
Description: Represents a single data channel within a remoteSource connector. Each endpoint corresponds to one measurement point in the external system and is paired with exactly one target — gauge or weatherStation — once the pairing is established (gaugeId and weatherStationId are mutually exclusive; at most one may be set — see Validations on both columns). Before pairing, the endpoint is unmatched and appears in the connector's unmatched endpoint panel. Endpoint data (identifier, location description, unit) comes from the external system; pairing to a target is performed by a user in the UI. A weather station may have multiple paired endpoints (e.g. separate channels for temperature, humidity, rainfall), distinguished by segment/measurement type on the endpoint's recorded values.
Data Attributes Table
| Attribute Name | Description | Data Type | Default Value | Required (= Nullable) | Unique | Format | Validations | Index | Example |
|---|---|---|---|---|---|---|---|---|---|
| id | Primary key. | UUID | Generated in code (app layer) | Yes | Yes | UUID v7 | - | Primary Key | 018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2 |
| tenantId | Tenant this record belongs to. | UUID | - | Yes | No | UUID v7 | Foreign Key → tenant; must exist | name: idx_remoteEndPoint_tenantId, type: btree | 018fa51f-fda1-79f4-8461-2cb8f1cabc10 |
| remoteSourceId | The connector this endpoint belongs to. | UUID | - | Yes | No | UUID v7 | Foreign Key → remoteSource; must exist | name: idx_remoteEndPoint_remoteSourceId, type: btree | 018fa51f-fda1-79f4-8461-2cb8f1cabc10 |
| gaugeId | The gauge this endpoint is paired with. Null when the endpoint is unmatched. | UUID | - | No | No | UUID v7 | Foreign Key → gauge; nullable; onDelete SET NULL. Mutually exclusive with weatherStationId — at most one of the two may be non-null. | name: idx_remoteEndPoint_gaugeId, type: btree | 018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2 |
| weatherStationId | The weather station this endpoint is paired with. Null when the endpoint is not paired to a weather station. | UUID | - | No | No | UUID v7 | Foreign Key → weatherStation; nullable; onDelete SET NULL. Mutually exclusive with gaugeId — at most one of the two may be non-null. | name: idx_remoteEndPoint_weatherStationId, type: btree | 018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2 |
| identifier | External identifier of this endpoint in the source system. Used to match incoming data to this endpoint. | String | - | Yes | No | - | Non-empty; unique with remoteSourceId. | name: idx_remoteEndPoint_remoteSourceId_identifier, type: btree (unique) | MRV-001-ELEC-A |
| locationDescription | Human-readable location or description of the measurement point, as provided by the external system. | String | - | Yes | No | - | Non-empty. | - | Pavilon A – elektroměr hlavní |
| unit | Raw unit label as provided by the external system (e.g. "kWh", "m3"). | String | - | Yes | No | - | Non-empty. | - | kWh |
| enabled | Whether this endpoint is actively receiving and processing data. Disabled endpoints retain historical data but stop accepting new readings. | Boolean | true | Yes | No | - | - | - | true |
| lastRecordedAt | Timestamp of the most recent data record received from this endpoint. Used to display endpoint health in the connector tab. | Timestamp with time zone | - | No | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Nullable; set automatically on each incoming record. | - | 2026-06-18T15:00:00Z |
| note | Optional free-text note added by a user (e.g. pairing reason, known issues). | Text | - | No | No | - | Nullable. | - | Párováno ručně – jiný název v Mervisu |
| infoJson | Freeform metadata received from the external system (additional attributes that don't map to dedicated columns). Read-only — set by the aggregator. | JSONB | - | No | No | JSON object — genuinely freeform, no fixed schema documented | Nullable. | - | {"deviceId": "MRV-001", "floor": 2} |
| createdAt | Timestamp of when the record was created. Immutable after insert. | Timestamp with time zone | now() — set in code | Yes | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Cannot be null; cannot be modified after creation. | - | 2025-03-16T18:00:00Z |
| updatedAt | Timestamp of the last update. | Timestamp with time zone | now() — set in code | Yes | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Cannot be null. | - | 2025-03-16T18:00:00Z |
| deletedAt | Timestamp of soft deletion. Null means active. Once set, immutable. | Timestamp with time zone | - | No | No | ISO 8601 — YYYY-MM-DDTHH:mm:ss.SSSZ | Immutable once set. Active records: WHERE deletedAt IS NULL | - | 2025-06-01T09:00:00Z |
| createdBy | Identifier of the actor who created the record. | String | - | Yes | No | type:actor | Non-empty. | - | system:aggregator |
| updatedBy | Identifier of the actor who last updated the record. | String | - | Yes | No | type:actor | Non-empty. | - | user:018ed0b3-c298-7c7a-96d5-8b36f5a7f8d2 |
Note on infoJson. Per the foundations doc, a JSONB column with a documented internal shape gets a JSON-DAT sibling file. infoJson is described on the source page as genuinely freeform passthrough metadata with no fixed key set (only one illustrative example is given) — no sibling file was created for it since there is no concrete shape to document; this is flagged for the analyst's attention rather than fabricated.
Discrepancy flagged during migration (per task brief). Index names on the source page used a remote_end_point (snake_case entity segment) naming style, e.g. idx_remote_end_point_tenantId; this migration normalises the entity segment to camelCase (idx_remoteEndPoint_tenantId) to match this project's idx_entityName_attributeName convention, without changing the underlying meaning. Earlier auditing separately noted documentation drift on remoteEndPoint/remoteSource against the real schema — this migration carries the Confluence content as-is and does not attempt to reconcile that drift.
Audited fields
Recorded on created (in full), updated (changed only) and deleted (in full): remoteSourceId, gaugeId, weatherStationId, identifier, locationDescription, unit, enabled, lastRecordedAt, note, infoJson.
Excluded: none — lastRecordedAt is set automatically by the aggregator rather than entered by a person, but per the same reasoning as gauge.direction/outputMode, an automatically-set column is still a real, stored value at write time and is audited like any other.
Every entry would carry subjectEntityType = remoteSource / subjectEntityId = remoteSourceId — an endpoint has no independent lifecycle outside the connector it belongs to. Whichever of gaugeId/weatherStationId is set at write time rides as a field on the entry, not as a second subject pin.
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, identifier is the natural candidate.