@devorash/core 0.1.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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -0
  3. package/dist/constants/api-url.gen.d.ts +4 -0
  4. package/dist/constants/api-url.gen.d.ts.map +1 -0
  5. package/dist/constants/api-url.gen.example.d.ts +7 -0
  6. package/dist/constants/api-url.gen.example.d.ts.map +1 -0
  7. package/dist/constants/api-url.gen.example.js +7 -0
  8. package/dist/constants/api-url.gen.example.js.map +1 -0
  9. package/dist/constants/api-url.gen.js +4 -0
  10. package/dist/constants/api-url.gen.js.map +1 -0
  11. package/dist/constants/index.d.ts +203 -0
  12. package/dist/constants/index.d.ts.map +1 -0
  13. package/dist/constants/index.js +236 -0
  14. package/dist/constants/index.js.map +1 -0
  15. package/dist/constants/sessionLifecycle.d.ts +22 -0
  16. package/dist/constants/sessionLifecycle.d.ts.map +1 -0
  17. package/dist/constants/sessionLifecycle.js +21 -0
  18. package/dist/constants/sessionLifecycle.js.map +1 -0
  19. package/dist/index.d.ts +15 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +72 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/security/index.d.ts +118 -0
  24. package/dist/security/index.d.ts.map +1 -0
  25. package/dist/security/index.js +345 -0
  26. package/dist/security/index.js.map +1 -0
  27. package/dist/security/request-body.d.ts +16 -0
  28. package/dist/security/request-body.d.ts.map +1 -0
  29. package/dist/security/request-body.js +84 -0
  30. package/dist/security/request-body.js.map +1 -0
  31. package/dist/security/signing.d.ts +127 -0
  32. package/dist/security/signing.d.ts.map +1 -0
  33. package/dist/security/signing.js +297 -0
  34. package/dist/security/signing.js.map +1 -0
  35. package/dist/types/index.d.ts +487 -0
  36. package/dist/types/index.d.ts.map +1 -0
  37. package/dist/types/index.js +19 -0
  38. package/dist/types/index.js.map +1 -0
  39. package/dist/utils/index.d.ts +211 -0
  40. package/dist/utils/index.d.ts.map +1 -0
  41. package/dist/utils/index.js +600 -0
  42. package/dist/utils/index.js.map +1 -0
  43. package/package.json +53 -0
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Constants for Devora SDKs
3
+ * @module @devorash/core/constants
4
+ */
5
+ // ============================================================================
6
+ // API Endpoints
7
+ // ============================================================================
8
+ /**
9
+ * Predefined endpoint constants for Devora SDK integration.
10
+ * Using these constants ensures:
11
+ * - Typo prevention (/impersonation vs /impersonate)
12
+ * - Automatic HTTP method detection
13
+ * - IDE autocomplete and documentation
14
+ * - Consistency across all customer integrations
15
+ */
16
+ export const DEVORA_ENDPOINTS = {
17
+ /**
18
+ * User search endpoint - allows Devora to search customer's users
19
+ * @method GET
20
+ * @path /user/search
21
+ * @query term - Search term (name, email, or user ID)
22
+ */
23
+ USER_SEARCH: "/user/search",
24
+ /**
25
+ * Get user by ID endpoint - retrieves a specific user's details
26
+ * @method GET
27
+ * @path /user/:id
28
+ * @params id - User ID to look up
29
+ */
30
+ USER_BY_ID: "/user/:id",
31
+ /**
32
+ * Impersonation start endpoint - generates auth token for session
33
+ * @method POST
34
+ * @path /impersonate/:id
35
+ * @params id - Target user ID to impersonate
36
+ */
37
+ IMPERSONATE: "/impersonate/:id",
38
+ /**
39
+ * Session termination endpoint - revokes impersonation session
40
+ * @method DELETE
41
+ * @path /impersonate/:id/terminate
42
+ * @params id - Session ID to terminate
43
+ */
44
+ TERMINATE: "/impersonate/:id/terminate",
45
+ /**
46
+ * Connection test endpoint - validates SDK setup (built-in)
47
+ * @method GET
48
+ * @path /test
49
+ * @internal This endpoint is automatically provided by the SDK
50
+ */
51
+ TEST: "/test",
52
+ /**
53
+ * Health check endpoint - SDK health and metrics (built-in)
54
+ * @method GET
55
+ * @path /health
56
+ * @internal This endpoint is automatically provided by the SDK
57
+ */
58
+ HEALTH: "/health",
59
+ };
60
+ /**
61
+ * HTTP methods for each endpoint (auto-detected when using constants)
62
+ */
63
+ export const ENDPOINT_METHODS = {
64
+ [DEVORA_ENDPOINTS.USER_SEARCH]: "GET",
65
+ [DEVORA_ENDPOINTS.USER_BY_ID]: "GET",
66
+ [DEVORA_ENDPOINTS.IMPERSONATE]: "POST",
67
+ [DEVORA_ENDPOINTS.TERMINATE]: "DELETE",
68
+ [DEVORA_ENDPOINTS.TEST]: "GET",
69
+ [DEVORA_ENDPOINTS.HEALTH]: "GET",
70
+ };
71
+ /**
72
+ * Built-in endpoints that cannot be overridden
73
+ */
74
+ export const PROTECTED_ENDPOINTS = [
75
+ DEVORA_ENDPOINTS.TEST,
76
+ DEVORA_ENDPOINTS.HEALTH,
77
+ ];
78
+ // ============================================================================
79
+ // Security Headers
80
+ // ============================================================================
81
+ /**
82
+ * HTTP headers used for HMAC authentication
83
+ */
84
+ export const SECURITY_HEADERS = {
85
+ /** HMAC-SHA256 signature (hex encoded) */
86
+ SIGNATURE: "x-devora-signature",
87
+ /** Unix timestamp in seconds when request was sent */
88
+ SENT_AT: "x-devora-sent-at",
89
+ /** API Key ID (public identifier) */
90
+ KEY_ID: "x-devora-key-id",
91
+ /** Organization ID */
92
+ ORG_ID: "x-devora-org-id",
93
+ /** Unique request identifier used for replay prevention */
94
+ REQUEST_ID: "x-devora-request-id",
95
+ /** Signature payload version */
96
+ SIGNATURE_VERSION: "x-devora-signature-version",
97
+ /** Session ID (for impersonation requests) */
98
+ SESSION_ID: "x-devora-session-id",
99
+ };
100
+ /**
101
+ * Frontend SDK headers
102
+ */
103
+ export const FRONTEND_HEADERS = {
104
+ /** Client API Key */
105
+ API_KEY: "x-devora-key",
106
+ /** Session ID */
107
+ SESSION: "x-devora-session",
108
+ /** Short-lived impersonation-session bearer token (never the customer auth token). */
109
+ SESSION_TOKEN: "x-devora-session-token",
110
+ };
111
+ // ============================================================================
112
+ // URL Parameters
113
+ // ============================================================================
114
+ /**
115
+ * URL parameters used for impersonation payload passing
116
+ */
117
+ /**
118
+ * Browser-session bridge: the customer route the browser SDK calls to restore
119
+ * an impersonation session in a new tab. Always allowed by the scope guards
120
+ * because it only mints a Devora resume code for an already-authenticated
121
+ * customer session.
122
+ */
123
+ export const BROWSER_SESSION_BRIDGE = {
124
+ /** Default customer route path. */
125
+ PATH: "/api/devora/browser-session",
126
+ /** Devora endpoint the customer backend calls with a signed server request. */
127
+ RESUME_CODE_ENDPOINT: "/api/sdk/browser-resume-code",
128
+ /** Devora endpoint the browser calls to redeem the code for its own capability. */
129
+ RESUME_ENDPOINT: "/api/sdk/browser-resume",
130
+ /** Non-secret per-tab identifier shape (also stored in sessionStorage). */
131
+ TAB_REF_PATTERN: /^[A-Za-z0-9_-]{4,96}$/,
132
+ };
133
+ export const URL_PARAMS = {
134
+ /** One-time code exchanged for the encrypted impersonation payload */
135
+ EXCHANGE_CODE: "devora_exchange",
136
+ };
137
+ // ============================================================================
138
+ // Default Configuration
139
+ // ============================================================================
140
+ import { DEVORA_API_ORIGIN, DEVORA_DASHBOARD_ORIGIN } from "./api-url.gen.js";
141
+ /**
142
+ * Default SDK configuration values
143
+ */
144
+ export const SDK_DEFAULTS = {
145
+ /** Devora API origin baked into the SDK package at build time. */
146
+ API_URL: DEVORA_API_ORIGIN,
147
+ /**
148
+ * The Devora dashboard origin, baked in at build time. Only a tab at this
149
+ * origin (or, for a customer app on loopback, a loopback dashboard) may hand
150
+ * an exchange verifier to the browser SDK.
151
+ */
152
+ DASHBOARD_ORIGIN: DEVORA_DASHBOARD_ORIGIN,
153
+ /** Timestamp tolerance in seconds (5 minutes) */
154
+ TIMESTAMP_TOLERANCE: 300,
155
+ /** Log batch size before flush */
156
+ LOG_BATCH_SIZE: 10,
157
+ /** Log flush interval in milliseconds (5 seconds) */
158
+ LOG_FLUSH_INTERVAL: 5000,
159
+ /** Maximum log queue size */
160
+ MAX_LOG_QUEUE_SIZE: 100,
161
+ };
162
+ // ============================================================================
163
+ // SDK Metadata
164
+ // ============================================================================
165
+ /**
166
+ * SDK package names
167
+ */
168
+ export const SDK_PACKAGES = {
169
+ CORE: "@devorash/core",
170
+ NODE: "@devorash/node",
171
+ BROWSER: "@devorash/browser",
172
+ EXPRESS: "@devorash/express",
173
+ HONO: "@devorash/hono",
174
+ FASTIFY: "@devorash/fastify",
175
+ REACT: "@devorash/react",
176
+ VUE: "@devorash/vue",
177
+ SVELTE: "@devorash/svelte",
178
+ SOLID: "@devorash/solid",
179
+ NEXT: "@devorash/nextjs",
180
+ };
181
+ /**
182
+ * Current SDK version (synced across all packages)
183
+ */
184
+ export const SDK_VERSION = "0.1.0";
185
+ // ============================================================================
186
+ // Error Codes
187
+ // ============================================================================
188
+ /**
189
+ * SDK error codes
190
+ */
191
+ export const ERROR_CODES = {
192
+ // Security errors (1xx)
193
+ MISSING_HEADERS: "DEVORA_101",
194
+ INVALID_TIMESTAMP: "DEVORA_102",
195
+ TIMESTAMP_EXPIRED: "DEVORA_103",
196
+ INVALID_SIGNATURE: "DEVORA_104",
197
+ ORG_MISMATCH: "DEVORA_105",
198
+ KEY_NOT_FOUND: "DEVORA_106",
199
+ KEY_REVOKED: "DEVORA_107",
200
+ MISSING_SIGNATURE: "DEVORA_108",
201
+ // Validation errors (2xx)
202
+ INVALID_CONFIG: "DEVORA_201",
203
+ MISSING_ENDPOINT: "DEVORA_202",
204
+ INVALID_HANDLER: "DEVORA_203",
205
+ DUPLICATE_ENDPOINT: "DEVORA_204",
206
+ BODY_TOO_LARGE: "DEVORA_205",
207
+ INVALID_API_KEY: "DEVORA_206",
208
+ INVALID_ORG_ID: "DEVORA_207",
209
+ // Runtime errors (3xx)
210
+ HANDLER_ERROR: "DEVORA_301",
211
+ NETWORK_ERROR: "DEVORA_302",
212
+ SESSION_EXPIRED: "DEVORA_303",
213
+ TOKEN_CONSUMED: "DEVORA_304",
214
+ // Scope errors (4xx)
215
+ SCOPE_VIOLATION: "DEVORA_401",
216
+ WRITE_BLOCKED: "DEVORA_402",
217
+ // Rate limiting errors (5xx)
218
+ RATE_LIMITED: "DEVORA_501",
219
+ TOO_MANY_REQUESTS: "DEVORA_502",
220
+ };
221
+ // ============================================================================
222
+ // HTTP Methods
223
+ // ============================================================================
224
+ /**
225
+ * HTTP methods considered as write operations (blocked in read-only mode)
226
+ */
227
+ export const WRITE_METHODS = ["POST", "PUT", "DELETE", "PATCH"];
228
+ /**
229
+ * HTTP methods considered as read operations (allowed in read-only mode)
230
+ */
231
+ export const READ_METHODS = ["GET", "HEAD", "OPTIONS"];
232
+ // ============================================================================
233
+ // Session Lifecycle
234
+ // ============================================================================
235
+ export * from "./sessionLifecycle.js";
236
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Session Lifecycle Constants for SDK
3
+ *
4
+ * These constants are used by the frontend SDK when ending sessions.
5
+ * They match the backend expectations.
6
+ */
7
+ /**
8
+ * Reasons the SDK can send when ending a session.
9
+ * These are mapped by the backend to EndReason values.
10
+ */
11
+ export declare const SDK_END_REASON: {
12
+ /** User clicked the "End Session" button in the customer app */
13
+ readonly USER_ENDED: "user_ended";
14
+ /** Frontend timer detected that the session has expired */
15
+ readonly EXPIRED: "expired";
16
+ /** Session was terminated externally (detected via validation check) */
17
+ readonly TERMINATED_EXTERNALLY: "terminated_externally";
18
+ /** Page is being unloaded (beforeunload event) */
19
+ readonly PAGE_UNLOAD: "page_unload";
20
+ };
21
+ export type SDKEndReason = (typeof SDK_END_REASON)[keyof typeof SDK_END_REASON];
22
+ //# sourceMappingURL=sessionLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionLifecycle.d.ts","sourceRoot":"","sources":["../../src/constants/sessionLifecycle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,cAAc;IAC1B,gEAAgE;;IAEhE,2DAA2D;;IAE3D,wEAAwE;;IAExE,kDAAkD;;CAEzC,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAA"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Session Lifecycle Constants for SDK
3
+ *
4
+ * These constants are used by the frontend SDK when ending sessions.
5
+ * They match the backend expectations.
6
+ */
7
+ /**
8
+ * Reasons the SDK can send when ending a session.
9
+ * These are mapped by the backend to EndReason values.
10
+ */
11
+ export const SDK_END_REASON = {
12
+ /** User clicked the "End Session" button in the customer app */
13
+ USER_ENDED: "user_ended",
14
+ /** Frontend timer detected that the session has expired */
15
+ EXPIRED: "expired",
16
+ /** Session was terminated externally (detected via validation check) */
17
+ TERMINATED_EXTERNALLY: "terminated_externally",
18
+ /** Page is being unloaded (beforeunload event) */
19
+ PAGE_UNLOAD: "page_unload",
20
+ };
21
+ //# sourceMappingURL=sessionLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionLifecycle.js","sourceRoot":"","sources":["../../src/constants/sessionLifecycle.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,gEAAgE;IAChE,UAAU,EAAE,YAAY;IACxB,2DAA2D;IAC3D,OAAO,EAAE,SAAS;IAClB,wEAAwE;IACxE,qBAAqB,EAAE,uBAAuB;IAC9C,kDAAkD;IAClD,WAAW,EAAE,aAAa;CACjB,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Devora SDK Core
3
+ * Shared types, constants, and utilities for all Devora SDKs
4
+ *
5
+ * @packageDocumentation
6
+ * @module @devorash/core
7
+ */
8
+ export type { DevoraRequest, DevoraResponse, DevoraUser, UserSearchRequest, UserSearchResponse, ImpersonationScope, ImpersonationDuration, DevoraImpersonationContext, ImpersonationStartRequest, ImpersonationStartResponse, ImpersonationTerminateRequest, ImpersonationTerminateResponse, ImpersonationUserInfo, ImpersonatePayload, ImpersonateCallback, SessionEndCallback, FrontendSDKConfig, ErrorHandlers, PayloadError, ScopeViolation, DevoraMaskingProfile, DevoraCapturePolicy, DevoraCaptureSnapshot, BackendSDKConfig, RouteHandler, RouteDefinition, LogEventType, LogEvent, SDKInfo, HealthCheckResponse, ConnectionTestResponse, SessionBridgeResult, BrowserResumeCode, } from "./types/index.js";
9
+ export { DEVORA_PRIVACY_MARKERS } from "./types/index.js";
10
+ export { DEVORA_ENDPOINTS, ENDPOINT_METHODS, PROTECTED_ENDPOINTS, type DevoraEndpointKey, type DevoraEndpointPath, SECURITY_HEADERS, FRONTEND_HEADERS, URL_PARAMS, BROWSER_SESSION_BRIDGE, SDK_DEFAULTS, SDK_PACKAGES, SDK_VERSION, ERROR_CODES, type DevoraErrorCode, WRITE_METHODS, READ_METHODS, type WriteMethod, type ReadMethod, SDK_END_REASON, type SDKEndReason, } from "./constants/index.js";
11
+ export { validateTimestamp, isValidTimestampTolerance, assertTimestampTolerance, isWriteMethod, matchEndpointPattern, normalizeRequestPath, isAmbiguousRequestPath, getRawRequestPath, METHOD_OVERRIDE_HEADERS, getPolicyMethods, getDenyMethods, joinMountedTarget, createBlockedResponse, generateRandomString, arrayBufferToHex, hexToArrayBuffer, DevoraSDKError, DevoraSecurityError, DevoraValidationError, DevoraConfigError, DevoraNetworkError, } from "./security/index.js";
12
+ export { SIGNING, SIGNED_HEADER_PATTERNS, strictEncode, encodePathParam, buildStrictQuery, isValidSignedPath, isValidSignedQuery, buildCanonicalString, getSingleHeader, parseSignatureHeaders, hasIdentityContentEncoding, replayNamespace, replayExpiresAtMs, parseVerifiedQuery, parseVerifiedJsonBody, routeRelativePath, type SigningDirection, type SignatureErrorCode, type HeaderMap, type SignatureHeaders, type SignatureHeaderResult, type CanonicalFields, type VerifiedBodyResult, } from "./security/signing.js";
13
+ export { createSuccessResponse, createErrorResponse, extractUrlParams, cleanImpersonationParams, matchPath, extractPathParams, getHeaderValue, getErrorStatusCode, RateLimiter, scopeAllowsWrite, getScopeDescription, createLogEvent, createSDKInfo, LogLevel, configureLogger, getLoggerConfig, resetLoggerConfig, createLogger, type LoggerConfig, type LogHandler, type Logger, validateApiKeyFormat, validateOrgIdFormat, safeJsonParse, safeJsonStringify, deepFreeze, createDeferred, } from "./utils/index.js";
14
+ export { readBoundedBody, readBoundedBytes, BodyReadError } from "./security/request-body.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,YAAY,EAEX,aAAa,EACb,cAAc,EAEd,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAElB,kBAAkB,EAClB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,0BAA0B,EAC1B,6BAA6B,EAC7B,8BAA8B,EAE9B,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,cAAc,EAEd,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EAErB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EAEf,YAAY,EACZ,QAAQ,EAER,OAAO,EACP,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,GACjB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAMzD,OAAO,EAEN,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAEvB,gBAAgB,EAChB,gBAAgB,EAEhB,UAAU,EACV,sBAAsB,EAEtB,YAAY,EAEZ,YAAY,EACZ,WAAW,EAEX,WAAW,EACX,KAAK,eAAe,EAEpB,aAAa,EACb,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,UAAU,EAEf,cAAc,EACd,KAAK,YAAY,GACjB,MAAM,sBAAsB,CAAA;AAM7B,OAAO,EAEN,iBAAiB,EACjB,yBAAyB,EACzB,wBAAwB,EAExB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EAErB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAEhB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EACN,OAAO,EACP,sBAAsB,EACtB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACvB,MAAM,uBAAuB,CAAA;AAM9B,OAAO,EAEN,qBAAqB,EACrB,mBAAmB,EAEnB,gBAAgB,EAChB,wBAAwB,EAExB,SAAS,EACT,iBAAiB,EAGjB,cAAc,EACd,kBAAkB,EAGlB,WAAW,EAEX,gBAAgB,EAChB,mBAAmB,EAEnB,cAAc,EAEd,aAAa,EAEb,QAAQ,EACR,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,MAAM,EAEX,oBAAoB,EACpB,mBAAmB,EAEnB,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,cAAc,GACd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Devora SDK Core
3
+ * Shared types, constants, and utilities for all Devora SDKs
4
+ *
5
+ * @packageDocumentation
6
+ * @module @devorash/core
7
+ */
8
+ export { DEVORA_PRIVACY_MARKERS } from "./types/index.js";
9
+ // ============================================================================
10
+ // Constants
11
+ // ============================================================================
12
+ export {
13
+ // Endpoints
14
+ DEVORA_ENDPOINTS, ENDPOINT_METHODS, PROTECTED_ENDPOINTS,
15
+ // Headers
16
+ SECURITY_HEADERS, FRONTEND_HEADERS,
17
+ // URL & Storage
18
+ URL_PARAMS, BROWSER_SESSION_BRIDGE,
19
+ // Defaults
20
+ SDK_DEFAULTS,
21
+ // Metadata
22
+ SDK_PACKAGES, SDK_VERSION,
23
+ // Error codes
24
+ ERROR_CODES,
25
+ // HTTP Methods
26
+ WRITE_METHODS, READ_METHODS,
27
+ // Session Lifecycle
28
+ SDK_END_REASON, } from "./constants/index.js";
29
+ // ============================================================================
30
+ // Security
31
+ // ============================================================================
32
+ export {
33
+ // Timestamps
34
+ validateTimestamp, isValidTimestampTolerance, assertTimestampTolerance,
35
+ // Scope
36
+ isWriteMethod, matchEndpointPattern, normalizeRequestPath, isAmbiguousRequestPath, getRawRequestPath, METHOD_OVERRIDE_HEADERS, getPolicyMethods, getDenyMethods, joinMountedTarget, createBlockedResponse,
37
+ // Tokens
38
+ generateRandomString, arrayBufferToHex, hexToArrayBuffer,
39
+ // Errors
40
+ DevoraSDKError, DevoraSecurityError, DevoraValidationError, DevoraConfigError, DevoraNetworkError, } from "./security/index.js";
41
+ // Request signing (v3)
42
+ export { SIGNING, SIGNED_HEADER_PATTERNS, strictEncode, encodePathParam, buildStrictQuery, isValidSignedPath, isValidSignedQuery, buildCanonicalString, getSingleHeader, parseSignatureHeaders, hasIdentityContentEncoding, replayNamespace, replayExpiresAtMs, parseVerifiedQuery, parseVerifiedJsonBody, routeRelativePath, } from "./security/signing.js";
43
+ // ============================================================================
44
+ // Utilities
45
+ // ============================================================================
46
+ export {
47
+ // Response helpers
48
+ createSuccessResponse, createErrorResponse,
49
+ // URL helpers
50
+ extractUrlParams, cleanImpersonationParams,
51
+ // Path matching
52
+ matchPath, extractPathParams,
53
+ // Query string
54
+ // Header utilities
55
+ getHeaderValue, getErrorStatusCode,
56
+ // Request canonicalization (for HMAC)
57
+ // Rate limiting
58
+ RateLimiter,
59
+ // Scope helpers
60
+ scopeAllowsWrite, getScopeDescription,
61
+ // Logging
62
+ createLogEvent,
63
+ // SDK info
64
+ createSDKInfo,
65
+ // Logger service
66
+ LogLevel, configureLogger, getLoggerConfig, resetLoggerConfig, createLogger,
67
+ // Validation
68
+ validateApiKeyFormat, validateOrgIdFormat,
69
+ // Misc
70
+ safeJsonParse, safeJsonStringify, deepFreeze, createDeferred, } from "./utils/index.js";
71
+ export { readBoundedBody, readBoundedBytes, BodyReadError } from "./security/request-body.js";
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkDH,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,OAAO;AACN,YAAY;AACZ,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB;AAGnB,UAAU;AACV,gBAAgB,EAChB,gBAAgB;AAChB,gBAAgB;AAChB,UAAU,EACV,sBAAsB;AACtB,WAAW;AACX,YAAY;AACZ,WAAW;AACX,YAAY,EACZ,WAAW;AACX,cAAc;AACd,WAAW;AAEX,eAAe;AACf,aAAa,EACb,YAAY;AAGZ,oBAAoB;AACpB,cAAc,GAEd,MAAM,sBAAsB,CAAA;AAE7B,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E,OAAO;AACN,aAAa;AACb,iBAAiB,EACjB,yBAAyB,EACzB,wBAAwB;AACxB,QAAQ;AACR,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,qBAAqB;AACrB,SAAS;AACT,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB;AAChB,SAAS;AACT,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAE5B,uBAAuB;AACvB,OAAO,EACN,OAAO,EACP,sBAAsB,EACtB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAQjB,MAAM,uBAAuB,CAAA;AAE9B,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,OAAO;AACN,mBAAmB;AACnB,qBAAqB,EACrB,mBAAmB;AACnB,cAAc;AACd,gBAAgB,EAChB,wBAAwB;AACxB,gBAAgB;AAChB,SAAS,EACT,iBAAiB;AACjB,eAAe;AACf,mBAAmB;AACnB,cAAc,EACd,kBAAkB;AAClB,sCAAsC;AACtC,gBAAgB;AAChB,WAAW;AACX,gBAAgB;AAChB,gBAAgB,EAChB,mBAAmB;AACnB,UAAU;AACV,cAAc;AACd,WAAW;AACX,aAAa;AACb,iBAAiB;AACjB,QAAQ,EACR,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,YAAY;AAIZ,aAAa;AACb,oBAAoB,EACpB,mBAAmB;AACnB,OAAO;AACP,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,cAAc,GACd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Security utilities for Devora SDKs
3
+ * @module @devorash/core/security
4
+ */
5
+ import type { SignatureErrorCode } from "./signing.js";
6
+ /**
7
+ * A timestamp tolerance is a whole, non-negative number of seconds. Zero means
8
+ * only the current second is accepted; there is no "falsy means default".
9
+ */
10
+ export declare function isValidTimestampTolerance(value: unknown): value is number;
11
+ /** Throws for configuration values that {@link isValidTimestampTolerance} rejects. */
12
+ export declare function assertTimestampTolerance(value: unknown, name?: string): void;
13
+ /**
14
+ * Validate timestamp is within acceptable window
15
+ */
16
+ export declare function validateTimestamp(requestTimestamp: number, toleranceSeconds?: number): {
17
+ valid: boolean;
18
+ error?: string;
19
+ };
20
+ /**
21
+ * Check if HTTP method is a write operation
22
+ */
23
+ export declare function isWriteMethod(method: string): boolean;
24
+ /**
25
+ * Path of an origin-form request target (`/path?query`), still percent-encoded.
26
+ *
27
+ * Absolute-form targets (`http://host/path`) are deliberately NOT unwrapped:
28
+ * routers disagree with any regex about where such a host ends (a `?` inside
29
+ * it moves the routed path to `/`), so the result does not start with `/` and
30
+ * {@link isAmbiguousRequestPath} rejects it.
31
+ */
32
+ export declare function getRawRequestPath(value: string): string;
33
+ /** Headers through which common middleware lets a client change the effective method. */
34
+ export declare const METHOD_OVERRIDE_HEADERS: readonly ["x-http-method-override", "x-http-method", "x-method-override"];
35
+ /** The query parameter method-override middleware reads (`?_method=DELETE`). */
36
+ export declare const METHOD_OVERRIDE_QUERY_PARAM = "_method";
37
+ /**
38
+ * Every method a request might execute as. The guard judges all of them, so a
39
+ * method-override middleware ordered after the guard cannot turn an allowed
40
+ * POST into a blocked DELETE. `target` (the raw request target) adds any
41
+ * `_method` query parameters. A `_method` field in a request body is invisible
42
+ * to a guard that runs before body parsing; see the guard docs.
43
+ */
44
+ export declare function getPolicyMethods(method: string, headers?: Record<string, string | string[] | undefined>, target?: string): string[];
45
+ /**
46
+ * Methods a deny rule must cover. Frameworks answer HEAD with the GET handler,
47
+ * so a GET deny rule also denies HEAD.
48
+ */
49
+ export declare function getDenyMethods(methods: string[]): string[];
50
+ /** Join a router mount prefix and a mount-relative origin-form target. */
51
+ export declare function joinMountedTarget(mountPath: string | undefined, target: string): string;
52
+ /** Reject paths whose segment boundaries differ between common routers. */
53
+ export declare function isAmbiguousRequestPath(value: string): boolean;
54
+ /** Decode one segment at a time, preserving case and separators. */
55
+ export declare function normalizeRequestPath(value: string): string;
56
+ /**
57
+ * Bounded iterative glob matching: * stays within a segment; ** spans zero or
58
+ * more whole segments. Allow rules preserve case/trailing slashes. Deny rules
59
+ * opt into conservative case-insensitive matching for non-strict routers.
60
+ */
61
+ export declare function matchEndpointPattern(pattern: string, path: string, options?: {
62
+ caseSensitive?: boolean;
63
+ ignoreTrailingSlash?: boolean;
64
+ }): boolean;
65
+ /**
66
+ * Create a blocked response for scope violations
67
+ */
68
+ export declare function createBlockedResponse(method: string, url: string): Response;
69
+ /**
70
+ * Generate a cryptographically secure random string for tokens/IDs.
71
+ *
72
+ * @throws {Error} If no secure random source is available.
73
+ * This is intentional - we must never fall back to Math.random()
74
+ * for security-sensitive operations like token generation.
75
+ */
76
+ export declare function generateRandomString(length?: number): string;
77
+ /**
78
+ * Convert ArrayBuffer to hex string
79
+ */
80
+ export declare function arrayBufferToHex(buffer: ArrayBuffer): string;
81
+ /**
82
+ * Convert hex string to ArrayBuffer
83
+ */
84
+ export declare function hexToArrayBuffer(hex: string): ArrayBuffer;
85
+ /**
86
+ * Base error class for Devora SDK errors
87
+ */
88
+ export declare class DevoraSDKError extends Error {
89
+ readonly code: string;
90
+ readonly statusCode: number;
91
+ constructor(message: string, code: string, statusCode?: number);
92
+ }
93
+ /**
94
+ * Security-related errors
95
+ */
96
+ export declare class DevoraSecurityError extends DevoraSDKError {
97
+ readonly securityCode: SignatureErrorCode;
98
+ constructor(message: string, securityCode: SignatureErrorCode, statusCode?: number);
99
+ }
100
+ /**
101
+ * Validation errors
102
+ */
103
+ export declare class DevoraValidationError extends DevoraSDKError {
104
+ constructor(message: string, code?: string);
105
+ }
106
+ /**
107
+ * Configuration errors
108
+ */
109
+ export declare class DevoraConfigError extends DevoraSDKError {
110
+ constructor(message: string);
111
+ }
112
+ /**
113
+ * Network/connectivity errors
114
+ */
115
+ export declare class DevoraNetworkError extends DevoraSDKError {
116
+ constructor(message: string);
117
+ }
118
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"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"}