@lunora/auth 1.0.0-alpha.106 → 1.0.0-alpha.108
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/dist/email-guard.d.mts +14 -12
- package/dist/email-guard.d.ts +14 -12
- package/dist/middleware.d.mts +22 -12
- package/dist/middleware.d.ts +22 -12
- package/dist/turnstile-middleware.d.mts +17 -6
- package/dist/turnstile-middleware.d.ts +17 -6
- package/package.json +3 -3
package/dist/email-guard.d.mts
CHANGED
|
@@ -33,13 +33,6 @@ interface EmailGateConfig {
|
|
|
33
33
|
* top of the built-in list. Wildcard/subdomain aware.
|
|
34
34
|
*/
|
|
35
35
|
denyDomains?: ReadonlyArray<string>;
|
|
36
|
-
/**
|
|
37
|
-
* Reserved for callers that branch on free-vs-business (e.g. gate a feature
|
|
38
|
-
* behind a business email). Purely advisory — {@link EmailClassification}'s
|
|
39
|
-
* `emailClass` already reports `free`, so this flag exists for symmetry/intent
|
|
40
|
-
* and never blocks. Defaults to `false`.
|
|
41
|
-
*/
|
|
42
|
-
flagFreeEmail?: boolean;
|
|
43
36
|
/**
|
|
44
37
|
* Opt-in MX deliverability verification. Off by default because it needs DNS
|
|
45
38
|
* (`@visulima/email-verifier/checks/mx` → `node:dns`), which is not available
|
|
@@ -60,10 +53,18 @@ interface EmailGateConfig {
|
|
|
60
53
|
/** Options for {@link emailGateMiddleware}: the base gate config plus how to read the email from `ctx`. */
|
|
61
54
|
interface EmailGateMiddlewareOptions<Context> extends EmailGateConfig {
|
|
62
55
|
/**
|
|
63
|
-
* Selector that pulls the signup email
|
|
64
|
-
* carries only the resolved identity, not the raw request body, so
|
|
65
|
-
*
|
|
66
|
-
*
|
|
56
|
+
* Selector that pulls the signup email off `ctx`. The procedure context
|
|
57
|
+
* carries only the resolved identity, not the raw request body, so the email
|
|
58
|
+
* travels in the function `args` — which the builder surfaces to middleware
|
|
59
|
+
* as `ctx.args` (validated, frozen). Mirrors `verifyTurnstileMiddleware`'s
|
|
60
|
+
* `token` selector:
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* export const signUp = mutation
|
|
64
|
+
* .input({ email: v.string() })
|
|
65
|
+
* .use(emailGateMiddleware({ email: (ctx) => ctx.args.email }))
|
|
66
|
+
* .mutation(async ({ args, ctx }) => { … });
|
|
67
|
+
* ```
|
|
67
68
|
*/
|
|
68
69
|
email: (context: Context) => string | undefined;
|
|
69
70
|
/**
|
|
@@ -111,7 +112,8 @@ declare const assertEmailAllowed: (email: string, config?: EmailGateConfig) => P
|
|
|
111
112
|
/**
|
|
112
113
|
* Lunora procedure middleware that gates a non-auth, signup-shaped
|
|
113
114
|
* `mutation`/`action` on the email-domain policy. Attach it with `.use()`; it
|
|
114
|
-
* reads the email from `ctx` via the `email` selector (
|
|
115
|
+
* reads the email from `ctx` via the `email` selector (declare it with
|
|
116
|
+
* `.input(...)` and read it back as `ctx.args.email`)
|
|
115
117
|
* and runs {@link assertEmailAllowed}, which throws a coded {@link LunoraError}
|
|
116
118
|
* (`EMAIL_DOMAIN_BLOCKED` / `EMAIL_UNDELIVERABLE` / `VALIDATION_ERROR`) the
|
|
117
119
|
* runtime maps to the matching status.
|
package/dist/email-guard.d.ts
CHANGED
|
@@ -33,13 +33,6 @@ interface EmailGateConfig {
|
|
|
33
33
|
* top of the built-in list. Wildcard/subdomain aware.
|
|
34
34
|
*/
|
|
35
35
|
denyDomains?: ReadonlyArray<string>;
|
|
36
|
-
/**
|
|
37
|
-
* Reserved for callers that branch on free-vs-business (e.g. gate a feature
|
|
38
|
-
* behind a business email). Purely advisory — {@link EmailClassification}'s
|
|
39
|
-
* `emailClass` already reports `free`, so this flag exists for symmetry/intent
|
|
40
|
-
* and never blocks. Defaults to `false`.
|
|
41
|
-
*/
|
|
42
|
-
flagFreeEmail?: boolean;
|
|
43
36
|
/**
|
|
44
37
|
* Opt-in MX deliverability verification. Off by default because it needs DNS
|
|
45
38
|
* (`@visulima/email-verifier/checks/mx` → `node:dns`), which is not available
|
|
@@ -60,10 +53,18 @@ interface EmailGateConfig {
|
|
|
60
53
|
/** Options for {@link emailGateMiddleware}: the base gate config plus how to read the email from `ctx`. */
|
|
61
54
|
interface EmailGateMiddlewareOptions<Context> extends EmailGateConfig {
|
|
62
55
|
/**
|
|
63
|
-
* Selector that pulls the signup email
|
|
64
|
-
* carries only the resolved identity, not the raw request body, so
|
|
65
|
-
*
|
|
66
|
-
*
|
|
56
|
+
* Selector that pulls the signup email off `ctx`. The procedure context
|
|
57
|
+
* carries only the resolved identity, not the raw request body, so the email
|
|
58
|
+
* travels in the function `args` — which the builder surfaces to middleware
|
|
59
|
+
* as `ctx.args` (validated, frozen). Mirrors `verifyTurnstileMiddleware`'s
|
|
60
|
+
* `token` selector:
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* export const signUp = mutation
|
|
64
|
+
* .input({ email: v.string() })
|
|
65
|
+
* .use(emailGateMiddleware({ email: (ctx) => ctx.args.email }))
|
|
66
|
+
* .mutation(async ({ args, ctx }) => { … });
|
|
67
|
+
* ```
|
|
67
68
|
*/
|
|
68
69
|
email: (context: Context) => string | undefined;
|
|
69
70
|
/**
|
|
@@ -111,7 +112,8 @@ declare const assertEmailAllowed: (email: string, config?: EmailGateConfig) => P
|
|
|
111
112
|
/**
|
|
112
113
|
* Lunora procedure middleware that gates a non-auth, signup-shaped
|
|
113
114
|
* `mutation`/`action` on the email-domain policy. Attach it with `.use()`; it
|
|
114
|
-
* reads the email from `ctx` via the `email` selector (
|
|
115
|
+
* reads the email from `ctx` via the `email` selector (declare it with
|
|
116
|
+
* `.input(...)` and read it back as `ctx.args.email`)
|
|
115
117
|
* and runs {@link assertEmailAllowed}, which throws a coded {@link LunoraError}
|
|
116
118
|
* (`EMAIL_DOMAIN_BLOCKED` / `EMAIL_UNDELIVERABLE` / `VALIDATION_ERROR`) the
|
|
117
119
|
* runtime maps to the matching status.
|
package/dist/middleware.d.mts
CHANGED
|
@@ -148,23 +148,33 @@ interface LunoraAuthApiContext<Auth extends LunoraAuth> {
|
|
|
148
148
|
* Lunora's procedure context does not currently carry the raw request headers
|
|
149
149
|
* (only the resolved identity — see `AuthState` in `@lunora/server`), so
|
|
150
150
|
* this middleware **cannot** pre-bind headers for you and does **not** do so.
|
|
151
|
-
* You MUST pass
|
|
152
|
-
*
|
|
151
|
+
* You MUST pass `Headers` explicitly into **every** `ctx.authApi.*` call. A
|
|
152
|
+
* procedure has no inbound `Headers` object, so rebuild one from what the
|
|
153
|
+
* transport forwarded in `args`:
|
|
153
154
|
*
|
|
154
155
|
* ```ts
|
|
155
156
|
* // lunora/orgs.ts
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
157
|
+
* export const createOrg = mutation
|
|
158
|
+
* .input({ cookie: v.string(), name: v.string() })
|
|
159
|
+
* .use(withAuthPlugins(auth))
|
|
160
|
+
* .mutation(async ({ args, ctx }) =>
|
|
161
|
+
* ctx.authApi.createOrganization({
|
|
162
|
+
* body: { name: args.name },
|
|
163
|
+
* // Rebuilt from the transport — the middleware cannot pre-bind them.
|
|
164
|
+
* headers: new Headers({ cookie: args.cookie }),
|
|
165
|
+
* }),
|
|
166
|
+
* );
|
|
167
|
+
* ```
|
|
159
168
|
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
169
|
+
* `ctx.authApi` is a PROCEDURE-context surface — this middleware installs it
|
|
170
|
+
* through the builder's `.use()` chain, which `httpAction` / `httpRoute` do not
|
|
171
|
+
* have (see `HttpActionCtx` in `@lunora/server`). An HTTP action already holds
|
|
172
|
+
* the real inbound `Headers`, so call the auth instance there directly:
|
|
162
173
|
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* });
|
|
174
|
+
* ```ts
|
|
175
|
+
* export const createOrgHttp = httpAction(async (ctx, request) => {
|
|
176
|
+
* const { name } = await request.json();
|
|
177
|
+
* const org = await auth.api.createOrganization({ body: { name }, headers: request.headers });
|
|
168
178
|
*
|
|
169
179
|
* return Response.json(org);
|
|
170
180
|
* });
|
package/dist/middleware.d.ts
CHANGED
|
@@ -148,23 +148,33 @@ interface LunoraAuthApiContext<Auth extends LunoraAuth> {
|
|
|
148
148
|
* Lunora's procedure context does not currently carry the raw request headers
|
|
149
149
|
* (only the resolved identity — see `AuthState` in `@lunora/server`), so
|
|
150
150
|
* this middleware **cannot** pre-bind headers for you and does **not** do so.
|
|
151
|
-
* You MUST pass
|
|
152
|
-
*
|
|
151
|
+
* You MUST pass `Headers` explicitly into **every** `ctx.authApi.*` call. A
|
|
152
|
+
* procedure has no inbound `Headers` object, so rebuild one from what the
|
|
153
|
+
* transport forwarded in `args`:
|
|
153
154
|
*
|
|
154
155
|
* ```ts
|
|
155
156
|
* // lunora/orgs.ts
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
157
|
+
* export const createOrg = mutation
|
|
158
|
+
* .input({ cookie: v.string(), name: v.string() })
|
|
159
|
+
* .use(withAuthPlugins(auth))
|
|
160
|
+
* .mutation(async ({ args, ctx }) =>
|
|
161
|
+
* ctx.authApi.createOrganization({
|
|
162
|
+
* body: { name: args.name },
|
|
163
|
+
* // Rebuilt from the transport — the middleware cannot pre-bind them.
|
|
164
|
+
* headers: new Headers({ cookie: args.cookie }),
|
|
165
|
+
* }),
|
|
166
|
+
* );
|
|
167
|
+
* ```
|
|
159
168
|
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
169
|
+
* `ctx.authApi` is a PROCEDURE-context surface — this middleware installs it
|
|
170
|
+
* through the builder's `.use()` chain, which `httpAction` / `httpRoute` do not
|
|
171
|
+
* have (see `HttpActionCtx` in `@lunora/server`). An HTTP action already holds
|
|
172
|
+
* the real inbound `Headers`, so call the auth instance there directly:
|
|
162
173
|
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* });
|
|
174
|
+
* ```ts
|
|
175
|
+
* export const createOrgHttp = httpAction(async (ctx, request) => {
|
|
176
|
+
* const { name } = await request.json();
|
|
177
|
+
* const org = await auth.api.createOrganization({ body: { name }, headers: request.headers });
|
|
168
178
|
*
|
|
169
179
|
* return Response.json(org);
|
|
170
180
|
* });
|
|
@@ -31,17 +31,26 @@ interface VerifyTurnstileMiddlewareOptions<Context> {
|
|
|
31
31
|
/** Override the error message thrown on a failed verdict. */
|
|
32
32
|
message?: string;
|
|
33
33
|
/**
|
|
34
|
-
* Selector that pulls the visitor IP
|
|
35
|
-
*
|
|
34
|
+
* Selector that pulls the visitor IP off `ctx` — typically `ctx.ip`, or
|
|
35
|
+
* `ctx.args.ip` when the caller sends it (the procedure context has no raw
|
|
36
|
+
* `Headers`). Optional.
|
|
36
37
|
*/
|
|
37
38
|
remoteip?: (context: Context) => string | undefined;
|
|
38
39
|
/** Your Turnstile secret key (the `TURNSTILE_SECRET_KEY` env var). */
|
|
39
40
|
secret: string;
|
|
40
41
|
/**
|
|
41
|
-
* Selector that pulls the `cf-turnstile-response` token
|
|
42
|
+
* Selector that pulls the `cf-turnstile-response` token off `ctx`. The
|
|
42
43
|
* procedure context carries only the resolved identity, **not** the raw
|
|
43
44
|
* inbound `Headers` (see `withAuthPlugins` in `./middleware`), so the token
|
|
44
|
-
*
|
|
45
|
+
* travels in the function `args` — which the builder surfaces to middleware
|
|
46
|
+
* as `ctx.args` (validated, frozen):
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* export const submit = mutation
|
|
50
|
+
* .input({ message: v.string(), turnstileToken: v.string() })
|
|
51
|
+
* .use(verifyTurnstileMiddleware({ secret: env.TURNSTILE_SECRET_KEY, token: (ctx) => ctx.args.turnstileToken }))
|
|
52
|
+
* .mutation(async ({ args, ctx }) => { … });
|
|
53
|
+
* ```
|
|
45
54
|
*/
|
|
46
55
|
token: (context: Context) => string | undefined;
|
|
47
56
|
/**
|
|
@@ -56,8 +65,10 @@ interface VerifyTurnstileMiddlewareOptions<Context> {
|
|
|
56
65
|
* Procedure middleware that enforces a Turnstile (CAPTCHA) check before the
|
|
57
66
|
* handler runs. Attach it with `.use()`. It reads the token (and optional IP)
|
|
58
67
|
* from `ctx` via the provided selectors — because the procedure context does
|
|
59
|
-
* not carry raw request headers, the token
|
|
60
|
-
* `args
|
|
68
|
+
* not carry raw request headers, the token is passed through the function
|
|
69
|
+
* `args` and read back as `ctx.args.<field>` (the builder surfaces the
|
|
70
|
+
* VALIDATED args on the middleware context, frozen). To gate the better-auth
|
|
71
|
+
* sign-in/sign-up flow itself, prefer
|
|
61
72
|
* better-auth's native `captcha` plugin (re-exported from `@lunora/auth/plugins`)
|
|
62
73
|
* — this middleware is for non-auth Lunora procedures.
|
|
63
74
|
*
|
|
@@ -31,17 +31,26 @@ interface VerifyTurnstileMiddlewareOptions<Context> {
|
|
|
31
31
|
/** Override the error message thrown on a failed verdict. */
|
|
32
32
|
message?: string;
|
|
33
33
|
/**
|
|
34
|
-
* Selector that pulls the visitor IP
|
|
35
|
-
*
|
|
34
|
+
* Selector that pulls the visitor IP off `ctx` — typically `ctx.ip`, or
|
|
35
|
+
* `ctx.args.ip` when the caller sends it (the procedure context has no raw
|
|
36
|
+
* `Headers`). Optional.
|
|
36
37
|
*/
|
|
37
38
|
remoteip?: (context: Context) => string | undefined;
|
|
38
39
|
/** Your Turnstile secret key (the `TURNSTILE_SECRET_KEY` env var). */
|
|
39
40
|
secret: string;
|
|
40
41
|
/**
|
|
41
|
-
* Selector that pulls the `cf-turnstile-response` token
|
|
42
|
+
* Selector that pulls the `cf-turnstile-response` token off `ctx`. The
|
|
42
43
|
* procedure context carries only the resolved identity, **not** the raw
|
|
43
44
|
* inbound `Headers` (see `withAuthPlugins` in `./middleware`), so the token
|
|
44
|
-
*
|
|
45
|
+
* travels in the function `args` — which the builder surfaces to middleware
|
|
46
|
+
* as `ctx.args` (validated, frozen):
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* export const submit = mutation
|
|
50
|
+
* .input({ message: v.string(), turnstileToken: v.string() })
|
|
51
|
+
* .use(verifyTurnstileMiddleware({ secret: env.TURNSTILE_SECRET_KEY, token: (ctx) => ctx.args.turnstileToken }))
|
|
52
|
+
* .mutation(async ({ args, ctx }) => { … });
|
|
53
|
+
* ```
|
|
45
54
|
*/
|
|
46
55
|
token: (context: Context) => string | undefined;
|
|
47
56
|
/**
|
|
@@ -56,8 +65,10 @@ interface VerifyTurnstileMiddlewareOptions<Context> {
|
|
|
56
65
|
* Procedure middleware that enforces a Turnstile (CAPTCHA) check before the
|
|
57
66
|
* handler runs. Attach it with `.use()`. It reads the token (and optional IP)
|
|
58
67
|
* from `ctx` via the provided selectors — because the procedure context does
|
|
59
|
-
* not carry raw request headers, the token
|
|
60
|
-
* `args
|
|
68
|
+
* not carry raw request headers, the token is passed through the function
|
|
69
|
+
* `args` and read back as `ctx.args.<field>` (the builder surfaces the
|
|
70
|
+
* VALIDATED args on the middleware context, frozen). To gate the better-auth
|
|
71
|
+
* sign-in/sign-up flow itself, prefer
|
|
61
72
|
* better-auth's native `captcha` plugin (re-exported from `@lunora/auth/plugins`)
|
|
62
73
|
* — this middleware is for non-auth Lunora procedures.
|
|
63
74
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/auth",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.108",
|
|
4
4
|
"description": "Auth for Lunora — a thin better-auth wrapper: email/password, OAuth, plugins, D1-backed",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
"@better-auth/oauth-provider": "1.7.1",
|
|
104
104
|
"@better-auth/passkey": "1.7.1",
|
|
105
105
|
"@better-auth/scim": "1.7.1",
|
|
106
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
107
|
-
"@lunora/values": "1.0.0-alpha.
|
|
106
|
+
"@lunora/errors": "1.0.0-alpha.27",
|
|
107
|
+
"@lunora/values": "1.0.0-alpha.35",
|
|
108
108
|
"@visulima/disposable-email-domains": "1.1.0",
|
|
109
109
|
"@visulima/email-verifier": "1.0.2",
|
|
110
110
|
"@visulima/free-email-domains": "1.0.1",
|