feat(mobile-sso): serve assetlinks.json + App Links redirect allowlist
Add the server side of Android App Links (M9 follow-up, docs/android/APP_LINKS.md): - GET /.well-known/assetlinks.json at the web root, gated by the new admin setting `mobile_app_links_enabled` (default off -> 404; on-but-no-fingerprint -> 404). Emits the Digital Asset Links statement for the fixed published package (MOBILE_APP_PACKAGE) + MOBILE_APP_CERT_SHA256 fingerprint(s). - mobileSso `/start` additionally accepts this shard's own self-origin https://<host>/mobile/callback when App Links are enabled — one additive exact-match entry, derived from APP_BASE_URL/request origin, never client input; the custom-scheme allowlist is never narrowed. The settings lookup is short-circuited for non-https redirects so custom-scheme rejections stay fast. - settings.isMobileAppLinksEnabled() (fail-closed) + getPublic().mobileAppLinks; admin updateSettings validates the boolean; seed default off. Tests: test/appLinks.test.js (route gating + allowlist). Full suite 284 pass. Swagger unchanged (web-root verification file is #swagger.ignore'd). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
This commit is contained in:
@@ -512,6 +512,15 @@ async function updateSettings(req, res) {
|
||||
) {
|
||||
return res.status(400).json({ message: 'Invalid game_account_signup value' })
|
||||
}
|
||||
// App Links toggle is a boolean stored as a 'true'/'false' string; accept a real
|
||||
// boolean or those two strings and normalize, reject anything else.
|
||||
if (settings.MOBILE_APP_LINKS_KEY in updates) {
|
||||
const v = updates[settings.MOBILE_APP_LINKS_KEY]
|
||||
if (v !== true && v !== false && v !== 'true' && v !== 'false') {
|
||||
return res.status(400).json({ message: 'Invalid mobile_app_links_enabled value' })
|
||||
}
|
||||
updates[settings.MOBILE_APP_LINKS_KEY] = String(v === true || v === 'true')
|
||||
}
|
||||
// The homepage teaser is rich text (HTML) from the shared editor — sanitize it
|
||||
// against the same allowlist as post/wiki bodies so a stored value is safe (the
|
||||
// client re-sanitizes on render as defense in depth).
|
||||
|
||||
Reference in New Issue
Block a user