テーマ
Research & Design Decisions — data-model
Purpose: data-model spec の design 書き直し(commit f106c92 以降の 3 系統データアーキテクチャへの適合)に至った調査・統合判断・トレードオフを記録する。
Summary
- Feature:
data-model - Discovery Scope: Extension(既存プロジェクトのデータ層を 3 系統に再構築する大規模拡張)
- Key Findings:
- リセットコミット 02b2612 により
prisma/、features/、lib/prisma.ts等が削除済み。design.md は「再構築前提」で書く必要がある。 - 要件 (
requirements.md) は CMS / Neon / Vercel ENV の 3 系統への明確な責務分離を既に規定済みで、design は「どの境界に何を置くか」を実装に翻訳するフェーズ。 package.jsonに Prisma 7.8+ /@prisma/adapter-pg/ Stripe 22 / Zod 4 は揃っているがmicrocms-js-sdk未導入。導入とnext.config.tsのimages.remotePatterns設定が design タスクの起点になる。
- リセットコミット 02b2612 により
Research Log
Topic 1: 現リポジトリの実体(リセット後)の確認
- Context: design 旧版は単一 Prisma モデル前提で書かれており、現リポジトリのコード実体と整合しているかを確認する必要があった。
- Sources Consulted:
ls/package.json/prisma.config.ts/docker-compose.yml/next.config.ts/lib/utils.ts- 直近コミット履歴(
02b2612,f106c92,9228efc)
- Findings:
prisma/ディレクトリは存在しない(リセット済み)。prisma.config.tsはprisma/schema.prismaを指す設定のみ残置。features/、app/api/、lib/prisma.ts、lib/microcms.tsは未作成。package.json:prisma ^7.8.0,@prisma/adapter-pg ^7.8.0,@prisma/client ^7.8.0,pg ^8.16.3,stripe ^22.1.0,zod ^4.3.6。microcms-js-sdkは無し。docker-compose.ymlでpostgres:17がローカル開発用に定義済み。
- Implications:
- design.md は「ゼロからの再構築」を前提に File Structure Plan を具体化する必要がある。
- 依存追加候補は
microcms-js-sdkのみ。Neon serverless adapter は不要(pg + adapter-pg で要件を満たす)。
Topic 2: 要件で求められている境界の精査
- Context: 旧 design は「全データを Prisma に持つ」前提で、
AdminUser/VoteStatus/*Snapshot列/totalAmountJpy等の冗長フィールドを抱えていた。新 requirements に照らして本当に必要な列を確定する必要があった。 - Sources Consulted:
.kiro/specs/data-model/requirements.md(7 entity × 40+ AC).kiro/steering/product.md、.kiro/steering/tech.md、.kiro/steering/structure.md
- Findings:
- Candidate / CreditPackage は microCMS 側で完全管理(編集権限・履歴・公開状態)。アプリ DB は ID 文字列でのみ参照する。
- 投票期間は Vercel ENV の
VOTING_PERIOD_START/VOTING_PERIOD_ENDで表現。DB シングルトンは要件外。 - 投票の不変性は「
Vote単独」ではなく「Purchase.status='SUCCEEDED'との JOIN」で表現する仕様(VoteStatus列は不要)。 - 購入額・クレジット合計はクライアントが集計可能なため
total*列は不要。価格はcreditPackages側の完全 immutable で担保(snapshot 列不要)。 - 管理者は外部の microCMS 管理画面で完結し、
AdminUserテーブル不要。
- Implications:
- Neon に保持するモデルは
Vote/Purchase/PurchaseItemの 3 つに縮退。 - 「決済成立 = 不変」を JOIN ベースで一貫させるため、
Voteにはstatusを一切持たせない。 - 価格・名称等の表示要素は読み取り時に microCMS から enrichment する。
- Neon に保持するモデルは
Topic 3: 横断参照(cross-boundary reference)の整合戦略
- Context: Vote/Purchase/PurchaseItem は外部 (microCMS) の Candidate / CreditPackage を参照する必要があるが、DB 上 FK を引けないため整合性戦略を確定する必要があった。
- Sources Consulted:
- requirements.md 「横断参照ルール」「整合性ポリシー」
- microCMS 公開仕様(IDは文字列/削除運用は archive 推奨)
- Findings:
- 「string ID で参照し、取得時に enrichment、欠落は表示側でフォールバック」というパターンが要件と一致。
- microCMS 側の archive 運用(hard delete を業務上禁止)でデータ消失リスクを許容範囲に抑えられる。
- 投票時の存在検証は read-time(取得後 nullable に縮退)で十分。書込時の serializable lock は過剰。
- Implications:
- Prisma の
candidateId/creditPackageIdはString @db.Text。 - サービス層(
features/cms/*とfeatures/candidates/voteAggregationService)が enrichment と欠落耐性を担う。
- Prisma の
Topic 4: キャッシュ・読取性能戦略
- Context: Home/Ranking 表示で
候補者リスト × 得票集計を高頻度に返す必要があり、microCMS API 制限と Neon コストの双方を最小化する必要があった。 - Sources Consulted:
- Next.js 15 Data Cache /
unstable_cacheの現行ドキュメント - microcms-js-sdk のクライアント設計
- Next.js 15 Data Cache /
- Findings:
- microCMS 取得結果は
unstable_cacheで 60〜180 秒 TTL のキャッシュが妥当。タグベース revalidate を介して webhook で即時無効化が可能。 - 得票集計は分単位で揺れるため、Neon 集計はキャッシュせず、
prisma.vote.groupBy({ where: { purchase: { status: 'SUCCEEDED' } } })で都度集計。
- microCMS 取得結果は
- Implications:
lib/microcms.tsで SDK client を singleton 生成。voteAggregationServiceはunstable_cacheを使わず、サーバ component 直叩きを許す。
Architecture Pattern Evaluation
| Option | Description | Strengths | Risks / Limitations | Notes |
|---|---|---|---|---|
| 単一 Prisma DB に全データを集約(旧 design) | Candidate/CreditPackage/VotingPeriod も全部 Postgres | FK で整合性強制可能、トランザクション一貫 | 編集 UI を自前実装、価格の改変リスク、運用負荷高 | requirements の 3 系統境界に反するため不採用 |
| 3 系統分離(採用) | microCMS / Neon / Vercel ENV を責務で分離 | 編集 UI 不要、価格不変を権限で担保、ENV で即時切替 | 横断 FK なし・enrichment コスト | requirements・steering と完全一致 |
| Neon serverless adapter | @neondatabase/serverless を直接利用 | Edge runtime 対応 | プロジェクトは Node ランタイム想定、追加依存と未検証コード | 不採用、@prisma/adapter-pg で十分 |
Design Decisions
Decision: 投票不変性を Vote の status カラムではなく Purchase.status との JOIN で表現する
- Context: requirements 4.x で「決済成立した投票のみが有効、不変」とされる。旧 design は
VoteStatusenum を持っていた。 - Alternatives Considered:
Vote.statusでPENDING / CONFIRMEDを持つ(二重管理)。Purchase.status='SUCCEEDED'を唯一の真実とし、Voteは status を持たない。
- Selected Approach: 2 を採用。集計クエリは
where: { purchase: { status: 'SUCCEEDED' } }で常に絞り込む。 - Rationale: 二重管理による不整合を構造的に排除でき、Purchase の状態変化と Vote の意味が一意に同期する。
- Trade-offs: 集計時に常に JOIN が必要だが、
@@index([candidateId])+@@index([status])で実用上問題なし。 - Follow-up:
voteAggregationService実装時にクエリプランを EXPLAIN で確認。
Decision: CreditPackage の不変性は microCMS のロール/フィールド権限で担保する
- Context: requirements 6.x の「単価・クレジット数は購入後に変更されてはならない」を満たす必要があった。
- Alternatives Considered:
PurchaseItemに*Snapshot列で価格を写し取る。- microCMS で当該パッケージの編集権限を作成者のみに制限し、価格変更を運用ルールで禁止。
- Selected Approach: 2 を採用。
PurchaseItemにはcreditPackageIdとquantityのみ保持。 - Rationale: snapshot 化は冗長で、価格を変えたい場合は「新パッケージ作成 + 旧パッケージ非公開」の運用で対応すれば十分。要件のスコープ外を増やさない。
- Trade-offs: 価格表示を過去の購入で復元するには microCMS から取り直す必要があるが、要件は「購入時の値を再現する義務」を課していないため許容。
- Follow-up: 運用 steering(structure.md / tech.md)の「microCMS スキーマ運用ルール」を後続で整備。
Decision: 投票期間を Vercel ENV (VOTING_PERIOD_START / VOTING_PERIOD_END) で管理する
- Context: requirements 7.x で「投票期間は管理者がコード変更なしに切り替えられる」「単一の真実」を要求。
- Alternatives Considered:
- Neon に
VotingPeriodシングルトンテーブルを置く(旧 design)。 - microCMS の単一オブジェクトコレクションで持つ。
- Vercel ENV で持ち、
lib/voting-period.tsでパース。
- Neon に
- Selected Approach: 3。
InvalidVotingPeriodErrorをMISSING / INVALID_FORMAT / INVERTED_RANGEの cause つきで投げる。 - Rationale: ENV 変更で即時切替、Postgres / microCMS 両方の依存を切れる、誤更新のリスクが最小。
- Trade-offs: 値の更新に Vercel への deploy/redeploy が必要だが、頻度が低いため許容。
- Follow-up:
home/votingspec の design で同じ util を参照することを明記。
Decision: ニックネームは正規化(NFKC + 連続空白圧縮 + 前後 trim + UTF-16 1〜32)で同一性判定する
- Context: requirements 5.x「同一文字列のニックネームを同一支援者として集計」「本人確認は行わない」。
- Alternatives Considered:
- 正規化なしで生文字列を保存。
- 正規化のうえ保存、表示も正規化済みを使う。
- Selected Approach: 2。
normalizeNickname()をfeatures/voting/services/nicknameService.tsに集約し、書込前に必ず通す。 - Rationale: 全角/半角/ゼロ幅スペース等の差で支援者ランキングが分散するのを防ぐ。表示も同じ文字列で行うため UI 上のブレも消える。
- Trade-offs: 元の入力を完全復元はできないが、要件上必要ない。
- Follow-up:
votingspec design で UI 側のバリデーション文言を整備。
Risks & Mitigations
- microCMS スキーマドリフト: microCMS 側で必須フィールド変更が起きると enrichment が壊れる。→ Zod による boundary parse、テストでスキーマ参照を固定。
- 横断参照の dangling: microCMS で候補者を archive ではなく削除した場合に enrichment が null になる。→ 表示側でフォールバック表示、運用 steering で hard delete 禁止を明記。
- Vercel ENV の誤設定:
VOTING_PERIOD_START >= VOTING_PERIOD_ENDなどで起動失敗。→getVotingPeriod()起動時検証で fail-fast、エラーページ表示で受付停止。 - Prisma 7 系の安定性: 7.8 は比較的新しいバージョン。→ adapter-pg 経由で動作確認、マイグレーションは feature branch で先行検証。
References
.kiro/specs/data-model/requirements.md— 本 design の WHAT を規定する一次ソース.kiro/steering/product.md/tech.md/structure.md— 3 系統データアーキテクチャの規約- commit
f106c92— 3 系統分離を spec/steering に反映した変更 - commit
02b2612— 業務ロジック層リセット(再構築の出発点) - Next.js 15 Data Cache / unstable_cache — microCMS 取得のキャッシュ戦略
- microcms-js-sdk — 採用 SDK
- Prisma
@prisma/adapter-pg— Neon Postgres 接続
Gap Analysis Re-run(2026-05-17 / tasks-generated 後の再検証)
design / tasks が approved 済みの状態で、
requirements.mdと現リポジトリ実体の差分を改めて分解し、実装フェーズ(/kiro-impl data-model)が安全に開始できるかを確認する。フォーマットは.claude/skills/kiro-validate-gap/rules/gap-analysis.mdの Output Checklist に従う。
Discovery Scope の再判定
- Extension: 既存 Next.js プロジェクトの空の足場(
app/page.tsxは再構築中プレースホルダ、components/ui/*は shadcn の汎用部品のみ、lib/utils.tsはcnだけ)に対して、データ層 3 系統(microCMS / Neon / Vercel ENV)と関連サービス層をゼロから追加する作業に相当する。Greenfield ではない(依存・設定・スケルトンは存在する)が、ドメインコードはほぼ未存在のため Extension の中でも「追加比率の高い拡張」に分類される。
1. Current State Investigation
Repo 構造とドメイン関連資産(実測)
| パス | 現状 | data-model spec への寄与 |
|---|---|---|
app/ | layout.tsx / page.tsx(プレースホルダ)/ providers.tsx(空ラッパー)/ globals.css のみ | データ層が組み込まれていないため、本 spec が lib/* / features/* を新設しても衝突しない |
components/ui/ | shadcn の button/card/dialog/input/label/sonner/table/textarea のみ | 直接編集可(spec 外)。data-model spec は触れない |
components/public/ | 未作成 | 本 spec のスコープ外(他 spec が後で作成) |
lib/ | utils.ts(cn() のみ) | prisma.ts / microcms.ts / voting-period.ts を新規追加するだけで衝突なし |
features/ | 未作成 | spec の File Structure Plan どおりに新規作成可能 |
prisma/ | 未作成(prisma.config.ts は prisma/schema.prisma を指す設定のみ残置) | schema.prisma / migrations/ / seed.ts をゼロから生成 |
types/ | 未作成 | 本 spec は型を features/cms/types.ts に集約する方針で types/** は使わない |
auth.ts / app/admin/** / app/api/auth/** / app/api/images/** | 存在しない(リセット済み) | structure.md の「保有しない」方針と整合、再導入禁止 |
docker-compose.yml | postgres:17 でローカル DB を提供 | Prisma 7 + adapter-pg と整合、追加変更不要 |
next.config.ts | 空の NextConfig | images.remotePatterns の追記が必要(task 1.2) |
package.json | @prisma/client@^7.8.0 / @prisma/adapter-pg@^7.8.0 / prisma@^7.8.0 / pg(間接) / zod@^4 / stripe@^22 / @stripe/stripe-js@^9 / tsx@^4(dev) | microcms-js-sdk が未導入。task 1.1 で追加が必要 |
tsconfig.json | strict: true、エイリアス @/* / @/components/* / @/design-tokens/* | @/features/* エイリアスが未定義(structure.md には記述あり)。data-model 実装で features/ ディレクトリを新設するため、import 文を @/features/... ベースで書く場合は tsconfig.json の paths 更新が必要。または @/features/... を @/* で代替する |
Conventions(structure.md と実体の擦り合わせ)
- 3 層モデル (
app/→features/→components/) は steering で固定。data-model spec はfeatures/とlib/のみ作成する(components/には触れない)。 - import エイリアス:
tsconfig.jsonには@/features/*が未定義。structure.md の「import エイリアス(実態)」セクションでは@/features/*を含むと記述されているが、現ファイルでは欠落。実装時にtsconfig.json直接編集が必要("直接編集可" パスに含まれる)か、@/features/*を使わず@/*を流用するかの判断点が生じる。 - テスト: 本リポジトリには Vitest / Playwright のセットアップが存在しない(package.json に依存なし)。design.md の Testing Strategy で想定されている Unit / Integration / E2E はインフラ未整備のため、本 spec のタスク 1〜9 の範囲では実行できない。テスト基盤導入は別 spec / steering 改訂の対象(research needed)。
- 環境変数:
.env.local/.env.exampleがリポジトリに存在するかは未確認だが、docker-compose.ymlはDATABASE_URLを期待する形式で書かれていない(直接接続文字列をローカルで組む前提)。MICROCMS_*/VOTING_PERIOD_*も追加が必要。
統合面(External Integration Surfaces)
- microCMS: SDK 未導入、コレクション未作成、API キー未発行。spec の task 2.1〜2.3 で運営オペレーション(コレクション・権限・キー発行)を実施する必要があり、コード作業の前段にデータ基盤の準備が必須。
- Neon: 接続情報(
DATABASE_URL)の本番値は未投入だが、ローカルはdocker-composeで代替可能。Prisma 7 + adapter-pg はパッケージ揃済み。 - Vercel ENV:
VOTING_PERIOD_START/VOTING_PERIOD_ENDの投入は運営オペレーション。getVotingPeriod()の起動時バリデーションは fail-fast 設計のため、開発時.env.localのテンプレートも合わせて整備する必要がある。 - Stripe: 本 spec のスコープ外(
votingspec 担当)だが、Purchase のpaymentIntentIdUNIQUE 制約と Webhook ハンドラのインターフェースは本 spec のスキーマで吸収済み。
2. Requirements Feasibility Analysis(Requirement-to-Asset Map)
| 要件 | 必要アセット | 現状アセット | Gap タグ |
|---|---|---|---|
| Feature 1(Candidate, AC 1.1–1.7) | microCMS candidates コレクション + ロール権限 + features/cms/services/candidateService.ts | コレクション未作成、サービス未作成 | Missing(運営オペ + コード) |
| Feature 2(CandidateImage, AC 2.1–2.7) | microCMS 画像フィールド(MIME 制限、5MB 上限)+ next.config.ts.images.remotePatterns | 未設定 / 未設定 | Missing(運営オペ + 設定) |
| Feature 3(CreditPackage, AC 3.1–3.7) | microCMS creditPackages コレクション + フィールド権限ロック + features/cms/services/creditPackageService.ts | 全て未作成 | Missing |
| Feature 4(Vote, AC 4.1–4.8) | Prisma Vote model + votes (candidateId) 等 index + voteAggregationService + nicknameService | 全て未作成 | Missing |
| Feature 5(Purchase, AC 5.1–5.6) | Prisma Purchase + PaymentStatus enum + UNIQUE 制約 + Webhook ハンドラとの IF | スキーマ未作成、Webhook ハンドラ未作成(voting spec 担当) | Missing(本 spec ではスキーマ部分のみ) |
| Feature 6(PurchaseItem, AC 6.1–6.5) | Prisma PurchaseItem + UNIQUE(purchaseId, creditPackageId) + CHECK (quantity ≥ 1) | 全て未作成 | Missing |
| Feature 7(VotingPeriod, AC 7.1–7.5) | Vercel ENV キー定義 + lib/voting-period.ts の getVotingPeriod + InvalidVotingPeriodError | 未投入 / 未作成 | Missing |
| 共通属性(id / createdAt / updatedAt) | Prisma @id @default(uuid()) / @default(now()) / @updatedAt | 未作成 | Missing |
| 越境参照規約 | String @db.Text カラム + 外部キー無し + 集計時 enrichment | 未作成 | Missing |
| ニックネーム正規化 | normalizeNickname(NFKC + 空白圧縮 + trim + 長さ検証) | 未作成 | Missing |
Unknown / Constraint
- Unknown 1:
tsconfig.jsonのpathsに@/features/*を追加するかどうかは、structure.md と実ファイルで言及が食い違っている(Research Needed: 既存 lint / build を壊さず追加できるか、design 段階で確定)。 - Unknown 2: テスト基盤(Vitest)が未導入のため、design.md / tasks.md で想定されている Unit / Integration テストは 現実装フェーズでは検証不能。完了判定を「コード書き起こし +
prisma validate+ ローカル DB マイグレーション適用」までに限るのか、テスト基盤導入を本 spec タスクに含めるのかは design レビュー時点で判断するべき(Research Needed)。 - Unknown 3: microCMS の「物理削除禁止」ロール権限がプラットフォーム機能だけで完全に強制可能かは microCMS の現行プラン依存(フィールド権限プランで担保する想定)。プラン未確定なら運用ルール + 監査ログによる事後検出に切り替える必要がある(Research Needed)。
- Constraint 1: 保護パス(
prisma/**/features/**/lib/prisma.ts等)は CLAUDE.md により直接編集禁止。/kiro-impl data-model経由のみで作成可能。 - Constraint 2:
package.jsonへの依存追加は spec/design に紐付くのが望ましいと CLAUDE.md にあり、microcms-js-sdk追加は本 spec の tasks 1.1 に明示済みで整合。
Complexity Signal
- 多くの要件は 新規ファイル追加 + 既存パターン踏襲 の単純な拡張で、ロジック面でアルゴリズム的に難しい部分はない。
- ただし「3 系統を整合的に縫う越境参照」「Webhook トランザクション境界」「環境変数の起動時バリデーション」など、統合点が多い点が複雑さの実体。本 spec は契約定義に留まり、実際の Webhook ハンドラや PaymentIntent 作成は
votingspec が担う構造で複雑度を局所化済み。
3. Implementation Approach Options
Option A — design.md / tasks.md にそのまま従う(Extend the Plan)
- 概要: 既に approved 済みの design.md(3 系統分離、Vote/Purchase/PurchaseItem の 3 モデル、microCMS 完全イミュータブル、ENV ベース投票期間)と tasks.md(9 セクション)をそのまま
/kiro-impl data-modelで順番に実装する。 - トレードオフ:
- 良: spec / steering / 過去の研究ログ全てと完全整合。再設計コスト 0。Boundary Commitments と Out-of-Boundary が明確で、他 spec への影響範囲がコントロール済み。
- 良: パッケージ追加が
microcms-js-sdkのみで済み、依存変更が極小。 - 悪: テスト基盤未整備のまま実装に入るため、design.md の Testing Strategy セクションは「該当ファイルを後で書く」前提となり、完了判定が緩くなる。
- 悪:
tsconfig.jsonの@/features/*不在が顕在化したときに、保護パスかどうか不明な微妙な編集(tsconfig.json自体は "直接編集可")を実行する判断が必要。
- 適合度: 高い。本 spec の Discovery Scope(Extension)と Boundary Commitments の整合性は完璧。
Option B — テスト基盤(Vitest)を本 spec に内包し、Unit / Integration を即時検証可能にする(Wider Extension)
- 概要: Option A のタスクに加え、
vitest.config.ts/vitest依存 /tsconfigの test 設定 /prisma/seed.tsの dummy データ整備を本 spec のタスクに追加する。 - トレードオフ:
- 良: design.md の Testing Strategy が実行可能になり、各レイヤーの単体検証が早期に成立。
normalizeNicknameの境界値・getVotingPeriodのエラー分岐・voteAggregationServiceの JOIN フィルタが、実装中に CI で守られる。 - 悪: tasks.md(approved 済み)を改変する必要があり、spec の再 approval が発生する。
- 悪: Vitest セットアップは本来 steering / testing spec の担当領域で、data-model spec のスコープを越える可能性が高い。
- 良: design.md の Testing Strategy が実行可能になり、各レイヤーの単体検証が早期に成立。
- 適合度: 中。テスト基盤の責務が data-model に過剰流入するため、別 spec で扱うのが筋。
Option C — ハイブリッド: design / tasks は維持しつつ、testability の最小限だけ取り込む
- 概要: Option A をベースに、(i) Prisma の
seed.tsを空ファイルで作成して将来の seed を妨げない、(ii)normalizeNickname/getVotingPeriodのような純関数は テスト基盤なしでもtsxで実行可能な smoke スクリプト(scripts/配下)を 1 本だけ用意してAcceptance確認に使う、という方針。Vitest は導入せず、本格テストは別 spec に切り出す。 - トレードオフ:
- 良: tasks.md の修正は seed.ts の追加(既に design.md にあり)と smoke script の追加だけで済み、approved 範囲を超える改変は最小。
- 良: 純関数の挙動を
/kiro-impl中に手動確認できるため、レビューア subagent の判定材料が増える。 - 悪:
scripts/**は保護パスのため、CLAUDE.md のガードを越えるには本 spec の design に追加するか、本 spec とは別の小さな spec(テスト基盤)を立てる必要がある。
- 適合度: 中〜高。Boundary を越えるリスクは小さいが、scripts 追加の合理化に design 改訂が必要。
4. Effort & Risk
| 観点 | 判定 | 1 行根拠 |
|---|---|---|
| Effort | M(3–7 日) | 新規ファイル数は中程度(lib/* 3 本 + features/* 4 本 + Prisma 一式)。難所は microCMS スキーマと Prisma マイグレーション + index 設定で、コード量より「運営オペ + 統合確認」のラウンドトリップがクリティカルパス。 |
| Risk | Medium | パターンは確立済み(Prisma / microCMS いずれも標準ライブラリ)。リスクは (1) microCMS フィールド権限がプラン依存、(2) テスト未整備による品質ゲートの不在、(3) 越境参照の dangling を本番で踏むまで気付きにくい設計。アーキテクチャ的な未知数はない。 |
5. design phase への推奨事項(実装直前の確認事項)
design.md は approved 済みだが、
/kiro-impl data-model起動前に以下の確認を済ませるとリスクが下がる。
- 推奨アプローチ: Option A(design / tasks の通り実装)。Option C の smoke script は必要に応じて、本 spec を
/kiro-implした後の Follow-up(testing-foundation等の新 spec)で対応する方が境界がきれい。 - Key Decisions(再確認):
- Vote 不変性は
Purchase.status='SUCCEEDED'JOIN で表現(Vote に status 列を持たせない)— 過去ログ Decision 1 と一致。 - CreditPackage の不変性は microCMS フィールド権限 で担保(PurchaseItem に snapshot を持たない)— Decision 2 と一致。
- VotingPeriod は Vercel ENV + 起動時 fail-fast バリデーション(DB シングルトンを使わない)— Decision 3 と一致。
- ニックネーム正規化は NFKC + 空白圧縮 + trim + UTF-16 1〜32(Server / Client 両方から import 可能な純関数として export)— Decision 4 と一致。
- Vote 不変性は
- tsconfig.json の
@/features/*パス追加:/kiro-implの最初のタスクで、import 文の書き方を@/features/...で統一する場合はtsconfig.jsonへの"@/features/*": ["./features/*"]追加が必要。tsconfig.jsonは CLAUDE.md の "直接編集可" パスに含まれるため、本 spec の作業中に追加してよい。design.md の File Structure Plan には現状この追加が明示されていないため、design レビュー時に Modified Files へ加筆するか、/kiro-impl内で例外的に編集する旨をレビューア subagent に申告する。 - 環境変数テンプレート:
.env.local/.env.exampleの整備は design / tasks に明示が薄い。MICROCMS_SERVICE_DOMAIN/MICROCMS_API_KEY_READONLY/VOTING_PERIOD_START/VOTING_PERIOD_END/DATABASE_URLのテンプレートを.env.exampleに追加する手順を/kiro-impl開始時に確認する(.env.exampleは spec 外パスのため直接編集可)。 - Research Needed(次フェーズに持ち越し):
- R1: microCMS の現プランで「物理削除禁止」「フィールド単位の編集ロック」がロールベースで強制可能か、コンソール上で実機確認する(task 2.1 / 2.2 の事前確認)。
- R2: テスト基盤(Vitest)導入を別 spec として立てるか、本 spec の Follow-up として
/kiro-spec-init "testing-foundation"を提案する。design.md の Testing Strategy 項目を「実行は別 spec」と注記する変更も検討。 - R3:
vote.createManyの SQL サイズ上限を、合計票数の上限想定(数千〜想定最大)でローカル PG に対し先行 EXPLAIN / ベンチで確認(task 3.2 / 4 系の補強)。 - R4:
next.config.tsのimages.remotePatternsに登録する microCMS の正確な配信ホスト(images.microcms-assets.io等)を、microCMS のドキュメント現行版で確認する(task 1.2)。
- 想定外時の Fallback: microCMS フィールド権限プランが要件を満たさなかった場合、CreditPackage の
name/credits/priceJpyを PurchaseItem に snapshot として保持 する迂回路に切り替える(design.md の Decision 2 を覆す変更)。この場合は requirements.md は変えず design.md / tasks.md / Prisma スキーマだけを更新する。