| name | feature-plan |
| description | Plan new SaaSWeave platform features end-to-end before coding — data model, core contracts, API, cache, jobs, auth, feature flags, i18n, console UI, admin, tests, and validation. Use when the user asks for a feature plan, implementation plan, backlog item design, or "how should we build X" for this monorepo. |
Feature Plan (SaaSWeave)
Produce a plan only unless the user explicitly asks to implement. Plans must account for every cross-cutting surface the feature might touch — not just API + UI.
Before planning
- Read the smallest relevant doc set from
AGENTS.md (start with .agents/end-to-end-features.md).
- Scan existing capabilities in
packages/core/src/features/types.ts (DEFAULT_FEATURES, PLANNED_FEATURES) — reuse patterns from similar shipped features.
- Grep the codebase for an existing partial implementation before designing from scratch.
Shipped feature inventory (reference)
| Key | Category | Typical surfaces |
|---|
api_keys | Core | DB, API keys lib, console /app/api-keys, webhooks events |
api_key_scopes | Core | packages/core/api-keys, requireApiKeyScope, key create UI |
webhooks | Core | DB, console webhooks, dispatchOrgWebhook, signing |
ai_assistant | AI | Console AI usage, metered billing, cache on reads |
sso | Security | Better Auth SSO plugin, settings panel, SAML registration |
audit_logs | Security | recordAudit, console /app/audit, admin audit |
audit_export | Security | Export API, rate limit, CSV/JSON, audit_export + audit_logs flags |
ip_allowlist | Security | DB rules, orgProcedure IP enforcement, settings panel, cache 60s |
magic_link | Security | Better Auth plugin, mailer template, global flag, auth rate limit |
usage_billing | Billing | recordUsage, Stripe meters, billing meters UI |
annual_billing | Billing | Stripe STRIPE_PRICES, checkout guard, billing UI interval toggle |
Roadmap-only keys live in PLANNED_FEATURES — do not plan them as toggleable until a real surface exists.
Planning workflow
Phase 1 — Problem & scope
Answer in the plan:
- User outcome — who benefits (workspace member, admin, integration caller)?
- Auth path — session only, API key, public, or platform admin?
- Tenant scope — per-organization, platform-wide, or user?
- Feature flag — new key in
DEFAULT_FEATURES (shipped) or PLANNED_FEATURES (roadmap)? Category?
- Plan gating — which
availableOn plan ids?
Phase 2 — Cross-cutting decision matrix
For each row, state Yes / No / N/A and the concrete approach. Do not skip rows — mark N/A with one line why.
| Concern | When Yes | Pattern in repo |
|---|
| DB migration | New/changed persisted fields | packages/db/src/schema/, vp run db:generate, vp run db:migrate |
| Core contract | Shared enums, limits, formatters across packages | packages/core/src/<domain>/, export in package.json |
| Feature flag (org) | Toggle per workspace | requireFeature("key"), isFeatureEnabledForOrg, requireConsoleFeature, nav featureKey |
| Feature flag (global) | Auth/platform behavior without org context | isFeatureGloballyEnabled in packages/db/src/features.ts |
| API procedure | New/changed RPC | orgProcedure, integrationProcedure, adminProcedure, requireApiKeyScope |
| IP allowlist | Org/integration mutations when ip_allowlist on | Automatic on orgProcedure / integrationProcedure via assertIpAllowedForOrganization |
| Audit log | Security-relevant mutations | recordAudit() — never throw from audit |
| Webhooks | External notification of domain events | dispatchOrgWebhook, extend WEBHOOK_EVENTS in core |
| Cache read | Expensive repeated reads, stable for TTL | cacheWrap + tags — see redis-workers-cache |
| Cache invalidate | Writes that stale cached reads | cacheInvalidateTag after mutation |
| Rate limit |
Do not cache: auth sessions, API key verification, export blobs, raw audit pages.
Phase 3 — Layer-by-layer design
Follow implementation order from end-to-end-features.md:
- DB — tables/columns, indexes, FKs, backfill strategy for existing rows
- Core — Zod schemas, constants, pure helpers (no DB imports in core)
- DB helpers — query/export functions in
packages/db if needed
- Application service — reusable domain/storage/provider logic in
packages/app
- Jobs/mailer — queue orchestration, processors, schedules, retention, notifications
- API — router shape, inputs, typed errors, enforcement middleware chain
- Web data layer —
*.query.ts / *.mutation.ts with queryOptions
- Routes & UI — page, guards, empty/error states
- Admin & flags — seed flag, admin toggle (usually already wired)
- Validation — commands from workflow.md
Phase 4 — Plan output format
Write the plan to docs/plans/<feature-slug>.md (or deliver in chat if the user only wants a draft). Use this structure:
# <Feature name> (`<feature_key>`)
## Goal
One paragraph: problem, user, success criteria.
## Current state
| Area | Status |
| ---- | ------ |
| ... | ... |
## Feature flag
- key, category, default `enabled`, `availableOn`
- Org-scoped vs global enforcement
## Cross-cutting checklist
| Concern | Decision | Notes |
| ------------- | -------- | ------------------ |
| DB migration | Yes/No | ... |
| Core contract | Yes/No | ... |
| Cache | Yes/No | key, TTL, tags |
| Rate limit | Yes/No | key, limit, window |
| i18n | Yes/No | key prefixes |
| ... | ... | ... |
## Data model
Schema snippets or field list; migration notes; legacy behavior.
## API
| Procedure | Auth | Middleware | Scopes |
| --------- | ---- | ---------- | ------ |
| ... | ... | ... | ... |
## Web UI
| Surface | Gating | Work |
| ------- | ------ | ---- |
| ... | ... | ... |
## Phases
| Phase | Deliverable | Validation |
| ----- | ----------- | ----------------- |
| 1a | ... | `vp check` in ... |
| 1b | ... | unit test ... |
## Tests
- Bullet list of meaningful tests (not trivial UI asserts)
## Open questions
- Only genuine product/architecture decisions left for the user
Phase 5 — Quality bar before "shipped"
A feature is not ready for DEFAULT_FEATURES until:
Similar-feature shortcuts
When planning, explicitly name the template feature to copy:
| Building | Copy from |
|---|
| Settings panel CRUD | sso-settings-panel.tsx, ip-allowlist-settings-panel.tsx |
| Console list + create sheet | api-keys-page.tsx, webhooks pages |
| Toggleable billing behavior | annual_billing + billing-page.tsx |
| Export + rate limit | audit-export.ts |
| Auth method | magic_link + OAuthButtons |
| Scoped API key access | api_key_scopes + requireApiKeyScope |
| Cached org settings | packages/api/src/lib/ip-allowlist.ts, settings.ts |
Anti-patterns
- Planning UI before API enforcement exists
- Feature flag in env only (prefer DB + admin toggle; env only for provider secrets)
- Duplicating domain literals in web and API (use
packages/core)
- Caching auth or API key verification
- Adding to
DEFAULT_FEATURES before console + API enforcement ship
- Skipping i18n because "it's internal" — console copy always goes through Paraglide
Additional resources