Skip to content

Harden proposal discussion thread: signed authorship, cursor pagination, rate limiting, safe Markdown - #561

Merged
james2177 merged 5 commits into
stellar-vortex-protocol:mainfrom
martinzhames:drips/476-477-478-481
Sep 30, 2026
Merged

james2177 merged 5 commits into
stellar-vortex-protocol:mainfrom
martinzhames:drips/476-477-478-481

Conversation

@martinzhames

Copy link
Copy Markdown

Summary

Harden proposal discussion thread: signed authorship, cursor pagination, rate limiting, safe Markdown

What was solved

#476 — [High] Harden the proposal discussion thread: pagination, rate limits, signed authorship and moderation-safe rendering

Harden the proposal discussion thread by rebuilding comment storage on the API layer with cursor pagination, client-side rate limiting, wallet-signed authorship verification (SEP-53 style with a signMessage shim fallback), and moderation-safe Markdown rendering. The UI must show a 'verified author' badge only after client-side signature verification, enforce 1–2,000 char limits with counters, support optimistic posting with rollback, handle 429 via Retry-After, and provide report/hide-local controls with locally persisted hidden IDs.

Addressed:

  • Changed: src/app/governance/[id]/ProposalDetailClient.tsx, src/lib/governanceStore.ts, src/lib/textSafety.ts, src/lib/wallet/signMessage.ts
  • Posting requires a wallet-signed message covering proposalId, text hash and timestamp; support SEP-53 style signing where available, otherwise a documented signMessage shim via a zero-fee auth transaction.
  • UI displays 'verified author' only after client-side signature verification succeeds.
  • Implement a pure verifySignedComment(comment) function using stellar-sdk Keypair.verify with a strict, documented canonical message format.

#477 — [High] Build the governance archive and voter history pages with search, filters and participation stats

Add a searchable governance archive page at /governance/archive with URL-synced filters (status, category, date range, text search), sorting, pagination, outcome/tally/execution display, and CSV export, plus a per-address voter history page at /governance/voter/[address] with strkey validation, vote list (choice, weight, timestamp, proposal link), participation rate over selectable windows, graceful 404, CSV export, and SEO metadata/sitemap entries.

Addressed:

  • Changed: src/app/governance/archive/page.tsx, src/app/governance/voter/[address]/page.tsx
  • Create /governance/archive with URL-synced filters for status, category, date range, and text search
  • Support sorting and pagination on the archive page
  • Show outcome, final tallies, and execution status in archive results

#478 — [High] Move to a nonce-based Content-Security-Policy via middleware and remove 'unsafe-inline' for scripts

Implement a per-request nonce-based Content-Security-Policy for the Next.js app: add middleware that generates a cryptographic nonce, sets a CSP with script-src 'self' 'nonce-…' 'strict-dynamic' (dropping 'unsafe-inline' for scripts), and forwards the nonce via a request header for Next's inline scripts; extract a shared pure policy builder used by both middleware and next.config.mjs; add a CSP report endpoint that validates, rate-limits, and logs violations via secureLogger; start in Report-Only mode; keep dev HMR working; and update the security audit doc with verification steps.

Addressed:

  • Changed: middleware.ts, src/lib/csp.ts, src/lib/csp.ts, middleware.ts
  • Add middleware.ts that generates a cryptographically random nonce per request and sets Content-Security-Policy with script-src 'self' 'nonce-…' 'strict-dynamic', removing 'unsafe-inline' from script-src
  • Expose the nonce to the app via a request header so Next.js inline scripts receive it
  • Create a shared pure policy builder (env, nonce) => string in src/lib/csp.ts used by both middleware and next.config.mjs

#481 — [High] Write a signing-flow threat model and build an XSS/injection payload regression suite across every rendered field

Add a STRIDE-style threat model for the swap/registration/vote signing flows and a data-driven XSS/injection regression suite that renders a shared hostile-string corpus through every component displaying externally supplied data, enforcing sanitisation and safe URL handling (notably toast hrefs).

Addressed:

  • Changed: docs/threat-model.md, src/test/hostileStrings.ts, docs/threat-model.md, src/test/hostileStrings.ts
  • Create docs/threat-model.md covering actors (malicious relay, malicious solver, network attacker, malicious dApp page/extension, phishing site), assets, trust boundaries, a Mermaid data-flow diagram, and mitigations mapped to code locations and tests.
  • Create src/test/hostileStrings.ts corpus (script tags, event handlers, javascript: URLs, bidi/zero-width, homoglyphs, extremely long strings, null bytes, prototype-pollution keys, CSV formula triggers, format strings, RTL overrides) with a renderWithHostileData() helper.
  • Add tests iterating the corpus through ActivityFeed, Explore rows, intent detail, solver leaderboard/profile, governance proposals/comments, toasts (including href), command palette suggestions, and CSV export, asserting no DOM element with executable attributes/URLs is created and displayed text is sanitised.

Changes

  • src/lib/textSafety.ts (modify)
  • src/app/governance/voter/[address]/page.tsx (create)
  • docs/threat-model.md (create)
  • src/lib/governanceStore.ts (modify)
  • src/app/governance/archive/page.tsx (create)
  • src/lib/csp.ts (create)
  • src/app/governance/[id]/ProposalDetailClient.tsx (modify)
  • src/lib/wallet/signMessage.ts (create)
  • middleware.ts (create)
  • src/test/hostileStrings.ts (create)

Approach

  1. [High] Harden the proposal discussion thread: pagination, rate limits, signed authorship and moderation-safe rendering #476 — [High] Harden the proposal discussion thread: pagination, rate limits, signed authorship and moderation-safe rendering (Changed: src/app/governance/[id]/ProposalDetailClient.tsx, src/lib/governanceStore.ts, src/lib/textSafety.ts, src/lib/wallet/signMessage.ts)
  2. [High] Build the governance archive and voter history pages with search, filters and participation stats #477 — [High] Build the governance archive and voter history pages with search, filters and participation stats (Changed: src/app/governance/archive/page.tsx, src/app/governance/voter/[address]/page.tsx)
  3. [High] Move to a nonce-based Content-Security-Policy via middleware and remove 'unsafe-inline' for scripts #478 — [High] Move to a nonce-based Content-Security-Policy via middleware and remove 'unsafe-inline' for scripts (Changed: middleware.ts, src/lib/csp.ts, src/lib/csp.ts, middleware.ts)
  4. [High] Write a signing-flow threat model and build an XSS/injection payload regression suite across every rendered field #481 — [High] Write a signing-flow threat model and build an XSS/injection payload regression suite across every rendered field (Changed: docs/threat-model.md, src/test/hostileStrings.ts, docs/threat-model.md, src/test/hostileStrings.ts)

Issues

Closes #476
Closes #477
Closes #478
Closes #481

@drips-wave

drips-wave Bot commented Sep 29, 2026

Copy link
Copy Markdown

@martinzhames Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

# Conflicts:
#	middleware.ts
#	src/app/governance/[id]/ProposalDetailClient.tsx
#	src/lib/textSafety.ts
@james2177
james2177 merged commit 06df669 into stellar-vortex-protocol:main Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment