共通規約 Conventions

Parky プロジェクト全体で守るべき共通ルールです。DB設計・コード・運用まで含みます。

Shared rules across the Parky project — covers DB design, code, and operations.

1. コードマスター方針1. Code-master strategy

ステータス・カテゴリ・種別などの列挙値は、日本語ラベルではなく コード値(英語小文字スネークケース)で DB に保存します。 表示ラベルは codes テーブル(コードマスター)で管理し、クライアント側で解決します。

Enum-like values (status, category, type…) are stored as lowercase snake_case code values, not Japanese labels. Display labels come from the codes table and are resolved client-side.

codes schema

category_id   -- 分類ID (e.g. 'admin_status')
code          -- コード値 (e.g. 'active')
display_label -- 表示名 (e.g. '有効')
lang          -- 言語コード (default 'ja')
sort_order    -- 表示順
is_deleted    -- 削除フラグ

フロントエンドでは useCode() フックで取得し、 code.label('admin_status', value) で表示名に変換、 code.options('admin_status') でドロップダウン選択肢を生成します。

Frontends use a useCode() hook: code.label('admin_status', value) → label, and code.options('admin_status') → dropdown options.

禁止: Never: CHECK制約に日本語を書かない。必ずコード値で定義する。 Do not put Japanese into CHECK constraints — always use code values.

カテゴリの代表例: admin_status, user_status, vehicle_type, session_status, notif_type, notif_status, notif_target, admin_notif_category, device_type, lot_status, lot_structure, payment_status, badge_category, theme_part_category, ticket_status, article_status, review_status, boost_status, revenue_channel ほか多数(実測で 50 以上)。 実際の完全なカテゴリ一覧は codes テーブルの SELECT DISTINCT category_id FROM codes で取得する。

Representative categories: admin_status, user_status, vehicle_type, session_status, notif_type, notif_status, notif_target, admin_notif_category, device_type, lot_status, lot_structure, payment_status, badge_category, theme_part_category, ticket_status, article_status, review_status, boost_status, revenue_channel, and many more (50+ total). For the full list query SELECT DISTINCT category_id FROM codes.

2. ソフトデリート方針2. Soft delete

ユーザーが直接操作する削除は ソフトデリートdeleted_at カラム)を使います。 完全削除は「ゴミ箱」画面からのみ実行可能にします。

User-initiated deletes use soft delete via a deleted_at column. Hard deletes are only possible from a Trash UI.

3. リンクテーブル(多対多)3. Link tables for M:N

エンティティ間の多対多・参照関係はリンクテーブル(中間テーブル)で持ち、 冗長な外部キーやデータコピーを避けます。

Many-to-many relations live in link tables — no redundant foreign keys or duplicated data.

例: parking_sessionsuser_id + parking_lot_idapp_usersparking_lots を参照します。

Example: parking_sessions references app_users and parking_lots via user_id + parking_lot_id.

4. べき等性4. Idempotency

すべてのスクリプト・SQL・マイグレーション・シード・データ操作はべき等でなければなりません。

Every script, SQL statement, migration, seed, and data operation must be idempotent.

5. 環境変数・シークレット5. Env vars & secrets

6. 命名規則6. Naming

7. コミット・デプロイ7. Commits & deploy

8. 一時作業ファイル8. Scratch outputs

9. 層規律(parky/api/ 内部構造)9. Layer discipline (internal structure of parky/api/)

Parky BFF(parky/api/)は 4 層構造 (bff / core / data / schema)+ shared / app で固定する。詳細決定は ADR-0005 (Layer-First の機械強制)

The Parky BFF (parky/api/) is organised as a 4-layer structure (bff / core / data / schema) + shared / app. See ADR-0005 (mechanical enforcement of Layer-First).

9.1 ディレクトリ構造9.1 Directory structure

parky/api/src/
├── bff/                   ← 画面 / endpoint 単位
│   ├── mobile/{views,actions,telemetry}/
│   ├── web/   admin/   owner/   marketing/
├── core/                  ← capability 単位
│   ├── parking-lots/  parking-sessions/  reviews/  gamification/
│   ├── subscriptions/ users/ auth/ notifications/
│   ├── pricing/       ← cross-domain orchestration
│   ├── home-feed/     ← cross-domain aggregate
│   └── search/
├── data/                  ← table cluster 単位(1 ファイル 1 table)
│   └── <table>.data.ts
├── schema/
│   ├── domain/            ← core 用(camelCase の意味論型)
│   ├── view/              ← bff 用(ViewEnvelope data 部分)
│   └── row/               ← data 用(snake_case の DB 列型)
├── shared/{lib,middleware,schema}/
└── app/
    ├── routes-manifest.ts
    └── index.ts

9.2 依存方向(厳守)9.2 Dependency direction (strict)

9.3 各層で書いていいこと / 書いてはいけないこと9.3 What each layer may / must not do

Layer OKOK NGNG
bff/ bff/ Zod schema / ViewEnvelope 組立 / core 呼出 Zod schemas / ViewEnvelope assembly / calling core SQL 直書き / if によるビジネス判定 / data 直叩き(単純 CRUD 除く) SQL / if-based business decisions / direct data calls (except pure CRUD)
core/ core/ domain 演算 / 複数 data の orchestration / 他 core 呼出 / domain → view 変換 Domain operations / orchestrating multiple data calls / calling sibling core / domain → view mapping SQL 直書き / HTTP 応答知識 / schema/view への逆依存 SQL / HTTP response knowledge / importing schema/view
data/ data/ SQL / postgres.js / Row → domain 変換 SQL / postgres.js / Row → domain translation ビジネスルール / 複数 table の混在(1 ファイル 1 table cluster)/ HTTP 応答知識 Business rules / mixing multiple tables in one file / HTTP response knowledge

9.4 「テーブル変更が BFF に染みない」保証9.4 Guarantee that table changes don't leak into BFF

app_users.display_namenickname に rename するケースを例に:

Example: renaming app_users.display_name to nickname:

  1. schema/row/app-users.row.ts の列を nickname に変更
  2. Update the column in schema/row/app-users.row.ts to nickname.
  3. data/app-users.data.ts の SQL と row → domain 変換を修正(displayName: row.nickname
  4. Update SQL and row → domain mapping in data/app-users.data.ts (displayName: row.nickname).
  5. schema/domain/app-user.tstouched しない(意味論 displayName を維持)
  6. schema/domain/app-user.ts is not touched — the semantic name displayName stays.
  7. core/bff/ はまったく修正不要
  8. No changes anywhere in core/ or bff/.

9.5 アンチパターン9.5 Anti-patterns

9.6 機械化9.6 Enforcement

詳細: Details: multi-channel BFF パターン・新規 endpoint の実装手順は アーキテクチャ / BFF 内部コード構造 を、 endpoint ごとの ViewEnvelope / ActionEnvelope / TelemetryAck 仕様は API レスポンス構造 を参照。 See Architecture / BFF internal code structure for the multi-channel BFF pattern and the implementation checklist for new endpoints; see API response structure for envelope-level field specs (ViewEnvelope / ActionEnvelope / TelemetryAck).