Skip to content

Read local state and recover replay

ALYT provides a bounded way to read local environmental state, keep it current with replay, and recover safely when replay cannot continue. The practical flow is: capture a bounded snapshot from the property-scoped export, durably store its facts and cursor together, request replay using the last committed cursor, and resnapshot whenever access, inventory, or retained history no longer line up. For model-safe reads inside an installed runtime, use POST /environment/context, which returns a bounded local view without native bindings, credentials, the replay cursor, or any authority grant.

Use these endpoints for the environmental record:

OperationEndpointRequest schemaResponse schema
SnapshotPOST /properties/:propertyId/environment/snapshot?tenantId=...alyt.environment-snapshot-query/draft-0.1.0alyt.environment-snapshot/draft-0.1.0
ReplayPOST /properties/:propertyId/environment/replay?tenantId=...alyt.environment-replay-query/draft-0.1.0alyt.environment-replay/draft-0.1.0

Snapshot and replay require ordinary household authentication, a current live session and membership, and explicit tenant and property scope. Current session and membership checks still apply even when a replay stream is unknown. Ordinary application API keys do not grant this export.

The exported snapshot includes a checksum and data with the tenant, property, inventory revision, decimal cursor, a finite read-only lease, a normalized view, and private native bindings. A checksum detects corruption; it is not a signature or a permission grant.

Use this sequence:

  1. Request a snapshot.
  2. Validate it and persist the snapshot facts and cursor together before serving them.
  3. Call replay with the last durably committed cursor in after.
  4. Apply the returned contiguous revision prefix.
  5. Commit updated facts and the new cursor together.
  6. In the next replay request, acknowledge only that committed cursor.
  7. If replay returns RESNAPSHOT, withdraw the old record and fetch a new authorized snapshot.

Duplicate committed revisions have no repeated effect. If a write fails, keep the previous durable cursor.

Decimal cursors are decimal strings that preserve signed 64-bit values. Do not convert them to JavaScript numbers.

A snapshot response uses alyt.environment-snapshot/draft-0.1.0. The useful developer-facing parts are:

  • tenantId
  • propertyId
  • inventoryRevision
  • cursor
  • authority
  • view
  • bindings

The read lease is finite and lasts at most five minutes. Treat it as temporary permission to read cached local state, not as a reusable token. WAN loss cannot renew that lease. Cloud-primary access requires current cloud permission, while commissioned local-primary access renews only with fresh authenticated local ALYT permission without WAN; replay does not automatically elect a new primary or a second writer.

Persistent local graph and event proposals

Section titled “Persistent local graph and event proposals”

The installed runtime also keeps the existing local graph record in alyt.local-environment/draft-0.2.0. That record uses the same single writer for snapshot facts, replay cursor, original event journal, and optional installed-routine footprints. The journal holds at most 64 events / 65,536 UTF-8 bytes, the full record is at most 217,088 bytes, and one sealed previous version is retained. Older 0.1 files migrate without renewing authority. Missing baseline history, gaps, stream changes, and inventory changes stay explicit; no complete history is loaded.

POST /environment/semantic-query uses the existing local internal key and returns the original typed semantic query/result contract with current context, source, and expiry. Requests, acknowledgements, and model claims never become physical observations.

The authenticated ALYT-owned stream also exposes POST /properties/:propertyId/environment/routine-footprints?tenantId=... and POST /properties/:propertyId/environment/event-proposal?tenantId=... on the same properties controller as internal: true. Footprints use alyt.routine-footprints/1.0.0 and report current routine version plus opaque room/entity/control refs with COMPLETE, PARTIAL, or UNKNOWN effect status. Event proposals recheck the original declared goal or scope, current physical cursor, inventory, membership, and unchanged physical preconditions, then submit a PENDING_APPROVAL record. The household review, deterministic fence, execution, and outcome verifier remain mandatory; transport ACK is not confirmation. Restart never resends a RUNNING intent. When the runner explicitly negotiates alyt.reasoning-graph-input/1.1.0, it may correlate findings against the exact selectedDeclaredGoalId and the supplied footprint revision, but typed targets remain unknown and the legacy 1.0 and frozen qualified contracts stay unchanged; the model only carries a claim, with physicalConfirmation:false and no authority to approve or update anything.

The normalized view contains model-safe records such as rooms, entities, controls, observations, and routines. Installed routine versions come from the hub’s installed report, not from a cloud desired definition. Validation of whether a routine can run happens separately.

bindings remain inside ALYT and cover exactly the returned inventory. They are engine-only and should never be exposed to a model.

Snapshot size is limited to 131,072 bytes.

Replay requests use:

  • streamId
  • inventoryRevision
  • after

A successful delta response is ordered, contiguous, and delivered as REPLAY. Each replayed field preserves its original occurrence time, receipt time, expiry, clock quality, provenance, and sequence.

Replaying a field does not make it fresh and does not re-run routines, button presses, semantic events, or commands. Compare replayed state with the canonical normalized field view instead of treating replay delivery time as physical observation time.

A bounded invisible record can advance the cursor without exposing native IDs.

Replay limits are:

  • at most 32 events
  • at most 65,536 bytes

If a replay page would exceed those limits, only a fully valid committed prefix is returned. Preserve explicit omissions and historyIncomplete instead of inventing missing history.

Replay can return RESNAPSHOT with one of these reasons:

  • STREAM_UNAVAILABLE
  • INVENTORY_CHANGED
  • RETENTION_GAP
  • CURSOR_AHEAD
  • INCOMPLETE_EVENT

When this happens:

  1. Withdraw read authority for the old record.
  2. Persist the invalidation barrier in both local versions.
  3. Request a newly authorized bounded snapshot.

Do not skip a missing revision. Do not continue serving a deleted entity from backup.

If tombstones are present, they name old model references, not native device identities.

Legacy retained values without a canonical journal record belong to the snapshot baseline. If that baseline changes, recover with a bounded resnapshot rather than silently carrying an old UNKNOWN value forward with an unchanged cursor. Original age and UNKNOWN quality are preserved.

The installed runtime keeps a separate environmental store. The environmental file never replaces property-config.json or the routine executor.

Persist one sealed record containing both snapshot facts and cursor, with atomic durable replacement. After restart, cached facts and cursor can load without current read permission, but they are not available as current local context until a fresh ALYT-authenticated response restores a valid lease.

Important behaviors:

  • a fresh authenticated response establishes a lease of at most five minutes
  • access refusal or re-enrollment withholds old reads immediately
  • unknown clock evidence remains UNKNOWN
  • failure or recovery does not clear ordinary property configuration

Fresh original authenticated Tenant replay does renew the finite 5 minute read lease only after current membership and session checks. Applying cached local replay does not renew permission or original physical expiry. Cloud-primary requires current cloud permission and cannot renew stale cloud access during WAN loss; commissioned local-primary can renew current local permission without WAN. There is no automatic primary election or second writer. Expired reads are withheld until a fresh authorized snapshot or live replay succeeds.

For bounded model-safe reads, call POST /environment/context on the installed runtime.

This endpoint is protected by the runtime’s existing local internal key. The key belongs to the trusted adapter, not the model.

Use request schema alyt.context-query/draft-0.1.0 with:

  • purpose
  • roomRefs
  • entityRefs
  • historyWindowMs
  • maxNodes
  • maxObservations
  • maxBytes
  • cursor

References and paging are pinned to the returned contextId and sourceRevision. Expired, changed, or foreign contexts and cursors require a new view.

The response contains model-safe evidence only. It excludes native bindings, tenant credentials, the replay cursor, and any permission grant.

Current paging behavior is bounded:

  • up to 32 cached page cursors
  • up to 8 cached local contexts
  • if the byte budget cannot fit a page, the query fails and you must increase maxBytes

The existing model view ceiling is 65,536 bytes.

Read-only projection configuration does not enable inference or execution. Disabling it preserves ordinary device control, routines, and current voice paths.

Snapshot and replay are narrower than staff-wide access: household permissions are narrower than staff, and the selected home’s current access is rechecked on every call. DEV credentials act in the developer sandbox, and LIVE credentials only for their own installed connector.

Never copy a platform internal key into the home, and never place trusted adapter credentials into model context.

Last updated