Entity References
An entity reference is a value that enables a part of the system to access an entity, inspect its public data, or request actions on it. Entity references are themselves values — they can be stored, transmitted, and processed by different parts of the system.
Pinned vs Floating References
Section titled “Pinned vs Floating References”Entities in the Arda system are journaled in a bitemporal sense. A reference to an entity can identify either:
-
Floating Reference: Identifies the complete lineage of versions of an entity. Accessing a floating reference requires specifying bitemporal coordinates to identify the specific version to access. When floating references are used with “now” time coordinates, the returned values may change depending on when the entity is accessed, or the entity may even have been deleted.
-
Pinned Reference: Identifies a specific bitemporal version (record) of an entity. Pinned references can rely on the fact that the version they point to will not change over time. In normal operation, no record is ever deleted, though OAM operations (archiving, purging) may remove records.
The choice between pinned and floating references is a domain-level concern. Business processes that must produce immutable records (e.g., a closed purchase order) should use pinned references to the reference data they captured at the time of the transaction.
Reference Structure
Section titled “Reference Structure”Regardless of the data type used to encode an entity reference, its information contents can be expressed using a standardized URI structure. The components are:
Schema
Section titled “Schema”The protocol used to access the entity:
| Schema | Protocol |
|---|---|
https | REST-based access using HTTPS (typically HTTP/1.1) |
grpc | gRPC-based access using HTTP/2 |
eventbus | Arda event bus based access (TBD) |
local | Access within the same component |
contextual | Interpreted by the user of the reference |
Authority
Section titled “Authority”The endpoint where the entity can be accessed. UserInfo must not be used in the authority section. The authority is mandatory for all schemas except contextual.
For https: a globally resolvable hostname or IP address; no port number (port 443 is implicit).
For grpc: a hostname resolvable within the Kubernetes cluster. By convention Arda components run in namespaces named <partition>-<component> (e.g., prod-operations), but the authority for a gRPC URI uses only the component name (e.g., operations). Components are not allowed to access entities outside their partition.
The unique identifier of the entity within the authority’s domain. For https:
module: The name of the module (service) managing the entityresource/entity-type: The type of entity among those managed by the module. Bothmoduleandresourcesegments must be present even when they have the same value.- Then one of:
{local-eid}— Floating reference: the UUID identifying the complete bitemporal lineage{local-eid}/rid/{local-rid}— Pinned reference: the UUID of a specific bitemporal record within the lineage
Query and Header Parameters
Section titled “Query and Header Parameters”Reference Parameters
Section titled “Reference Parameters”An entity reference is completely defined by its schema, authority, and path. One additional parameter is useful for floating references when an entity has been deleted:
includedeleted=true: Return the last version of the entity at the time of deletion rather than a “not found” response. The default for all references is to return “not found” if the entity does not exist at the specified bitemporal coordinates.
Standard Access Parameters
Section titled “Standard Access Parameters”These parameters are not part of the entity reference itself but are standard parameters used in requests that address an entity:
| Parameter | Description |
|---|---|
tenantid | UUID of the tenant that the entity belongs to. Mandatory for regular user requests. Encoded as an HTTP header for the https schema. |
effectiveasof | Unix epoch milliseconds specifying the effective time dimension. If omitted, the server uses its local clock as “now”. Encoded as a query parameter for https. |
recordedasof | Unix epoch milliseconds specifying the recorded time dimension. If omitted, the server uses its local clock as “now”. Encoded as a query parameter for https. |
Note on current system (as of 2025-12): The system is not yet consistent in using
operationtimevseffectiveasoffor mutation operations. Use ofrequestIdfor idempotency is also limited at this time.
Excluded from this document: gRPC, eventbus, local, and contextual schema path details are described in the source document but are implementation-level concerns. Protocol-specific header encoding details belong in the API reference section of the Current System documentation.
Implementation in Kotlin
Section titled “Implementation in Kotlin”Within Arda backend modules (Kotlin / Ktor / Exposed), an entity reference is realised as a sealed interface with at least one nested Value data class, both implementing EntityPayload:
@Serializablesealed interface ItemReference : EntityPayload { @Serializable(with = UUIDSerializer::class) override val eId: EntityId @Serializable(with = UUIDSerializer::class) val rId: UUID? // present when pinning to a specific version; null for floating val name: String? // cached display field (so consumers can render without re-fetch)
@Serializable data class Value( @Serializable(with = UUIDSerializer::class) override val eId: EntityId, @Serializable(with = UUIDSerializer::class) override val rId: UUID? = null, override val name: String? = null, ) : ItemReference { override fun validate(ctx: ApplicationContext, mutation: Mutation) = Result.success(Unit) companion object { fun fromItem(item: Item, rId: UUID? = null): Value = Value(item.eId, rId, item.name) } }}The eId carries the floating identity (the entity, regardless of version). The optional rId pins the reference to a specific bitemporal record (the version of the entity at the moment the reference was captured). Cached display fields are stored alongside so consumers can render the reference without re-fetching the target entity.
The seal lets the type evolve (e.g., a future ItemReference.External(...) variant for entities owned by a remote system) without breaking existing call sites.
When persisted, the reference value object is flattened into the holder’s table with prefix-based column naming (e.g., "ITEM_REFERENCE_entity_id", "ITEM_REFERENCE_item_name", "ITEM_REFERENCE_record_id"). This keeps the foreign-side data accessible without a join while explicitly preserving “no SQL FK across services” for cross-service references — see Data Authority Module Pattern § Cross-Service Isolation.
For the broader design playbook (when to introduce a reference family, how to choose the cached display fields, how to handle resend chains and parent-child relationships), see Information Model Design.
Copyright: © Arda Systems 2025-2026, All rights reserved