befb31137ebb
feat: UI-8 homograph warning — non-blocking row in Entry URL editor + save.ts offer banner when page domain is non-ASCII/punycode
- time
- 2026-06-10 03:37 UTC · 4 months ago
- machine
- koh2
- agent
- claude-opus-4-8
- session
- audit fix integration
- parent
- 41ef91e27e40
↓ peach-browser-befb3113.tar.gzatlas at this save
files changed3 files
src/content/save.ts+17 −1src/popup/styles/popup.css+11 −0src/popup/views/Entry.tsx+13 −1src/content/save.ts+17 −1
@@ -1,4 +1,4 @@1-import { extractDomain } from "../shared/domain";1+import { detectHomograph, extractDomain } from "../shared/domain";22 import { ACCENT_COLORS } from "../shared/types";33 import type { VaultEntry } from "../shared/types";44 @@ -110,6 +110,13 @@110110 color: rgba(240,232,216,0.42);111111 margin: 0 0 12px;112112 }113+ .banner-warn {114+ font-family: "IBM Plex Mono", "SFMono-Regular", monospace;115+ font-size: 10px;116+ line-height: 1.4;117+ color: #C8A840;118+ margin: 0 0 12px;119+ }113120 .banner-actions {114121 display: flex;115122 gap: 8px;@@ -155,6 +162,15 @@155162 const subEl = banner.appendChild(document.createElement("p"));156163 subEl.className = "banner-sub";157164 subEl.textContent = subtitle;165+166+ // UI-8 / LV-2: non-blocking homograph warning when the page's own address167+ // is non-ASCII or punycode — never blocks saving.168+ if (detectHomograph(location.hostname)) {169+ const warnEl = banner.appendChild(document.createElement("p"));170+ warnEl.className = "banner-warn";171+ warnEl.textContent =172+ "⚠ This site's address contains non-ASCII or punycode characters. Verify it's the site you intend.";173+ }158174 159175 const actionsEl = banner.appendChild(document.createElement("div"));160176 actionsEl.className = "banner-actions";src/popup/styles/popup.css+11 −0
@@ -648,6 +648,17 @@648648 color: var(--peach-t2);649649 margin-bottom: 2px;650650 }651+/* UI-8 / LV-2: non-blocking homograph warning under the URL editor. */652+.peach-homograph-warning {653+ margin: 4px 0 2px;654+ padding: 6px 8px;655+ border-radius: 6px;656+ background: color-mix(in srgb, var(--peach-breach) 12%, transparent);657+ border: 1px solid color-mix(in srgb, var(--peach-breach) 36%, transparent);658+ color: var(--peach-t1);659+ font-size: 0.6875rem;660+ line-height: 1.4;661+}651662 .peach-additional-url-row {652663 display: flex;653664 align-items: center;src/popup/views/Entry.tsx+13 −1
@@ -2,7 +2,7 @@22 import type { ProFeature, VaultEntry } from "../../shared/types";33 import { isPasskeyOnly } from "../../shared/types";44 import { detectBrowser } from "../../shared/browser";5-import { getDisplayDomain } from "../../shared/domain";5+import { detectHomograph, getDisplayDomain } from "../../shared/domain";66 import { faviconUrl, faviconImgSig, globeFaviconSig, titleInitials, titleBackground } from "../../shared/favicon";77 import { generateTOTP, parseOtpauthURI } from "../../crypto/totp";88 import { sendMessage, triggerPipPulse, triggerRing } from "../App";@@ -723,6 +723,18 @@723723 />724724 <InlineSaveCancelRow onSave={saveField} onCancel={cancelEdit} saving={saving()} />725725 </div>726+ <Show727+ when={728+ detectHomograph(draft()) ||729+ additionalUrlsDraft().some((u) => detectHomograph(u))730+ }731+ >732+ {/* UI-8 / LV-2: non-blocking homograph warning. */}733+ <p class="peach-homograph-warning">734+ ⚠ This URL contains non-ASCII or punycode characters.735+ Verify it's the site you intend.736+ </p>737+ </Show>726738 <div class="peach-additional-urls">727739 <Show when={additionalUrlsDraft().length > 0}>728740 <span class="peach-label peach-additional-urls-label">also matches</span>