* fix(frontend): make the panel usable with screen readers
* fix(frontend): keep mobile tab names and the inbound expiry hint
Review of #6907 found two gaps in the screen-reader pass:
- On phone-width screens catTabLabel renders only the icon and names the
tab by putting aria-label on it, but callers now pass that icon with
aria-hidden for the desktop label, so every Settings, Xray and Host
category tab lost its name under TalkBack. catTabLabel now clears
aria-hidden on the icon it uses as the name.
- DateTimePicker forwarded id and aria-label but not aria-describedby,
so the inbound expiry hint ("leave blank to never expire") was never
attached. It now forwards it on both the Gregorian and Jalali input.
Zod 4: use the `error` param instead of the deprecated `message`.
lint:deprecated missed these because tsgolint's no-deprecated does not
resolve object-literal properties on a `string | Params` union.
Geodata: key geo entry rows by page position. antd deprecates rowKey's
index argument, and kind:value repeats within a page because the reader
drops domain attributes (22 pairs in geosite_IR.dat, 108 in geosite_RU).
Nord/PIA: the "All cities/regions" option used a null value, which antd
warns on. Map it through a sentinel at the Select boundary so form state
stays null, with tests that fail when the sentinel is not mapped back.
Tests:
- Run the oxlint guard through node; .bin/oxlint is a sh shim Windows
cannot spawn, and the swallowed error left both guard cases vacuous.
- Start unit workers with --no-experimental-webstorage; msw's localStorage
probe made Node 25+ warn once per forked worker.
- Set IS_REACT_ACT_ENVIRONMENT, which RTL never sets with globals: false,
and settle the async updates it exposed inside act(). The row-cells
memo test now fails when memo is removed.
- Disable antd's click wave in Storybook; it re-rendered inside the next
story's act() and tripped "not configured to support act".
- Assert InboundFormModal's validation log instead of leaking it, and
give the rule-form test a well-formed clients/list response.
* feat(pia): add login-and-add WireGuard outbounds (#2)
* fix(pia): keep PIA outbounds identifiable after the editor strips hostname
The outbound editor drops piaHostname, so last-segment matching failed for hyphenated servers. Identify rows by the computed tag, re-encrypt stored tokens onto the active key, skip unusable catalog rows, and always release the catalog refresh latch.