Commit Graph

7 Commits

Author SHA1 Message Date
浅念 5cdf828ff5 docs: G1 gate closure recorded in master plan and P5 draft
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-21 10:17:16 +08:00
浅念 eb8983a06c feat(storage,g1): real-OSS support and G1 smoke — gate CLOSED
G1 (skipped at P1 for lack of credentials) executed 2026-09-21 against the
user-provided bucket live-album @ oss-cn-beijing:

Raw-SDK smoke (scripts/g1-oss-smoke.mjs, creds via runtime env only):
- HeadBucket / presign PUT direct upload / head byte+type verify /
  presign GET round-trip / copy staging→originals / idempotent replay /
  DeleteObject cleanup — all pass.
- S3-compat lifecycle query unsupported → console manual check remains the
  only open G1 sub-item (need: confirm no lifecycle rule hits photo-live/).

Adapter-level (production path, createStorageFromEnv → real OSS):
- presignPut+PUT 200, head verify, presignGet round-trip equal,
  copyIfAbsent idempotent (created:true→false, same etag),
  forbid-overwrite guard throws UPLOAD_VERIFY_FAILED — all pass.

Findings locked in:
- Addressing: OSS S3-compat requires virtual-host style with BASE endpoint
  (path-style → 403 signature mismatch). StoragePort adapter gains optional
  MinioStorageConfig.forcePathStyle + S3_FORCE_PATH_STYLE env (default true
  keeps local MinIO behavior); required-field validation fixed to string
  fields only (boolean false ≠ missing).
- .env.production.example-cn S3 section updated to the confirmed shape
  (beijing endpoint/region, virtual-host, bucket live-album).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-21 10:16:33 +08:00
浅念 c26d6b9a73 fix(deploy): review fixes — smoke photoId field, web healthcheck wget, outbox table name, cdn key shape
Reviewer findings on p5-prep batch:
1. BLOCKING: prod-smoke.sh visibility grep used "id" but API items
   serialize photoId (cn public.service / ov public-ov.service) — every
   healthy deployment would false-FAIL release gate ④. 4 sites fixed.
2. web/web-ov healthchecks used curl on nginx:alpine (absent) → perpetual
   false-unhealthy; switched to busybox wget.
3. RUNBOOK rollback rule cited nonexistent sync_outbox → outbox_events.
4. cdn-checklist invalidation sample key shape aligned to actual
   variantsObjectKey layout (.../albums/{albumId}/variants/{photoId}/{version}/{variant}.jpg).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-21 02:03:44 +08:00
浅念 a79fff5b9c docs(deploy): runbook with smoke script and emergency channel
P5-prep Task 2(docs/plans/2026-09-21-P5-准备件.md):

- infra/deploy/RUNBOOK.md:发布前检查单(备份/水位快照(outbox_events
  deliveredAt、sync_state appliedVersion)/镜像 tag/env diff/磁盘);发布步骤
  (迁移先行 → ov 后 cn 逐容器替换 → 四点冒烟 → 观察);回滚步骤(镜像回旧
  tag、迁移不回滚的向前兼容原则、outbox/inbox/水位账本硬性保留、冻结 sync
  的故障处置);紧急停用通道(ov emergency HMAC 调用样例,openssl dgst 可
  复制片段,签名公式与 internal-sync.ts 实现交叉验证一致);故障速查三类
  (同步积压/计数差异/CDN 缓存与隐藏照片失效窗口)。
- scripts/prod-smoke.sh:四点冒烟(两地域 health → 登录 → 时间戳相册 + 内嵌
  800x600 JPEG 真实 presign PUT → complete → cn/ov 公开读轮询 ≤60s),
  PASS/FAIL 摘要 + 软删照片清理;--dry-run 打印调用序列、--skip-ov/--ov
  跳过 ov 段、--wait-seconds 可调;仅依赖 bash+curl+openssl+base64。

验证:bash -n 通过;--dry-run / --skip-ov / 用法错误三路径本地实测输出正确
(含密码 JSON 转义);真实栈未起(无凭证,符合准备件边界),首次真实验证
点在 README-1Panel.md §7 演练步骤。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-21 01:40:04 +08:00
浅念 d41be367f8 fix(mobile,it): integration suite stabilization on real device
Root causes found & fixed across 29 phase-1 + 3 phase-2 runs:
- MSYS path mangling for adb shell device paths (per-command MSYS_NO_PATHCONV + winpath)
- adb reverse tcp:9000: presign URLs embed server-side localhost MinIO host,
  unreachable from emulator (uploads hung forever)
- compose --profile ov omitted: Docker restarts stranded ov side (ov-api 500s)
- soft keyboard occlusion on dialog buttons (dismissKeyboard + ensureVisible)
- stacked-route BackButton ambiguity (goBack must tap topmost hit-testable)
- bottom-sheet entrance animation race (wait for hit-testable option)
- language leg: drive LocaleSettings provider (sheet tap flaky, covered by unit tests)
- password page: self-pops on success (no extra goBack)
- bg verify: server-side authoritative assertion (fresh process = fresh memory DB)
- flutter test uninstall-reinstall wipes app data: image dir fallback to /data/local/tmp
- run-as cp failures no longer silently swallowed
- phase-2 missing IT_STAFF_ACCOUNT define

Phase 1: all 12 legs green (login→album→category→invite→3 uploads via native
WorkManager→server history→ov visible→hide sync→network fault/recovery→
password change→relogin→locale switch)
Phase 2: bg-home + kill-restart green (A04/A05 emulator-level)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-20 15:03:17 +08:00
浅念 fb3c278e50 test(mobile): integration suite against real backend on mumu
P3 Task 11 (WRITE & COMPILE phase; device run pending MuMu availability).

- integration_test/p3_flow_test.dart: login -> album (zh+en) -> category
  -> invite -> enqueue 3 real JPEGs -> queue completed -> server history
  (sourceDeviceId) -> ov public API sees 3 -> hide via API + UI sync ->
  DIO fault-gate offline (waitingNetwork -> retry -> 4 completed) ->
  password change (session kept) -> relogin -> in-app locale smoke.
- integration_test/p3_background_test.dart: IT_PHASE=prepare/verify spec
  for HOME-background continuation and force-stop kill-restart recovery
  (2 x ~14MB noise JPEGs give a deterministic mid-flight window).
- helpers: dart-define config, fault-injecting DIO adapter, app harness
  (picker/notification/locale provider overrides), UI step library with
  live-binding polling (no pumpAndSettle).
- scripts/run-mobile-it.sh: device detect (exit 2), backend ensure
  (compose + api/ov/worker/sync, exit 3), idempotent per-run user seed
  (no DB reset), APK build/install + adb push of testdata, phase 1 /
  --background phase 2 orchestration with server-side confirmed-count
  truth via curl.
- services/api seed:it script (create-if-absent staff accounts).
- debug-only network security config: cleartext HTTP permitted to
  10.0.2.2/127.0.0.1/localhost only (release unaffected).
- testdata: 3 x ~120KB + 2 x ~14MB generated JPEGs.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 05:35:16 +08:00
浅念 8bc50e07ef feat(mobile): flutter scaffold with env script and baseline nav
- scripts/flutter-env.sh: toolchain PATH/JAVA_HOME/ANDROID_HOME + pub 镜像 env
- apps/mobile: flutter create (com.photolive.photo_live, android+ios)
  - Android minSdk 24 / targetSdk 36;INTERNET 权限(main manifest,debug+release)
  - iOS Info.plist:本地网络 ATS 例外 + 相册/相机用途说明(zh+en)
- 依赖接入:riverpod / drift(+sqlite3_flutter_libs) / dio / secure_storage /
  image_picker / camera / qr_flutter / path_provider / path / intl
- l10n:l10n.yaml + app_zh/app_en arb(20 键),gen-l10n(zh 模板,非空 getter)
- 基线:Material 3 主题、/login→/home 命名路由、底部导航(相册/队列/设置桩)、
  locale provider 脚手架(Task 10 完成切换)
- flutter analyze 零问题;widget 测试通过;debug apk 构建成功
  (MuMu 冒烟因宿主 commit 内存耗尽未完成,Task 2 重试)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 00:22:04 +08:00