// Creates a document (title only — the CRDT `body` starts empty and is // established by the first `documents.setBody` write). The handler's // `assertOwnTenant` guard rejects cross-tenant spoofing: input.tenantId MUST // match the resolved subject's tenantId, else a typed `TenantMismatch`. import { defineMutation } from '@voltro/protocol' import { TenantMismatch } from '@voltro/plugin-multitenancy/guard' import { Schema } from 'effect' export const createDocument = defineMutation({ name: 'documents.create', // Open: inserts a title the caller supplied into the caller's own tenant // (`assertOwnTenant` rejects a mismatched `tenantId`) and touches no existing // row. With no auth strategy configured every caller is an anonymous Subject // holding no scopes, so a `guards: [{ scope }]` would deny all of them. openAccess: 'inserts a new document (title only, empty CRDT body) into the caller\'s own tenant; ' + '`assertOwnTenant` rejects a mismatch and no existing row is touched. No auth strategy ' + 'ships here, so there is no identity a scope guard could name.', target: { table: 'documents', op: 'insert', shape: (input: { tenantId: string; title: string }) => ({ title: input.title, body: null, tenantId: input.tenantId, createdAt: new Date(), }), }, input: Schema.Struct({ tenantId: Schema.String, title: Schema.NonEmptyString, }), output: Schema.Struct({ id: Schema.String, title: Schema.String, // The CRDT `body` rides the wire as its encoded bytes (nullable until the // first edit establishes it). Decode with `decodeCrdtText()` on the client. body: Schema.NullOr(Schema.Uint8ArrayFromBase64), tenantId: Schema.String, createdAt: Schema.Date, }), error: TenantMismatch, })