Skip to content

docs(deeplink): record why the mail link keeps its portal hop - #156

Merged
kipavy merged 1 commit into
devfrom
docs/deeplink-2b-closeout
Aug 19, 2026
Merged

docs(deeplink): record why the mail link keeps its portal hop#156
kipavy merged 1 commit into
devfrom
docs/deeplink-2b-closeout

Conversation

@kipavy

@kipavy kipavy commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Closes out Part 2B of #144 in code. No behaviour change.

Why

The attenuated doc comment stated the stronger form of a verified link as settled fact — "once the mail link opens the app directly the app receives the raw token instead." That change is not being made, so the sentence would have been false in the file that defines trust.

Enterprise mail rewriters (Outlook SafeLinks, Defender ATP) re-encode a mailed link onto their own logging host, so the tap resolves against that host: no App Link fires, the mail client's in-app browser follows the redirect, and the app never sees the link. Whether a fragment survives that round trip is undocumented, and the shape is on record as breaking — FusionAuth #629, "Magic links don't work when Outlook 'safe links' are enabled". Against an unmeasurable carrier risk on a path that gates custom-handle claiming and account recovery, mailing the raw token buys one browser flash: the portal already deep-links the app the moment it succeeds.

The classification is unaffected. attenuated reasons about the strongest form a verified link could carry, not the form it carries today. The full argument is in the #144 comment.

Also

Two assertions in deepLinkUrl.test.ts could not fail: isSilentIntent returns false for every intent while the class has no members, so expect(...).toBe(false) was vacuous in both places. One typecheck-gated assertion that SilentIntent is never replaces them — a real tripwire for the day a route joins silent, since no runtime assertion can pin an empty class.

Verification

  • node ./node_modules/typescript/bin/tsc --noEmit -p tsconfig.json — exit 0, empty output.
  • CI=true npx vitest run — 480 files, 3721 tests, all passing, exit 0.
  • The new assertion was proven to bite: temporarily setting notification: "silent" produced deepLinkUrl.test.ts(90,9): error TS2322: Type 'true' is not assignable to type 'false', then reverted.

The `attenuated` doc comment stated the stronger form of a `verified`
link as settled fact — "once the mail link opens the app directly the
app receives the raw token instead". That change is not being made, so
the sentence would have been false in the file that defines trust.

Enterprise rewriters (SafeLinks, Defender ATP) re-encode a mailed link
onto their own host, so the tap resolves there: no App Link fires and
the app never sees the link. Whether a fragment survives is
undocumented. Against that, mailing the raw token buys one browser
flash, because the portal already deep-links the app on success.

The classification is unaffected — `attenuated` reasons about the
strongest form the link could carry, not the form it carries today.

Also replaces two `isSilentIntent(...) === false` assertions that could
not fail: the guard returns false for every intent while the class has
no members. One typecheck-gated assertion that `SilentIntent` is
`never` takes their place, verified to fail when a route joins `silent`.
@kipavy
kipavy merged commit 2501a2a into dev Aug 19, 2026
4 checks passed
@kipavy
kipavy deleted the docs/deeplink-2b-closeout branch August 19, 2026 23:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant