## Why

套餐激活系统存在两类根本性缺陷：一是多个 Model 的时间字段定义为非指针 `time.Time`，导致"待生效"状态下零值（`0001-01-01 00:00:43`）被写入数据库，污染历史数据并造成查询误判；二是排队激活的核心执行链存在逻辑断链——`HandlePackageQueueActivation` 调用的 `ActivateQueuedPackage(carrierType, carrierID)` 方法设计为"发现过期包 → 标记过期 → 激活下一个"的完整循环，但轮询处理器（`HandlePackageActivationCheck`）已提前完成了"标记过期"步骤。当 Asynq 任务执行时，过期触发条件已消失，`ActivateQueuedPackage` 空转返回，payload 中携带的 `PackageUsageID` 未被使用，导致所有排队中的套餐永久卡在 `status=0`，且系统对重启后的孤儿 pending 套餐完全无感知。当前已有至少 4 条套餐使用记录受影响（TEST5G 设备 3 条 + 其他 6 条被零值污染）。

## What Changes

- **Model 层**：将 `PackageUsage.ActivatedAt`、`ExpiresAt` 改为 `*time.Time`（需同步数据库迁移去除 NOT NULL 约束）；将 `PersonalCustomerDevice.LastUsedAt`、`PersonalCustomerICCID.LastUsedAt`、`PersonalCustomerPhone.VerifiedAt` 改为 `*time.Time`（DB 列已 nullable，无需迁移）
- **数据修复**：将现有 9 条 `tb_package_usage` 中 `activated_at/expires_at = '0001-01-01'` 的记录更新为 `NULL`
- **激活逻辑修复**：在 `ActivationService` 新增 `ActivateSpecificPackage(packageUsageID)` 方法，`HandlePackageQueueActivation` 改为直接调用该方法激活 payload 指定的具体套餐，而非重跑"查找过期包"流程
- **孤儿恢复机制**：`HandlePackageActivationCheck`（每 10 秒）新增孤儿扫描：检测载体无 `status=1` 包但存在 `status=0 AND pending_realname_activation=false` 包的情形，直接触发激活任务，同时覆盖重启恢复和 Asynq 任务丢失两种场景

## Capabilities

### New Capabilities

- `time-field-nullable-fix`：将语义上可为空的时间字段从 `time.Time` 改为 `*time.Time`，防止 GORM 将零值写入数据库；包含 Model 修改、数据库迁移、历史数据清洗、赋值代码修正（共 5 个字段，跨 4 个 Model）

### Modified Capabilities

- `package-queue-activation`：修复排队激活执行链断链问题，新增孤儿套餐恢复机制；原 spec 定义的"主套餐过期后 20 秒内激活下一个"的 SLA 要求将真正得到保障，同时新增系统重启后的自动恢复保证

## Impact

**受影响文件：**
- `internal/model/package.go` — `PackageUsage` 模型
- `internal/model/personal_customer_device.go` — 个人客户设备绑定模型
- `internal/model/personal_customer_iccid.go` — 个人客户 ICCID 绑定模型
- `internal/model/personal_customer_phone.go` — 个人客户手机验证模型
- `internal/service/package/activation_service.go` — 新增 `ActivateSpecificPackage` 方法
- `internal/polling/package_activation_handler.go` — 修改 `HandlePackageQueueActivation` 逻辑 + 新增孤儿扫描
- `internal/service/order/service.go` — 修正零值赋值
- `internal/task/auto_purchase.go` — 修正零值赋值（同类问题）
- 数据库迁移文件（新增）— `tb_package_usage.activated_at/expires_at` DROP NOT NULL

**下游影响：**
- 所有读取 `PackageUsage.ActivatedAt/ExpiresAt` 的代码需适配指针类型（nil 判断）
- 现有 9 条脏数据将被修复为 NULL
- 排队中的 TEST5G 套餐（id=2,3,6）将在修复部署后自动被孤儿扫描激活
