Relax the browser-supplied provider endpoint policy so any public HTTPS
endpoint works (DeepSeek relays, one-api/new-api gateways) without a preset
match, while keeping private/loopback/metadata targets gated behind
OPENPENCIL_WEB_AI_ENDPOINT_ALLOWLIST. Closing the preset lock required real
connect-time defenses:
- New provider_dial: browser-originated credentials dial PublicOnly — resolve
the host, reject any reserved resolution, and pin the client to the screened
addresses (kills DNS rebinding). .no_proxy() is load-bearing: an env/system
proxy would otherwise re-resolve the target and bypass the pin. Operator-owned
and allowlisted endpoints stay Trusted.
- Require Content-Type: application/json on POST /api/ai/* and
/api/settings/credentials so cross-origin simple requests can't reach them.
Also fixes credential-persistence issues found while auditing the switch:
OPENPENCIL_PERSIST_WEB_CREDENTIALS_SERVER accepts true/1/yes/on; credential
sync stops retrying deterministic 4xx and surfaces the failure in the settings
modal (15 locales), clearing on a corrective edit, disabled persistence, or 403.
🤖 Generated with [Claude Code](https://claude.com/claude-code)