# Invite Link Limits Implementation Plan

## Checklist

1. Update Trellis planning artifacts and get approval to start implementation.
2. Load pre-development specs with `trellis-before-dev`.
3. Update `modules/core/server/schema.ts`:
   - Add `maxUses` and `usedCount` integer columns to `organizationInvitations`.
4. Generate or add the Drizzle migration for the new columns.
5. Update shared invitation types and row mappers:
   - `modules/core/types.ts`
   - `modules/core/server/settings.ts`
   - `modules/core/server/store.ts`
6. Update invitation creation API:
   - Parse `validityDays` and `maxUses`.
   - Validate positive integer ranges.
   - Persist `expiresAt`, `maxUses`, and `usedCount`.
7. Update invitation registration flow:
   - Reject exhausted links.
   - Increment usage inside the transaction.
   - Mark status accepted only when `usedCount` reaches `maxUses`.
   - Guard concurrent consumption with an update predicate.
8. Update frontend:
   - Add validity and maximum-use controls to `OrganizationInviteDialog`.
   - Display usage count in `OrganizationDetailClient`.
   - Update invitation explanatory text where it still says invitations are one-time only.
9. Run validation:
   - `pnpm lint`
   - `pnpm type-check`
   - `pnpm test` if tests are relevant or fast enough after type changes.
   - `pnpm build` if lint/type-check pass.

## Risk Points

- Concurrent registrations could over-consume an invite unless the update predicate checks `used_count < max_uses`.
- Existing accepted invitations should remain unusable regardless of migrated counter defaults.
- Frontend numeric inputs submit strings, so backend parsing must not trust the client.

## Rollback Points

- Before migration: schema/API/UI changes can be reverted together.
- After migration: reverting code while keeping columns is safe because defaults preserve one-use invite behavior.
