// Creates a note. The handler's `assertOwnTenant` guard rejects // cross-tenant spoofing — input.tenantId MUST match the resolved // subject's tenantId, else the rpc layer surfaces a typed // `TenantMismatch` error. import { defineMutation } from '@voltro/protocol' import { TenantMismatch } from '@voltro/plugin-multitenancy/guard' import { Schema } from 'effect' export const createNote = defineMutation({ name: 'notes.create', // Open, deliberately — see `queries/notes.query.ts` for the long form. In // short: `assertOwnTenant` still rejects a `tenantId` that does not match the // resolved subject, but with no auth strategy configured that subject is // anonymous and holds no scopes, so any `guards: [{ scope }]` would deny // every caller instead of some of them. openAccess: 'inserts a note carrying only what the caller sent, into the caller\'s own tenant ' + '(`assertOwnTenant` rejects a mismatch). No auth strategy ships in this template, so ' + 'there is no identity a scope guard could name.', target: { table: 'notes', op: 'insert', shape: (input: { tenantId: string; title: string; body: string }) => ({ title: input.title, body: input.body, done: false, tenantId: input.tenantId, createdAt: new Date(), }), }, input: Schema.Struct({ tenantId: Schema.String, title: Schema.NonEmptyString, body: Schema.String, }), output: Schema.Struct({ id: Schema.String, title: Schema.String, body: Schema.String, done: Schema.Boolean, tenantId: Schema.String, createdAt: Schema.Date, }), error: TenantMismatch, })