// `content.get` — one content row by id, for the edit form. Returns the full // row (arbitrary per-type fields), so the output is a loose record rather than a // closed struct. `status` selects the table: 'draft' (the editor's in-progress // copy, the default) or 'published' (the live copy). A row outside the caller's // tenant reads as absent (null) — the store scope never returns it. import { defineAction } from '@voltro/protocol' import { Schema } from 'effect' export const getContent = defineAction({ name: 'content.get', // Editors only — it returns the FULL row, every per-type field, for a // caller-supplied id. Tenant scoping already makes another tenant's row read // as absent; this decides whether an unauthenticated visitor may ask at all. // Satisfied by a signed-in session (`auth.resolveScopes` in app.config.ts // grants `content:read` to a matched subject); anonymous callers hold no // scopes and are refused. guards: [{ scope: 'content:read' }], input: Schema.Struct({ type: Schema.NonEmptyString, id: Schema.NonEmptyString, status: Schema.optional(Schema.Literal('draft', 'published')), }), output: Schema.Struct({ row: Schema.NullOr(Schema.Record({ key: Schema.String, value: Schema.Unknown })), }), })