1このシステムは何?
学会の「演題投稿 → 査読 → 採否 → プログラム編成 → 参加登録 → 決済 → 当日運営」を一気通貫で管理するSaaS。
2全体構造(セキュリティ5層)
ユーザー(ブラウザ) 演者 / 査読者 / 管理者 / HP訪問者 HTTPS 1 Layer 1: Edge Middleware(middleware.ts) AIクローラー → 403ブロック(14パターン) レート制限(パス別、デフォルト60req/分) / ロール不足 → /login にリダイレクト 通過リクエストのみ 2 Layer 2: ページ(src/app/) (hp)/ 公開HP 🔓 (auth)/ ログイン 🔓 (main)/ 一般機能 🔒 admin/ 管理画面 🔒 api/ API 🔒 approve/ 共同演者 🔓 データ操作 3 Layer 3: Server Actions(src/lib/actions/ 43ファイル) 全アクションの先頭で: requireAuth() → ログイン確認 / requireRole('organizer') → ロール権限確認 Layer 4: Zodバリデーション 4 Layer 4: Zodバリデーション — abstract.ts / auth.ts / registration.ts → 入力データの型・形式を検証 検証済みデータ 5 Layer 5: Supabase RLS(行レベルセキュリティ) 「誰が」「どのデータを」見れるかをDB側で強制 author 自分の演題のみ reviewer 自分の査読のみ organizer 全データ閲覧・編集 service_role(RLSバイパス) Webhook + Cronのみ / 他は禁止 Supabase PostgreSQL 37マイグレーション / 30+テーブル
3ロール階層(権限の強さ)
admin Level 4 — 最高権限(全機能) organizer Level 3 — 管理者画面28セクション reviewer Level 2 — 査読機能 author Level 1 — 演題投稿・閲覧のみ ▼ 含む ▼ 含む ▼ 含む
4演題の状態遷移(ライフサイクル)
draft 下書き 投稿確定 submitted 提出済み 査読割当 under_review 査読中 採択 accepted 採択 不採択 rejected 不採択 revision_requested 修正依頼 ※ どの状態からも → withdrawn(取り下げ)に遷移可能
5外部サービスとの接続
endai-system Next.js on Vercel Supabase DB + Auth + RLS Stripe 決済 Resend メール送信 Claude API Haiku: FAQチャット 月$5上限 Sonnet: 演題支援 Web Push ブラウザ通知
6決済フロー(Stripe連携)
参加者 endai Stripe Supabase ① 参加登録 ② Checkout Session 作成 ③ Stripe決済画面リダイレクト ④ カード入力・決済 ⑤ Webhook通知(署名検証) ⑥ status更新 → paid/confirmed ⑦ 確認メール送信
7Claude API 匿名化フロー
演題データ 氏名・所属を含む (個人情報あり) anonymizer.ts ローカル処理 氏名 → SPEAKER-001 所属 → ORG-001 匿名化済み Claude API カテゴリ分類 フォーマットチェック 7日で自動削除 IDのみ claude-logger.ts PIIマスクして記録 (トークン数のみ)
8Server Actions の分類(43ファイル)

演題管理

  • abstract.ts — 投稿CRUD、下書き保存、排他制御
  • coauthor-approval.ts — 共同演者トークン承認
  • admin.ts — 採否判定一括、ページネーション

査読

  • review.ts — 割り当て(利益相反チェック付き)、提出
  • reviewer.ts — 査読者管理、CSVインポート
  • reviewer-invitation.ts — トークン招待フロー

AI連携

  • ai-abstract.ts — フォーマットチェック(Sonnet)
  • ai-email.ts — メール文面生成(Sonnet)
  • ai-analytics.ts — 統計コメント生成(Haiku)
  • ai-review-criteria.ts — 査読基準生成(Sonnet)

決済・登録

  • registration.ts — Stripe Checkout、クーポン
  • auth.ts — login/register/logout、Google OAuth

通知・メール

  • batch-email / bulk-email
  • notification / push

その他

  • timetable / session-qa / survey
  • chatbot-inquiry / checkin / faq
  • sns-post 等
9データベース主要テーブル(関係図)
conferences (大会) categories (カテゴリ) sessions (セッション) registration_fees (参加費マスタ) abstracts (演題本体) session_assignments (割り当て) registrations (参加登録) abstract_authors 著者、approval_token abstract_affiliations (所属機関) reviews 査読、8項目スコア payment_logs Stripe決済ログ coupons 割引クーポン reviewer_conflicts (利益相反)

コミュニケーション系: announcements / email_notifications / notifications / push_subscriptions / session_qa / batch_emails
拡張系: ads / surveys / chatbot_inquiries / researcher_profiles / research_outputs / audit_logs / access_logs

10管理画面のセクション構成(28セクション)
カテゴリセクション
演題管理abstracts, categories, export
査読管理reviewers, review-progress, review-criteria
プログラムtimetable, timetable/editor
登録・決済registrations, registration-fees, coupons
問い合わせinquiries, chatbot-inquiries, chatbot-escalations, faqs
メールemail-templates, email-history, batch-emails
告知announcements, ads, sns
分析statistics, access-logs, audit-logs
その他surveys, checkin, conference, users
11設計上の注意点
項目内容
単一大会想定 conferenceslimit(1).single() でクエリ。複数大会未対応
排他制御の限界 submission-queue は in-memory。Vercelインスタンス間で共有されない。DBの UNIQUE 制約が最終防衛ライン
service_role の限定使用 Stripe Webhook と Cron の2箇所のみ
コスト管理 FAQ(Haiku)+ 問い合わせ(Sonnet)で月$5上限を共有