Integrated Execution Playbook (UI Refactor x Storage Persistence)
Date:
2026-04-04
Audience: maintainers and contributors
Goal: one delivery track for user-panel refactor and storage/backup rollout
1. Current Engineering Truth
1.1 Strong baseline
- Role baseline exists (
member/reviewer/admin) with route-level guards. - WebUI is already modularized (state helpers, i18n, compare/detail modules).
- Interface + E2E tests already cover key workflows and role boundaries.
- Market page already has card-first catalog and compare/detail behaviors.
1.2 Remaining debt
app.jsis still an orchestration-heavy monolith.- User core flows exist but are spread across mixed surfaces.
- Install/upload options are partially implicit and not normalized cross-page.
- Long-retention persistence strategy is still thin under constrained local disk.
1.3 Incremental progress (2026-04-07)
upload_options.replace_existingis now behaviorally effective: a new submission can retire previous pending submissions for the same user/template.- Market submission storage now persists
upload_optionsin SQLite (including auto-migration for older tables missingupload_options_json). - WebUI status vocabulary was aligned to the execution contract by adding localized labels for
queued/running/succeeded/failed/cancelled/stale, reducing raw status leakage in member/reviewer/admin surfaces. profile-packsubmit flow now also supports behavioralreplace_existing: previous pending submissions (same user + same pack) are retired toreplaced, with audit and response fields (replaced_submission_ids,replaced_submission_count).- Template submit now supports idempotent replay with
upload_options.idempotency_key(orIdempotency-Keyheader at WebUI route level): retried requests return the existing submission instead of duplicating records. - Idempotency scope conflicts are now rejected deterministically (
idempotency_key_conflict) when the same key is reused for a different template/version scope. profile-packsubmit now has the same idempotency model (submit_options.idempotency_key+ header pass-through) with replay and conflict audit events.
1.4 Incremental progress (2026-04-10)
- Member page now has a hard-boundary serving model:
/memberprefersmember.safe.htmland keeps admin/reviewer controls out of the member source template. - Runtime still performs post-auth defensive pruning for privileged scopes, so source-template boundary and runtime boundary are both enforced.
- WebUI binding decomposition moved to a shared slice registry (
app_binding_slices.js) andbindButtons()is now an orchestration shell over slice-level binders. - Slice-surface and route-surface meta tests were added to prevent regressions in script order, boundary serving, and member DOM safety.
1.5 Incremental progress (2026-04-10, observability pass)
- Public-market autopublish now emits deterministic pipeline trace metadata (
pipeline_trace_id+ stable stage event ids) across decision/publish/snapshot/backup-handoff stages. - Entry payload and API publish response now carry the same pipeline trace envelope to support deterministic cross-system correlation.
- Audit chain adds explicit
profile_pack.public_market.snapshot_rebuiltandprofile_pack.public_market.backup_handoffevents for operator-facing lifecycle visibility. - Public-market backup manifest now includes snapshot-level pipeline summary fields (
pipeline_trace_count, latest trace and stage events).
1.6 Incremental progress (2026-04-10, readability gate pass)
- A deterministic meta-level contrast guard was added for core WebUI theme tokens (member + market critical text/background pairs).
- Contrast regressions on key semantic tokens now fail CI before merge.
1.7 Incremental progress (2026-04-10, anonymous-member authz consistency pass)
- Anonymous-member default API allowlist was aligned with published capability surfaces by adding package-download and notifications read endpoints.
- Interface tests now pin both sides of the contract: default allowlist permits these reads, and explicit allowlist override still blocks them.
1.8 Incremental progress (2026-04-10, owner-binding hardening pass)
- Member uninstall route now enforces owner binding under auth-enabled mode, closing a cross-owner uninstall path.
- Interface tests now cover both branches explicitly: cross-owner uninstall is denied (
403), own uninstall still succeeds.
2. Cross-Plan Decisions
2.1 Unified state vocabulary
Installation/task and backup/restore jobs must share deterministic statuses:
queued | running | succeeded | failed | cancelled | stale
2.2 Contract-first sequence
To avoid drift from parallel rewrites:
- Freeze contracts and payloads.
- Implement backend compatibility layer.
- Bind UI to contracts.
- Replace layout shell last.
2.3 Audit as hard requirement
All storage actions and install option mutations must write audit events with request-id + actor-role.
3. Execution Phases
Phase A - Contract freeze
- Member installation endpoints + payload option extensions.
- Storage job and restore endpoint contracts.
- Docs-first spec updates and meta tests.
Phase B - Backend first
- Installation list/refresh services.
- Payload option validation/defaulting.
- Storage policy/job/restore state model.
- Restic+rclone adapter behind a service boundary.
Phase C - Frontend integration
- Apply Stitch-generated shell with runtime ID preservation.
- Keep top search + locale +
Import local AstrBot configas first-class actions. - Unify upload/install option panel behavior in
/memberand/market. - Hydrate task and installation states from new endpoints.
Phase D - Hardening
- Full interface/unit/E2E matrix.
- Failure injection:
- API
429/403/500 - backup budget reached
- restore checksum mismatch
- API
- Audit and i18n completeness check.
4. Tradeoffs
- Vanilla enhancement now vs full framework migration
- Chosen: vanilla enhancement now to preserve compatibility and test anchors.
- Google Drive as cold backup vs object storage replacement
- Chosen: cold backup only, never hot serving.
- Big-bang delivery vs layered rollout
- Chosen: layered rollout for lower blast radius and easier rollback.
5. Pitfalls to Avoid
- Directly replacing runtime IDs with generated markup.
- Adding new controls without capability mapping.
- Uploading fragmented raw directories to Drive.
- Marking backup success without restore-prepare verification.
- Running backup jobs without disk watermark guard.
6. Completion Gates
- Full test suite green, including WebUI E2E.
- No RBAC regression on restricted routes.
- Member and market option behavior is equivalent.
- Backup/restore actions leave deterministic state transitions and audit trails.