@hienlh/ppm 0.8.25 → 0.8.26

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/CHANGELOG.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # Changelog
2
2
 
3
- ## [0.8.25] - 2026-03-24
3
+ ## [0.8.26] - 2026-03-24
4
4
 
5
5
  ### Changed
6
6
  - **Temporary export/import**: Exported accounts no longer include refresh tokens — imported accounts are temporary (~1h access-only). Prevents token rotation conflicts between machines.
7
7
  - **Temporary account UI**: Shows "Temporary" badge for accounts without refresh token, "Expired" badge when expired. Expired temporary accounts cannot be re-enabled.
8
8
  - **Auto-cleanup**: Expired temporary accounts (no refresh token) are automatically deleted after 7 days.
9
9
  - **Export warning**: Export dialog now explains that exported accounts are temporary and the importing machine should login directly for permanent access.
10
+ - **Invalid refresh token cleanup**: When refresh fails with `invalid_grant`, clears the refresh token so the account becomes temporary (same lifecycle rules apply: can't re-enable when expired, auto-deleted after 7 days)
10
11
 
11
12
  ## [0.8.24] - 2026-03-24
12
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.8.25",
3
+ "version": "0.8.26",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -530,6 +530,11 @@ class AccountService {
530
530
  if (!res.ok) {
531
531
  const errorBody = await res.text().catch(() => "");
532
532
  console.error(`[accounts] Refresh failed for ${accountId}: ${res.status} ${errorBody}`);
533
+ // invalid_grant = refresh token permanently dead → clear it so account becomes temporary
534
+ if (errorBody.includes("invalid_grant")) {
535
+ console.log(`[accounts] Clearing invalid refresh token for ${account.email ?? accountId} — account is now temporary`);
536
+ updateAccount(accountId, { refresh_token: encrypt("") });
537
+ }
533
538
  if (disableOnFail) {
534
539
  this.setDisabled(accountId);
535
540
  }