コンテンツにスキップ

UI for Admin — 概要

4D 運用スタッフが Guinness 管理者 API(api-admin)を操作するためのバックオフィス Web UI。


目的

  • 管理者アカウント・組織・プロジェクト・アプリユーザーの CRUD
  • 認証(ログイン・パスワード忘れ・パスワードリセット・プロフィール取得)
  • ロール(RBAC)に応じた操作可否の制御

スコープ

含むもの

  • 認証フロー全般(/auth/login、/auth/logout、/auth/forgot_password、/auth/reset_password、/auth/me)
  • /admins、/organizations、/projects、/users の一覧・詳細・作成・編集・ソフト削除・ハード削除
  • ロールフラグ(admin_access、organization_access、project_access、user_access)に基づく画面・ボタンのガード

含まないもの

  • エンドユーザー向け UI(デザイン取込・コード生成など)→ ui-user
  • MCP サーバー関連 UI → mcp-v2

バックエンド契約

  • API ソース: GenAI-Guinness-backend/apps/admin
  • OpenAPI 3.1 スペック: /api/v1/doc(JSON)
  • Swagger UI: /api/v1/docs
  • バージョン: v1(/api/v1 プレフィックス)

認証

パターン: httpOnly Cookie + ステートレス Next.js プロキシ。

採用理由:

  • JWT は JavaScript から到達不可(XSS 耐性)
  • Next.js 側にセッション状態がないので水平スケールが単純
  • SameSite=Lax + 同一オリジンプロキシで CSRF を回避

Next.js が設定する Cookie:

Cookie 属性 TTL
admin_token httpOnly, Secure, SameSite=Lax 約 15 分
admin_refresh_token httpOnly, Secure, SameSite=Lax 長期(バックエンド設定に従う)

認証フロー

フロー 動作
ログイン フォーム → Next.js /api/auth/login → 管理者 API /auth/login → 2 つの Cookie をセット → { user } のみをブラウザに返却(トークンは返さない) → TanStack Query の auth/me キャッシュをプライム
認証済みリクエスト ブラウザ /api/proxy/<path> → プロキシが Cookie 読込 → Authorization: Bearer 付与して管理者 API に転送
401 時のトークン更新 プロキシが /auth/refresh(リフレッシュ Cookie を添付)→ 成功なら admin_token Cookie を更新しオリジナルリクエストをリプレイ。ブラウザ側フェッチャーは単一の refresh Promise で並列 401 をコアレッシング(バーストごとに 1 回の refresh のみ発生)
ログアウト Next.js /api/auth/logout → 管理者 API /auth/logout(サーバー側セッション行を削除)→ 両 Cookie を削除
パスワード忘れ / リセット セッションは不要。Next.js ルートが管理者 API に素通し

採用しない方式(理由付き)

  • localStorage / sessionStorage に JWT を保存 — XSS リスク。JS から到達可能
  • インメモリのみ(リロードで消える / サイレントリフレッシュが複雑)
  • NextAuth — バックエンドセッションと衝突
  • Amplify Auth SDK — Cognito 直通のため、管理者 API のセッションテーブルと DB 由来 RBAC をバイパス

バックエンド確認事項

  1. リフレッシュエンドポイントの正確なパスとリクエスト / レスポンス形状(routes/v1/auth.ts に refreshTokenRoute のインポートはあるが詳細未確認)
  2. リフレッシュトークンの rotation 有無と、rotation 直後の旧トークンに対する grace window の有無
  3. レスポンスエンベロープ移行計画({ success, data } vs 旧形式)— フェッチャーの正規化レイヤーに影響

RBAC

管理者 API は各管理者に role フラグを付与する:

  • admin_access
  • organization_access
  • project_access
  • user_access

各フラグは AccessLevel(NONE / READ / READ_WRITE)を持つ。UI は 3 層でガードする:

  1. middleware.ts(エッジ) — admin_token Cookie の有無をチェック。なければ /login へ
  2. (authenticated)/layout.tsx(サーバーコンポーネント) — /auth/me を取得し { user, role } を Provider で子に注入。レイアウトレベルの必須フラグが READ 未満なら 404
  3. ページ / ボタン単位 — useCan(flag, level) でボタンや画面要素を非表示 / 無効化
{useCan('organization_access', 'READ_WRITE') && <CreateOrganizationButton />}

ページ構成(主要画面)

ルート 必要なロール 機能
/login 認証不要 ログイン
/forgot-password, /reset-password 認証不要 パスワードリセットフロー
/admins admin_access >= READ 管理者一覧
/admins/[id] admin_access >= READ 管理者詳細・編集(READ_WRITE でボタン表示)
/organizations organization_access >= READ 組織一覧
/organizations/[id] organization_access >= READ 組織詳細・編集
/projects project_access >= READ プロジェクト一覧(organization_id フィルタ、ページネーション、ソート)
/projects/[id] project_access >= READ プロジェクト詳細・編集
/users user_access >= READ アプリユーザー一覧
/users/[id] user_access >= READ アプリユーザー詳細・編集
/profile 認証済み 自分のプロフィール(/auth/me)、パスワード変更

アクター

運用管理者


関連ドキュメント