# 仕様規則

## 基本

- 文書はUTF-8、Markdown、改行LFで保存する。
- 文書名・ディレクトリ名・DBテーブル名は英小文字の`kebab-case`または`snake_case`を使い、同じ階層では形式を混在させない。
- 仕様文書の見出しは、目的、前提、仕様、例外、テストの順で構成する。
- 日時は保存時にUTCのISO 8601（例：`2027-09-01T10:00:00Z`）、表示時は`Asia/Tokyo`とする。
- 日付だけの場合は`YYYY-MM-DD`、対象月は`YYYY-MM`とする。
- 日本語の表示文言はLINE応答テンプレートに集約し、コード内に分散させない。

## ディレクトリ

```text
docs/
  README.md
  specs/                 # 仕様書・規則・評価
  json/                  # 取得元の証跡（YYYY-MM単位）
  examples/              # 個人情報を含まない例
```

実装時の推奨構成：

```text
src/
  collector/             # セミナーサイト取得
  importer/              # JSONからDBへの取込
  line_bot/              # LINE Webhook・応答
  search/                # 検索条件解析・検索
  shared/                # 設定、日時、ログ、エラー
tests/
  fixtures/              # 匿名化した固定データ
```

## JSON

- 月別正規化ファイルは `docs/json/YYYY-MM.json` とする。
- 元画面の証跡は `docs/json/YYYY-MM-original-table.json` とする。
- JSONのキーはcamelCaseではなく`snake_case`とする。
- JSONのトップレベルには、少なくとも`captured_at`、`month`、`source_url`、`records`、`observed_count`を含める。
- `seminar_id`は文字列として扱い、数値化しない。
- 空値は原則`null`、複数値は配列とする。取得できなかった値と空文字を混同しない。
- 元データは上書きせず、同一月を再取得する場合も最新取得結果を別コミットまたはバックアップで追跡できるようにする。

## DB

- 主キーは内部UUIDまたはDB生成整数、取得元識別子は`source_seminar_id`として一意制約を付ける。
- 検索用の正規化値と、画面由来の`*_raw`値を分けて保持する。
- 取得のたびに削除せず、`first_seen_at`、`last_seen_at`、`is_active`で履歴と掲載終了を表現する。
- すべての時刻列はUTCで保存する。
- スキーマ変更はマイグレーションファイルで管理し、手作業で本番DBを変更しない。

## ログと秘密情報

- パスワード、アクセストークン、LINE署名、Webhook本文の個人情報をログに出さない。
- ログレベルは`DEBUG`、`INFO`、`WARNING`、`ERROR`の4段階とする。
- 認証情報は`.env`をコミットせず、環境変数またはSecrets Managerから読む。
- `.seminar-storage-state.json`はローカル専用で、共有・公開・Git登録しない。
