- U1: Admin login page with isolated token/state management (#admin hash route)
- U2: Admin review list + role detail page with approve/reject actions
- U3: Admin sync form, QR code display, and system config editor
- U4: Creator role cards show review status, run status, and QR code
- U5: Order API (POST/GET /api/orders, GET /api/orders/:id) with auth
- U6: Frontend payment flow calls POST /api/orders and shows real QR code
- Fix e2e test: add qrCodeUrl to synced test role for payment flow
P0:
- sync-token.js: remove dead consumeSyncToken code, use crypto.randomBytes for jti
P1:
- admin-sync.js: add SSRF protection (protocol/host allowlist, block private IPs in prod)
- admin-sync.js: add POST /:roleId/reset for syncing state recovery
- admin-sync.js: use BASE_URL env var instead of forgeable Host header
- admin-sync.js: guard catch block to only rollback syncing->failed (not approved)
- admin-config.js: write-protect SYNC_SECRET from manual override
- admin-config.js: add updatedAt to PUT response
- roles.js: reset reviewStatus to pending_review when editing synced role
- roles.js: filter GET /:id by reviewStatus=synced
- scripts/migrate-existing-roles-to-synced.js: data migration for existing roles
P2:
- server.js: mock-hermes use explicit allowlist [development, test]
- auth.js: ADMIN_JWT_SECRET fail-fast in production
- hermes.js: unify error messages to Chinese
- admin-sync.js: do not leak err.message in response
- admin.js: validate pagination params (page/pageSize bounds)
All 54 E2E tests pass (19 admin-sync-flow + 35 existing).