This PR adds two product-facing flows on the create and marketing surfaces.
Stakeholder management extends publish and post-publish editing: invite stakeholders by email, resend or revoke invites, and accept invites via a one-time verify link. The create flow gains a manage-stakeholders path from confirm-stakeholders and profile, with API coverage and Prisma persistence.
Ask an organizer (CR-107) replaces link-based marketing CTAs with a Create-shell modal (email + question). Submissions go to POST /api/organizer-inquiry with validation, rate limits, and a honeypot; delivery is email-only via ORGANIZER_INQUIRY_TO and existing SMTP. Staging inbox wiring is tracked in CR-114.
Changes
Stakeholders:RuleStakeholder model and migration; stakeholder routes under app/api/rules/[id]/stakeholders (list, invite, revoke, resend); GET /api/invites/rule-stakeholder/verify; publish path sends stakeholder invite mail; PublishedStakeholdersManagePanel and confirm-stakeholders updates; create-flow navigation and lib/create/api client helpers; mail helper for stakeholder invites.
Ask an organizer:AskOrganizerInquiry modal (Create shell, TextInput / TextArea, optional showHelpIcon={false} on email); modal-only AskOrganizer CTA on home, learn, and blog; POST /api/organizer-inquiry with Zod schema, per-IP and per-email rate limits, honeypot silent success; sendOrganizerInquiryNotification with replyTo; ORGANIZER_INQUIRY_TO documented in .env.example; optional footerClassName on Create for full-width footer actions.
Create / export: Rule export and TextBlock row media handling; progress bar removed on edit-rule screens; small create-flow and profile polish.
i18n:messages/en/modals/askOrganizerInquiry.json and related marketing / askOrganizer copy; success copy without em dash or semicolon.
Tests: Unit coverage for organizer-inquiry route, stakeholder routes, publish with invites, and verify route; component and page tests for AskOrganizer and create-flow surfaces; E2E critical journey opens the organizer dialog.
Screenshots
How to Test
Copy .env.example to .env. Set SESSION_SECRET, DATABASE_URL, and ORGANIZER_INQUIRY_TO. For real SMTP locally: docker compose up -d postgres mailhog, SMTP_URL=smtp://localhost:1025, Mailhog at http://localhost:8025. Run npx prisma migrate dev, then npm run dev.
Ask an organizer: On /, /learn, or a blog post, click Ask an organizer. Confirm email has no help icon, Confirm Question is centered, validation on bad input, and success copy reads smoothly. Submit a valid question; expect POST /api/organizer-inquiry → 200 { ok: true } and a message to ORGANIZER_INQUIRY_TO with visitor reply-to and request id (or a dev log if SMTP_URL is unset).
Stakeholders: Publish a rule with stakeholder emails (signed in, backend sync on if drafts use the API). Exercise manage-stakeholders from create or profile: invite, resend, revoke. Open the verify link in the same browser; confirm access and mail in Mailhog or logs.
Automated:npx tsc --noEmit, npx vitest run, npx next build. Optionally npm run e2e for the homepage organizer dialog step.
Notes
Deploy: Set ORGANIZER_INQUIRY_TO per environment; staging follow-up is CR-114. Production needs a real support or organizer inbox at cutover.
Organizer inquiries are email-only (no Prisma row); rate limits stay in-memory per instance.
Stakeholder invites reuse the magic-link mail pattern (hashed token, 15-minute TTL).
Storybook LinkCta on AskOrganizer keeps a legacy link CTA for comparison; marketing pages use the modal path only.
## Overview
This PR adds two product-facing flows on the create and marketing surfaces.
**Stakeholder management** extends publish and post-publish editing: invite stakeholders by email, resend or revoke invites, and accept invites via a one-time verify link. The create flow gains a manage-stakeholders path from confirm-stakeholders and profile, with API coverage and Prisma persistence.
**Ask an organizer ([CR-107](https://linear.app/community-rule/issue/CR-107/feature-ask-an-organizer))** replaces link-based marketing CTAs with a Create-shell modal (email + question). Submissions go to `POST /api/organizer-inquiry` with validation, rate limits, and a honeypot; delivery is email-only via `ORGANIZER_INQUIRY_TO` and existing SMTP. Staging inbox wiring is tracked in [CR-114](https://linear.app/community-rule/issue/CR-114/backend-staging-wire-ask-an-organizer-smtp-test-inbox).
## Changes
- **Stakeholders:** `RuleStakeholder` model and migration; stakeholder routes under `app/api/rules/[id]/stakeholders` (list, invite, revoke, resend); `GET /api/invites/rule-stakeholder/verify`; publish path sends stakeholder invite mail; `PublishedStakeholdersManagePanel` and confirm-stakeholders updates; create-flow navigation and `lib/create/api` client helpers; mail helper for stakeholder invites.
- **Ask an organizer:** `AskOrganizerInquiry` modal (Create shell, `TextInput` / `TextArea`, optional `showHelpIcon={false}` on email); modal-only `AskOrganizer` CTA on home, learn, and blog; `POST /api/organizer-inquiry` with Zod schema, per-IP and per-email rate limits, honeypot silent success; `sendOrganizerInquiryNotification` with `replyTo`; `ORGANIZER_INQUIRY_TO` documented in `.env.example`; optional `footerClassName` on Create for full-width footer actions.
- **Create / export:** Rule export and `TextBlock` row media handling; progress bar removed on edit-rule screens; small create-flow and profile polish.
- **i18n:** `messages/en/modals/askOrganizerInquiry.json` and related marketing / askOrganizer copy; success copy without em dash or semicolon.
- **Tests:** Unit coverage for organizer-inquiry route, stakeholder routes, publish with invites, and verify route; component and page tests for AskOrganizer and create-flow surfaces; E2E critical journey opens the organizer dialog.
## Screenshots
<img width="1126" alt="Screenshot 2026-05-11 at 6.12.58 PM.png" src="attachments/822613e9-9ce5-44e4-9fd2-688c058d0bda">
<img width="1126" alt="Screenshot 2026-05-11 at 6.14.32 PM.png" src="attachments/2ebd6dea-8363-405b-9705-8caaf1b30786">
<img width="1126" alt="Screenshot 2026-05-11 at 6.14.56 PM.png" src="attachments/1c64a742-5d25-4a48-b7c3-c0aa8fd864cc">
<img width="1126" alt="Screenshot 2026-05-11 at 6.15.06 PM.png" src="attachments/9a74d16f-982f-49d5-b19b-433cadf88bd9">
## How to Test
1. Copy `.env.example` to `.env`. Set `SESSION_SECRET`, `DATABASE_URL`, and `ORGANIZER_INQUIRY_TO`. For real SMTP locally: `docker compose up -d postgres mailhog`, `SMTP_URL=smtp://localhost:1025`, Mailhog at http://localhost:8025. Run `npx prisma migrate dev`, then `npm run dev`.
2. **Ask an organizer:** On `/`, `/learn`, or a blog post, click **Ask an organizer**. Confirm email has no help icon, **Confirm Question** is centered, validation on bad input, and success copy reads smoothly. Submit a valid question; expect `POST /api/organizer-inquiry` → 200 `{ ok: true }` and a message to `ORGANIZER_INQUIRY_TO` with visitor reply-to and request id (or a dev log if `SMTP_URL` is unset).
3. **Stakeholders:** Publish a rule with stakeholder emails (signed in, backend sync on if drafts use the API). Exercise manage-stakeholders from create or profile: invite, resend, revoke. Open the verify link in the same browser; confirm access and mail in Mailhog or logs.
4. **Automated:** `npx tsc --noEmit`, `npx vitest run`, `npx next build`. Optionally `npm run e2e` for the homepage organizer dialog step.
## Notes
- **Deploy:** Set `ORGANIZER_INQUIRY_TO` per environment; staging follow-up is [CR-114](https://linear.app/community-rule/issue/CR-114/backend-staging-wire-ask-an-organizer-smtp-test-inbox). Production needs a real support or organizer inbox at cutover.
- Organizer inquiries are **email-only** (no Prisma row); rate limits stay in-memory per instance.
- Stakeholder invites reuse the magic-link mail pattern (hashed token, 15-minute TTL).
- Storybook **LinkCta** on AskOrganizer keeps a legacy link CTA for comparison; marketing pages use the modal path only.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Overview
This PR adds two product-facing flows on the create and marketing surfaces.
Stakeholder management extends publish and post-publish editing: invite stakeholders by email, resend or revoke invites, and accept invites via a one-time verify link. The create flow gains a manage-stakeholders path from confirm-stakeholders and profile, with API coverage and Prisma persistence.
Ask an organizer (CR-107) replaces link-based marketing CTAs with a Create-shell modal (email + question). Submissions go to
POST /api/organizer-inquirywith validation, rate limits, and a honeypot; delivery is email-only viaORGANIZER_INQUIRY_TOand existing SMTP. Staging inbox wiring is tracked in CR-114.Changes
RuleStakeholdermodel and migration; stakeholder routes underapp/api/rules/[id]/stakeholders(list, invite, revoke, resend);GET /api/invites/rule-stakeholder/verify; publish path sends stakeholder invite mail;PublishedStakeholdersManagePaneland confirm-stakeholders updates; create-flow navigation andlib/create/apiclient helpers; mail helper for stakeholder invites.AskOrganizerInquirymodal (Create shell,TextInput/TextArea, optionalshowHelpIcon={false}on email); modal-onlyAskOrganizerCTA on home, learn, and blog;POST /api/organizer-inquirywith Zod schema, per-IP and per-email rate limits, honeypot silent success;sendOrganizerInquiryNotificationwithreplyTo;ORGANIZER_INQUIRY_TOdocumented in.env.example; optionalfooterClassNameon Create for full-width footer actions.TextBlockrow media handling; progress bar removed on edit-rule screens; small create-flow and profile polish.messages/en/modals/askOrganizerInquiry.jsonand related marketing / askOrganizer copy; success copy without em dash or semicolon.Screenshots
How to Test
.env.exampleto.env. SetSESSION_SECRET,DATABASE_URL, andORGANIZER_INQUIRY_TO. For real SMTP locally:docker compose up -d postgres mailhog,SMTP_URL=smtp://localhost:1025, Mailhog at http://localhost:8025. Runnpx prisma migrate dev, thennpm run dev./,/learn, or a blog post, click Ask an organizer. Confirm email has no help icon, Confirm Question is centered, validation on bad input, and success copy reads smoothly. Submit a valid question; expectPOST /api/organizer-inquiry→ 200{ ok: true }and a message toORGANIZER_INQUIRY_TOwith visitor reply-to and request id (or a dev log ifSMTP_URLis unset).npx tsc --noEmit,npx vitest run,npx next build. Optionallynpm run e2efor the homepage organizer dialog step.Notes
ORGANIZER_INQUIRY_TOper environment; staging follow-up is CR-114. Production needs a real support or organizer inbox at cutover.