@pattern-js/mod-identity 0.4.0 → 0.5.0

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.
Files changed (62) hide show
  1. package/dist/deliver.d.ts +6 -0
  2. package/dist/deliver.d.ts.map +1 -1
  3. package/dist/deliver.js +32 -5
  4. package/dist/deliver.js.map +1 -1
  5. package/dist/frontend.d.ts +7 -4
  6. package/dist/frontend.d.ts.map +1 -1
  7. package/dist/frontend.js +20 -63
  8. package/dist/frontend.js.map +1 -1
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/mod.d.ts.map +1 -1
  14. package/dist/mod.js +10 -3
  15. package/dist/mod.js.map +1 -1
  16. package/dist/ops.d.ts.map +1 -1
  17. package/dist/ops.js +86 -13
  18. package/dist/ops.js.map +1 -1
  19. package/dist/options.d.ts +24 -0
  20. package/dist/options.d.ts.map +1 -1
  21. package/dist/options.js +4 -0
  22. package/dist/options.js.map +1 -1
  23. package/dist/pages/html.d.ts.map +1 -1
  24. package/dist/pages/html.js +15 -0
  25. package/dist/pages/html.js.map +1 -1
  26. package/dist/pages/login.d.ts +14 -2
  27. package/dist/pages/login.d.ts.map +1 -1
  28. package/dist/pages/login.js +21 -3
  29. package/dist/pages/login.js.map +1 -1
  30. package/dist/service.d.ts +44 -1
  31. package/dist/service.d.ts.map +1 -1
  32. package/dist/service.js +67 -4
  33. package/dist/service.js.map +1 -1
  34. package/dist/store/memory.d.ts.map +1 -1
  35. package/dist/store/memory.js +0 -0
  36. package/dist/store/memory.js.map +1 -1
  37. package/dist/store/migrations.d.ts.map +1 -1
  38. package/dist/store/migrations.js +8 -0
  39. package/dist/store/migrations.js.map +1 -1
  40. package/dist/store/sqlite.d.ts.map +1 -1
  41. package/dist/store/sqlite.js +28 -2
  42. package/dist/store/sqlite.js.map +1 -1
  43. package/dist/store/types.d.ts +24 -0
  44. package/dist/store/types.d.ts.map +1 -1
  45. package/dist/store/types.js.map +1 -1
  46. package/dist/tokens.d.ts +13 -1
  47. package/dist/tokens.d.ts.map +1 -1
  48. package/dist/tokens.js +20 -2
  49. package/dist/tokens.js.map +1 -1
  50. package/dist/user-page.d.ts +13 -0
  51. package/dist/user-page.d.ts.map +1 -0
  52. package/dist/user-page.js +204 -0
  53. package/dist/user-page.js.map +1 -0
  54. package/dist/workflows.d.ts +2 -1
  55. package/dist/workflows.d.ts.map +1 -1
  56. package/dist/workflows.js +13 -4
  57. package/dist/workflows.js.map +1 -1
  58. package/docs/index.md +75 -11
  59. package/docs/ops/identity.code.callback.md +17 -0
  60. package/docs/ops/identity.token.callback.md +3 -1
  61. package/docs/ops/identity.users.setRoles.md +5 -4
  62. package/package.json +5 -5
package/dist/deliver.d.ts CHANGED
@@ -19,6 +19,12 @@ export interface DeliverInput {
19
19
  origin?: string | null;
20
20
  /** Token expiry (ms epoch) — turns "expires soon" into "valid for 7 days" in the copy. */
21
21
  expiresAt?: number;
22
+ /**
23
+ * The short sign-in code bound to the same token (raw digits, e.g. "482913").
24
+ * Rides the hook payload so custom templates can render it — the PWA path,
25
+ * where the link opens in the wrong cookie jar and the user types this instead.
26
+ */
27
+ code?: string;
22
28
  }
23
29
  export interface DeliverResult {
24
30
  delivered: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAExE;AA8CD,wBAAsB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA6B9F"}
1
+ {"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAExE;AAwED,wBAAsB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA+B9F"}
package/dist/deliver.js CHANGED
@@ -8,6 +8,7 @@
8
8
  * printed to the server console — which is precisely the zero-config dev
9
9
  * login, and the same primitive bootstrap uses.
10
10
  */
11
+ import { formatCode } from "./tokens.js";
11
12
  export const DELIVER_TOKEN_HOOK = "identity.deliverToken";
12
13
  /** Best-effort absolute URL — `origin` (from the trigger's `url`) + the callback path. */
13
14
  export function absoluteUrl(path, origin) {
@@ -43,8 +44,9 @@ function humanTtl(expiresAt) {
43
44
  * every channel subscribed to the hook (email, SMS, chat…) gets sensible
44
45
  * wording for free, and a forked delivery workflow may still write its own.
45
46
  */
46
- function copyFor(purpose, ttl) {
47
- const expiry = ttl ? `The link is single-use and valid for ${ttl}.` : "The link is single-use and expires soon.";
47
+ function copyFor(purpose, ttl, code) {
48
+ const what = code ? "link and code are" : "link is";
49
+ const expiry = ttl ? `The ${what} single-use and valid for ${ttl}.` : `The ${what} single-use and expire${code ? "" : "s"} soon.`;
48
50
  switch (purpose) {
49
51
  case "invite":
50
52
  return {
@@ -52,14 +54,37 @@ function copyFor(purpose, ttl) {
52
54
  message: `You've been invited to join. Open the link below to accept the invitation — your account is created on the spot, then you sign in for the first time. ${expiry}`,
53
55
  };
54
56
  case "login":
55
- return { subject: "Your sign-in link", message: `Open the link below to sign in. ${expiry}` };
57
+ return {
58
+ subject: "Your sign-in link",
59
+ message: code
60
+ ? // The code is the installed-app path: the link would open in the
61
+ // system browser, but a typed code signs in wherever the user is.
62
+ `Open the link below to sign in — or enter the code ${formatCode(code)} where you requested it. ${expiry}`
63
+ : `Open the link below to sign in. ${expiry}`,
64
+ };
56
65
  default:
57
66
  return { subject: `Your ${purpose} link`, message: `Open the link below to continue. ${expiry}` };
58
67
  }
59
68
  }
69
+ /**
70
+ * In production an emailed link must not be built from the request: the Host
71
+ * header is client-controlled, so a forged one would mail a victim a VALID
72
+ * token pointing at someone else's domain. Dev keeps the request origin
73
+ * (localhost just works); production requires PATTERN_PUBLIC_URL.
74
+ */
75
+ function linkOrigin(ctx, requestOrigin) {
76
+ const configured = configuredOrigin(ctx);
77
+ if (configured)
78
+ return configured;
79
+ const env = ctx.env?.NODE_ENV ?? process.env.NODE_ENV;
80
+ if (env === "production") {
81
+ throw new Error("mod-identity: PATTERN_PUBLIC_URL is required in production — emailed links are not built from the request's Host header, which a client can forge. Set it to your public origin (https://app.example.com).");
82
+ }
83
+ return requestOrigin;
84
+ }
60
85
  export async function deliverToken(ctx, input) {
61
- const url = absoluteUrl(input.path, configuredOrigin(ctx) ?? input.origin);
62
- const { subject, message } = copyFor(input.purpose, humanTtl(input.expiresAt));
86
+ const url = absoluteUrl(input.path, linkOrigin(ctx, input.origin));
87
+ const { subject, message } = copyFor(input.purpose, humanTtl(input.expiresAt), input.code);
63
88
  const payload = {
64
89
  email: input.email,
65
90
  url,
@@ -67,6 +92,7 @@ export async function deliverToken(ctx, input) {
67
92
  delivered: false,
68
93
  subject,
69
94
  message,
95
+ ...(input.code !== undefined ? { code: input.code } : {}),
70
96
  ...(input.expiresAt !== undefined ? { expiresAt: input.expiresAt } : {}),
71
97
  };
72
98
  let result;
@@ -82,6 +108,7 @@ export async function deliverToken(ctx, input) {
82
108
  if (!delivered) {
83
109
  console.log(`\n[pattern] ✉ ${input.purpose} link for ${input.email}\n` +
84
110
  `[pattern] ${url}\n` +
111
+ (input.code ? `[pattern] code: ${formatCode(input.code)}\n` : "") +
85
112
  `[pattern] (deliver these yourself by subscribing a workflow to the "${DELIVER_TOKEN_HOOK}" hook)\n`);
86
113
  }
87
114
  return { delivered, url };
@@ -1 +1 @@
1
- {"version":3,"file":"deliver.js","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deliver.js","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,12 @@
1
1
  /**
2
- * @pattern-js/mod-identity — admin screens (Tier-1 declarative, zero build).
2
+ * @pattern-js/mod-identity — admin screens.
3
3
  *
4
- * Users / Invite / Sessions under an "Access" category. Every view and action
5
- * names its own dedicated route (see `./admin-routes.ts`) — there is no generic
6
- * op invoker; the routes are admin-scope-gated and the ops re-check scopes too.
4
+ * Users / Invite / Sessions under the "Administration" section — Tier-1 declarative
5
+ * (zero build) except the user DETAILS page, which is Tier-2: a roles editor
6
+ * needs interactivity the declarative kinds can't express. Every view and
7
+ * action names its own dedicated route (see `./admin-routes.ts`) — there is no
8
+ * generic op invoker; the routes are admin-scope-gated and the ops re-check
9
+ * scopes too.
7
10
  */
8
11
  import type { FrontendContribution } from "@pattern-js/core";
9
12
  export declare function identityFrontend(): FrontendContribution;
@@ -1 +1 @@
1
- {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../src/frontend.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,wBAAgB,gBAAgB,IAAI,oBAAoB,CA2NvD"}
1
+ {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../src/frontend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAI7D,wBAAgB,gBAAgB,IAAI,oBAAoB,CA4KvD"}
package/dist/frontend.js CHANGED
@@ -1,18 +1,22 @@
1
1
  /**
2
- * @pattern-js/mod-identity — admin screens (Tier-1 declarative, zero build).
2
+ * @pattern-js/mod-identity — admin screens.
3
3
  *
4
- * Users / Invite / Sessions under an "Access" category. Every view and action
5
- * names its own dedicated route (see `./admin-routes.ts`) — there is no generic
6
- * op invoker; the routes are admin-scope-gated and the ops re-check scopes too.
4
+ * Users / Invite / Sessions under the "Administration" section — Tier-1 declarative
5
+ * (zero build) except the user DETAILS page, which is Tier-2: a roles editor
6
+ * needs interactivity the declarative kinds can't express. Every view and
7
+ * action names its own dedicated route (see `./admin-routes.ts`) — there is no
8
+ * generic op invoker; the routes are admin-scope-gated and the ops re-check
9
+ * scopes too.
7
10
  */
8
11
  import { PATHS } from "./admin-routes.js";
12
+ import { USER_PAGE_REMOTE } from "./user-page.js";
9
13
  export function identityFrontend() {
10
14
  return {
11
15
  menu: [
12
- { category: "Access", label: "Users", icon: "users", path: "/x/identity/users", order: 10 },
13
- { category: "Access", label: "Invites", icon: "user-plus", path: "/x/identity/invite", order: 20 },
14
- { category: "Access", label: "Sessions", icon: "key-round", path: "/x/identity/sessions", order: 30 },
15
- { category: "Access", label: "API tokens", icon: "key-square", path: "/x/identity/api-tokens", order: 40 },
16
+ { category: "Administration", label: "Users", icon: "users", path: "/x/identity/users", order: 10 },
17
+ { category: "Administration", label: "Invites", icon: "user-plus", path: "/x/identity/invite", order: 20 },
18
+ { category: "Administration", label: "Sessions", icon: "key-round", path: "/x/identity/sessions", order: 30 },
19
+ { category: "Administration", label: "API tokens", icon: "key-square", path: "/x/identity/api-tokens", order: 40 },
16
20
  ],
17
21
  pages: [
18
22
  {
@@ -40,60 +44,13 @@ export function identityFrontend() {
40
44
  },
41
45
  },
42
46
  {
43
- // The user details page: profile + run metrics, three declarative views
44
- // over dedicated routes — the :userId param fills each route's path.
47
+ // The user details page, Tier-2: identity card + actions, a roles
48
+ // editor that knows the roles map (and warns that saving signs the
49
+ // user out), sessions, run stats — and the subscription panel when
50
+ // mod-billing is around (duck-typed off its customers route).
45
51
  path: "/x/identity/users/:userId",
46
- views: [
47
- { title: "Profile", view: { kind: "detail", route: { method: "GET", path: PATHS.user } } },
48
- {
49
- // Editing roles needs an input, which a row action can't carry —
50
- // so it lives here as a form (the page's :userId fills the route).
51
- title: "Set roles",
52
- view: {
53
- kind: "form",
54
- schema: {
55
- type: "object",
56
- properties: {
57
- roles: {
58
- type: "string",
59
- description: 'Comma-separated — REPLACES the current set, e.g. "admin" (empty = plain user). Ends the user\'s sessions.',
60
- },
61
- },
62
- },
63
- route: { method: "POST", path: PATHS.userSetRoles },
64
- },
65
- },
66
- {
67
- title: "Runs by workflow (recent window)",
68
- view: {
69
- kind: "table",
70
- route: { method: "GET", path: PATHS.userRunStats },
71
- columns: [
72
- { key: "workflow", label: "Workflow" },
73
- { key: "runs", label: "Runs" },
74
- { key: "errors", label: "Errors" },
75
- { key: "avg ms", label: "Avg ms" },
76
- { key: "last run", label: "Last run" },
77
- ],
78
- },
79
- },
80
- {
81
- title: "Sessions",
82
- view: {
83
- kind: "table",
84
- route: { method: "GET", path: PATHS.userSessions },
85
- columns: [
86
- { key: "status", label: "Status", format: "badge" },
87
- { key: "created", label: "Created", format: "date" },
88
- { key: "lastSeen", label: "Last seen", format: "date" },
89
- { key: "userAgent", label: "Device" },
90
- ],
91
- rowActions: [
92
- { label: "Revoke", route: { method: "DELETE", path: PATHS.session }, args: { sessionId: "id" }, icon: "log-out", confirm: true },
93
- ],
94
- },
95
- },
96
- ],
52
+ title: "User",
53
+ module: USER_PAGE_REMOTE,
97
54
  },
98
55
  {
99
56
  // Invites: send (form) + the sent list with statuses, one page.
@@ -198,10 +155,10 @@ export function identityFrontend() {
198
155
  },
199
156
  ],
200
157
  commands: [
201
- { id: "identity.invite", label: "Invite user…", group: "Access", icon: "user-plus", path: "/x/identity/invite" },
158
+ { id: "identity.invite", label: "Invite user…", group: "Administration", icon: "user-plus", path: "/x/identity/invite" },
202
159
  { id: "identity.whoami", label: "Who am I?", group: "Access", icon: "user", route: { method: "GET", path: PATHS.whoami } },
203
160
  ],
204
- // Lives on the admin's Settings page (System → Settings), with the other knobs.
161
+ // Lives on the admin's Settings page (Administration → Settings), with the other knobs.
205
162
  settings: [
206
163
  {
207
164
  id: "identity",
@@ -1 +1 @@
1
- {"version":3,"file":"frontend.js","sourceRoot":"","sources":["../src/frontend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frontend.js","sourceRoot":"","sources":["../src/frontend.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,15 +6,15 @@
6
6
  */
7
7
  export { identityMod } from "./mod.js";
8
8
  export { default } from "./mod.js";
9
- export { resolveOptions, type IdentityOptions, type ResolvedIdentityOptions } from "./options.js";
10
- export { DefaultIdentityService, API_TOKEN_PREFIX, API_TOKEN_SCOPES, type ApiTokenScope, type FindOrCreateInput, type IdentityService, type IssuedToken, type LoginMethod, type MintedApiToken, type MintedSession, type ResolvedSession, } from "./service.js";
9
+ export { resolveOptions, type IdentityOptions, type RateBudget, type ResolvedIdentityOptions } from "./options.js";
10
+ export { DefaultIdentityService, API_TOKEN_PREFIX, API_TOKEN_SCOPES, MAX_CODE_ATTEMPTS, type ApiTokenScope, type FindOrCreateInput, type IdentityService, type IssuedToken, type LoginMethod, type MintedApiToken, type MintedSession, type ResolvedSession, } from "./service.js";
11
11
  export { identityService, IDENTITY_SERVICE } from "./service-key.js";
12
12
  export { sessionAuthProvider, SESSION_PROVIDER_NAME } from "./auth-provider.js";
13
13
  export { apiTokenAuthProvider, API_TOKEN_PROVIDER_NAME } from "./api-token-provider.js";
14
14
  export { deliverToken, absoluteUrl, DELIVER_TOKEN_HOOK, type DeliverInput, type DeliverResult } from "./deliver.js";
15
15
  export { parseCookies, serializeSessionCookie, clearSessionCookie } from "./cookies.js";
16
16
  export { isCrossSiteWrite, isStateChanging } from "./csrf.js";
17
- export { randomToken, sha256hex, normalizeEmail, looksLikeEmail } from "./tokens.js";
17
+ export { randomToken, randomCode, normalizeCode, formatCode, sha256hex, normalizeEmail, looksLikeEmail } from "./tokens.js";
18
18
  export { renderLoginPage, renderSentPage } from "./pages/login.js";
19
19
  export { layout, escapeHtml, safeNextPath } from "./pages/html.js";
20
20
  export { memoryIdentityStores } from "./store/memory.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACpH,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,SAAS,GACf,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACnH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACpH,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5H,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,SAAS,GACf,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -7,14 +7,14 @@
7
7
  export { identityMod } from "./mod.js";
8
8
  export { default } from "./mod.js";
9
9
  export { resolveOptions } from "./options.js";
10
- export { DefaultIdentityService, API_TOKEN_PREFIX, API_TOKEN_SCOPES, } from "./service.js";
10
+ export { DefaultIdentityService, API_TOKEN_PREFIX, API_TOKEN_SCOPES, MAX_CODE_ATTEMPTS, } from "./service.js";
11
11
  export { identityService, IDENTITY_SERVICE } from "./service-key.js";
12
12
  export { sessionAuthProvider, SESSION_PROVIDER_NAME } from "./auth-provider.js";
13
13
  export { apiTokenAuthProvider, API_TOKEN_PROVIDER_NAME } from "./api-token-provider.js";
14
14
  export { deliverToken, absoluteUrl, DELIVER_TOKEN_HOOK } from "./deliver.js";
15
15
  export { parseCookies, serializeSessionCookie, clearSessionCookie } from "./cookies.js";
16
16
  export { isCrossSiteWrite, isStateChanging } from "./csrf.js";
17
- export { randomToken, sha256hex, normalizeEmail, looksLikeEmail } from "./tokens.js";
17
+ export { randomToken, randomCode, normalizeCode, formatCode, sha256hex, normalizeEmail, looksLikeEmail } from "./tokens.js";
18
18
  export { renderLoginPage, renderSentPage } from "./pages/login.js";
19
19
  export { layout, escapeHtml, safeNextPath } from "./pages/html.js";
20
20
  export { memoryIdentityStores } from "./store/memory.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAsD,MAAM,cAAc,CAAC;AAClG,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,GASjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAyC,MAAM,cAAc,CAAC;AACpH,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,oBAAoB,GAWrB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAuE,MAAM,cAAc,CAAC;AACnH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GASlB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAyC,MAAM,cAAc,CAAC;AACpH,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5H,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,oBAAoB,GAWrB,MAAM,kBAAkB,CAAC"}
package/dist/mod.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAA+D,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChH,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAwBpE,wBAAgB,WAAW,CAAC,OAAO,GAAE,eAAoB,GAAG,UAAU,CA8DrE;AAED,+EAA+E;;AAC/E,wBAA6B"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAkF,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnI,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAwBpE,wBAAgB,WAAW,CAAC,OAAO,GAAE,eAAoB,GAAG,UAAU,CAsErE;AAED,+EAA+E;;AAC/E,wBAA6B"}
package/dist/mod.js CHANGED
@@ -15,7 +15,7 @@
15
15
  import { existsSync } from "node:fs";
16
16
  import { fileURLToPath } from "node:url";
17
17
  import { localFs, provideFilesystem } from "@pattern-js/runtime-node";
18
- import { AUTH_LOGIN_URL, IDENTITY_SERVICE, defineMod, z } from "@pattern-js/core";
18
+ import { AUTH_LOGIN_URL, ENGINE_INTROSPECT, IDENTITY_SERVICE, defineMod, z } from "@pattern-js/core";
19
19
  import { resolveOptions } from "./options.js";
20
20
  import { DefaultIdentityService } from "./service.js";
21
21
  import { sessionAuthProvider } from "./auth-provider.js";
@@ -50,7 +50,7 @@ export function identityMod(options = {}) {
50
50
  ops: identityOps,
51
51
  // Auth-page routes + the admin Access screens' dedicated routes (one
52
52
  // purposeful endpoint per screen and action, replacing the invoke path).
53
- workflows: [...endpointWorkflows(opts.mount), ...identityAdminRoutes()],
53
+ workflows: [...endpointWorkflows(opts.mount, opts.rateLimit.perClient), ...identityAdminRoutes()],
54
54
  authProviders: [sessionAuthProvider(() => service), apiTokenAuthProvider(() => service)],
55
55
  hooks: [
56
56
  {
@@ -78,9 +78,16 @@ export function identityMod(options = {}) {
78
78
  engine.provideService(IDENTITY_SERVICE, service);
79
79
  engine.provideService(AUTH_LOGIN_URL, `${opts.mount}/login`);
80
80
  },
81
- ready: async () => {
81
+ ready: async (engine) => {
82
82
  if (!service)
83
83
  return;
84
+ // `pattern ops/validate/run`: an inspection, not a server; no link to mint.
85
+ if (engine.service(ENGINE_INTROSPECT))
86
+ return;
87
+ if (process.env.NODE_ENV === "production" && !process.env.PATTERN_PUBLIC_URL?.trim()) {
88
+ console.warn("[pattern] ⚠ NODE_ENV=production without PATTERN_PUBLIC_URL: sign-in and invite links will NOT be emailed " +
89
+ "(they would be built from the client-controlled Host header). Set PATTERN_PUBLIC_URL to your public origin.");
90
+ }
84
91
  // Bootstrap-on-empty: the first admin signs up through a one-time link.
85
92
  const count = await service.listUsers().then((u) => u.length);
86
93
  if (count > 0)
package/dist/mod.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.js","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mod.js","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"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"}
package/dist/ops.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwE9F,6EAA6E;AAC7E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAM,CAAC;AAomBxG,eAAO,MAAM,WAAW,EAAE,YAAY,EA2BrC,CAAC"}
1
+ {"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAA2C,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyE9F,6EAA6E;AAC7E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAM,CAAC;AA4pBxG,eAAO,MAAM,WAAW,EAAE,YAAY,EA4BrC,CAAC"}
package/dist/ops.js CHANGED
@@ -243,6 +243,11 @@ const usersGet = jsonOp("identity.users.get", "One user's profile for the detail
243
243
  created: new Date(user.createdAt).toLocaleString(),
244
244
  "active sessions": active.length,
245
245
  "user id": user.id,
246
+ // Raw fields for the Tier-2 user page (the display strings above stay
247
+ // for anything still rendering this as a plain detail view).
248
+ rolesList: user.roles,
249
+ knownRoles: Object.keys(svc.options.roles),
250
+ createdAt: user.createdAt,
246
251
  };
247
252
  }, { sensitivity: "privileged" });
248
253
  const usersRunStats = jsonOp("identity.users.runStats", "Per-workflow run counts for a user, from the admin's retained run window (admin). Args { userId }.", { in: { userId: z.string() }, out: "stats" }, async (args, svc, ctx) => {
@@ -379,13 +384,40 @@ const apiTokensRevoke = jsonOp("identity.apiTokens.revoke", "Revoke an API token
379
384
  /* ── auth pages & flows ────────────────────────────────────────────────── */
380
385
  const loginPage = authOp("identity.login.page", "Render the login page from the registered login methods. Query { next?, error?, sent? }.", { query: ["next", "error", "sent"] }, (args, svc) => {
381
386
  if (args.sent)
382
- return page(renderSentPage(String(args.sent)));
387
+ return page(renderSentPage(String(args.sent), {
388
+ action: `${svc.options.mount}/code`,
389
+ email: String(args.sent),
390
+ next: typeof args.next === "string" ? args.next : undefined,
391
+ }));
383
392
  return page(renderLoginPage({
384
393
  methods: svc.loginMethods(),
385
394
  next: args.next,
386
395
  error: args.error ? String(args.error) : undefined,
387
396
  }));
388
397
  });
398
+ /**
399
+ * The shared login tail (link AND code callbacks): a just-consumed token →
400
+ * the user, per the EFFECTIVE signup policy (admin-toggleable, not the
401
+ * construction-time option). Returns only vetted error codes.
402
+ */
403
+ async function userFromToken(svc, token) {
404
+ if (!token.emailNorm)
405
+ return { error: "invalid-token" };
406
+ const data = token.data ?? {};
407
+ const invite = token.purpose === "invite";
408
+ const user = await svc.findOrCreateByIdentity({
409
+ provider: typeof data.provider === "string" ? data.provider : "magic-link",
410
+ subject: token.emailNorm,
411
+ email: token.emailNorm,
412
+ allowCreate: invite || (await svc.getSignup()) === "open",
413
+ roles: invite && Array.isArray(data.roles) ? data.roles : undefined,
414
+ });
415
+ if (!user)
416
+ return { error: "signup-closed" };
417
+ if (user.disabled)
418
+ return { error: "account-disabled" };
419
+ return { user };
420
+ }
389
421
  const tokenCallback = authOp("identity.token.callback", "The login/invite callback: consumes a single-use token and finds-or-creates the user per the signup policy. A login mints a session and redirects with the cookie set; an invite acceptance creates the account and lands on the /invited page — the first sign-in stays an explicit act.", { query: ["t", "next"], userAgent: true }, async (args, svc, req) => {
390
422
  const loginUrl = `${svc.options.mount}/login`;
391
423
  const raw = String(args.t ?? "");
@@ -404,18 +436,10 @@ const tokenCallback = authOp("identity.token.callback", "The login/invite callba
404
436
  if (invite && inviteRecord?.revokedAt != null) {
405
437
  return redirectTo(`${loginUrl}?error=invite-revoked`);
406
438
  }
407
- const user = await svc.findOrCreateByIdentity({
408
- provider: typeof data.provider === "string" ? data.provider : "magic-link",
409
- subject: token.emailNorm,
410
- email: token.emailNorm,
411
- // The EFFECTIVE policy (admin-toggleable), not the construction-time option.
412
- allowCreate: invite || (await svc.getSignup()) === "open",
413
- roles: invite && Array.isArray(data.roles) ? data.roles : undefined,
414
- });
415
- if (!user)
416
- return redirectTo(`${loginUrl}?error=signup-closed`);
417
- if (user.disabled)
418
- return redirectTo(`${loginUrl}?error=account-disabled`);
439
+ const resolved = await userFromToken(svc, token);
440
+ if (resolved.error || !resolved.user)
441
+ return redirectTo(`${loginUrl}?error=${resolved.error}`);
442
+ const user = resolved.user;
419
443
  const next = safeNextPath(args.next ?? data.next ?? req.home);
420
444
  if (invite) {
421
445
  // Acceptance ≠ sign-in: stamp the record, then explain what happened and
@@ -427,6 +451,28 @@ const tokenCallback = authOp("identity.token.callback", "The login/invite callba
427
451
  const minted = await svc.mintSession(user.id, { userAgent: args.userAgent ?? null });
428
452
  return redirectTo(next, sessionCookie(svc, minted.token));
429
453
  });
454
+ const codeCallback = authOp("identity.code.callback", "The sign-in code callback: consumes a code-bearing login token by { email, code } and mints the session in the browsing context that POSTED — the PWA/standalone path, where the emailed link would land its cookie in the system browser's jar instead of the installed app's. Wrong guesses re-render the sent page identically for unknown emails and wrong codes (no enumeration) with status 401; the token's wrong-guess budget burns it, link included.", { body: ["email", "code", "next"], userAgent: true }, async (args, svc, req) => {
455
+ const email = String(args.email ?? "").trim();
456
+ const next = safeNextPath(args.next);
457
+ const token = looksLikeEmail(email)
458
+ ? await svc.consumeTokenByCode(email, String(args.code ?? ""), "login")
459
+ : null;
460
+ if (!token) {
461
+ // One page for wrong code / unknown email / expired / burned — nothing
462
+ // to enumerate. The 401 makes the outcome machine-readable for SPAs.
463
+ return page(renderSentPage(looksLikeEmail(email) ? email : "that address", {
464
+ action: `${svc.options.mount}/code`,
465
+ email,
466
+ next,
467
+ error: "invalid-code",
468
+ }), 401);
469
+ }
470
+ const resolved = await userFromToken(svc, token);
471
+ if (resolved.error || !resolved.user)
472
+ return redirectTo(`${svc.options.mount}/login?error=${resolved.error}`);
473
+ const minted = await svc.mintSession(resolved.user.id, { userAgent: args.userAgent ?? null });
474
+ return redirectTo(safeNextPath(args.next ?? token.data?.next ?? req.home), sessionCookie(svc, minted.token));
475
+ });
430
476
  const invitedPage = authOp("identity.invited.page", "The invite-accepted interstitial: your account is ready, sign in for the first time — with a continue button carrying the invite's next path into the login page.", { query: ["next"] }, (args, svc) => page(renderInvitedPage({ mount: svc.options.mount, next: safeNextPath(args.next) })));
431
477
  const logout = authOp("identity.logout", "Revoke the current session and clear the cookie. POST (same-origin; the CSRF guard makes forged logouts inert).", {}, async (_args, svc, req) => {
432
478
  const sessionId = req.principal.kind === "user" ? req.principal.claims?.sessionId : undefined;
@@ -495,10 +541,37 @@ export const identityOps = [
495
541
  apiTokensRevoke,
496
542
  loginPage,
497
543
  tokenCallback,
544
+ codeCallback,
498
545
  logout,
499
546
  welcomePage,
500
547
  invitedPage,
501
548
  bootstrapPage,
502
549
  bootstrapSubmit,
503
550
  ];
551
+ // Replay-safety stamps for the helper-built ops above (absent ⇒ "external").
552
+ // Reads are pure; CAS-guarded writes converge on repeat. Deliberately NOT
553
+ // stamped: invite/loginLink/apiTokens.create (each call mints or sends).
554
+ const OP_EFFECTS = {
555
+ "identity.whoami": "pure",
556
+ "identity.users.list": "pure",
557
+ "identity.users.get": "pure",
558
+ "identity.users.runStats": "pure",
559
+ "identity.invites.list": "pure",
560
+ "identity.settings.get": "pure",
561
+ "identity.sessions.list": "pure",
562
+ "identity.apiTokens.list": "pure",
563
+ "identity.users.setRoles": "idempotent",
564
+ "identity.users.toggleDisabled": "idempotent",
565
+ "identity.users.revokeSessions": "idempotent",
566
+ "identity.users.delete": "idempotent",
567
+ "identity.invites.revoke": "idempotent",
568
+ "identity.settings.set": "idempotent",
569
+ "identity.sessions.revoke": "idempotent",
570
+ "identity.apiTokens.revoke": "idempotent",
571
+ };
572
+ for (const op of identityOps) {
573
+ const e = OP_EFFECTS[op.type];
574
+ if (e)
575
+ op.effects = e;
576
+ }
504
577
  //# sourceMappingURL=ops.js.map