# Phase 1 Migration Plan: file_uuid → file_uuid

> Version: V4.0 | Date: 2026-04-28
> Status: Planning

---

## Overview

将所有 `file_uuid` 重命名为 `file_uuid`，统一术语定义。

### Impact Summary

| Category | Count | Priority |
|----------|-------|----------|
| **Migration SQL** | 6 files | High |
| **Rust API** | ~20 files | High |
| **Portal Vue** | 3 files | Medium |
| **Documents** | 121 refs | Low |

---

## Phase 1.1: Database Migration

### Tables Affected

| Table | Column | New Name |
|-------|--------|----------|
| `face_detections` | `file_uuid` | `file_uuid` |
| `face_clusters` | `file_uuid` | `file_uuid` |
| `person_identities` | `file_uuid` | `file_uuid` |
| `person_appearances` | `file_uuid` | `file_uuid` |
| `chunks` | `file_uuid` | `file_uuid` |
| `files` | - | (already has `uuid`) |

### Indexes Affected

| Old Index | New Index |
|-----------|-----------|
| `idx_face_detections_file_uuid` | `idx_face_detections_file_uuid` |
| `idx_face_clusters_file_uuid` | `idx_face_clusters_file_uuid` |
| `idx_person_identities_file_uuid` | `idx_person_identities_file_uuid` |

### Migration Script

```sql
-- Migration: 011_rename_file_uuid_to_file_uuid.sql
-- Date: 2026-04-28

BEGIN;

-- 1. face_detections
ALTER TABLE face_detections 
RENAME COLUMN file_uuid TO file_uuid;

DROP INDEX IF EXISTS idx_face_detections_file_uuid;
CREATE INDEX idx_face_detections_file_uuid ON face_detections(file_uuid);
DROP INDEX IF EXISTS idx_face_detections_frame;
CREATE INDEX idx_face_detections_frame ON face_detections(file_uuid, frame_number);

-- 2. face_clusters
ALTER TABLE face_clusters 
RENAME COLUMN file_uuid TO file_uuid;

DROP INDEX IF EXISTS idx_face_clusters_file_uuid;
CREATE INDEX idx_face_clusters_file_uuid ON face_clusters(file_uuid);

-- 3. person_identities (will be removed in Phase 2, but rename for consistency)
ALTER TABLE person_identities 
RENAME COLUMN file_uuid TO file_uuid;

DROP INDEX IF EXISTS idx_person_identities_file_uuid;
CREATE INDEX idx_person_identities_file_uuid ON person_identities(file_uuid);

-- 4. person_appearances
ALTER TABLE person_appearances 
RENAME COLUMN file_uuid TO file_uuid;

DROP INDEX IF EXISTS idx_person_appearances_file_uuid;
CREATE INDEX idx_person_appearances_file_uuid ON person_appearances(file_uuid);
DROP INDEX IF EXISTS idx_person_appearances_time;
CREATE INDEX idx_person_appearances_time ON person_appearances(file_uuid, start_time, end_time);

-- 5. chunks (if exists)
ALTER TABLE chunks 
RENAME COLUMN file_uuid TO file_uuid;

-- 6. Update constraint names
ALTER TABLE face_detections 
DROP CONSTRAINT IF EXISTS unique_detection_per_frame,
ADD CONSTRAINT unique_detection_per_frame UNIQUE (file_uuid, frame_number, x, y, width, height);

ALTER TABLE face_clusters 
DROP CONSTRAINT IF EXISTS face_recognition_results_file_uuid_key,
ADD CONSTRAINT face_clusters_file_uuid_key UNIQUE (file_uuid);

ALTER TABLE person_identities 
DROP CONSTRAINT IF EXISTS unique_person_identity,
ADD CONSTRAINT unique_person_identity UNIQUE (file_uuid, face_identity_id, speaker_id);

COMMIT;
```

---

## Phase 1.2: Rust API Migration

### Files Affected

| File | Changes |
|------|---------|
| `src/api/face_recognition.rs` | Rename struct fields |
| `src/api/videos.rs` | Rename endpoints |
| `src/api/identities.rs` | Update query params |
| `src/api/person_identity.rs` | (will be removed in Phase 2) |
| `src/core/db/*.rs` | Rename column bindings |

### Migration Steps

1. Rename struct fields:
```rust
// Before
pub struct FaceResult {
    pub file_uuid: String,
}

// After
pub struct FaceResult {
    pub file_uuid: String,
}
```

1. Rename route parameters:
```rust
// Before
"/api/v1/face/results/:file_uuid"

// After
"/api/v1/face/results/:file_uuid"
```

1. Update SQLx bindings:
```rust
// Before
sqlx::query!("WHERE file_uuid = $1", file_uuid)

// After
sqlx::query!("WHERE file_uuid = $1", file_uuid)
```

---

## Phase 1.3: Portal Migration

### Files Affected

| File | Changes |
|------|---------|
| `portal/src/views/IdentitiesView.vue` | Rename field references |
| `portal/src/views/PersonsView.vue` | Rename field references |
| `portal/src/views/IdentityDetailView.vue` | Rename field references |
| `portal/src-tauri/src/api/*.rs` | Rename struct fields |

### Migration Steps

1. Rename TypeScript interfaces:
```typescript
// Before
interface Identity {
  file_uuid: string;
}

// After
interface Identity {
  file_uuid: string;
}
```

1. Update Vue templates:
```vue
<!-- Before -->
<div>影片: {{ identity.file_uuid }}</div>

<!-- After -->
<div>影片: {{ identity.file_uuid }}</div>
```

---

## Phase 1.4: Document Migration

### Files Affected

- `docs_v1.0/**/*.md` (121 refs)
- `AGENTS.md` (already updated)

### Migration Steps

```bash
# Batch replacement (MacOS/Linux)
find docs_v1.0 -name "*.md" -type f \
  -exec sed -i '' 's/file_uuid/file_uuid/g' {} \;

# Verify changes
grep -r "file_uuid" docs_v1.0/*.md | wc -l
```

---

## Execution Order

| Step | Description | Est. Time |
|------|-------------|-----------|
| 1 | Create DB migration script | 5 min |
| 2 | Run DB migration (dev schema) | 2 min |
| 3 | Update Rust API | 30 min |
| 4 | Update Portal | 20 min |
| 5 | Run tests | 10 min |
| 6 | Batch update docs | 5 min |
| **Total** | | **~1 hour** |

---

## Rollback Plan

```sql
-- Rollback migration
BEGIN;

ALTER TABLE face_detections RENAME COLUMN file_uuid TO file_uuid;
ALTER TABLE face_clusters RENAME COLUMN file_uuid TO file_uuid;
ALTER TABLE person_identities RENAME COLUMN file_uuid TO file_uuid;
ALTER TABLE person_appearances RENAME COLUMN file_uuid TO file_uuid;
ALTER TABLE chunks RENAME COLUMN file_uuid TO file_uuid;

-- Restore indexes
DROP INDEX idx_face_detections_file_uuid;
CREATE INDEX idx_face_detections_file_uuid ON face_detections(file_uuid);

-- ... (repeat for other tables)

COMMIT;
```

---

## Test Commands

```bash
# After migration, verify API still works
cargo run --bin momentry_playground -- server

# Test endpoints
curl "http://localhost:3003/api/v1/files/384b0ff44aaaa1f14cb2cd63b3fea966"
curl "http://localhost:3003/api/v1/files/384b0ff44aaaa1f14cb2cd63b3fea966/identities"

# Run tests
cargo test --lib
cargo clippy --lib
```

---

## Status Checklist

- [ ] Create migration script (011_rename_file_uuid.sql)
- [ ] Test migration on dev schema
- [ ] Update Rust API
- [ ] Update Portal
- [ ] Run cargo test
- [ ] Run cargo clippy
- [ ] Batch update docs
- [ ] Verify all endpoints work

---

## Next Phase

After Phase 1 completion:
- **Phase 2**: Architecture simplification (remove person_identities table)
- **Phase 3**: Implement new binding logic
- **Phase 4**: Portal UI update
