Skip to content

feat(support): user issue reporting (endpoint + web dialog) - #943

Open
Rasbandit wants to merge 9 commits into
mainfrom
feat/issue-reporting
Open

feat(support): user issue reporting (endpoint + web dialog)#943
Rasbandit wants to merge 9 commits into
mainfrom
feat/issue-reporting

Conversation

@Rasbandit

@Rasbandit Rasbandit commented Jul 7, 2026

Copy link
Copy Markdown
Member

User issue reporting — backend endpoint + web dialog

Lets users report issues from the web app (and, via the paired plugin PR, from Obsidian). Reports are stored in Postgres keyed to the user + a timestamp, and a Discord webhook pings on each new report. Logs/traces are not copied: user_id + inserted_at is the pointer into Loki/Tempo.

What's here

  • issue_reports table + Engram.Support.create_report/3. Server-stamps user_id/vault_id/device_fingerprint; RLS-allowlisted (founder cross-tenant triage, no per-user read path).
  • Engram.Notifications.Discord — fire-and-forget webhook (Task.start), no-ops when DISCORD_WEBHOOK_URL is unset (self-host/dev), carries a ±10 min LogQL window. Guarded with allowed_mentions: %{parse: []} so a report body cannot smuggle @everyone.
  • POST /api/reports on the auth-but-not-onboarding scope (onboarding/billing-blocked users can still report), rate-limited 5/hr/user. Added reports to the host_rewrite @api_top_segments allowlist (would otherwise silent-404 in prod).
  • Web: "Report a bug" dialog in Settings → Account.

Verification

  • Full gate green: mix format, credo --strict 0, sobelow --exit, mix test 3502/0.
  • Live smoke on a booted stack + real DB: 201 for web + plugin surfaces, 422 invalid surface, 401 unauth; rows show server-stamped user_id, 12-char device_fingerprint, best-effort vault_id from X-Vault-ID, status="open".

Follow-ups (deferred, non-blocking)

  • DISCORD_WEBHOOK_URL SOPS secret in engram-infra for prod (feature no-ops safely until then).
  • app_version length cap; server-side description trim; rate-limit-before-validation ordering.

Paired with the plugin PR (report-issue command + modal) — engram-app/Engram-obsidian#192.

🤖 Generated with Claude Code

Rasbandit and others added 7 commits July 7, 2026 14:56
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds Engram.Notifications.Discord (pure build_report_payload/2 +
fire-and-forget notify_report/2, Task.start so a slow/failing
Discord never blocks a report submit). Reads DISCORD_WEBHOOK_URL
in runtime config, top-level guarded so self-host/dev/test no-op.
Wires notify_report into Support.create_report/3 after insert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds useReportBug() mutation (mirrors useUpdateProfile), a
ReportBugDialog (controlled Dialog + plain textarea, no shadcn
textarea exists), and a ReportBugSection mounted before
DangerZoneSection on the account settings page.
Report-bug dialog used a divergent Tailwind string for its textarea,
making it render inconsistently with sibling settings inputs
(email-section, password-section, danger-zone-section, delete-vault-dialog,
active-vaults-section). Adopt the shared idiom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- build_report_payload/2 now returns allowed_mentions: %{parse: []}
  so Discord will not resolve @everyone/@here/role mentions embedded
  in user-controlled report.description. Without this, any
  authenticated user could ping the whole ops server via a bug report.
- ellipsis/1 now compares String.length (graphemes) instead of
  byte_size, matching the grapheme-based String.slice truncation used
  to build the content. Previously a multibyte-heavy description under
  @desc_limit graphemes but over @desc_limit bytes would be left
  unchanged by the slice yet still get a trailing "…" appended.
@Rasbandit Rasbandit added the phase/expand Migration adds nullable cols, tables, or CONCURRENTLY indexes; forward-compatible label Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

phase/expand Migration adds nullable cols, tables, or CONCURRENTLY indexes; forward-compatible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant