Skip to content
6 changes: 6 additions & 0 deletions .claude/skills/GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ A **Skill** is a scoped, reusable workflow that encodes:
- Many detailed examples needed
- Separate reference material helps token efficiency

### Korean Translation Requirement (MUST)

When you create or update a skill:
- ALSO create/update a Korean translation at `.claude/skills/<skill-name>/md-ko-ver/SKILL.md`.
- Ensure the file is saved as UTF-8 (한글 인코딩 깨짐 방지).

---

## Required Sections
Expand Down
245 changes: 245 additions & 0 deletions .claude/skills/flyway/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
---
name: flyway
description: >
Use this skill when creating or modifying database schema migrations or
resolving Flyway validation/repair issues. It enforces immutable migrations,
ddl-auto=validate usage, safe backfills, and profile-scoped auto-repair rules.
---

# Flyway Migrations

Use Flyway for all schema changes and migration recovery. This skill is scoped
to database schema workflow only.

## When to Activate

Use this skill when:
- Creating or editing a SQL migration under `src/main/resources/db/migration`
- Adding or changing JPA entity fields that require schema updates
- Handling Flyway errors (checksum mismatch, failed validation, failed migrate)
- Planning a baseline (initial schema) migration for clean environments
- Changing DDL-related settings (e.g., `ddl-auto`)

## Out of Scope (DO NOT use this skill)

- Business logic changes unrelated to schema
- Data correction scripts not tied to schema evolution
- Performance tuning, query optimization, or index analysis only
- Test data cleanup (see `test-code` skill)

---

# Core Rules/Principles

## 🚨 CRITICAL: NEVER edit an applied migration

**Rule:** Once a migration version is applied to any DB, do NOT modify or delete
its SQL file. Always add a new migration.

**Why this matters:**
- Editing breaks Flyway checksum validation.
- Inconsistent environments lead to irreversible schema drift.

## MUST: Use Flyway for all schema changes

All schema changes MUST be represented as Flyway migrations in
`src/main/resources/db/migration`.

**Why this matters:** `ddl-auto` is set to `validate`, so Hibernate will not
modify schemas. Without Flyway migrations, the app will fail to boot.

## MUST: Keep `ddl-auto=validate`

Never commit `ddl-auto=update/create`. Use `validate` across profiles.

**Why this matters:** Automatic schema mutation bypasses versioned migrations
and makes reproducible environments impossible.

## IMPORTANT: Auto-repair is dev/test only

Auto-repair is enabled for `local`, `test`, and `test-dev` profiles only.
Never enable auto-repair in production.

**Why this matters:** Repair can hide accidental migration edits. Production
must fail fast and require explicit review.

## IMPORTANT: NOT NULL changes require safe backfill

Use the pattern: add nullable column -> backfill -> set NOT NULL.

**Why this matters:** Avoids startup failures and partial updates.

---

# Workflow

## Step 1: Determine Change Scope

**DO:**
- Identify which entities/fields require schema changes.
- Search for existing migrations covering the same change.

**DO NOT:**
- Modify an existing migration file.

**Verify:**
- [ ] No existing migration already covers the change.

**Output:** A clear list of schema changes.

## Step 2: Create a New Migration

**DO:**
- Create a new SQL file under `src/main/resources/db/migration`.
- Use naming: `VYYYYMMDD__short_description.sql`.

**DO NOT:**
- Use vague names like `update.sql`.

**Verify:**
- [ ] Filename is unique and ordered.
- [ ] SQL is idempotent when possible (e.g., `IF NOT EXISTS` for columns).

**Output:** New migration file path.

## Step 3: Handle Backfills Safely

**DO:**
- For NOT NULL: add nullable column -> backfill -> set NOT NULL.
- Use deterministic backfills (no random values).

**DO NOT:**
- Skip backfill and apply NOT NULL immediately.

**Verify:**
- [ ] Backfill covers all existing rows.
- [ ] Constraints applied after backfill.

**Output:** Backfill SQL steps.

## Step 4: Validate and Apply

**DO:**
- Run `./gradlew test` or `./gradlew build`.
- If checksum mismatch: `flyway.repair()` (dev/test only) then re-run.

**DO NOT:**
- Enable auto-repair in production.

**Verify:**
- [ ] Build/test succeeds with `ddl-auto=validate`.

**Output:** Test/build result and any repair action.

---

# Output Contract

Return exactly:
1. **Migration File:** path + filename
2. **Schema Change Summary:** what changed + backfill (if any)
3. **Safety Notes:** NOT NULL pattern / repair usage / profile scope
4. **Verification:** tests or build command run

---

# Common Anti-Patterns (MUST AVOID)

## ❌ Anti-Pattern 1: Editing an applied migration

**DON'T:**
```sql
-- ❌ Editing an already-applied migration
ALTER TABLE trade_item ADD COLUMN net_payload_weight DECIMAL(19,2);
-- (later edited to add IF NOT EXISTS)
```

**✅ CORRECT:**
```sql
-- ✅ Add a new migration file instead
ALTER TABLE trade_item ADD COLUMN IF NOT EXISTS net_payload_weight DECIMAL(19,2);
```

**Consequences:**
- Flyway checksum mismatch and blocked boot.
- Divergent schemas across environments.

## ❌ Anti-Pattern 2: Using `ddl-auto=update`

**DON'T:**
```yaml
spring:
jpa:
hibernate:
ddl-auto: update # ❌ breaks migration discipline
```

**✅ CORRECT:**
```yaml
spring:
jpa:
hibernate:
ddl-auto: validate # ✅ schema managed by Flyway
```

**Consequences:**
- Untracked schema drift.
- Non-reproducible environments.

## ❌ Anti-Pattern 3: Forcing NOT NULL without backfill

**DON'T:**
```sql
ALTER TABLE trade_item ADD COLUMN net_payload_weight DECIMAL(19,2) NOT NULL;
```

**✅ CORRECT:**
```sql
ALTER TABLE trade_item ADD COLUMN net_payload_weight DECIMAL(19,2);
UPDATE trade_item SET net_payload_weight = weight - COALESCE(weight_loss, 0);
ALTER TABLE trade_item MODIFY COLUMN net_payload_weight DECIMAL(19,2) NOT NULL;
```

**Consequences:**
- Migration fails on existing data.
- Partial deployment rollbacks.

---

# Summary Checklist

## Migration File:
- [ ] New migration file created (no edits to applied files)
- [ ] Filename follows `VYYYYMMDD__short_description.sql`
- [ ] SQL is idempotent where possible

## Data Safety:
- [ ] Backfill included for NOT NULL changes
- [ ] No destructive schema changes without explicit approval

## Environment:
- [ ] `ddl-auto=validate` remains unchanged
- [ ] Auto-repair only in dev/test profiles

**If ANY item is unchecked, schema drift or startup failures may occur.**

---

# Output Expectations

When this skill is active, you MUST:

1. State the migration filename and path.
2. Explain the backfill/constraint sequence if NOT NULL is involved.
3. Call out any repair action and profile scope.

**Before writing code:**
- Confirm whether a baseline migration exists for clean DBs.

**When making changes:**
- Never modify existing migration files.
- Keep `ddl-auto=validate` in committed configs.

**NEVER:**
- Enable auto-repair in production.
- Commit hardcoded DB credentials.
Loading
Loading