コンテンツにスキップ
Documents for MorningStatusApp
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

世代マトリックス データ設計書

最終更新: 2026-09-21 関連 Issue: MorningStatusApp#1571(親Issue)/ #128(初版の設計書作成)/ #141(原仕様に沿った表示への改訂)/ MorningStatusApp#1632(実装)


1. 概要

OGメンバーの子供の誕生年と、現役メンバーの誕生年が交差する「世代の重なり」を年×メンバーのグリッドで可視化する世代マトリックス(Generational Matrix)機能のデータ設計。

親Issue(MorningStatusApp#1571)での検討の結果、以下の方針で設計する。

  • OGの子供について、性別・氏名等の機微な属性は一切保持せず、生年(西暦)のみを新規データとして追加する
  • 既存の Vercel Blob 書き込みはすべて access: 'public' であり非公開データの置き場に使えないため、子供の生年データは Neon(Vercel Postgres)に格納する
  • 画面自体もナビゲーションから一切リンクしない隠しルートとし、加えてシークレットモード(本書§3)で保護する。詳細な画面仕様は 世代マトリックス 画面設計書 を参照

本人(OG・現役問わず全メンバー)の生年月日・加入日・卒業日は、既存の Member.profile.dob・joinDate・gradDate(Vercel Blob members.json)をそのまま使う。新規に追加するのは子供の生年データのみ。


2. テーブル設計

2-1. member_children(MemberChild)

OGメンバーの子供1人につき1レコードを持つ。同じメンバーが複数の子供を持つ場合は複数行になる(一意制約なし)。

カラム 型 制約 説明
id INT PK, AUTO INCREMENT ID
memberId VARCHAR(50) NOT NULL 親であるメンバーの ID(Blob members.json の Member.id を参照。member_relationships(メンバー関係性マップ データ設計書 §2-1)と同様、DBレベルのFK制約は持たない)
birthYear INT NOT NULL 子供の生年(西暦)。月日は保持しない
  • インデックス: memberId(単列)
  • Prisma モデル名: MemberChild(@@map("member_children"))
  • 運用上、memberId は現時点でOGメンバーのみを想定する(現役メンバーの子供は本書執筆時点で公表情報が存在しないため)。ただしDBレベルでOG限定を強制する制約は設けない。将来的に現役メンバーの子供が公表された場合も、同じテーブル・同じ手順でそのまま追加できる

氏名・性別・誕生日(月日)を持たない理由は本書§1の通り。本人の誕生(●)・加入(▲)・卒業(▼)と、子供の誕生(☆)の描画仕様は 世代マトリックス 画面設計書 §4を参照。


3. シークレットモードのアクセス制御

環境変数・ガード関数の定義は 環境変数一覧 §4「シークレットモードとは」を正とする。本節では世代マトリックスに固有の認証フローのみを記載する。

  • 合言葉の検証: POST /api/secret-mode/verify(body: { passcode: string })で process.env.SECRET_MODE_PASSCODE と一致するか検証する
  • セッションCookie: 検証成功時、secret_mode_session という httpOnly Cookie を発行する(secure: 本番のみ、sameSite: 'lax'、有効期限30日)。値は {expiresAt(epoch秒)}.{signature} の形式で、signature は SECRET_MODE_PASSCODE を鍵とした crypto.createHmac('sha256', ...) によるHMAC署名(Node.js標準の crypto モジュールのみで完結させ、新規パッケージは追加しない)
  • 検証: requireSecretMode()(lib/secret-mode.ts)が secret_mode_session Cookieを読み、expiresAt を鍵に再計算した署名と一致し、かつ expiresAt が現在時刻より未来であることを確認する。いずれかを満たさない場合は未認証として扱う
  • デスクトップモード(requireDesktopMode()、lib/desktop-mode.ts)は「ビルド時に固定される実行モード」を見るだけの単純な環境変数チェックだが、シークレットモードは「同一デプロイ上でブラウザセッションごとに認証状態が変わる」ため、Cookie発行・署名検証が必要になる点がデスクトップモードとの違い

4. データ投入運用

子供の生年データは今後も継続的に追加・更新される想定のため、拡張可能な手動運用スクリプトとして設計する。既存の手動登録スクリプト(scripts/console/register-tour-festival.ts 等)と同じ「CSV入力 → スクリプト実行 → Neonへ反映」のパターンを踏襲する。

  • スクリプト: scripts/console/import-member-children.ts(実装は MorningStatusApp#1632)
  • 入力: data/inputs/member-children.csv(1行目ヘッダー: memberId,birthYear)
  • 動作: CSVの各行を member_children にINSERTする。既存の完全一致行(同じ memberId・birthYear)がある場合はスキップし重複登録を防ぐ(一意制約はテーブル側に持たせず、スクリプト側のロジックで判定する。同じ親から同じ年に複数の子供が生まれるケース(双子等)は稀だが、その場合は完全一致になり後発分がスキップされてしまうため、既知の制約として実装Issue側に申し送る)
  • --dry-run: 実データへの書き込み前に差分(追加予定行)を表示するドライランモードを持たせる(本リポジトリの手動データ操作スクリプトの既定パターン)

初期データ投入時は、本書§5の参考データをCSV化して1回だけ実行する想定。


5. 初期データ(参考データ)

親Issue(MorningStatusApp#1571)のコメントに記載された実データ。列=メンバー(誕生年順)、行=西暦年、セル内 * は本人の誕生年、+ は子供の誕生年を表す。表記ゆれ・体裁は原文のまま記録する(CSV化・整形は実装Issue側で行う)。なお、*・+ は親Issueでイメージを伝えるために使われた表記で、画面の記号(●・☆)とは異なる(世代マトリックス 画面設計書 §4-2)。

6期まで(ママがたくさん)

中澤裕子 石黒彩 安倍なつみ 飯田圭織 福田明日香 保田圭 矢口真里 市井紗耶香 後藤真希 石川梨華 吉澤ひとみ 辻希美 加護亜依 高橋愛 紺野あさ美 小川麻琴 新垣里沙 藤本美貴 亀井絵里 道重さゆみ 田中れいな
1973 *
1978 *
1980 *
1981 * *
1983 * *
1984 *
1985 * * * *
1986 *
1987 * * *
1988 * * *
1989 * *
2000 +
2002 +
2004 + +
2007 + +
2010 +
2012 + + +
2013 + + +
2015 + + + +
2016 + + +
2017 + + + +
2018 + + + + +
2019 + +
2020 + +
2021 + +
2022 +
2024 + +
2025 +
2026 +

7期から14期

久住小春 光井愛佳 ジュンジュン リンリン 譜久村聖 生田衣梨奈 鞘師里保 鈴木香音 飯窪春菜 石田亜佑美 佐藤優樹 工藤遥 小田さくら 尾形春水 野中美希 牧野真莉愛 羽賀朱音 加賀楓 横山玲奈 森戸知沙希
1988 *
1991 *
1992 *
1993 *
1994 *
1996 *
1997 * *
1998 * *
1999 * * * * * *
2000 *
2001 * *
2002 *

15期以降

北川莉央 岡村ほまれ 山﨑愛生 櫻井梨央 井上春華 弓桁朱琴 杉原明紗 安田美結 鈴木もあ 石川華望
2004 *
2005 * * *
2006 *
2008 *
2011 *
2012 *
2013 * *

改訂履歴(バージョン降順に記載)

版 更新日 変更内容
1.1 2026-09-21 【v10.6.1(MorningStatusApp#1650。実装後の改修)】§1に、画面で使う加入日・卒業日も既存の Member.profile を使う旨を追記。§2-1の描画仕様の参照先を、記号の変更(*・+ → ●・☆)に合わせて画面設計書 §4 に改め、§5に参考データの表記(*・+)が画面の記号と異なる旨を追記した(morning-status-blume#141)
1.0 2026-09-20 【v10.6.0(MorningStatusApp#1632)】初版作成(morning-status-blume#128)

このページは役に立ちましたか?