Queries
A query is a declared, access-checked read of a view or of owned records, so reads are as visible to the tool as writes. Never hand-write an HTTP read endpoint over runtime.store: declare a query.
View queries
Section titled “View queries”.query('MyOrders', { access: 'user', input: t.object({ status: t.optional(t.enum('placed', 'cancelled')) }), view: 'customer-orders', // The caller's own rows: the actor scopes the filter, never an input field. where: (input, actor) => q.eq('customerId', actor.id).eq('status', input.status), order: [['orderId', 'desc']], examples: [ { name: "only the caller's orders, newest id first", actor: { id: 'c1', roles: [] }, input: {}, rows: [{ orderId: 'o1', customerId: 'c1', status: 'placed', totalCents: 1 }, { orderId: 'o2', customerId: 'c2', status: 'placed', totalCents: 1 }, { orderId: 'o3', customerId: 'c1', status: 'cancelled', totalCents: 1 }], expect: { items: ['o3', 'o1'] }, }, { name: 'anonymous callers are unauthenticated', actor: null, input: {}, expect: { rejects: 'unauthenticated' } }, ],})whereusesq.eq / in / notIn / gte / lte / between / contains / prefix; undefined values skip the filter.where(input, actor, { state, now })also sees the query’sreadsand the runtime clock (pure), so a page can depend on the caller’s records and the time:q.in('storeId', state.following?.storeIds ?? []).gte('expiresAt', now).page: { size, max }bounds the page. Keyset pagination:nextis an opaque cursor (order values + key), stable while rows are inserted.atlas checkerrors on unknown fields and on an order no index serves after theeqfilters (ATLAS023, ATLAS024), and warns on a filter no index helps.
Guarded view queries. A list only some callers may see is a view query with reads and a pure guard that runs before the page is read: guard: ({ state }, r) => (state.member ? null : r.reject('not-store-member')).
Record queries
Section titled “Record queries”.query('MyProduct', { access: 'user', input: t.object({ id: t.string }), reads: { product: { from: 'products', key: (input) => input.id } }, select: ({ state, actor }, r) => (state.product?.sellerId === actor.id ? state.product : r.reject('product-not-found')), output: Product, examples: [/* { name, actor, input, state, expect: { result: { id: 'p1' } } } */],})reads work as in commands; select({ input, state, actor, now }) is pure; the output shape strips extras and validates. Sensitive output only with non-public access (ATLAS022). r.reject(code) for domain codes.
Calling a query
Section titled “Calling a query”await runtime.query('StoreProducts', { storeId: 's1' }, { actor, after, limit });// { outcome: 'ok', result: { items, next } } | rejectionAccess is required on every query (ATLAS021), as for commands, but never 'internal'. Scope “my rows” with the actor in where or in a read key, never an input field.
Codes: unknown-query, invalid-input (input, after, limit), unauthenticated, forbidden, query-failed (select, guard or where threw; the text is in the trace), store-failed, upcast-failed, result-invalid, plus domain codes from select.
Read your own writes
Section titled “Read your own writes”Views lag their commit. A dispatch can wait for them:
await runtime.dispatch(cmd, { actor, await: 'views' }); // or ['store-profiles'], timeoutMs (default 2000)// -> { outcome: 'accepted', facts, awaited: true } (false: timed out; the command committed anyway, never a failure)'views'waits for every view fed by the emitted facts; a list of names waits for those views.'all'waits for the whole cascade: every capability consumer fed by the dispatch’s facts and sent commands, then by what those deliveries wrote, and so on.- Edge subscribers and scheduled commands are never awaited. It waits for delivery and never delivers: without workers anywhere it times out with
awaited: false. - Over HTTP: the
Atlas-Await: viewsheader (or view names, orall), honored for identified callers only unless the router’sallowAwaitsays otherwise.