@learncard/lca-api-service 1.6.2 → 1.6.3
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/AGENTS.md +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/index.js +2 -2
- package/dist/publish-metafile.json +1 -1
- package/package.json +9 -9
- package/src/routes/escrow.ts +12 -1
- package/test/keys-escrow.spec.ts +18 -0
- package/test/keys-pin-sign-in.spec.ts +34 -2
package/AGENTS.md
CHANGED
|
@@ -143,7 +143,7 @@ Lost-login recovery issues single-use, 15-minute tokens (`src/cache/recoverySess
|
|
|
143
143
|
- The revoke re-splits the same key; it does not evict a device that already holds the private key (see `services/escrow-enclave-app/SECURITY.md` D19). After the commit it emails the contact and verified recovery addresses (`account-secured`, awaited within a 3 s budget, fail-open); the copy assumes the reader may not have run it and may have lost their login, says the recovery methods were reset, and sends them to the tenant support address (or the organization, when there is none) rather than to lost-login recovery, which the revoke itself disabled.
|
|
144
144
|
- A successful PIN release sends the `escrow-pin-sign-in` notice ("Not you? Secure your account", link to `/account/secure` on the tenant app URL) instead of `escrow-hold-released`. It is sent fail-open within the escrow notification budget.
|
|
145
145
|
- `getEscrowPinStatus().wrongAttempts` counts verified wrong entries only and is omitted for legacy records that cannot tell (until a reservation initialises the verified counter to 0; clients therefore also read the status before a release).
|
|
146
|
-
- `escrow.enroll` accepts `expectedPinCharges: { attemptsRemaining, wrongAttempts }` with a new `pinSalt` (the keep-mode same-PIN refresh). It is checked against the current PIN, then (software mode) again in the write's filter, or (authority mode) by the lease claim below, so a guess reserved or resolved after the client's check makes it CONFLICT instead of being wiped by the fresh generation. A non-zero `wrongAttempts` is
|
|
146
|
+
- `escrow.enroll` accepts `expectedPinCharges: { attemptsRemaining, wrongAttempts }` with a new `pinSalt` (the keep-mode same-PIN refresh). It is checked against the current PIN, then (software mode) again in the write's filter, or (authority mode) by the lease claim below, so a guess reserved or resolved after the client's check makes it CONFLICT instead of being wiped by the fresh generation. A non-zero `wrongAttempts` is accepted (own-typos rule, D19: the client sends it only when every recorded wrong entry is its own from the same sign-in flow) but must match the stored verified count exactly and can never exceed the charges; lca-api cannot tell whose entries they are, it only guarantees nothing changed since the client's check. Because clients count every "Incorrect PIN." response as their own recorded entry, a PIN mismatch whose failure write matched no record (re-enrolled/rotated/disabled under the compare) returns CONFLICT (`escrowChangedMessage`), never the mismatch text.
|
|
147
147
|
- **PIN-operation lease (authority mode).** Every relayed owner-signed intent (`escrow.enroll`, `escrow.disable`/`remove`) runs under `applyEnrollmentIntentUnderLease` (`src/routes/escrow.ts`): `claimEscrowEnrollmentLease` sets `userKey.escrowEnrollmentLease` in one write conditioned on the read blob + PIN record, no other lease and no live `escrowPinCompares` marker; then the authority call; then `commitEscrowEnrollmentLease`, conditioned on the lease id and the replaced `blobHash` (not on charges), which also removes the lease. `reserveEscrowPinAttempt` refuses while any lease exists and pushes a compare marker (`compareId`) that `completeRecovery` pulls once the authority answers (kept until its TTL after a transport failure). `startRecovery` and `completeRecovery` answer 429 `Automatic recovery is being updated…` under a live lease, before creating a hold or charging; `completeRecovery` also refuses (FORBIDDEN, uncharged) a PIN hold whose `holdRecord.hold.blobHash` is not the current blob's. The rewrap job (`src/jobs/escrowBlobRewrap.ts`) claims the same lease (`action: 'rewrap'`) around `rewrapEscrowBlob` in authority mode. Releasing a compare marker is best effort (its TTL covers a miss). TTLs: `ESCROW_ENROLLMENT_LEASE_TTL_MS` / `ESCROW_PIN_COMPARE_TTL_MS` = 120 s (4x the 30 s max `ESCROW_ENCLAVE_REMOTE_TIMEOUT_MS`).
|
|
148
148
|
- **Reconciliation.** If the commit write misses or the authority call fails ambiguously, `settleEscrowEnrollmentLease` (`src/services/escrow-enclave/enrollmentLease.ts`) reads the authority state and adopts it when it is exactly the lease's commit (enrollment version +1, epoch, PIN generation, share version, returned envelope identity), using the salt/PIN action recorded in the lease; a definite refusal releases the lease; an unknown outcome keeps it until expiry. `settleExpiredEscrowLease` runs on start/complete/enroll/disable/authority-state, so a crash converges on the next request. A settle that finds the same commit already persisted counts as adopted. A lost response still fails the request even when its commit is adopted (no receipt to return). `/keys/auth-share` reports `escrowBlobIdentity` so authority-mode clients can detect and repair any copy mismatch that is left, and `escrowUpdating` while a lease is held so they do not mistake an in-progress operation for a stale copy. Live-Mongo coverage: `test/keys-pin-lease.spec.ts`.
|
|
149
149
|
- Software-mode PIN carry ignores releases completed before `escrowPin.enabledAt`, so a PIN re-set at the same version after a PIN sign-in survives the next rotation.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @welibraryos/lca-api-service
|
|
2
2
|
|
|
3
|
+
## 1.6.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1923](https://github.com/learningeconomy/LearnCard/pull/1923) [`27be1a449118c3c9b69f1fd961cf0b7fe3cbcdb6`](https://github.com/learningeconomy/LearnCard/commit/27be1a449118c3c9b69f1fd961cf0b7fe3cbcdb6) Thanks [@Custard7](https://github.com/Custard7)! - PIN sign-in: wrong PIN entries made during the same sign-in on the same device are now treated as the user's own typos (own-typos rule, approved). They no longer trigger the "someone may have tried your PIN" warning, and they no longer block the same-PIN budget refresh. Only wrong entries recorded before the sign-in started, or entries from anywhere else during it, still count. The coordinator records the PIN status when the flow starts, counts its own mismatch responses, and passes both to the strategy (`input.pinAttempts`). The strategy refreshes the PIN only when nothing was recorded before the flow and every status read shows exactly the flow's own entries. lca-api now accepts a non-zero `expectedPinCharges.wrongAttempts`, but still writes only while the PIN shows exactly those charges, so a foreign entry that lands at any point still blocks the refresh. A flow is bound to one PIN generation and ends at any sign-in, and lca-api answers "Incorrect PIN." only for a wrong entry it actually recorded (otherwise CONFLICT). Sign-up now requires a recovery PIN ("Create your PIN": "You'll use it to sign in on new devices."), but it fails open. The step is skipped when escrow is not confirmed available in time. A save that errors or hangs (30s deadline) shows the error and allows a retry, and "Skip for now" appears from the second failed save (the announced error then says so, and focus returns to the PIN boxes); that skip writes no prompt flag, so the first-time PIN prompt asks again on a later start.
|
|
8
|
+
|
|
9
|
+
App copy and layout: the new-device PIN screen is now "Confirm it's you" ("Enter your 6-digit PIN to finish signing in."), without the tinted panel behind the PIN boxes, with "Other ways to confirm", "Approve from another device", "Show N more", and one quiet "Trouble signing in?" link to the 7-day path (accounts without a PIN keep their existing screen). The post-PIN-sign-in sheet replaces its yes/no question with "You're signed in" / "Done" plus a quiet "Lost a device? Secure your account" link, or, when wrong entries other than the user's own typos are recorded, an amber "Someone may have tried your PIN" warning leading with "Choose a new PIN" (with "Not now"). Account Recovery settings replace the boxed "Signed in somewhere you don't recognize?" card with a quiet "Sign out of other devices" row under "Security" at the end, marked with an amber dot while wrong PIN entries other than the user's excused own typos are recorded against the current PIN (`ready.escrowPinAttention`); the secure flow's confirm screen keeps the full explanation, now uses a red destructive button, and focuses Cancel first. Translated into es, fr and ar.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`27be1a449118c3c9b69f1fd961cf0b7fe3cbcdb6`](https://github.com/learningeconomy/LearnCard/commit/27be1a449118c3c9b69f1fd961cf0b7fe3cbcdb6)]:
|
|
12
|
+
- @learncard/sss-key-manager@0.2.7
|
|
13
|
+
- @learncard/types@5.24.2
|
|
14
|
+
- @learncard/core@9.4.43
|
|
15
|
+
- @learncard/helpers@1.7.3
|
|
16
|
+
- @learncard/init@2.5.9
|
|
17
|
+
- @learncard/did-web-plugin@1.1.43
|
|
18
|
+
- @learncard/didkit-plugin@1.10.9
|
|
19
|
+
- @learncard/didkit-plugin-node@0.3.9
|
|
20
|
+
|
|
3
21
|
## 1.6.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/dist/index.js
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 167154761 bytes
|
|
4
|
+
sha256: 0155bee05ab40b14590269d8a180e4d3cdf5c384081336c941a5948dcbbdc4d0
|