@inoku/lepan 0.7.67 → 0.7.70

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/README.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  This public repository contains versioned LifeDrive installation assets built from the private LifeAlbum source repository.
4
4
 
5
+ ## Version 0.7.70
6
+
7
+ The account service now serializes login renewal for each user, preventing
8
+ simultaneous requests from overwriting temporary login files. It also discovers
9
+ Leither's current local service port before each request, verifies the node's
10
+ identity before using a changed endpoint, and follows port changes without an
11
+ account-service restart. The existing mobile login protocol and stored data
12
+ formats are unchanged.
13
+
14
+ Both fixes are included in the packaged service for Linux, macOS and Windows.
15
+
5
16
  For an ordinary Windows or macOS installation, download the matching package from LePan's Cloudflare-backed download URLs:
6
17
 
7
18
  - **Windows 10/11 or Windows Server (x64):** [LePan-Setup-windows-x64.exe](https://lepan.org/download/LePan-Setup-windows-x64.exe)
@@ -112,6 +123,21 @@ already exist, use **My devices** on a paired phone to invite another device. An
112
123
  interrupted first claim must be resumed on the original phone with its original
113
124
  invitation. Ordinary `--upgrade` does not renew invitations.
114
125
 
126
+ ### Reconnect after forgetting the only phone
127
+
128
+ Run `npx --yes @inoku/lepan@latest --recover-device Owner` on the computer hosting
129
+ Leither, substituting the existing account name or user ID. Scan the displayed
130
+ QR code to reconnect to that same account. This node-operator action preserves
131
+ account keys, files, backups, and other devices. The reconnect invitation is
132
+ private and expires in ten minutes; rerun the same command if it expires before
133
+ being claimed. The account service briefly restarts, while Leither keeps running.
134
+ Normal phone-to-phone invitations still require device-manager approval.
135
+
136
+ First-account pairing prepares the file catalog before opening Files and adds
137
+ `Getting started with LePan.txt` once. The guide can be renamed or deleted and is
138
+ not duplicated when another phone joins. First setup also grants each account
139
+ write access only to its own node staging directory when Leither requires it.
140
+
115
141
  An existing installation is backed up before replacement. The explicit `--upgrade` path requires the saved application and key-auth owner state before changing files, synchronizes the same published application MID, and does not rerun device or domain setup. This release intentionally does not migrate the earlier password-owner prototype. Application files are active only after Leither advances the application from `cur` to `last`; a publication timeout leaves the prior `last` version serving users.
116
142
 
117
143
  Source code and design documentation are maintained separately. No device key, identity bundle, PPT, publisher key, or node-specific application MID is included in these release assets.
package/USER_MANUAL.md CHANGED
@@ -151,13 +151,16 @@ like a key: do not post it, email it to others, or paste it anywhere public.
151
151
 
152
152
  Within ten minutes of the invitation being printed:
153
153
 
154
- 1. Scan the installer’s final QR code or the QR image that opens automatically. The saved image path is a fallback for remote sessions or computers without an image viewer. If you used the standalone shell installer, copy the whole invitation block instead.
154
+ 1. Leave the installer’s final QR code or the QR image that opens automatically visible on the computer. The saved image path is a fallback for remote sessions or computers without an image viewer. If you used the standalone shell installer, copy the whole invitation block instead.
155
155
  2. Open LifeDrive on the phone. The **Set up your LifeDrive** screen opens by itself (or open **Settings → Set up users**).
156
- 3. Enter **Your name** and a name for this device.
156
+ 3. Review **Your name** and the name for this device. Android fills in **Owner** and the phone model; you can change either.
157
157
  4. Tap **Scan QR code** and point the phone at the terminal or saved image. You can also use **Paste node identity** or **Choose identity file**.
158
158
 
159
- The phone creates its own device key, claims the node, and opens your new, empty
160
- personal drive. You are now the node's first user and its **administrator**, and
159
+ The phone creates its own device key, claims the node, and opens your personal
160
+ drive after its file list is ready. Files contains **Getting started with LePan.txt**,
161
+ a short guide to Files, Backups, connecting other phones, and keeping access to
162
+ your account. It is added once per account; reconnecting a phone does not duplicate
163
+ it, and deleting or renaming it does not cause it to return. You are now the node's first user and its **administrator**, and
161
164
  this phone is a **device manager**.
162
165
 
163
166
  You can close the setup screen without pairing to look around the app. Tapping an
@@ -360,12 +363,26 @@ What remains true:
360
363
  - **Other users are unaffected.** Their drives and devices keep working.
361
364
  - **Recovery needs the node operator.** Contact whoever runs the node.
362
365
 
363
- For node operators: LifeDrive does not yet include a repair command that binds a
364
- new device to an existing user. The setup invitation (`--household`) only works
365
- on a node that has no users, so it cannot be used for this. Until the repair
366
- command exists, recovering a user who has lost every device needs help from the
367
- LifeDrive maintainers. Do not delete or edit `.lifedrive-household/` to try to
368
- work around it: it holds every user's authority and the authorization journal.
366
+ For node operators: run this on the computer hosting Leither, replacing `Owner`
367
+ with the existing account name (quote names containing spaces), or its exact user
368
+ ID if names are duplicated:
369
+
370
+ ```bash
371
+ npx --yes @inoku/lepan@latest --recover-device Owner
372
+ ```
373
+
374
+ The account service briefly stops to issue a private reconnect invitation, then
375
+ starts again before the QR code is shown. Scan it under **Settings → Set up users**
376
+ on the phone. It enrolls a new device manager into the same account; account keys,
377
+ Files, Backups, and other devices are preserved. A reconnect invitation expires
378
+ in ten minutes unless that phone has already begun claiming it. Treat it as a
379
+ private account-access key. An expired, unclaimed code can be replaced by rerunning
380
+ the same command. Once connected, remove access for the forgotten device from
381
+ **My devices**. Leither itself stays running.
382
+
383
+ The node operator's local access authorizes this recovery; ordinary device
384
+ invitations still require approval from a paired device manager. `--household`
385
+ remains first-account setup and cannot replace an existing account.
369
386
 
370
387
  ### 5.4 Prevent lockout
371
388
 
package/bin/lifedrive.js CHANGED
@@ -42,7 +42,7 @@ async function showPairingCode(resultPath) {
42
42
  // The child writes this only after setup succeeds. Never scrape its output:
43
43
  // it can contain node keys as well as the mobile device's pairing identity.
44
44
  const pairing = JSON.parse(fs.readFileSync(resultPath, "utf8"));
45
- if (pairing.version !== 1 || !["lifedrive-device-identity", "lifedrive-node-setup"].includes(pairing.type)) {
45
+ if (pairing.version !== 1 || !["lifedrive-device-identity", "lifedrive-node-setup", "lifedrive-user-identity"].includes(pairing.type)) {
46
46
  throw new Error("Unsupported pairing data");
47
47
  }
48
48
  const directory = fs.readFileSync(`${resultPath}.directory`, "utf8");
@@ -52,7 +52,7 @@ async function showPairingCode(resultPath) {
52
52
  // The node enforces expiry and returns account details after a successful claim.
53
53
  // Keep the full invitation in the import file, and leave legacy identities intact.
54
54
  // iOS still requires certificate_sha256 even when Leither transport uses a key.
55
- const qrPayload = pairing.type === "lifedrive-node-setup"
55
+ const qrPayload = pairing.type !== "lifedrive-device-identity"
56
56
  ? JSON.stringify(Object.fromEntries([
57
57
  "type", "version", "app_id", "node_id", "endpoint", "transport",
58
58
  "transport_key", "certificate_sha256", "request_id", "secret",
@@ -65,12 +65,12 @@ async function showPairingCode(resultPath) {
65
65
  // Keep a private copy even when QR generation succeeds.
66
66
  fs.writeFileSync(identityPath, payload, { flag: "wx", mode: 0o600 });
67
67
  const options = { errorCorrectionLevel: "M", margin: 4, scale: 8 };
68
- const privacyNote = pairing.type === "lifedrive-node-setup"
68
+ const privacyNote = pairing.type !== "lifedrive-device-identity"
69
69
  ? "Keep it private. This invitation expires ten minutes after creation."
70
70
  : "This contains your device private key. Keep it private and delete it after pairing.";
71
71
  const renewalHint = pairing.type === "lifedrive-node-setup"
72
72
  ? "\nInvitation expired? Run this again on the node:\n npx --yes @inoku/lepan@latest --household\n"
73
- : "";
73
+ : pairing.type === "lifedrive-user-identity" ? "\nInvitation expired? Run the same reconnect command again on this computer.\n" : "";
74
74
  let modules;
75
75
  try {
76
76
  const QRCode = require("qrcode");
@@ -153,6 +153,7 @@ function windowsArguments(values) {
153
153
  const valueOptions = new Map([
154
154
  ["--leither-root", "-LeitherRoot"],
155
155
  ["--storage-max-gb", "-StorageMaxGB"],
156
+ ["--recover-device", "-RecoverDevice"],
156
157
  ]);
157
158
  const switches = new Map([
158
159
  ["--no-install-leither", "-NoInstallLeither"],
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/lifedrive-bundle.tar.gz
3
- size: 44139682 bytes
4
- sha256: 2173717546eb881f72dce0fdd7a5a6727bfc5286b4c23f948528b9d8f1a2fde8
3
+ size: 44302859 bytes
4
+ sha256: e955159113a918b02b42273b28e52ab12357ddfc551f0e0b7bed7a0a0527a1d4
@@ -1 +1 @@
1
- 2173717546eb881f72dce0fdd7a5a6727bfc5286b4c23f948528b9d8f1a2fde8 lifedrive-bundle.tar.gz
1
+ e955159113a918b02b42273b28e52ab12357ddfc551f0e0b7bed7a0a0527a1d4 lifedrive-bundle.tar.gz
@@ -8,6 +8,7 @@ param(
8
8
  [switch]$LeitherService,
9
9
  [switch]$Upgrade,
10
10
  [switch]$Household,
11
+ [string]$RecoverDevice,
11
12
  [switch]$Help
12
13
  )
13
14
 
@@ -28,6 +29,7 @@ Windows options:
28
29
  --leither-service Configure Leither startup only.
29
30
  --upgrade Upgrade an existing Windows LePan installation.
30
31
  --household Set up household users or renew an unclaimed setup invitation.
32
+ --recover-device USER Reconnect a phone to an existing account name or user ID.
31
33
 
32
34
  Run Windows Terminal or PowerShell as Administrator. Windows setup supports
33
35
  native x64 Windows 10/11 and Windows Server; WSL and Git Bash are not required.
@@ -35,6 +37,10 @@ native x64 Windows 10/11 and Windows Server; WSL and Git Bash are not required.
35
37
  }
36
38
 
37
39
  if ($Help) { Show-Usage; return }
40
+ if ($RecoverDevice) {
41
+ if ($Upgrade -or $LeitherService) { throw "Use --recover-device separately from --upgrade and --leither-service." }
42
+ $Household = $true
43
+ }
38
44
  if ($Upgrade -and $LeitherService) { throw "Use -Upgrade and -LeitherService separately." }
39
45
  if ($StorageMaxGB -lt 0) { throw "Leither storage must be a positive whole number of gigabytes." }
40
46
  if ($StorageMaxGB -eq 0 -and $env:LIFEDRIVE_STORAGE_MAX_GB) {
@@ -469,7 +475,7 @@ if ($Upgrade) {
469
475
  return
470
476
  }
471
477
  try {
472
- & (Join-Path $root "lifedrive-identity\setup-node.ps1") -LeitherRoot $root
478
+ & (Join-Path $root "lifedrive-identity\setup-node.ps1") -LeitherRoot $root -RecoverDevice $RecoverDevice
473
479
  } catch {
474
480
  if ($identityTaskStopped) {
475
481
  try { Start-ScheduledTask -TaskName $identityTaskName } catch {}
@@ -12,6 +12,7 @@ LEITHER_SERVICE_ONLY=0
12
12
  LEITHER_SERVICE_BOOTSTRAPPED=0
13
13
  HOUSEHOLD_CONFIG=""
14
14
  HOUSEHOLD_SETUP=0
15
+ RECOVER_DEVICE=""
15
16
  STORAGE_MAX_GB="${LIFEDRIVE_STORAGE_MAX_GB:-}"
16
17
  setup_command_args=()
17
18
  setup_arg_count=0
@@ -29,6 +30,7 @@ Installer options:
29
30
  --release-base URL Alternate GitHub Release asset base URL.
30
31
  --upgrade Upgrade an existing LePan without changing device authorization.
31
32
  --household Set up household users or renew an unclaimed setup invitation.
33
+ --recover-device USER Reconnect a phone to an existing account, using its name or user ID.
32
34
  --household-config FILE Install mobile-led household setup using a private service configuration.
33
35
 
34
36
  Setup options are forwarded to lifeDrive-setup.sh. Common examples:
@@ -53,6 +55,12 @@ while (( $# )); do
53
55
  --household)
54
56
  HOUSEHOLD_SETUP=1
55
57
  ;;
58
+ --recover-device)
59
+ shift
60
+ [[ $# -gt 0 && -n "$1" && "$1" != --* ]] || { echo "--recover-device requires an existing account name or user ID" >&2; exit 2; }
61
+ RECOVER_DEVICE="$1"
62
+ HOUSEHOLD_SETUP=1
63
+ ;;
56
64
  --household-config)
57
65
  shift
58
66
  [[ $# -gt 0 && -f "$1" ]] || { echo "--household-config requires a configuration file" >&2; exit 2; }
@@ -103,6 +111,10 @@ while (( $# )); do
103
111
  shift
104
112
  done
105
113
 
114
+ if [[ -n "$RECOVER_DEVICE" ]] && (( operation_count )); then
115
+ echo "Use --recover-device separately from --upgrade and device-management options." >&2
116
+ exit 2
117
+ fi
106
118
  if (( operation_count > 1 )); then
107
119
  echo "Choose only one of --upgrade, --add-device, --list-devices, or --revoke-device." >&2
108
120
  exit 2
@@ -942,7 +954,7 @@ chmod 700 "$LEITHER_WORKDIR/lifeDrive/"*.sh
942
954
  export LIFEDRIVE_WORKDIR="$LEITHER_WORKDIR"
943
955
  export LIFEDRIVE_LEITHER_PATH="$LEITHER_WORKDIR/Leither"
944
956
  if (( HOUSEHOLD_SETUP )); then
945
- /bin/bash "$LEITHER_WORKDIR/lifedrive-identity/setup-node.sh" "$LEITHER_WORKDIR"
957
+ /bin/bash "$LEITHER_WORKDIR/lifedrive-identity/setup-node.sh" "$LEITHER_WORKDIR" "$RECOVER_DEVICE"
946
958
  exit 0
947
959
  fi
948
960
  if [[ -n "$HOUSEHOLD_CONFIG" ]]; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inoku/lepan",
3
- "version": "0.7.67",
3
+ "version": "0.7.70",
4
4
  "description": "Install LePan and its Leither runtime on Linux, macOS, or Windows",
5
5
  "os": [
6
6
  "linux",