@iqauth/sdk 2.6.3 → 2.7.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 (112) hide show
  1. package/README.md +173 -1
  2. package/dist/browser-session.d.mts +4 -4
  3. package/dist/browser-session.d.ts +4 -4
  4. package/dist/browser-session.js +181 -41
  5. package/dist/browser-session.mjs +3 -3
  6. package/dist/browser.d.mts +5 -5
  7. package/dist/browser.d.ts +5 -5
  8. package/dist/browser.js +271 -32
  9. package/dist/browser.mjs +10 -8
  10. package/dist/{chunk-6I6RM4MN.mjs → chunk-6PJRLRB4.mjs} +33 -3
  11. package/dist/chunk-C2ZTBOAC.mjs +36 -0
  12. package/dist/{chunk-LIZYFXH7.mjs → chunk-DFWHSDYQ.mjs} +1 -1
  13. package/dist/chunk-GLXSIGVS.mjs +66 -0
  14. package/dist/{chunk-TKZTCPEK.mjs → chunk-GN37E64I.mjs} +32 -40
  15. package/dist/{chunk-WQWBJSSS.mjs → chunk-HVHNYPDC.mjs} +6 -6
  16. package/dist/{chunk-W3F4JYGP.mjs → chunk-JXQI62A7.mjs} +108 -18
  17. package/dist/{chunk-UNYDG2L4.mjs → chunk-NUO2I65G.mjs} +56 -23
  18. package/dist/chunk-PMAFENVI.mjs +229 -0
  19. package/dist/chunk-RR2MGPTK.mjs +2724 -0
  20. package/dist/{chunk-76W5TLQQ.mjs → chunk-RTJAIBXY.mjs} +220 -20
  21. package/dist/{chunk-6TDJJER7.mjs → chunk-RUJXRTEW.mjs} +164 -5
  22. package/dist/{chunk-3JULWS6F.mjs → chunk-WCELYTJ3.mjs} +3 -3
  23. package/dist/{chunk-MKKZULZR.mjs → chunk-WIFG74IK.mjs} +1 -1
  24. package/dist/{chunk-BVV54LPI.mjs → chunk-YVALAG3B.mjs} +10 -4
  25. package/dist/cli/index.js +2 -2
  26. package/dist/cli/index.mjs +2 -2
  27. package/dist/{client-kYlJFgPv.d.mts → client-BGFnBpfc.d.mts} +47 -4
  28. package/dist/{client-BNQe3AgF.d.ts → client-CDQ21LvW.d.ts} +47 -4
  29. package/dist/{doctor-YYNHNMLD.mjs → doctor-JAFXWU3X.mjs} +2 -2
  30. package/dist/errors-Jl1Jtm-6.d.mts +107 -0
  31. package/dist/errors-Jl1Jtm-6.d.ts +107 -0
  32. package/dist/{express-B6_1vBYZ.d.mts → express-CVNQEkOr.d.mts} +2 -2
  33. package/dist/{express-CHpfa7D_.d.ts → express-Piv2WhWM.d.ts} +2 -2
  34. package/dist/express.d.mts +7 -6
  35. package/dist/express.d.ts +7 -6
  36. package/dist/express.js +349 -52
  37. package/dist/express.mjs +39 -12
  38. package/dist/fastify.d.mts +2 -0
  39. package/dist/fastify.d.ts +2 -0
  40. package/dist/fastify.js +332 -52
  41. package/dist/fastify.mjs +23 -8
  42. package/dist/hono.d.mts +2 -0
  43. package/dist/hono.d.ts +2 -0
  44. package/dist/hono.js +329 -52
  45. package/dist/hono.mjs +20 -8
  46. package/dist/index-5KSZEnDe.d.ts +1626 -0
  47. package/dist/index-CKoZHAoc.d.mts +1626 -0
  48. package/dist/index.d.mts +56 -8
  49. package/dist/index.d.ts +56 -8
  50. package/dist/index.js +565 -69
  51. package/dist/index.mjs +29 -9
  52. package/dist/{keys-NLWFAOEM.mjs → keys-6Y776TG2.mjs} +2 -2
  53. package/dist/locales.d.mts +1 -1
  54. package/dist/locales.d.ts +1 -1
  55. package/dist/mobile.d.mts +77 -7
  56. package/dist/mobile.d.ts +77 -7
  57. package/dist/mobile.js +276 -41
  58. package/dist/mobile.mjs +98 -3
  59. package/dist/next.d.mts +2 -1
  60. package/dist/next.d.ts +2 -1
  61. package/dist/next.js +391 -201
  62. package/dist/next.mjs +22 -7
  63. package/dist/pkce-7WKV4OIN.mjs +11 -0
  64. package/dist/{provisioningBridge-DnTfzdZK.d.ts → provisioningBridge-CGpMRie4.d.ts} +1 -1
  65. package/dist/{provisioningBridge-88xjOS2n.d.mts → provisioningBridge-M5G47LWO.d.mts} +1 -1
  66. package/dist/{publishableKey-BaR0HoAH.d.ts → publishableKey-f2kq-rKw.d.mts} +1 -1
  67. package/dist/{publishableKey-BaR0HoAH.d.mts → publishableKey-f2kq-rKw.d.ts} +1 -1
  68. package/dist/react-permissions.d.mts +52 -0
  69. package/dist/react-permissions.d.ts +52 -0
  70. package/dist/react-permissions.js +239 -0
  71. package/dist/react-permissions.mjs +97 -0
  72. package/dist/react.d.mts +9 -1624
  73. package/dist/react.d.ts +9 -1624
  74. package/dist/react.js +343 -36
  75. package/dist/react.mjs +59 -2611
  76. package/dist/{reverify-4UEJXUS6.mjs → reverify-C64QXKJO.mjs} +2 -2
  77. package/dist/server/handlers.d.mts +148 -3
  78. package/dist/server/handlers.d.ts +148 -3
  79. package/dist/server/handlers.js +410 -11
  80. package/dist/server/handlers.mjs +12 -3
  81. package/dist/server.d.mts +151 -8
  82. package/dist/server.d.ts +151 -8
  83. package/dist/server.js +406 -50
  84. package/dist/server.mjs +93 -11
  85. package/dist/service.d.mts +4 -4
  86. package/dist/service.d.ts +4 -4
  87. package/dist/service.js +181 -41
  88. package/dist/service.mjs +3 -3
  89. package/dist/{signIn-CiIBTJIh.d.mts → signIn-BLFnz8SV.d.ts} +78 -3
  90. package/dist/{signIn-CCY4JE5G.mjs → signIn-SHBW6Z4T.mjs} +2 -1
  91. package/dist/{signIn-OCr88Zf8.d.ts → signIn-T-CZ6t6r.d.mts} +78 -3
  92. package/dist/test.mjs +3 -3
  93. package/dist/{tokens-DCyzzn8L.d.mts → tokens-Bqhmqq_R.d.ts} +9 -2
  94. package/dist/{tokens-aHiGFr_E.d.ts → tokens-CITeoG6P.d.mts} +9 -2
  95. package/dist/{types-6bNdxesb.d.ts → types-BdQ2lqfT.d.mts} +1 -1
  96. package/dist/{types-6bNdxesb.d.mts → types-BdQ2lqfT.d.ts} +1 -1
  97. package/dist/{types-DZAflmmq.d.mts → types-XOV9XPVi.d.mts} +99 -10
  98. package/dist/{types-DZAflmmq.d.ts → types-XOV9XPVi.d.ts} +99 -10
  99. package/dist/webhooks.d.mts +100 -17
  100. package/dist/webhooks.d.ts +100 -17
  101. package/dist/webhooks.js +164 -15
  102. package/dist/webhooks.mjs +7 -1
  103. package/dist/ws.d.mts +2 -2
  104. package/dist/ws.d.ts +2 -2
  105. package/dist/ws.js +80 -30
  106. package/dist/ws.mjs +4 -4
  107. package/docs/error-handling.md +101 -0
  108. package/docs/guides/effective-permissions.md +171 -0
  109. package/package.json +13 -3
  110. package/dist/chunk-UKZLOHZG.mjs +0 -83
  111. package/dist/errors-CDdl24MP.d.mts +0 -52
  112. package/dist/errors-CDdl24MP.d.ts +0 -52
@@ -0,0 +1,171 @@
1
+ # Effective permissions: `useEffectivePermissions` + wildcard utilities
2
+
3
+ Some IQAuth apps have hundreds of permission nodes. Stuffing the full set
4
+ into the JWT `entitlements` claim is impractical — tokens grow past header
5
+ limits and rotation gets expensive. The canonical pattern is:
6
+
7
+ 1. Keep the JWT small. Carry only the **roles** + a *coarse* subset of
8
+ `entitlements` for instant first-paint gating.
9
+ 2. Fetch the **full** effective permission set on demand from the issuer
10
+ and use it for fine-grained UI gating.
11
+ 3. Use the **same** wildcard semantics on the client and the server so the
12
+ two halves can never drift and produce the classic "user can see the
13
+ page but every API call 403s" foot-gun.
14
+
15
+ The SDK ships:
16
+
17
+ - `hasPermission(set, id)` and `expandPermissions(set)` — pure utilities
18
+ re-exported from `@iqauth/sdk`.
19
+ - `useEffectivePermissions({ appKey })` — React hook in `@iqauth/sdk/react/permissions` (separate sub-entry so the main React entry never pulls in TanStack Query unless you actually use this hook). Re-exported from
20
+ `@iqauth/sdk/react`.
21
+
22
+ ## Wildcard semantics
23
+
24
+ Permission ids are dot-separated keys: `metrics`, `metrics.read`,
25
+ `billing.invoices.delete`. Two wildcard forms are supported:
26
+
27
+ | Pattern | Matches |
28
+ | --------------- | ------------------------------------------------------------- |
29
+ | `*` | Every permission id (root wildcard). |
30
+ | `<prefix>.*` | `<prefix>` itself **and** every descendant. |
31
+
32
+ Examples:
33
+
34
+ - `metrics.*` matches `metrics`, `metrics.read`, `metrics.foo.bar`.
35
+ - `metrics.*` does **not** match `metric`, `metricsX`, or
36
+ `billing.metrics`.
37
+ - `*` matches everything, including any wildcard query.
38
+
39
+ Wildcards in the middle of an id (e.g. `metrics.*.read`) are treated as
40
+ literal strings and match nothing useful — keep wildcards at the leaf.
41
+
42
+ `expandPermissions(set)` normalizes a set: dedupes, sorts, and strips
43
+ entries already implied by a broader wildcard. It does **not** enumerate
44
+ descendants of a wildcard (that set is open-ended).
45
+
46
+ ```ts
47
+ import { expandPermissions, hasPermission } from "@iqauth/sdk";
48
+
49
+ expandPermissions(["metrics.*", "metrics.read", "billing.read"]);
50
+ // → ["billing.read", "metrics.*"]
51
+
52
+ hasPermission(["metrics.*"], "metrics.foo.bar"); // true
53
+ hasPermission(["metrics.read"], "metrics.write"); // false
54
+ ```
55
+
56
+ ## When to use the hook vs raw `entitlements`
57
+
58
+ - **JWT `entitlements`** — instant, sync, available the moment the user is
59
+ authenticated. Good for top-level navigation gating where a small,
60
+ hand-picked subset is enough. **Hard size budget: keep `entitlements`
61
+ under ~50 entries to stay well under header limits across proxies.**
62
+ - **`useEffectivePermissions()`** — async, network-backed, returns the
63
+ *complete* per-app set. Good for granular feature gating, action
64
+ buttons, admin-only fields. Cached for 5 minutes per
65
+ `(user, tenant, appKey)`.
66
+
67
+ The hook automatically falls back to `claims.entitlements` while the
68
+ fetch is in flight, so first paint is never blocked.
69
+
70
+ ## React usage
71
+
72
+ The hook is backed by [TanStack Query](https://tanstack.com/query). The
73
+ SDK declares `@tanstack/react-query` as an **optional** peer dependency
74
+ — install it (`npm i @tanstack/react-query`) and mount a
75
+ `QueryClientProvider` somewhere above `<IQAuthProvider/>`:
76
+
77
+ ```tsx
78
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
79
+ import { IQAuthProvider } from "@iqauth/sdk/react";
80
+
81
+ const queryClient = new QueryClient();
82
+
83
+ <QueryClientProvider client={queryClient}>
84
+ <IQAuthProvider publishableKey={…}>
85
+ <App />
86
+ </IQAuthProvider>
87
+ </QueryClientProvider>
88
+ ```
89
+
90
+ Then anywhere inside:
91
+
92
+ ```tsx
93
+ import { SignedIn } from "@iqauth/sdk/react";
94
+ import { useEffectivePermissions } from "@iqauth/sdk/react/permissions";
95
+
96
+ function BillingPanel() {
97
+ const { permissions, hasPermission, isLoading, error, refetch } =
98
+ useEffectivePermissions({ appKey: "iqreuse" });
99
+
100
+ if (error) return <p>Couldn't load permissions: {error.message}</p>;
101
+
102
+ return (
103
+ <section aria-busy={isLoading}>
104
+ {hasPermission("billing.invoices.read") && <InvoiceList />}
105
+ {hasPermission("billing.invoices.write") && <NewInvoiceButton />}
106
+ {/* Wildcards work too — granted via `billing.*` or `*` */}
107
+ {hasPermission("billing.invoices.delete") && <DeleteInvoiceButton />}
108
+ </section>
109
+ );
110
+ }
111
+ ```
112
+
113
+ ### What the hook returns
114
+
115
+ ```ts
116
+ {
117
+ permissions: string[]; // normalized set
118
+ hasPermission: (id: string) => boolean; // wildcard-aware
119
+ isLoading: boolean;
120
+ error: { code: string; message: string } | null;
121
+ refetch: () => Promise<void>; // bypass staleTime
122
+ }
123
+ ```
124
+
125
+ ### Behaviour
126
+
127
+ - **Caching.** Results are cached in-memory for 5 minutes per
128
+ `(issuer, tenantId, userId, appKey)`. Repeat mounts within the window
129
+ do not refetch. Override with `staleTime` (ms).
130
+ - **Single-flight.** Concurrent renders/mounts share one in-flight
131
+ request — you will not see a thundering herd of `/permissions/effective`
132
+ calls when many components mount at once.
133
+ - **No focus refetch.** The hook does **not** refetch on window focus.
134
+ Trigger `refetch()` after a mutation that changes permissions
135
+ (group assignment, role change, override write).
136
+ - **Platform admin short-circuit.** If the JWT carries
137
+ `roles: ["platform_admin", …]` the hook returns `permissions: ["*"]`
138
+ and `hasPermission` always returns `true` without a network round trip.
139
+ - **Entitlements fallback.** While the first fetch is in flight,
140
+ `permissions` is seeded from `claims.entitlements` so first paint isn't
141
+ blocked. The fetch result replaces this on success.
142
+
143
+ ### Endpoint shape
144
+
145
+ The hook calls the existing issuer endpoint:
146
+
147
+ ```
148
+ GET /api/v1/tenants/{tenantId}/users/{userId}/permissions/effective?appKey=<appKey>
149
+ ```
150
+
151
+ It expects an `ApiResponse.success(...)` body whose `data` is an array of
152
+ `{ scope: string; effect: "allow" | "deny"; … }` rows (the same shape
153
+ returned by `permissionService.resolveEffectivePermissions`). Rows with
154
+ `effect === "deny"` are stripped and the remaining `scope` strings are
155
+ fed through `expandPermissions()`.
156
+
157
+ No new server route is required.
158
+
159
+ ### Server-side parity
160
+
161
+ Use the **same** utilities for server-side authorization checks so the
162
+ two halves cannot drift:
163
+
164
+ ```ts
165
+ import { hasPermission } from "@iqauth/sdk";
166
+
167
+ // Inside an Express/Fastify/Hono route handler:
168
+ if (!hasPermission(grantedPermissionSet, "billing.invoices.delete")) {
169
+ return res.status(403).json({ error: { code: "PERMISSION_DENIED" } });
170
+ }
171
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iqauth/sdk",
3
- "version": "2.6.3",
3
+ "version": "2.7.0",
4
4
  "description": "TypeScript SDK for IQAuth — the canonical way for all IQ projects to integrate with IQAuthService",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -29,6 +29,11 @@
29
29
  "import": "./dist/react.mjs",
30
30
  "require": "./dist/react.js"
31
31
  },
32
+ "./react/permissions": {
33
+ "types": "./dist/react-permissions.d.ts",
34
+ "import": "./dist/react-permissions.mjs",
35
+ "require": "./dist/react-permissions.js"
36
+ },
32
37
  "./server": {
33
38
  "types": "./dist/server.d.ts",
34
39
  "import": "./dist/server.mjs",
@@ -96,7 +101,7 @@
96
101
  "docs"
97
102
  ],
98
103
  "scripts": {
99
- "build": "tsup src/index.ts src/browser-session.ts src/browser.ts src/react.ts src/server.ts src/server/handlers.ts src/express.ts src/fastify.ts src/hono.ts src/next.ts src/mobile.ts src/service.ts src/ws.ts src/test.ts src/webhooks.ts src/locales.ts src/cli/index.ts --format cjs,esm --dts --clean --external react --external react-dom --external next/headers",
104
+ "build": "tsup src/index.ts src/browser-session.ts src/browser.ts src/react.ts src/react-permissions.ts src/server.ts src/server/handlers.ts src/express.ts src/fastify.ts src/hono.ts src/next.ts src/mobile.ts src/service.ts src/ws.ts src/test.ts src/webhooks.ts src/locales.ts src/cli/index.ts --format cjs,esm --dts --clean --external react --external react-dom --external next/headers --external @tanstack/react-query",
100
105
  "test": "vitest run",
101
106
  "test:watch": "vitest",
102
107
  "test:coverage": "vitest run --coverage",
@@ -108,7 +113,8 @@
108
113
  },
109
114
  "peerDependencies": {
110
115
  "react": ">=18",
111
- "react-dom": ">=18"
116
+ "react-dom": ">=18",
117
+ "@tanstack/react-query": ">=4"
112
118
  },
113
119
  "peerDependenciesMeta": {
114
120
  "react": {
@@ -116,9 +122,13 @@
116
122
  },
117
123
  "react-dom": {
118
124
  "optional": true
125
+ },
126
+ "@tanstack/react-query": {
127
+ "optional": true
119
128
  }
120
129
  },
121
130
  "devDependencies": {
131
+ "@tanstack/react-query": "^5.60.5",
122
132
  "@types/jsonwebtoken": "^9.0.7",
123
133
  "@types/node": "^20.0.0",
124
134
  "@types/react": "^18.0.0",
@@ -1,83 +0,0 @@
1
- // src/webhooks.ts
2
- import crypto from "crypto";
3
- var WebhookSignatureError = class extends Error {
4
- constructor(code, message) {
5
- super(message);
6
- this.name = "WebhookSignatureError";
7
- this.code = code;
8
- }
9
- };
10
- function toBuffer(p) {
11
- if (typeof p === "string") return Buffer.from(p, "utf8");
12
- if (Buffer.isBuffer(p)) return p;
13
- return Buffer.from(p);
14
- }
15
- function parseHeader(header) {
16
- let t = NaN;
17
- const v1 = [];
18
- for (const part of header.split(",")) {
19
- const [k, v] = part.split("=", 2);
20
- if (!k || v === void 0) continue;
21
- const key = k.trim();
22
- const value = v.trim();
23
- if (key === "t") t = Number(value);
24
- else if (key === "v1") v1.push(value);
25
- }
26
- return { t, v1 };
27
- }
28
- function timingSafeEqualHex(a, b) {
29
- if (a.length !== b.length) return false;
30
- try {
31
- return crypto.timingSafeEqual(Buffer.from(a, "hex"), Buffer.from(b, "hex"));
32
- } catch {
33
- return false;
34
- }
35
- }
36
- function verifyWebhookSignature(opts) {
37
- const headerRaw = Array.isArray(opts.header) ? opts.header[0] : opts.header;
38
- if (!headerRaw || typeof headerRaw !== "string") {
39
- throw new WebhookSignatureError("MISSING_HEADER", "Missing X-IQAuth-Signature header");
40
- }
41
- if (!opts.secret) {
42
- throw new WebhookSignatureError("MISSING_SECRET", "secret is required");
43
- }
44
- const { t, v1 } = parseHeader(headerRaw);
45
- if (!Number.isFinite(t) || v1.length === 0) {
46
- throw new WebhookSignatureError("MALFORMED_HEADER", `Could not parse signature header: ${headerRaw}`);
47
- }
48
- const tolerance = opts.toleranceSeconds ?? 300;
49
- const now = opts.nowSeconds ?? Math.floor(Date.now() / 1e3);
50
- if (Math.abs(now - t) > tolerance) {
51
- throw new WebhookSignatureError(
52
- "TIMESTAMP_OUT_OF_TOLERANCE",
53
- `Signature timestamp ${t} is outside the ${tolerance}s tolerance window (now=${now})`
54
- );
55
- }
56
- const body = toBuffer(opts.payload);
57
- const expected = crypto.createHmac("sha256", opts.secret).update(`${t}.`).update(body).digest("hex");
58
- const matched = v1.some((sig) => timingSafeEqualHex(sig, expected));
59
- if (!matched) {
60
- throw new WebhookSignatureError("SIGNATURE_MISMATCH", "Webhook signature does not match expected value");
61
- }
62
- let parsed;
63
- try {
64
- parsed = JSON.parse(body.toString("utf8"));
65
- } catch {
66
- throw new WebhookSignatureError("MALFORMED_BODY", "Webhook body is not valid JSON");
67
- }
68
- return parsed;
69
- }
70
- function isValidWebhookSignature(opts) {
71
- try {
72
- verifyWebhookSignature(opts);
73
- return true;
74
- } catch {
75
- return false;
76
- }
77
- }
78
-
79
- export {
80
- WebhookSignatureError,
81
- verifyWebhookSignature,
82
- isValidWebhookSignature
83
- };
@@ -1,52 +0,0 @@
1
- /**
2
- * SOURCE REFS:
3
- * - Route file: src/lib/response.ts (error envelope: { success: false, error: { code, message } })
4
- * - All route files for error code extraction
5
- * - Verified claims: N/A (error module)
6
- * - Last verified: Phase 0 Research Summary
7
- */
8
- declare class IQAuthError extends Error {
9
- code: string;
10
- status?: number;
11
- raw?: unknown;
12
- constructor(code: string, message: string, status?: number, raw?: unknown);
13
- }
14
- declare const ErrorCodes: {
15
- readonly VALIDATION_ERROR: "VALIDATION_ERROR";
16
- readonly INVALID_CREDENTIALS: "INVALID_CREDENTIALS";
17
- readonly ACCOUNT_INACTIVE: "ACCOUNT_INACTIVE";
18
- readonly ACCOUNT_LOCKED: "ACCOUNT_LOCKED";
19
- readonly INSUFFICIENT_PERMISSIONS: "INSUFFICIENT_PERMISSIONS";
20
- readonly TOKEN_INVALID: "TOKEN_INVALID";
21
- readonly TOKEN_EXPIRED: "TOKEN_EXPIRED";
22
- readonly TOKEN_REVOKED: "TOKEN_REVOKED";
23
- readonly USER_INACTIVE: "USER_INACTIVE";
24
- readonly INTERNAL_ERROR: "INTERNAL_ERROR";
25
- readonly NOT_FOUND: "NOT_FOUND";
26
- readonly SESSION_INVALID: "SESSION_INVALID";
27
- readonly SESSION_EXPIRED: "SESSION_EXPIRED";
28
- readonly REFRESH_TOKEN_REUSED: "REFRESH_TOKEN_REUSED";
29
- readonly PASSWORD_EXPIRED: "PASSWORD_EXPIRED";
30
- readonly PIN_EXPIRED: "PIN_EXPIRED";
31
- readonly PASSWORD_POLICY_VIOLATION: "PASSWORD_POLICY_VIOLATION";
32
- readonly MFA_INVALID_CODE: "MFA_INVALID_CODE";
33
- readonly MFA_METHOD_UNAVAILABLE: "MFA_METHOD_UNAVAILABLE";
34
- readonly MFA_RATE_LIMITED: "MFA_RATE_LIMITED";
35
- readonly MFA_ENROLLMENT_REQUIRED: "MFA_ENROLLMENT_REQUIRED";
36
- readonly API_KEY_REQUIRED: "API_KEY_REQUIRED";
37
- readonly API_KEY_INVALID: "API_KEY_INVALID";
38
- readonly AUTH_REQUIRED: "AUTH_REQUIRED";
39
- readonly ALREADY_EXISTS: "ALREADY_EXISTS";
40
- readonly FORBIDDEN: "FORBIDDEN";
41
- readonly OAUTH_NOT_CONFIGURED: "OAUTH_NOT_CONFIGURED";
42
- readonly UPLOAD_ERROR: "UPLOAD_ERROR";
43
- readonly EMAIL_SERVICE_UNAVAILABLE: "EMAIL_SERVICE_UNAVAILABLE";
44
- readonly INVALID_CODE: "INVALID_CODE";
45
- readonly CODE_ALREADY_USED: "CODE_ALREADY_USED";
46
- readonly CODE_EXPIRED: "CODE_EXPIRED";
47
- readonly CODE_IP_MISMATCH: "CODE_IP_MISMATCH";
48
- readonly UNKNOWN_PAYLOAD: "UNKNOWN_PAYLOAD";
49
- };
50
- type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
51
-
52
- export { ErrorCodes as E, IQAuthError as I, type ErrorCode as a };
@@ -1,52 +0,0 @@
1
- /**
2
- * SOURCE REFS:
3
- * - Route file: src/lib/response.ts (error envelope: { success: false, error: { code, message } })
4
- * - All route files for error code extraction
5
- * - Verified claims: N/A (error module)
6
- * - Last verified: Phase 0 Research Summary
7
- */
8
- declare class IQAuthError extends Error {
9
- code: string;
10
- status?: number;
11
- raw?: unknown;
12
- constructor(code: string, message: string, status?: number, raw?: unknown);
13
- }
14
- declare const ErrorCodes: {
15
- readonly VALIDATION_ERROR: "VALIDATION_ERROR";
16
- readonly INVALID_CREDENTIALS: "INVALID_CREDENTIALS";
17
- readonly ACCOUNT_INACTIVE: "ACCOUNT_INACTIVE";
18
- readonly ACCOUNT_LOCKED: "ACCOUNT_LOCKED";
19
- readonly INSUFFICIENT_PERMISSIONS: "INSUFFICIENT_PERMISSIONS";
20
- readonly TOKEN_INVALID: "TOKEN_INVALID";
21
- readonly TOKEN_EXPIRED: "TOKEN_EXPIRED";
22
- readonly TOKEN_REVOKED: "TOKEN_REVOKED";
23
- readonly USER_INACTIVE: "USER_INACTIVE";
24
- readonly INTERNAL_ERROR: "INTERNAL_ERROR";
25
- readonly NOT_FOUND: "NOT_FOUND";
26
- readonly SESSION_INVALID: "SESSION_INVALID";
27
- readonly SESSION_EXPIRED: "SESSION_EXPIRED";
28
- readonly REFRESH_TOKEN_REUSED: "REFRESH_TOKEN_REUSED";
29
- readonly PASSWORD_EXPIRED: "PASSWORD_EXPIRED";
30
- readonly PIN_EXPIRED: "PIN_EXPIRED";
31
- readonly PASSWORD_POLICY_VIOLATION: "PASSWORD_POLICY_VIOLATION";
32
- readonly MFA_INVALID_CODE: "MFA_INVALID_CODE";
33
- readonly MFA_METHOD_UNAVAILABLE: "MFA_METHOD_UNAVAILABLE";
34
- readonly MFA_RATE_LIMITED: "MFA_RATE_LIMITED";
35
- readonly MFA_ENROLLMENT_REQUIRED: "MFA_ENROLLMENT_REQUIRED";
36
- readonly API_KEY_REQUIRED: "API_KEY_REQUIRED";
37
- readonly API_KEY_INVALID: "API_KEY_INVALID";
38
- readonly AUTH_REQUIRED: "AUTH_REQUIRED";
39
- readonly ALREADY_EXISTS: "ALREADY_EXISTS";
40
- readonly FORBIDDEN: "FORBIDDEN";
41
- readonly OAUTH_NOT_CONFIGURED: "OAUTH_NOT_CONFIGURED";
42
- readonly UPLOAD_ERROR: "UPLOAD_ERROR";
43
- readonly EMAIL_SERVICE_UNAVAILABLE: "EMAIL_SERVICE_UNAVAILABLE";
44
- readonly INVALID_CODE: "INVALID_CODE";
45
- readonly CODE_ALREADY_USED: "CODE_ALREADY_USED";
46
- readonly CODE_EXPIRED: "CODE_EXPIRED";
47
- readonly CODE_IP_MISMATCH: "CODE_IP_MISMATCH";
48
- readonly UNKNOWN_PAYLOAD: "UNKNOWN_PAYLOAD";
49
- };
50
- type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
51
-
52
- export { ErrorCodes as E, IQAuthError as I, type ErrorCode as a };