@mathismeadows/roamer-device-auth 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mathismeadows/roamer-device-auth",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "private": false,
5
5
  "mcpName": "com.mathismeadows/roamer-mcp",
6
6
  "type": "module",
@@ -538,7 +538,22 @@ async function doGetValidTokens(clientSlug, forceRefresh, forceFreshLogin = fals
538
538
  const active = forceFreshLogin ? null : await readActiveIdentity(clientSlug);
539
539
  const identityKey = active?.identityKey ?? null;
540
540
 
541
- let tokens = forceRefresh || forceFreshLogin ? null : await readCachedTokens(clientSlug, identityKey);
541
+ // BUG (found live, same session, immediately post-1.5.0-publish): identityKey being null
542
+ // here is ambiguous between "no active identity has ever been established" (must never read
543
+ // any file — force a fresh sign-in) and "explicitly asked for the identity-less cache" (only
544
+ // ever true from a 2-arg test call). cacheFilePath maps a null identityKey to the exact same
545
+ // filename AUTH-54 shipped alongside — the pre-AUTH-54 file every already-authenticated
546
+ // client already had on disk. Without this guard, a machine upgrading straight from a
547
+ // pre-AUTH-54 version silently keeps reusing that old file forever (a real "reused existing
548
+ // creds" notification a user hit immediately after this shipped) and never establishes an
549
+ // active-identity pointer at all — reproducing the exact silent-stale-identity bug AUTH-54
550
+ // exists to fix, and permanently hiding that identity from login/logout/status, which only
551
+ // ever look at the new (client, identity)-keyed files. noActiveIdentity forces the same
552
+ // fresh-sign-in path a genuinely first-ever run takes, which is what self-heals into a real
553
+ // active pointer + a new-format file — see the fresh-sign-in branch below.
554
+ const noActiveIdentity = !forceFreshLogin && !active;
555
+
556
+ let tokens = forceRefresh || forceFreshLogin || noActiveIdentity ? null : await readCachedTokens(clientSlug, identityKey);
542
557
 
543
558
  if (!forceRefresh && !forceFreshLogin && tokens?.access_token && !expiresSoon(tokens)) {
544
559
  return { tokens, reusedSilently: true, identityKey, label: active?.label };
@@ -700,8 +715,12 @@ async function doGetValidTokensLoopback(clientSlug, forceRefresh, forceFreshLogi
700
715
 
701
716
  const active = forceFreshLogin ? null : await readActiveIdentity(clientSlug);
702
717
  const identityKey = active?.identityKey ?? null;
718
+ // See doGetValidTokens's identical guard above for why this is required, not optional: a
719
+ // null identityKey here would otherwise silently resolve to the exact pre-AUTH-54 filename.
720
+ const noActiveIdentity = !forceFreshLogin && !active;
703
721
 
704
- let tokens = forceRefresh || forceFreshLogin ? null : await readLoopbackTokens(clientSlug, issuerUrl, identityKey);
722
+ let tokens =
723
+ forceRefresh || forceFreshLogin || noActiveIdentity ? null : await readLoopbackTokens(clientSlug, issuerUrl, identityKey);
705
724
 
706
725
  if (!forceRefresh && !forceFreshLogin && tokens?.access_token && !expiresSoon(tokens)) {
707
726
  return { tokens, reusedSilently: true, identityKey, label: active?.label };