// Effect-mode: gate on the `seats` entitlement (free = 1), then write the // pending invite. Because the free plan grants a single seat, the FIRST invite // after sign-up already trips `EntitlementExceeded` unless the tenant has // upgraded / bought seats — which is exactly the seat-management moment the // frontend's team page surfaces. import { Effect } from 'effect' import type { AppContext } from '@voltro/runtime' import { EffectStore } from '@voltro/runtime' import { requireEntitlement } from '@voltro/plugin-billing' const execute = (input: { email: string }, ctx: AppContext) => Effect.gen(function* () { yield* requireEntitlement(ctx, 'seats', 1) const store = yield* EffectStore const row = yield* store.insert('invites', { email: input.email, status: 'pending' }) return { id: row['id'] as string, email: row['email'] as string, status: row['status'] as string, tenantId: row['tenantId'] as string, } }) export default execute