@nxgt/janus-hono 0.7.3 → 0.7.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/README.md CHANGED
@@ -37,7 +37,7 @@ bun add @nxgt/janus-hono @nxgt/janus hono
37
37
  ```
38
38
 
39
39
  Every peer is required: `@nxgt/janus`, `hono` (4.13.4 or later) and
40
- `typescript` (6). `@nxgt/janus` is a **peer**, never a dependency: this package
40
+ `typescript` (6 or 7). `@nxgt/janus` is a **peer**, never a dependency: this package
41
41
  defines no error class, so the `JanusError` you catch is the one you import.
42
42
  Like `@nxgt/janus`, it expects `"moduleResolution": "bundler"`: the
43
43
  declarations import without extensions, so `nodenext` is not supported.
@@ -618,7 +618,13 @@ app.post('/invitation/accept', csrf({ origin: ORIGIN }), async (c) => {
618
618
  const invitation = await invitations.spend(hash(token), new Date()); // yours: once, unexpired
619
619
  if (invitation === null) return c.json({ code: 'INVITATION_INVALID' }, 404);
620
620
 
621
- const result = await auth.signInProven(invitation.userId, { device: deviceOf(c) });
621
+ // The invitation reached the inbox: prove it first — on an address never proved, this
622
+ // drops a password, a second factor and sessions somebody else set on it.
623
+ const user = await auth.get(invitation.userId);
624
+ if (user.email !== invitation.email) return c.json({ code: 'INVITATION_INVALID' }, 404);
625
+ await auth.verifyEmail.proveFirst(user);
626
+ // Then sign in — last, since proveFirst revokes every session.
627
+ const result = await auth.signInProven(user, { device: deviceOf(c) });
622
628
  if (result.status === 'secondFactor') {
623
629
  setCookie(c, CHALLENGE, result.challenge, { ...scope, expires: result.expiresAt });
624
630
  return c.redirect('/sign-in/second-factor', 303);
@@ -628,6 +634,11 @@ app.post('/invitation/accept', csrf({ origin: ORIGIN }), async (c) => {
628
634
  });
629
635
  ```
630
636
 
637
+ `verifyEmail.proveFirst` (`@nxgt/janus` 0.22) comes first, and before any
638
+ `setPassword` your form makes: it drops the password and revokes every
639
+ session. The check on `email` keeps it from proving an address the user
640
+ changed since the invitation was sent.
641
+
631
642
  Not `magicLink.request` then `confirm` at once: `request` counts against
632
643
  the mail throttle per address, so five anonymous requests for the invitee's
633
644
  address would answer this route 429. See [`@nxgt/janus`'s
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/janus-hono",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
4
4
  "description": "Hono middleware for @nxgt/janus: the signed-in user on every request, the session cookie, routes guarded by a permission, and every error as its status",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -49,14 +49,14 @@
49
49
  ]
50
50
  },
51
51
  "devDependencies": {
52
- "@nxgt/janus": "^0.21.0",
52
+ "@nxgt/janus": "^0.22.1",
53
53
  "@types/bun": "^1.4.2",
54
54
  "hono": "^4.13.9",
55
55
  "zod": "^4.6.5"
56
56
  },
57
57
  "peerDependencies": {
58
- "@nxgt/janus": "^0.21.0",
58
+ "@nxgt/janus": "^0.22.1",
59
59
  "hono": "^4.13.4",
60
- "typescript": "^6.0.3"
60
+ "typescript": "^6.0.3 || ^7.0.0"
61
61
  }
62
62
  }