アプリ全体の仕様を一箇所にまとめた、私たち(ユーザー & Claude)の共有認識ページ。認識がずれたらまずここを直す。Claude が作業のたびに更新する。
最終更新: 2026-07-25 対象: Toddyi(Todo & Productivity) 環境: dev のみ(prod 不可侵) URL: dev.toddyi.love/working-memory.html
ルート:G:\My Drive\Prompts\Toddyi (Drive で開く)。実装・レビュー前に必ず照合し、認識のズレを防ぐ。
| フォルダ | 内容 |
|---|---|
| wireframe/ | ワイヤーフレーム。現在 tasks.png(Tasks 画面) |
| DDL/ | DEV DB の DDL を定期エクスポート。最新 toddyi_dev_ddl_2026-07-25.sql(13テーブル) |
| Rest/ | REST API 設計書。Toddyi_REST_API_design.md(レビュー待ち) |
DDL 生成:bash script/export_ddl.sh(dev DB のみ・prod 不可侵)→ Drive の DDL フォルダへ Claude がアップロード。
実コード準拠の詳細仕様。dev 配信(noindex / no-auth)。機能ごとに「仕様書 → レビュー → 修正」で回す。
tasks-spec.html#sf(Tasks 内 Folder 章)
未作成:Habits / Pomodoro / Countdowns / Notifications / Matrix / Calendar(依頼時に作成)。
db/schema.rb(version 2026_07_13_020005)から起こしたもの。Toddyi は個人向け生産性 Web アプリ。Ruby on Rails 8 + Hotwire によるサーバーレンダリングで、SPA フレームワークを使わない。タスク・カレンダー・習慣トラッキング・ポモドーロ・アイゼンハワーマトリクス・カウントダウン・タイマー・通知・Stripe サブスク課金を備える。Capacitor で Android/iOS のストアアプリ化も対応。
Markdown ノート・フォルダ・優先度・タグ・スケジュール・完了・ライブ検索
FullCalendar。日クリックで作成、ドラッグで移動、リサイズで期間変更
緊急×重要の 2×2、象限間ドラッグ&ドロップ
日次/週次、7日グリッド、ワンタップ check-in、ストリーク
focus/break タイマー、音+ブラウザ通知、セッション記録
永続化ストップウォッチ/カウントダウン、pause/reset/lap
秒精度 HH:MM:SS、任意で毎年繰り返し
誕生日+寿命+睡眠から残り時間を可視化
アプリ内通知センター、未読バッジ、期限リマインダ自動生成
Stripe 月額サブスク Free/Pro
Email/Password + OAuth(Google / GitHub / Microsoft / Apple)+ TOTP 2FA
en/ja/de/zh、ライト/ダーク(永続)
| レイヤー | 技術 |
|---|---|
| フレームワーク | Ruby on Rails 8.1 (~> 8.1.1) |
| 言語 | Ruby 3.4(.ruby-version=3.4.9 / dev コンテナ実行系 3.3.8) |
| フロント | Hotwire(Turbo + Stimulus)via importmap-rails、SPA なし |
| DB | MySQL / MariaDB(mysql2 ~> 0.5) |
| 認証 | Devise + omniauth-google-oauth2 / omniauth-github / omniauth-entra-id / omniauth-apple、2FA は rotp/rqrcode |
| 課金 | Stripe(stripe gem) |
| CSS | Pico CSS + Tailwind CSS 4(tailwindcss-rails ~> 4.4)+ コンポーネント CSS |
| アセット | Propshaft |
| サーバー | Puma |
| セッション | activerecord-session_store(DB セッション) |
| Markdown | redcarpet |
| モバイル | Capacitor 7(Android/iOS ラッパー)+ Codemagic CI |
| メール | SMTP 直送(ActionMailer 無効、独自 AuthMailNotifier)。dev は Mailpit |
コードは機能ドメインごとの名前空間で整理されている(app/models/features/*, app/controllers/features/*)。
| ドメイン | コントローラ | モデル |
|---|---|---|
| planning | tasks, task_folders, countdowns, life | Task, TaskFolder, Countdown |
| tracking | habits, habit_checkins, pomodoro, timers | Habit, HabitCheckin, PomodoroSession, Timer, Timers::TimerLap, Notification |
| accounts | users/ | User |
| account | notifications, subscriptions, two_factor_settings, two_factor_challenges | — |
| integrations | stripe_webhooks, seo | — |
| api | api_docs(Swagger UI + OpenAPI) | — |
レンダリングは Turbo Stream / Turbo Frame 中心。習慣 check-in やタスク toggle は Turbo Stream で部分更新。
database_authenticatable, registerable, confirmable, recoverable, rememberable, validatable, omniauthable(provider は OauthConfig.configured_keys=認証情報が揃っているものだけ)
AuthMailNotifier.confirmation 経由で SMTP 直送。User.from_omniauth は oauth_identities を (provider, uid) で検索し、なければ同一 email の既存アカウントに新しい identity を足してリンク(既存の identity は消さない)。OAuth 新規はランダムパスワード付与+password_configured=false(後からパスワード設定を促す)。users.provider/uid は #232 で廃止(1 つしか持てず、後から使ったものに上書きされていた)。| プロバイダー | strategy | コールバック |
|---|---|---|
google_oauth2 |
/users/auth/google_oauth2/callback |
|
| GitHub | github |
/users/auth/github/callback |
| Microsoft | entra_id |
/users/auth/entra_id/callback |
| Apple | apple |
/users/auth/apple/callback |
プロバイダーごとの差異(config/oauth_config.rb に集約。詳細は ADR 0008)
| 注意点 | |
|---|---|
| GitHub | メールを非公開にできる。user:email スコープ必須。返ってくるのは primary かつ検証済みのアドレスなので、アドレスが来た=検証済み(claim は無い) |
| Microsoft | xms_edov はアプリ登録で要求したときしか付かない。無ければ未検証扱い(既存アカウントへのリンクを拒否し、新規は確認メール) |
| Apple | client secret が無い。.p8 から JWT を署名して生成するため team_id / key_id / 秘密鍵も設定に要る |
| Apple | コールバックがクロスサイト POST(response_mode=form_post)。SameSite=Lax の Cookie が送られず state 検証に失敗する。AppleCallbackRedirect ミドルウェアが POST を同じパスへのリダイレクトに変換し、トップレベル GET で戻す(Cookie を SameSite=None に緩めない) |
| Apple | email は初回認可のときしか送られてこない。2 回目以降は sub のみ。これが identity テーブルを必要とした理由 |
rotp で Base32 シークレット生成、rqrcode で登録用 QR。issuer は "Toddyi"。verify_otp)。otp_enabled かつ otp_secret 存在で有効。two_factor/challenge でコード入力。設定は resource :two_factor。TURNSTILE_SITE_KEY/SECRET_KEY)。local/test は検証バイパス。sessions テーブル)。/api/docs と /api/openapi.json は HTTP Basic 認証。資格情報未設定なら 503 で fail closed。toggle(完了切替), move(並べ替え/フォルダ移動), preview(Markdown プレビュー), calendar/events(カレンダー用), matrix(マトリクス)。tasks#index。FREE_TASK_LIMIT)。超過時は作成不可でアラート。FullCalendar ベース。日クリックで作成、ドラッグで移動、リサイズで span 変更。start_date/end_date を利用。
urgent × important の 2×2。象限間ドラッグ&ドロップで両フラグを更新。
daily/weekly), target_per_week(既定7), archived。habit_checkins(done_on 単位、habit_id+done_on にユニーク制約)。7日グリッド + ストリーク、Turbo Stream 更新。FREE_HABIT_LIMIT)。kind)。音 + ブラウザ通知。pomodoro_sessions に記録(started_at/ended_at/duration_seconds/task 紐付け任意)。直近10件表示。stopwatch(0) / countdown(1)。running/started_at/elapsed_seconds をサーバー保持。current_elapsed = elapsed + now−started_at)。countdown は duration で上限クランプ。start/pause/reset/lap。lap は timer_laps(elapsed_seconds 記録、新しい順)。属性:title, event_at, color, recurring(毎年)。秒精度 HH:MM:SS 表示。CRUD。
birth_on, life_expectancy_years, daily_sleep_hours(既定8.0)。death_on = birth_on + 寿命年。awake_fraction = (24−睡眠)/24。両方設定済みで life_configured?。resource :life(show/update のみ)。既知の落とし穴:「保存できるが hourglass が出ない」は多くの場合 dev/prod の環境取り違えであって JS バグではない。まず環境を疑う。
info/reminder/success/warning), url, read_at。read_all で一括既読。期限リマインダを自動生成。直近100件表示。月額サブスク。プランは free / pro(User::PLANS)。
| プラン | タスク | 習慣 | その他 |
|---|---|---|---|
| Free | 最大 30 | 最大 3 | 基本機能 |
| Pro | 無制限 | 無制限 | 全機能 |
subscription#checkout(Checkout セッション作成)→ Stripe → Webhook で plan 更新。portal で顧客ポータル。POST /stripe/webhook:checkout.session.completed, customer.subscription.{created,updated,deleted}。status が active/trialing → pro、それ以外/削除 → free。stripe_customer_id, stripe_subscription_id, subscription_status, current_period_end。StripeConfig.configured? で必須 4 キー検証、欠落時はエラー(無言無効化しない)。schema version 2026_07_13_020005 / charset utf8mb4。FK は基本 on_delete: cascade(pomodoro→task は nullify)。
| テーブル | 主な列 | 関連 |
|---|---|---|
| users | email, encrypted_password, name, plan, otp_enabled/otp_secret, password_configured, birth_on, life_expectancy_years, daily_sleep_hours, stripe_* | has_many 各種 |
| oauth_identities | provider, uid((provider,uid) と (user_id,provider) が一意) |
user。1 ユーザー × 1 プロバイダーにつき 1 行 |
| tasks | title, notes, completed, due/start/end_date, important, urgent, priority, position, tag | user, task_folder |
| task_folders | name(user+name ユニーク) | user, has_many tasks |
| countdowns | title, event_at, color, recurring | user |
| habits | name, description, color, frequency, target_per_week, archived | user, has_many checkins |
| habit_checkins | done_on(habit+done_on ユニーク) | habit |
| pomodoro_sessions | kind, started_at, ended_at, duration_seconds | user, task(nullify) |
| timers | name, mode, running, started_at, elapsed_seconds, duration_seconds | user, has_many laps |
| timer_laps | elapsed_seconds | timer |
| notifications | title, body, kind, url, read_at | user |
| sessions | session_id, data(DB セッション) | — |
| パス | 用途 |
|---|---|
/ |
root → tasks#index(未ログインは /users/sign_in へ) |
/tasks … |
CRUD + calendar/events/matrix/preview(collection), move/toggle(member) |
/task_folders |
CRUD(show 除く) |
/habits + /habit_checkins |
習慣 + shallow な check-in create/destroy |
/countdowns |
CRUD |
/life |
show/update |
/notifications |
index/update/destroy + read_all |
/pomodoro |
show/create |
/timers |
CRUD + start/pause/reset/lap(member) |
/subscription |
show + checkout/portal |
/stripe/webhook |
Stripe Webhook 受信 |
/two_factor, /two_factor/challenge |
2FA 設定・チャレンジ |
/up |
ヘルスチェック(200=正常起動) |
/robots.txt, /sitemap.xml |
SEO(seo コントローラ) |
/api/docs, /api/openapi.json |
Swagger UI / OpenAPI(Basic 認証) |
欠落時は無言無効化せずエラーになる設計(fail fast)。
| 変数 | 用途 |
|---|---|
| RAILS_ENV | development / test / production |
| APP_VERSION | 必須。compose で未設定だと docker compose がエラー(コンテナ稼働自体には無影響) |
| APP_HOST | SEO 生成の正準ホスト(sitemap 等) |
| DB_HOST/PORT/USERNAME/PASSWORD | DB 接続(既定値なし・必須) |
| DEVISE_MAILER_SENDER / MAIL_FROM | 認証・SMTP 送信元 |
| SMTP_HOST/PORT/SECURITY/USER/PASS | SMTP 送信 |
| GOOGLE_CLIENT_ID / SECRET | Google OAuth |
| GITHUB_OAUTH_CLIENT_ID / SECRET | GitHub OAuth(任意) |
| MICROSOFT_CLIENT_ID / SECRET | Microsoft OAuth(任意) |
| APPLE_CLIENT_ID / TEAM_ID / KEY_ID / PRIVATE_KEY | Apple OAuth(任意・4 つ揃って初めて有効) |
| STRIPE_SECRET_KEY / PRICE_ID / WEBHOOK_SECRET / PUBLISHABLE_KEY | 課金(4 つ必須) |
| TURNSTILE_SITE_KEY / SECRET_KEY | CAPTCHA(local/test はバイパス) |
| API_DOCS_USERNAME / PASSWORD | API ドキュメント Basic 認証 |
| CAPACITOR_SERVER_URL / APP_ID / APP_NAME | モバイルビルド |
**dev/prod 完全分離。**prod のデータ・コンテナには絶対に触れない。これは絶対制約。
docker-compose.yml(dev)/ docker-compose.prod.yml(prod)。Dockerfile.dev(Ruby 3.4 コンテナ, image toddyi-dev:latest)。起動時に bundle install && rails db:prepare && rails s。.:/rails でマウント → public/ は認証なし・即時静的配信(このページもそれ)。dev.toddyi.love → 127.0.0.1:3001(web)へプロキシ。script/drun でコンテナ内実行。| コンテナ | 状態 | ポート (127.0.0.1) |
|---|---|---|
| todo-dev-web | Up | 3001 → 3000 |
| todo-dev-db (MariaDB) | Up | 3307 → 3306 |
| todo-dev-doc | Up | 8286 → 80 |
| todo-dev-mailpit | Up (healthy) | 8025 → 8025 |
ヘルスチェック /up = HTTP 200。ルート / = 302 → sign_in → 200。
en / ja / de / zh(config/locales)。manifest.webmanifest + service-worker.js。SW は静的 install/offline 資産のみキャッシュし、認証済み HTML はネットワーク取得(プライベートデータをキャッシュしない)。/robots.txt, /sitemap.xml。本番は APP_HOST に公開オリジンを設定。/api/docs Swagger UI(Basic 認証)。codemagic.yaml:android-aab, ios-release)。**方針:**Git Push・Issue 作成・PR 作成の認証情報は
~/.env.globalに集約する。作業前にこれを読み込んでから git / GitHub 操作を行う。
set -a; source ~/.env.global; set +a(そのシェルの git/API 操作で有効化)。GITHUB_TOKEN(Issue/PR/API + git push 用の PAT)。$GITHUB_TOKEN を参照するので、source 済みなら通常の git push でよい(SSH 鍵は使わない)。| 項目 | 状態 | メモ |
|---|---|---|
| remote origin | HTTPS | https://github.com/LoveKapibarasan/Todo.git。SSH 鍵は不通(Permission denied)なので HTTPS+トークンで push する |
| 認証 | env token | credential helper が $GITHUB_TOKEN を都度参照(config に secret は書かない)。push 前に source ~/.env.global が必要 |
gh CLI |
未インストール | Issue/PR は GitHub API 直叩き(curl + Bearer) |
~/.env.global |
作成済 | GITHUB_TOKEN 格納済(値は非公開) |
source ~/.env.global で GH_TOKEN を渡し gh issue create / gh pr create。curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/repos/LoveKapibarasan/Todo/issues 等の API 直叩き。**秘密情報の扱い:**トークン値はこの公開ページ・コミット・ログに絶対に書かない。
~/.env.globalのみに保持し、出力時は redact する。
コミット規約:コミットメッセージ末尾に Co-Authored-By: Claude ...、PR 本文末尾に生成表記を付す(リポジトリ標準)。push/コミットはユーザー指示時のみ。
Q1.(解決)~/.env.global 作成済・トークン確認済。git は HTTPS+env トークンで push 可能に。Issue/PR は API 直叩き方式で確定(gh は未導入のまま)。
Q2. フォルダ分け機能の正確なスコープ(グループ表示 / D&D / 階層 / 色・並び順)は Issue #1 に暫定記載。実装開始前に確定する。
Q3. DDL 是正(Issue #2 / #3–#25)の着手順。Folder #1 の前に最低限ブロッカー(#5 FKカスケード・#6 所有者整合・#11 folder列・#13 並び順index)を先行させるか要判断。
2026-07-26Tasks 将来設計(#84 ツリー)の「実装」選択分を実施・マージ・Close:#85 検索OR(+タグ再利用バグ修正)/ #88+#90 status enum(pending/completed/archived)+ archive/restore、Free上限は active / #86 folder parent_id(階層・循環ガード) / #87 タスクの folder 内 reorder(position 使用開始) / #89 CalendarEvent 設計 ADR 0004。全テスト最大116件 green、DDL r8 を Drive へ。残 open は #91(god-object 原則)・親#84・#1。
2026-07-26**#80 実装**:スケジュール列を start_at/deadline_at/end_at にリネーム(締切と予定スパンを名前で分離、型は datetime のまま)。CHECK 張替・全参照/JS/i18n/テスト更新、105件 green・merge(eecd515)。さらに Tasks の将来設計レビューを 親 #84 + #85–#91 に起票(Search OR / Folder parent_id / position / status enum / CalendarEvent 分離 / Free上限×archive / Task god-object)。tasks-spec も同期。
2026-07-26Tasks 続き Continue:#76(tasks.tag 廃止・検索を join 化)/ #82(Tasks::Query 抽出)を実装・マージ・Close(c64debe)。全テスト 105件 green。DDL r7(tasks.tag 削除)を Drive へ。残 open は **#80(スケジューリング defer)・#83(FULLTEXT future)**+親#68・#1。
2026-07-26Tasks 機能レビューを 親 #68 + サブ #69–#83 に起票 → 11件を実装・マージ・Close(734a2c0)。move の 422握り潰し・toggle 冪等・タグ同期のトランザクション/レース・日付検証・events 予定のみ・#tag 完全一致・matrix SQL化。全テスト 100件 green。残 open: #76/#80/#82/#83(設計/将来)+親#68・#1。
2026-07-26スタック残件 Continue:#61 Action Mailer 移行(facade・Mailpit E2E)/ #57 2FA リカバリコードを実装・マージ・Close(80f4742)。全テスト 93件 green。DDL r6(18テーブル)を Drive へ。#55(Pico撤去) は視覚回帰リスク大 → 段階計画 ADR 0002 を確定し open のまま(親 #52・#1 も open)。
2026-07-26スタック講評を 親 #52 + サブ #53–#67 に起票。12件を実装・マージ・Close(39bb2d8):Markdownサービス+サニタイズ / Stripeサービス分離 / OAuthメール検証 / Ruby3.4.10・MariaDB11.4固定 / セッション堅牢化+trim / スタックdocs。全テスト 84件 green。#55(Pico撤去)・#57(2FAリカバリ)・#61(ActionMailer移行)は大規模のため計画付きで open(#52親・#1 も open)。
2026-07-26REST 設計 hardening(#26 / #27–#51)を全実装・main にマージ・Close(910b829)。webhook 500/冪等・XSS/オープンリダイレクト・並行ロック・JSONエンベロープ/401・レート制限(Rack::Attack)・ページング・folderコマンド・OpenAPI拡充+Swagger・モバイルADR。全テスト 81件 green。DDL r5 と設計書 v2 を Drive へ。残 open は #1 のみ。
2026-07-26ユーザーの REST 設計レビュー(24点+Swagger)を 親 Issue #26 + サブ #27–#51 に起票。うち #27/#28 は #21 マージ済コードの実バグ(webhook always-200 / 冪等性の記録順)。実装は指示待ち。
2026-07-26REST API 設計書 Toddyi_REST_API_design.md を作成し Drive の Rest/ へ配置(全エンドポイント・パラメータ・認証・既知ギャップを網羅)。ユーザーレビュー待ち。
2026-07-25据え置き Issue #20/#21/#22 を実装・main にマージ・Close(b776d8e)。#20 otp_secret 暗号化(dev/test はローカル鍵、prod は要鍵設定)/ #21 subscriptions+stripe_events(webhook 冪等性)/ #22 tags+task_tags(tasks.tag はキャッシュ維持)。全テスト 55件 green。DDL r4(17テーブル)を Drive へ。残 open は #1(Folder UI) のみ。
2026-07-25DDL 設計是正を main にマージ(42f8407、origin/main へ push)。Issue #2 と #3–#19/#23/#24/#25 を Close。全テスト 49件 green。DDL r3(マージ後)を Drive へ。#1(Folder UI) は未着手・未依頼のため open。#20/#21/#22 は据え置きで open。
2026-07-25Folder ブロッカーを実装(migration 3本 = #5 FK規則統一 / #11 folder列 / #13・#14 task並び順+index、+ #12 名前正規化)。dev DB 適用済・テスト 12件 green・FKカスケード動作確認。DDL r2 を Drive へ。
2026-07-25⚠️ ローカル main は origin/main より3コミット先行(features/ 名前空間リファクタ等が未 push)。feature ブランチはローカル main を基点に作り直した。
2026-07-25DDL 設計是正の 親 Issue #2 と サブ Issue #3–#25(全23項目)を作成。Folder 機能 #1 のブロッカーは #5/#6/#11/#12/#13/#14。
2026-07-25DEV DDL を Drive の DDL/ フォルダへエクスポート開始(script/export_ddl.sh、dev DB のみ)。資料バナーを wireframe/DDL/Rest 構成に更新。
2026-07-25デザイン資料の所在(G:\My Drive\Prompts\Toddyi / Drive フォルダ)をページ冒頭に追加。現在 tasks.png ワイヤーフレーム 1 点。
2026-07-25フォルダ分け機能の Feature Issue #1 作成 + ブランチ feature/task-folder-organization を push。SSH 不通のため origin を HTTPS 化し env トークンの credential helper を設定。§12 現状を修正。
2026-07-25§12「開発ワークフロー」を追加:Git Push・Issue・PR の認証は ~/.env.global に集約(remote は SSH、gh 未導入、ファイル未作成)。
2026-07-25実コード(Rails 8.1 / schema 2026_07_13_020005)から全機能の仕様を一から書き起こし、Working Memory を完全な仕様書に更新。
2026-07-25Working Memory ページ新規作成(dev 稼働状況・エンドポイント・環境分離の前提を記録)。
public/working-memory.html ・ noindex ・ Claude が随時更新。出典:リポジトリ実コード + README.md + db/schema.rb。