Skip to content

REC registry client

celine.sdk.rec_registry. Six repositories import it. It wraps the generated registry client so callers see short method names and Pydantic schemas instead of Response objects — the general shape of every wrapper in this SDK.

What is stated here is only the part of that wrapper where a wrong answer is indistinguishable from a right one: the three batch lookups, whose empty list is a real answer the service gives on purpose. The rest of the wrapper — every single-id lookup, the writes, the user-scoped client — is not specified yet.

The service's own behaviour belongs to rec-registry, not here; where a requirement below mirrors one of its, the identifier is named so the two can be kept honest.


Batch asset lookups

lookup_assets_by_sensor_ids and lookup_assets_by_user_ids are mirrors: one starts from a device and finds its owner, the other starts from owners and finds their devices.

Both sit in front of routes where an empty list means something. A sensor id that matches nothing contributes no row (rec-registry REQ-0043); a user id belonging to nobody and a member who owns nothing are deliberately indistinguishable, so that the route cannot be used to discover who is registered (rec-registry REQ-0045). Everything below follows from that: the wrapper must never add a third meaning to a sentence that already has two.

REQ-0120 — a refused batch lookup raises, and never answers an empty list

A response the generated client does not parse into a list of assets — a 422 parsed as HTTPValidationError, or any status parsed as None — raises RecRegistryApiError carrying the status code and the response body.

Returning [] there is the failure this requirement exists to prevent: it fails in the direction that loses data quietly, because the caller is told, in the only language the method has, that nothing matched. A consumer resolving six hundred sensor ids for a dataspace query would conclude that none of them are registered.

The exception is the wrapper's own, not the generated layer's, and mirrors celine.sdk.dt.util.DTApiError.

REQ-0121 — a batch larger than the bound is split, not refused

Both routes accept at most MAX_BATCH_LOOKUP_IDS ids — 500, mirrored from rec-registry, where REQ-0043 and REQ-0045 read one shared constant of that name and 501 is a 422.

The wrapper splits a longer input into consecutive requests of at most that many ids and concatenates the rows in request order. Chunking is invisible to the caller: the bound is a property of the route, not a mistake the caller made.

The number is named once. It has been written twice before, in the service, and the two copies disagreed for months (rec-registry#37).

REQ-0122 — an empty batch asks nothing

No ids means no request and an empty list, matching the service, which answers an empty list without querying.

REQ-0123 — the older singular name still works

lookup_asset_by_sensor_ids — singular asset — remains as a deprecated alias delegating to lookup_assets_by_sensor_ids. It is the name digital-twin calls, and this SDK reaches its consumers through a version bump with no file in those repositories changing, so a removed method fails at runtime rather than at build.


The DID batch

REQ-0124 — the DID batch answers members, and shares the bound and the refusal rule

lookup_members_by_dids resolves a set of dataspace DIDs to the members holding them, across communities. It is the join between the connector's answer to who consented — stated in DIDs — and the registry's answer to what they hold (rec-registry REQ-0061).

It answers members, not assets, and that is the requirement rather than an implementation detail. Onboarding writes a participant's declared supply point onto the member and registers no asset, because a meter's sensor_id is assigned at physical installation — so an asset-shaped answer is empty for every participant whose meter is not yet commissioned, which is most of the population a consent-gated export covers. Every row therefore carries delivery_points, and its did, which is what lets the caller attribute a row back to the DID it asked about.

It shares the batch helper with the two asset lookups and therefore shares REQ-0120 (a refusal raises rather than answering an empty list), REQ-0121 (a batch over MAX_BATCH_LOOKUP_IDS is split and concatenated in request order) and REQ-0122 (an empty batch asks nothing). Sharing is the point: three routes with the same empty-list hazard and one implementation of it is why a fourth cannot quietly get it wrong.

A DID belonging to nobody and a member holding no supply points are deliberately indistinguishable at the service (rec-registry REQ-0061), and the wrapper adds no third meaning.