Skip to content
Registry StackDocsDevelopment (unreleased)

Base Registry Engine client capabilities

View as Markdown

The Base Registry Engine (BReg) namespace exposes native registry operations through Rust, @registrystack/client in Node, and registry-stack-client in Python. Rust owns validation and protocol behavior; the bindings expose the same selected capabilities. The table is generated from the maintained client capability inventory, checked against compiled server contracts and language exports.

CapabilityRust and PythonNode
metadata
registry_contract
registryContract
direct reads
get_record
list_records
continue_list
lookup_record
getRecord
listRecords
continueList
lookupRecord
native gis
get_geojson_record
list_geojson_records
continue_geojson_list
getGeoJsonRecord
listGeoJsonRecords
continueGeoJsonList
current
list_current_records
continue_current_list
listCurrentRecords
continueCurrentList
as of
list_records_as_of
continue_as_of_list
listRecordsAsOf
continueAsOfList
snapshot
list_snapshot_records
continue_snapshot_list
listSnapshotRecords
continueSnapshotList
revisions
record_revisions
get_record_revision
recordRevisions
getRecordRevision
proposal history
get_record
getRecord
relationships
list_relationship_records
continue_relationship_list
listRelationshipRecords
continueRelationshipList
direct writes
create_record
patch_record
createRecord
patchRecord
batch
batch_records
batchRecords
attachments
upload_attachment
download_attachment
delete_attachment
uploadAttachment
downloadAttachment
deleteAttachment
lifecycle
lifecycle_actions
execute_lifecycle_action
lifecycleActions
executeLifecycleAction
create recovery
prepare_create
recover_create
prepareCreate
recoverCreate
lifecycle recovery
prepare_lifecycle_action
recover_lifecycle_action
prepareLifecycleAction
recoverLifecycleAction
immediate actions
action_target_conditions
invoke_action
actionTargetConditions
invokeAction
tombstone
tombstone_record
tombstoneRecord

Python takes read options as keyword arguments; Node takes an options object. Rust uses an operation-specific request type. The client API reference defines client construction, outcomes, errors, attachments, and lifecycle promotion.

Parsed metadata retains operation selectors, relationship paths, reference-operation details, vocabulary labels, immediate actions, and change-request capabilities. Spatial query descriptors identify the geometry property, CRS84 coordinates, and allowed spans. Batch and tombstone descriptors carry their executable request contracts. Labels, reference descriptions, and paths convey no additional authority. The server filters every descriptor using the current caller and selected profile.

Select an immediate action by action identifier and profile, or a batch or tombstone by entity identifier and profile. Selection binds the operation to the source, package revision, profile, route, and request contract. A missing optional descriptor on an older server can still be read; an absent executable contract cannot produce a binding and returns an unsupported-capability selection error.

Upgrade the client and server together. Older strict metadata decoders can reject the added descriptors even when your application does not invoke those operations. These additions require no database migration and do not change grants or retention.

Direct native lists accept bbox alongside the scalar filters permitted by the profile. A box is four decimal strings in west, south, east, north order. Rust constructs BRegBoundingBox::new(west, south, east, north); Node passes a four-element array and Python passes a four-tuple. Coordinates use CRS84 longitude and latitude ranges, inclusive edges, and non-crossing bounds. Zero-area boxes are valid. The client rejects non-finite coordinates, reversed bounds, invalid ranges, and boxes exceeding the 256-byte wire bound. The server enforces the selected profile’s geometry/query grants and maximum spans.

For a configured establishments route and map-reader profile, a native JSON list uses:

page = client.list_records(
"establishments", access_profile="map-reader",
bbox=("100", "13", "101", "14"), top=20,
)
const page = await client.listRecords('establishments', {
accessProfile: 'map-reader', bbox: ['100', '13', '101', '14'], top: 20,
});

Use the separate GeoJSON get/list methods when you need a Feature or FeatureCollection. GeoJSON keeps Point or null geometry, selected properties, and revision metadata separate from the shared Registry Record decoder. Omitting the geometry property with select yields null geometry. A GeoJSON get supplies no mutation ETag; fetch a native record before a mutation that needs one. Use the matching GeoJSON continuation method for subsequent pages. The six /v1/gis adapter routes serve QGIS directly and have no SDK wrappers.

Temporal, revision, and relationship reads

Section titled “Temporal, revision, and relationship reads”

Current and as-of collection methods use separate routes and request types. An as-of request requires asOf in Node or as_of in Python. A snapshot request accepts the server’s snapshot reference and validAt timestamp forms (valid_at in Python). Capture the returned snapshot reference to repeat a read at that committed state. Snapshot continuations retain that identity across intervening writes. Current authority and retained-history coverage still govern every read.

Individual revision retrieval and revision lists return bounded inert JSON bytes. Read body as a Buffer in Node or bytes in Python and use a lossless JSON parser when needed. Revision lists return at most the newest 100 retained revisions and have no continuation. Proposal history is different: read the record’s request.history.nextAfterProposalVersion, then pass that value as requestHistoryAfterProposalVersion to the next record get (request_history_after_proposal_version in Python). Stop when that history cursor is null.

A relationship read takes the entity route, source-record UUID, and configured path route as three separate arguments. Discover the path through parsed metadata. The server applies path-specific authority and target projections, which can differ from direct target-list access. Only that path’s permitted scalar query options apply; bbox and temporal combinations are refused. Pass a complete continuation unchanged to the matching operation’s continuation method. Continuations bind route, profile, representation, and collection identity and accept no replacement first-page query options.

An immediate action can operate without generic record-get authority. Select its binding from metadata, retrieve target conditions explicitly, then invoke using the same binding, validated inputs, conditions, and your idempotency key. Invocation never refreshes conditions or retries automatically. Required, optional, and nullable inputs remain distinct. The action contract supplies field types and bounds; receipts expose only effects permitted by the selected profile. A declared business refusal exposes its bounded refusal code through the ordinary client error.

Batch requests contain same-entity create or patch items allowed by their selected contract, with per-item preconditions where required. Rust uses BRegBatchBuilder; Node and Python provide the equivalent structured request. An optional batch-level correction context carries a bounded reason and source references. The client validates fields, preconditions, and aggregate item/body limits before sending one atomic request. A stale item or constraint failure rolls back every item. Interval constraints are evaluated on the final batch state. The batch receipt has a snapshot and results, rather than a Registry Record envelope.

Tombstone requires its selected binding, a record ETag, and your idempotency key. Its native revision envelope identifies the resulting revision. The record disappears from live lists while permitted retained history remains readable. Record ETags and lifecycle ETags are distinct.

Prepare create or lifecycle evidence before the initial send, then persist its byte export in application-owned sensitive storage. The evidence contains the original request, conditions, profile/package binding, and caller-chosen idempotency key, with token-free and redacted string/debug representations. It is sensitive even though it carries no bearer token.

After restart, import the bytes, fetch fresh caller-filtered metadata under the original principal, and select the matching create binding or lifecycle authority. Recovery validates that binding and saved request before you explicitly replay the original attempt. An already-applied lifecycle action can be recovered even after it disappears from the current record. Do not replace its original conditions or idempotency key after an unknown outcome.

Node uses BRegPreparedCreate.fromBytes or BRegPreparedLifecycle.fromBytes and toBytes. Python uses from_bytes and to_bytes; Rust uses from_slice and as_bytes. Node and Python return opaque recovered attempts for the explicit recovered-execution methods. The application owns principal binding, integrity, access control, and lifetime of saved evidence. Importing evidence does not authenticate its owner or deserialize executable authority. Persisted recovery for other mutation families is outside this contract.