a205e1e3d989
add SUBMIT_FEEDBACK message type, handler, FEEDBACK_ENDPOINT constant, version bump to 2.1.0
- time
- 2026-04-26 13:24 UTC · 6 months ago
- machine
- koh2
- parent
- e42e2b44e8f8
↓ peach-browser-a205e1e3.tar.gzatlas at this save
files changed5 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/messages.ts+31 −1src/shared/types.ts+1 −0manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.0.3",4+ "version": "2.1.0",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.0.3",4+ "version": "2.1.0",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "2.0.3",3+ "version": "2.1.0",44 "description": "Zero-knowledge password manager",55 "type": "module",66 "scripts": {src/background/messages.ts+31 −1
@@ -29,6 +29,12 @@2929 { prefix: "192.168." },3030 ];3131 32+// Empty disables network submission while the UI continues to function as a33+// no-op (the handler returns ok:true without calling fetch). When set, the34+// URL is validated by `isAllowedCanaryWebhookUrl` before any request, so the35+// same private-IP/HTTPS rules that gate canary webhooks apply here.36+const FEEDBACK_ENDPOINT = "";37+3238 export function setupMessageHandler(): void {3339 chrome.runtime.onMessage.addListener(3440 (msg: unknown, sender, sendResponse) => {@@ -474,6 +480,29 @@474480 const declined = await vault.isCardDeclined(last4, expMonth, expYear);475481 return { ok: true, data: declined };476482 }483+ case "SUBMIT_FEEDBACK": {484+ const { category, message, version, browser } = msg.payload as {485+ category: string;486+ message: string;487+ version: string;488+ browser: string;489+ };490+ if (!message.trim()) return { ok: false, error: "message is empty" };491+ if (!FEEDBACK_ENDPOINT) return { ok: true };492+ if (!isAllowedCanaryWebhookUrl(FEEDBACK_ENDPOINT)) {493+ return { ok: false, error: "invalid feedback endpoint" };494+ }495+ try {496+ const res = await fetch(FEEDBACK_ENDPOINT, {497+ method: "POST",498+ headers: { "Content-Type": "application/json" },499+ body: JSON.stringify({ category, message, version, browser, source: "peach-extension" }),500+ });501+ return { ok: res.ok, error: res.ok ? undefined : `HTTP ${res.status}` };502+ } catch (err) {503+ return { ok: false, error: err instanceof Error ? err.message : "network error" };504+ }505+ }477506 default:478507 return { ok: false, error: "unknown message type" };479508 }@@ -508,7 +537,8 @@508537 type !== "GET_PENDING_PASSKEY" &&509538 type !== "GET_PASSKEY_PROVIDER_STATE" &&510539 type !== "DECLINE_CARD_SAVE" &&511- type !== "IS_CARD_DECLINED"540+ type !== "IS_CARD_DECLINED" &&541+ type !== "SUBMIT_FEEDBACK"512542 );513543 }514544 src/shared/types.ts+1 −0
@@ -197,6 +197,7 @@197197 | "RECORD_MANUAL_SUMMON"198198 | "DECLINE_CARD_SAVE"199199 | "IS_CARD_DECLINED"200+ | "SUBMIT_FEEDBACK"200201 | "GET_VAULT_STATUS"201202 // Content-script-bound message types — sent BY the background TO content202203 // scripts. They never reach messages.ts's switch. Kept in this union so