knowless 1.1.4 → 1.1.5
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 +35 -0
- package/GUIDE.md +33 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,41 @@ v1.0.0 are:
|
|
|
30
30
|
- Documentation corrections
|
|
31
31
|
- Helper exports that pull existing mechanism back into the library
|
|
32
32
|
|
|
33
|
+
## [1.1.5] — 2026-05-09
|
|
34
|
+
|
|
35
|
+
Documentation-only release. plato (Mode A adopter) hit a real seam
|
|
36
|
+
under `bodyOverride`: they want to reorder the body (expiry warning
|
|
37
|
+
before URL) AND keep the "Last sign-in" security signal. The current
|
|
38
|
+
contract drops the line under override — deliberately, since override
|
|
39
|
+
is full-content replacement — and that read as a missing capability.
|
|
40
|
+
It isn't: `auth.deriveHandle(email)` and a parallel `createStore`
|
|
41
|
+
handle calling `getLastLogin(handle)` already give adopters everything
|
|
42
|
+
they need to compose the signal themselves. The gap was discoverability,
|
|
43
|
+
not surface area. Considered exporting a `formatLastLogin` helper to
|
|
44
|
+
centralize the canonical wording across adopters; held off under the
|
|
45
|
+
walk-away default-no, since the population that hits the
|
|
46
|
+
override + reorder + want-signal intersection is narrow (most
|
|
47
|
+
`bodyOverride` uses are per-call subject branding without a sign-in
|
|
48
|
+
event), and the drift risk for the few who do is small and recoverable.
|
|
49
|
+
Cross-product wording consistency for operators running multiple
|
|
50
|
+
knowless adopters belongs in a shared module on the operator side, not
|
|
51
|
+
in knowless. Revisit if a second independent adopter asks for the
|
|
52
|
+
helper. No code changes.
|
|
53
|
+
|
|
54
|
+
### Documented
|
|
55
|
+
|
|
56
|
+
- `GUIDE.md` Mode A walkthrough — added a "Composing the 'Last
|
|
57
|
+
sign-in' security signal under `bodyOverride`" callout right after
|
|
58
|
+
the `auth.deriveHandle` paragraph. Explains why the line doesn't
|
|
59
|
+
auto-append on overridden bodies (override is full-content
|
|
60
|
+
replacement, AF-26), points at the existing recipe
|
|
61
|
+
(`auth.deriveHandle` + parallel `createStore` + `getLastLogin`),
|
|
62
|
+
notes that `upsertLastLogin` only fires on callback consumption so
|
|
63
|
+
a pre-call read matches what knowless reads internally, and
|
|
64
|
+
includes a worked example. Targeted at adopters who reorder the
|
|
65
|
+
body and want the signal back; default-path adopters (no override)
|
|
66
|
+
are unaffected.
|
|
67
|
+
|
|
33
68
|
## [1.1.4] — 2026-05-08
|
|
34
69
|
|
|
35
70
|
Documentation + small bug fix. Adopters (plato, addypin, bareagent,
|
package/GUIDE.md
CHANGED
|
@@ -384,6 +384,39 @@ and `startLogin` would compute. The bare `deriveHandle` re-export
|
|
|
384
384
|
takes pre-normalized input; use the instance method unless you
|
|
385
385
|
have a specific reason to call the lower-level primitive.
|
|
386
386
|
|
|
387
|
+
> **Composing the "Last sign-in" security signal under
|
|
388
|
+
> `bodyOverride`.** The default last-sign-in line lives in
|
|
389
|
+
> `composeBody` and does **not** auto-append on overridden bodies —
|
|
390
|
+
> override is full-content replacement (handlers.js AF-26). If your
|
|
391
|
+
> override needs the same signal, look up the timestamp before
|
|
392
|
+
> calling `startLogin` and interpolate it yourself. Everything you
|
|
393
|
+
> need is already exported: `auth.deriveHandle(email)` returns the
|
|
394
|
+
> handle, and a parallel read-only `createStore(dbPath)` exposes
|
|
395
|
+
> `getLastLogin(handle)` (Unix ms when the handle exists, `null` for
|
|
396
|
+
> sham / new / opted-out). `upsertLastLogin` only fires on callback
|
|
397
|
+
> consumption, so a pre-call read returns the same value knowless
|
|
398
|
+
> reads internally. Wording stays your responsibility under override —
|
|
399
|
+
> small drift cost for taking the wheel.
|
|
400
|
+
>
|
|
401
|
+
> ```js
|
|
402
|
+
> import { createStore } from 'knowless';
|
|
403
|
+
> const store = createStore(process.env.KNOWLESS_DB_PATH);
|
|
404
|
+
> // ... in your request handler ...
|
|
405
|
+
> const handle = auth.deriveHandle(email);
|
|
406
|
+
> const lastLoginAt = store.getLastLogin(handle); // null for sham/new
|
|
407
|
+
> await auth.startLogin({
|
|
408
|
+
> email,
|
|
409
|
+
> bodyOverride: ({ url }) =>
|
|
410
|
+
> `Click to sign in:\n\n${url}\n\n` +
|
|
411
|
+
> `This link expires in 15 minutes. If you didn't request this,\n` +
|
|
412
|
+
> `ignore this email.\n` +
|
|
413
|
+
> (lastLoginAt != null
|
|
414
|
+
> ? `\nLast sign-in: ${new Date(lastLoginAt).toISOString()}.\n` +
|
|
415
|
+
> `If that wasn't you, do not click the link above.\n`
|
|
416
|
+
> : ''),
|
|
417
|
+
> });
|
|
418
|
+
> ```
|
|
419
|
+
|
|
387
420
|
> **Set `failureRedirect: '/'` — it's part of the silent-miss
|
|
388
421
|
> contract, not just a UX knob.** The default falls back to
|
|
389
422
|
> `loginPath` (typically `/login`). That's a partial enumeration
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knowless",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Small, opinionated, full-stack passwordless auth for Node.js services that don't need to email their users for anything but the sign-in link.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|