feat(frontend): preserve draft work and improve accessible discovery and recovery states #48

Open
opened 2026-10-14 03:11:53 +00:00 by PlasticDigits · 0 comments
Owner

Scope and source

Priority: P2. Gap coverage: GAP-032, GAP-034, GAP-035, GAP-036. Derived from GAP_1791945837.md, reviewed code commit f8dbe93df953a78b17cb3304b717dcf84c4cd517. Current e476a68da09645c2308cbf47b90211fcaffcb7af adds only the report, so implementation findings remain applicable. Report evidence is local reproduction/source inspection unless explicitly proposed; no production exploit or current live-readiness claim.

Coverage and sequencing: gap backlog tracker. Workstream 12. Dependencies: 08, 10, 11, 15.

Current codebase

Compose lacks save/restore, navigation warning, title-edit UI, diff/cancel/history; whitespace collapses and regex tag stripping can double-escape entities. Lists fetch once and conflate loading/error/empty; requests lack timeout/abort/typed error/retry handling. Modal has no trap/restored focus/inert background and repeated IDs, fields/errors lack proper associations. Search/status/personal views, dated attribution and snapshot guidance are sparse; referenced favicon.svg is absent.

Why this implementation is needed

Draft authors can lose work during wallet/Legal navigation and users cannot reliably recover, discover current polls or participate with keyboards/assistive tools.

Relevant files

Save bounded local draft data per chain/address/proposal/revision with explicit recovery/discard; preserve supported paragraphs/entities, title edits and amendment diff/cancel/history. Protect unsaved navigation and recover after Legal return. Add keyed paginated search/status/my-drafts/my-votes using bounded server reads; show full copyable address, validated explorer links, author/opener/update/comment dates and concise register-before-open explanation. Watchlists/reminders are optional follow-ons with clear permission/retention limits. Distinguish loading/empty/error/missing-ID, add timeout/abort, typed retries/Retry-After, mutation stages, error boundary and catch-all routes. Build modal focus trap/restore/inert background with unique IDs and labeled fields, errors/counters/live statuses; supply legitimate branding assets.

Constraints and guardrails

Preserve standalone offchain advisory voting, no new smart contracts or archive-node dependency, BSC as a core electorate, raw 18-decimal integer balances and separate Terra/BSC address identities. Keep Legal fail-closed transactional UI and the proven DEX Terra/Bridge EVM connectors; no browser BSC balance RPC, seed/key prompt or embedded admin/model credential. API must retain a restricted role separate from the ledger writer. Freeze at actual opening, never at draft creation or a client-supplied height. Agents own design, implementation, review and evidence under repository guidance; do not shift approvals/tests to the human or invent PASS evidence.

Acceptance criteria

Multiline/entities round-trip without content loss and local recovery never restores another identity's draft. Slow/unavailable lists differ from true empty; 404/429/offline recover without duplicate writes. Keyboard focus stays correctly scoped and returns, labels/errors/status announcements work. Discovery pagination/filter/personal context and favicon are correct with bounded responses.

Test plan: supported paths, failure paths and concurrency

Compose/amend multiline, amp/lt/entities/Unicode, cancel/title/diff, unsaved navigation, reload/Legal redirect, wallet change, storage disabled/full/corrupt and revision conflict. Loading/offline/timeout/invalid JSON/404/429, lost write response, retry/unmount and unknown route. Search/filter/pagination/personal views across empty/large datasets. Keyboard Tab/Shift-Tab/Escape, nested/modal reopen, opener removal, automated a11y plus mobile/screen-reader and visual review.

Test plan: attack, hack and abuse vectors

Poisoned/stale local drafts, storage cross-account leakage, unsafe explorer/open redirect links, XSS in search/history/comments and oversized saved content; retry-induced duplicate writes; inaccessible traps and background action execution. No signing secrets in local draft storage; read permissions and Legal gate remain enforced.

Verification and completion criteria

Attach round-trip/recovery browser tests, loading/error matrix and keyboard/a11y findings with tested mobile/screen-reader conditions. Measure contrast/touch targets rather than assuming compliance; verify optional notification behavior is disabled unless actually implemented/tested.

Record commit and pinned toolchain, commands/results and sanitized artifacts. Relevant Rust changes require cargo test --workspace --lib plus isolated Postgres integration (explicit guarded LEDGER_TEST_DATABASE_URL); frontend changes require npm test and production build plus relevant browser cases. Run secret scanning for new fixtures/config. Exercise fresh/upgrade migrations when schema/grants change; report skipped/live-only checks explicitly.

<!-- voting-gap-1791945837:12 --> ## Scope and source **Priority:** P2. **Gap coverage:** GAP-032, GAP-034, GAP-035, GAP-036. Derived from [GAP_1791945837.md](https://git.cl8y.com/code/voting/src/branch/main/gaps/GAP_1791945837.md), reviewed code commit `f8dbe93df953a78b17cb3304b717dcf84c4cd517`. Current `e476a68da09645c2308cbf47b90211fcaffcb7af` adds only the report, so implementation findings remain applicable. Report evidence is local reproduction/source inspection unless explicitly proposed; no production exploit or current live-readiness claim. Coverage and sequencing: [gap backlog tracker](https://git.cl8y.com/code/voting/issues/35). Workstream **12**. Dependencies: [08](https://git.cl8y.com/code/voting/issues/43), [10](https://git.cl8y.com/code/voting/issues/45), [11](https://git.cl8y.com/code/voting/issues/46), [15](https://git.cl8y.com/code/voting/issues/47). ## Current codebase Compose lacks save/restore, navigation warning, title-edit UI, diff/cancel/history; whitespace collapses and regex tag stripping can double-escape entities. Lists fetch once and conflate loading/error/empty; requests lack timeout/abort/typed error/retry handling. Modal has no trap/restored focus/inert background and repeated IDs, fields/errors lack proper associations. Search/status/personal views, dated attribution and snapshot guidance are sparse; referenced favicon.svg is absent. ## Why this implementation is needed Draft authors can lose work during wallet/Legal navigation and users cannot reliably recover, discover current polls or participate with keyboards/assistive tools. ## Relevant files - [`frontend/src/pages/VoteNewPage.tsx`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/pages/VoteNewPage.tsx) - [`frontend/src/pages/VoteDetailPage.tsx`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/pages/VoteDetailPage.tsx) - [`frontend/src/pages/VoteListPage.tsx`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/pages/VoteListPage.tsx) - [`frontend/src/utils/proposalSections.ts`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/utils/proposalSections.ts) - [`frontend/src/services/operatorVoting.ts`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/services/operatorVoting.ts) - [`frontend/src/components/ui/Modal.tsx`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/components/ui/Modal.tsx) - [`frontend/src/components/proposal/ProposalSectionFields.tsx`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/components/proposal/ProposalSectionFields.tsx) - [`frontend/src/App.tsx`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/App.tsx) - [`frontend/src/routes.ts`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/routes.ts) - [`frontend/src/index.css`](https://git.cl8y.com/code/voting/src/branch/main/frontend/src/index.css) - [`frontend/public/wallets/PROVENANCE.md`](https://git.cl8y.com/code/voting/src/branch/main/frontend/public/wallets/PROVENANCE.md) ## Recommended solution Save bounded local draft data per chain/address/proposal/revision with explicit recovery/discard; preserve supported paragraphs/entities, title edits and amendment diff/cancel/history. Protect unsaved navigation and recover after Legal return. Add keyed paginated search/status/my-drafts/my-votes using bounded server reads; show full copyable address, validated explorer links, author/opener/update/comment dates and concise register-before-open explanation. Watchlists/reminders are optional follow-ons with clear permission/retention limits. Distinguish loading/empty/error/missing-ID, add timeout/abort, typed retries/Retry-After, mutation stages, error boundary and catch-all routes. Build modal focus trap/restore/inert background with unique IDs and labeled fields, errors/counters/live statuses; supply legitimate branding assets. ## Constraints and guardrails Preserve standalone offchain advisory voting, no new smart contracts or archive-node dependency, BSC as a core electorate, raw 18-decimal integer balances and separate Terra/BSC address identities. Keep Legal fail-closed transactional UI and the proven DEX Terra/Bridge EVM connectors; no browser BSC balance RPC, seed/key prompt or embedded admin/model credential. API must retain a restricted role separate from the ledger writer. Freeze at actual opening, never at draft creation or a client-supplied height. Agents own design, implementation, review and evidence under repository guidance; do not shift approvals/tests to the human or invent PASS evidence. ## Acceptance criteria Multiline/entities round-trip without content loss and local recovery never restores another identity's draft. Slow/unavailable lists differ from true empty; 404/429/offline recover without duplicate writes. Keyboard focus stays correctly scoped and returns, labels/errors/status announcements work. Discovery pagination/filter/personal context and favicon are correct with bounded responses. ## Test plan: supported paths, failure paths and concurrency Compose/amend multiline, amp/lt/entities/Unicode, cancel/title/diff, unsaved navigation, reload/Legal redirect, wallet change, storage disabled/full/corrupt and revision conflict. Loading/offline/timeout/invalid JSON/404/429, lost write response, retry/unmount and unknown route. Search/filter/pagination/personal views across empty/large datasets. Keyboard Tab/Shift-Tab/Escape, nested/modal reopen, opener removal, automated a11y plus mobile/screen-reader and visual review. ## Test plan: attack, hack and abuse vectors Poisoned/stale local drafts, storage cross-account leakage, unsafe explorer/open redirect links, XSS in search/history/comments and oversized saved content; retry-induced duplicate writes; inaccessible traps and background action execution. No signing secrets in local draft storage; read permissions and Legal gate remain enforced. ## Verification and completion criteria Attach round-trip/recovery browser tests, loading/error matrix and keyboard/a11y findings with tested mobile/screen-reader conditions. Measure contrast/touch targets rather than assuming compliance; verify optional notification behavior is disabled unless actually implemented/tested. Record commit and pinned toolchain, commands/results and sanitized artifacts. Relevant Rust changes require `cargo test --workspace --lib` plus isolated Postgres integration (explicit guarded LEDGER_TEST_DATABASE_URL); frontend changes require `npm test` and production build plus relevant browser cases. Run secret scanning for new fixtures/config. Exercise fresh/upgrade migrations when schema/grants change; report skipped/live-only checks explicitly.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/voting#48
No description provided.