theokit 0.12.0 → 0.13.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 (131) hide show
  1. package/dist/{actions-virtual-module-SQDY3V5X.js → actions-virtual-module-3CDQTWOC.js} +6 -6
  2. package/dist/{actions-virtual-module-PNPRCEOS.js → actions-virtual-module-EIPXX4ZB.js} +3 -3
  3. package/dist/adapters/web-shim.d.ts +67 -0
  4. package/dist/adapters/ws-shim.d.ts +55 -0
  5. package/dist/agent-events-DosDXkSV.d.ts +94 -0
  6. package/dist/agents-typed-client-SAWAAH7K.js +142 -0
  7. package/dist/agents-typed-client-SAWAAH7K.js.map +1 -0
  8. package/dist/agents-typed-client-UTEQUA63.js +143 -0
  9. package/dist/agents-typed-client-UTEQUA63.js.map +1 -0
  10. package/dist/{app-typed-client-5GYEOYP3.js → app-typed-client-7PBFWZUE.js} +3 -3
  11. package/dist/{app-typed-client-QG7BVZYW.js → app-typed-client-CSOK7NPC.js} +6 -6
  12. package/dist/audit-log-BQWM5YLG.d.ts +60 -0
  13. package/dist/body-parser-web-FV5HWCY3.js +71 -0
  14. package/dist/body-parser-web-FV5HWCY3.js.map +1 -0
  15. package/dist/boot/index.d.ts +39 -0
  16. package/dist/{build-QFRLSEZ4.js → build-HXND27XG.js} +11 -11
  17. package/dist/{chunk-223EFY5X.js → chunk-2J7XU3PW.js} +68 -27
  18. package/dist/chunk-2J7XU3PW.js.map +1 -0
  19. package/dist/{chunk-RESN62GB.js → chunk-2KZQPDYR.js} +5 -48
  20. package/dist/chunk-2KZQPDYR.js.map +1 -0
  21. package/dist/chunk-3S3BNW5K.js +445 -0
  22. package/dist/chunk-3S3BNW5K.js.map +1 -0
  23. package/dist/{chunk-6FYD34NX.js → chunk-BQDGES7C.js} +28 -28
  24. package/dist/{chunk-6FYD34NX.js.map → chunk-BQDGES7C.js.map} +1 -1
  25. package/dist/chunk-EXP56GFQ.js +52 -0
  26. package/dist/chunk-EXP56GFQ.js.map +1 -0
  27. package/dist/chunk-F4YUPDJ2.js +115 -0
  28. package/dist/chunk-F4YUPDJ2.js.map +1 -0
  29. package/dist/{chunk-NAZ4E2GT.js → chunk-KXA37ONC.js} +2 -2
  30. package/dist/chunk-NHJMZCAS.js +32 -0
  31. package/dist/chunk-NHJMZCAS.js.map +1 -0
  32. package/dist/{chunk-43D6XNDR.js → chunk-O62MW4MT.js} +91 -18
  33. package/dist/chunk-O62MW4MT.js.map +1 -0
  34. package/dist/chunk-RSVN727G.js +1 -0
  35. package/dist/{chunk-7CBRKNQA.js → chunk-RYTZYFSD.js} +198 -6
  36. package/dist/chunk-RYTZYFSD.js.map +1 -0
  37. package/dist/chunk-UNLA45FY.js +235 -0
  38. package/dist/chunk-UNLA45FY.js.map +1 -0
  39. package/dist/{chunk-GFMQJHXX.js → chunk-WR4F4EEZ.js} +1082 -1074
  40. package/dist/chunk-WR4F4EEZ.js.map +1 -0
  41. package/dist/{chunk-AD74EAK3.js → chunk-ZSTZXR2D.js} +1 -30
  42. package/dist/chunk-ZSTZXR2D.js.map +1 -0
  43. package/dist/cli/index.js +5 -5
  44. package/dist/client/index.d.ts +418 -0
  45. package/dist/client/index.js +84 -3
  46. package/dist/client/index.js.map +1 -1
  47. package/dist/csrf-BBrEZSBW.d.ts +107 -0
  48. package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
  49. package/dist/define-websocket-CdK94O-D.d.ts +64 -0
  50. package/dist/{dev-GBXOTXUP.js → dev-OWW4XVIH.js} +10 -10
  51. package/dist/{dev-emit-FEFEDLZF.js → dev-emit-5MDSBP5D.js} +3 -3
  52. package/dist/{dev-emit-O4EGOSNV.js → dev-emit-QH2YGZXN.js} +2 -2
  53. package/dist/devtools/entry.d.ts +5 -0
  54. package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
  55. package/dist/health-route-C0hk64_U.d.ts +57 -0
  56. package/dist/index-B40qUSrQ.d.ts +575 -0
  57. package/dist/index.d.ts +361 -0
  58. package/dist/index.js +6 -4
  59. package/dist/index.js.map +1 -1
  60. package/dist/internal-api-4YTJDITC.js +83 -0
  61. package/dist/internal-api-EFKZWIYZ.js +66 -0
  62. package/dist/internal-api-EFKZWIYZ.js.map +1 -0
  63. package/dist/job-backend-CgC8Xf33.d.ts +68 -0
  64. package/dist/match-CfbEFRG4.d.ts +26 -0
  65. package/dist/{openapi-VR6AFBLJ.js → openapi-FHY6HC6I.js} +7 -7
  66. package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
  67. package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
  68. package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
  69. package/dist/rate-limit-store-BEJnhWdw.d.ts +72 -0
  70. package/dist/react-query/index.d.ts +33 -0
  71. package/dist/{registry-Q2TZQLUH.js → registry-34LL7NF4.js} +1 -1
  72. package/dist/{routes-LRYOIIAI.js → routes-EW7TP7NJ.js} +2 -2
  73. package/dist/schema-BpH6ivDY.d.ts +74 -0
  74. package/dist/server/agent/index.d.ts +229 -0
  75. package/dist/server/agent/index.js +2 -1
  76. package/dist/server/auth/index.d.ts +419 -0
  77. package/dist/server/cost/index.d.ts +177 -0
  78. package/dist/server/cron/index.d.ts +208 -0
  79. package/dist/server/define/index.d.ts +313 -0
  80. package/dist/server/define/index.js +4 -2
  81. package/dist/server/http/index.d.ts +11 -0
  82. package/dist/server/index.d.ts +848 -0
  83. package/dist/server/index.js +9 -294
  84. package/dist/server/index.js.map +1 -1
  85. package/dist/server/jobs/index.d.ts +348 -0
  86. package/dist/server/observability/index.d.ts +324 -0
  87. package/dist/server/plugins/index.d.ts +17 -0
  88. package/dist/server/rate-limit/index.d.ts +105 -0
  89. package/dist/server/realtime/index.d.ts +15 -0
  90. package/dist/server/scan/index.d.ts +126 -0
  91. package/dist/server/scan/index.js +1 -1
  92. package/dist/server/security/index.d.ts +193 -0
  93. package/dist/server/storage/index.d.ts +22 -0
  94. package/dist/server/webhook/index.d.ts +148 -0
  95. package/dist/{start-3ZHAXSJE.js → start-KIQ5TTLR.js} +76 -13
  96. package/dist/start-KIQ5TTLR.js.map +1 -0
  97. package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
  98. package/dist/storage-types-DsDTCPbp.d.ts +96 -0
  99. package/dist/vite-plugin/index.d.ts +115 -0
  100. package/dist/vite-plugin/index.js +6 -4
  101. package/dist/{vite-plugin-WO72VLYR.js → vite-plugin-RK66K26Z.js} +7 -7
  102. package/dist/vite-plugin-RK66K26Z.js.map +1 -0
  103. package/package.json +4 -4
  104. package/dist/chunk-223EFY5X.js.map +0 -1
  105. package/dist/chunk-3LVRAGAZ.js +0 -73
  106. package/dist/chunk-3LVRAGAZ.js.map +0 -1
  107. package/dist/chunk-43D6XNDR.js.map +0 -1
  108. package/dist/chunk-7CBRKNQA.js.map +0 -1
  109. package/dist/chunk-AD74EAK3.js.map +0 -1
  110. package/dist/chunk-GFMQJHXX.js.map +0 -1
  111. package/dist/chunk-PBEH6NXR.js +0 -44
  112. package/dist/chunk-PBEH6NXR.js.map +0 -1
  113. package/dist/chunk-PIVX3DYW.js +0 -142
  114. package/dist/chunk-PIVX3DYW.js.map +0 -1
  115. package/dist/chunk-PPPR5DGR.js +0 -1
  116. package/dist/chunk-RESN62GB.js.map +0 -1
  117. package/dist/start-3ZHAXSJE.js.map +0 -1
  118. /package/dist/{actions-virtual-module-SQDY3V5X.js.map → actions-virtual-module-3CDQTWOC.js.map} +0 -0
  119. /package/dist/{actions-virtual-module-PNPRCEOS.js.map → actions-virtual-module-EIPXX4ZB.js.map} +0 -0
  120. /package/dist/{app-typed-client-5GYEOYP3.js.map → app-typed-client-7PBFWZUE.js.map} +0 -0
  121. /package/dist/{app-typed-client-QG7BVZYW.js.map → app-typed-client-CSOK7NPC.js.map} +0 -0
  122. /package/dist/{build-QFRLSEZ4.js.map → build-HXND27XG.js.map} +0 -0
  123. /package/dist/{chunk-NAZ4E2GT.js.map → chunk-KXA37ONC.js.map} +0 -0
  124. /package/dist/{chunk-PPPR5DGR.js.map → chunk-RSVN727G.js.map} +0 -0
  125. /package/dist/{dev-GBXOTXUP.js.map → dev-OWW4XVIH.js.map} +0 -0
  126. /package/dist/{dev-emit-FEFEDLZF.js.map → dev-emit-5MDSBP5D.js.map} +0 -0
  127. /package/dist/{dev-emit-O4EGOSNV.js.map → dev-emit-QH2YGZXN.js.map} +0 -0
  128. /package/dist/{vite-plugin-WO72VLYR.js.map → internal-api-4YTJDITC.js.map} +0 -0
  129. /package/dist/{openapi-VR6AFBLJ.js.map → openapi-FHY6HC6I.js.map} +0 -0
  130. /package/dist/{registry-Q2TZQLUH.js.map → registry-34LL7NF4.js.map} +0 -0
  131. /package/dist/{routes-LRYOIIAI.js.map → routes-EW7TP7NJ.js.map} +0 -0
@@ -0,0 +1,105 @@
1
+ import { R as RateLimitConfig, a as RateLimitResult } from '../../rate-limit-BdNDZ3vt.js';
2
+ export { c as createRateLimiter, b as createRateLimiterWeb } from '../../rate-limit-BdNDZ3vt.js';
3
+ import { R as RateLimitStore } from '../../rate-limit-store-BEJnhWdw.js';
4
+ export { I as InMemoryStore, a as RateLimitState } from '../../rate-limit-store-BEJnhWdw.js';
5
+ import { IncomingMessage } from 'node:http';
6
+
7
+ /**
8
+ * T2.2 — Per-route + per-user rate limiting.
9
+ *
10
+ * Layered on top of `rate-limit-store.ts`. The route map allows
11
+ * declarative policies ("strict /api/login, loose everything else")
12
+ * driven by config, not handler-decorated. `keyBy` selects what
13
+ * identifier the limiter buckets on.
14
+ *
15
+ * ADR D2: per-route via path matching, NOT per-handler decorator.
16
+ * Operators can tune policies without touching route definitions.
17
+ */
18
+ type KeyByMode = 'ip' | 'session' | 'user' | ((req: IncomingMessage) => string);
19
+ interface RouteRateLimitConfig {
20
+ /** Fallback config used when no per-route entry matches. */
21
+ default?: RateLimitConfig;
22
+ /** Map of path pattern → config. Exact-string keys (RegExp via API). */
23
+ routes?: Record<string, RateLimitConfig>;
24
+ /** Same as `routes` but each entry is a [pattern, config] tuple, RegExp allowed. */
25
+ routePatterns?: readonly [string | RegExp, RateLimitConfig][];
26
+ /** Bucket identifier strategy. Default 'ip'. */
27
+ keyBy?: KeyByMode;
28
+ /** Cookie name used by keyBy='session'. Defaults to 'theo_session'. */
29
+ cookieName?: string;
30
+ /** Optional shared store (for multi-route correlation). Default per-limiter InMemoryStore. */
31
+ store?: RateLimitStore;
32
+ }
33
+ /**
34
+ * Test whether `path` matches `pattern`. String patterns are compared
35
+ * after trailing-slash normalization (EC-5). RegExp uses `.test` after
36
+ * resetting `lastIndex` (defensive against `/g` flag).
37
+ */
38
+ declare function matchRoutePattern(path: string, pattern: string | RegExp): boolean;
39
+ /**
40
+ * Build the rate-limit bucket key for the request based on `keyBy`.
41
+ *
42
+ * EC-6: session mode reads the configured `cookieName`. With the wrong
43
+ * cookie name (e.g., default 'theo_session' but app uses 'app_session'),
44
+ * we fall back to IP so anonymous users still get rate-limited rather
45
+ * than sharing an empty bucket.
46
+ */
47
+ declare function deriveKey(req: IncomingMessage, keyBy: KeyByMode, cookieName: string): Promise<string>;
48
+ /**
49
+ * Per-route rate limiter factory. Returns a sync checker compatible with
50
+ * the existing api-middleware shape.
51
+ *
52
+ * Backwards-compatibility (ADR D2): a flat `{ windowMs, max }` config is
53
+ * accepted and treated as `default` (no per-route variants).
54
+ */
55
+ declare function createRouteRateLimiter(config: RouteRateLimitConfig | RateLimitConfig): (req: IncomingMessage) => Promise<RateLimitResult>;
56
+ /**
57
+ * T5a.2 Phase D slice 1/3 — Web-Standards rate-limiter inputs context.
58
+ *
59
+ * Web `Request` has no equivalent of `req.socket.remoteAddress` (Node
60
+ * runtime concept) or `req.user` (set by upstream middleware). The
61
+ * Web-shaped rate-limiter requires the caller to pass these explicitly:
62
+ *
63
+ * - `clientIp` — resolved per-runtime (Node: `socket.remoteAddress`;
64
+ * CF Workers: `request.headers.get('cf-connecting-ip')`; Vercel:
65
+ * `x-forwarded-for` first hop; Bun/Deno: adapter-specific).
66
+ * - `userId` — resolved by auth middleware (Phase D slice 3/3 ships
67
+ * the Web-shaped session helper).
68
+ *
69
+ * Defaults: `clientIp = 'unknown'`, `userId = undefined` (matches the
70
+ * IncomingMessage path's fallback semantics).
71
+ */
72
+ interface DeriveKeyRequestContext {
73
+ clientIp?: string;
74
+ userId?: string;
75
+ }
76
+ /**
77
+ * T5a.2 Phase D slice 1/3 — Web-Standards-shaped key derivation.
78
+ *
79
+ * Mirror of `deriveKey(req: IncomingMessage, keyBy, cookieName)` for the
80
+ * Web `Request` shape. Same `'ip' | 'session' | 'user'` enum cases (the
81
+ * `function` callback case is IncomingMessage-only because the existing
82
+ * `KeyByMode` callback type is Node-shaped; Web callers use the enum
83
+ * cases or call a future `KeyByModeWeb` shape — out of T5a.2 Phase D scope).
84
+ *
85
+ * Uses `getCookieFromRequest` (Phase B slice 6/6) for session-mode cookie
86
+ * lookup. Cookie parsing has the same CR-009 percent-encoding safety.
87
+ */
88
+ declare function deriveKeyFromRequest(request: Request, keyBy: Exclude<KeyByMode, (req: IncomingMessage) => string>, cookieName: string, ctx?: DeriveKeyRequestContext): Promise<string>;
89
+ /**
90
+ * T5a.2 Phase D slice 1/3 — Web-Standards rate-limiter factory.
91
+ *
92
+ * Mirror of `createRouteRateLimiter(config)` returning a checker that
93
+ * accepts `(request: Request, ctx?: DeriveKeyRequestContext)` instead of
94
+ * `(req: IncomingMessage)`. Same `RouteRateLimitConfig` accepted; same
95
+ * `keyBy` enum cases; same `InMemoryStore` constraint (CR-005 guard).
96
+ *
97
+ * Same returned `RateLimitResult` shape (headers + limited boolean).
98
+ *
99
+ * Web `Request` has no `req.url` path-only property — uses
100
+ * `new URL(request.url).pathname + search` to derive the URL the way the
101
+ * IncomingMessage path's `req.url ?? ''` would.
102
+ */
103
+ declare function createRouteRateLimiterWeb(config: RouteRateLimitConfig | RateLimitConfig): (request: Request, ctx?: DeriveKeyRequestContext) => Promise<RateLimitResult>;
104
+
105
+ export { type DeriveKeyRequestContext, type KeyByMode, RateLimitConfig, RateLimitResult, RateLimitStore, type RouteRateLimitConfig, createRouteRateLimiter, createRouteRateLimiterWeb, deriveKey, deriveKeyFromRequest, matchRoutePattern };
@@ -0,0 +1,15 @@
1
+ import { b as WebSocketLike } from '../../define-websocket-CdK94O-D.js';
2
+ import 'node:http';
3
+
4
+ declare class ChannelManager {
5
+ private rooms;
6
+ private wsRooms;
7
+ subscribe(ws: WebSocketLike, room: string): void;
8
+ unsubscribe(ws: WebSocketLike, room: string): void;
9
+ broadcast(room: string, data: unknown, exclude?: WebSocketLike): void;
10
+ broadcastAll(data: unknown): void;
11
+ getRoomSize(room: string): number;
12
+ cleanup(ws: WebSocketLike): void;
13
+ }
14
+
15
+ export { ChannelManager };
@@ -0,0 +1,126 @@
1
+ import { S as ServerRouteNode } from '../../match-CfbEFRG4.js';
2
+ export { L as LoadModule, c as compilePattern, a as createProductionLoader, b as createViteLoader, m as matchRoute } from '../../match-CfbEFRG4.js';
3
+ import 'vite';
4
+
5
+ interface ActionNode {
6
+ filePath: string;
7
+ actionPath: string;
8
+ }
9
+ /**
10
+ * Enriched manifest entry per plan g3-server-actions-and-useaction v1.2
11
+ * § Phase 1 / T1.4 + ADR D4. Consumed by virtual module `@theo/actions`
12
+ * (T3.1) and G4 devtools "Actions" tab (T5.1).
13
+ */
14
+ interface ActionManifestEntry {
15
+ name: string;
16
+ filePath: string;
17
+ urlPath: string;
18
+ accept: 'form' | 'json';
19
+ hasInput: boolean;
20
+ /**
21
+ * P#4 plugin-forms shared-schema convention (per plan p4-plugin-forms v1.1 T1.1).
22
+ * When present, points to an isomorphic schema file at
23
+ * `<serverDir>/actions/schemas/<basename>.ts` exporting `export const schema = z.object(...)`.
24
+ * Virtual module emits `import {schema} from '<schemaFilePath>'` + attaches as
25
+ * `actions.X.__zodSchema` so client-side <TheoForm> can drive zodResolver.
26
+ * Undefined when convention not followed (graceful degrade — TheoForm still
27
+ * works via explicit `schema={...}` prop escape hatch).
28
+ */
29
+ schemaFilePath?: string;
30
+ }
31
+ /**
32
+ * EC-2: structured error for scan-time defects (name collision, reserved
33
+ * identifier, etc.). Throw at scan time to fail loud — silent shadowing is
34
+ * a security/correctness footgun.
35
+ */
36
+ declare class ActionScanError extends Error {
37
+ readonly code: 'NAME_COLLISION' | 'RESERVED_NAME';
38
+ readonly conflictingPaths: readonly string[];
39
+ constructor(code: 'NAME_COLLISION' | 'RESERVED_NAME', message: string, conflictingPaths: readonly string[]);
40
+ }
41
+ /**
42
+ * Backward-compatible: original simple-shape scanner used by existing
43
+ * consumers. Preserved verbatim; new consumers should call
44
+ * `scanServerActionsEnriched`.
45
+ */
46
+ declare function scanServerActions(serverDir: string): ActionNode[];
47
+ /**
48
+ * Enriched scan: light AST detection of `accept: 'form'|'json'` + `input:`
49
+ * presence via regex-after-comment-stripping (EC-9). Throws ActionScanError
50
+ * on file/dir name collision (EC-2) or reserved JS identifier names.
51
+ *
52
+ * Output `ActionManifestEntry[]` is sorted by `name` for deterministic
53
+ * `.theokit/actions-manifest.json` emission.
54
+ */
55
+ declare function scanServerActionsEnriched(serverDir: string): ActionManifestEntry[];
56
+
57
+ /**
58
+ * A discovered agent file. `name` is the client-facing key; `agentPath` is the mounted
59
+ * SSE route (M0/M1 `UIMessageStream`).
60
+ */
61
+ interface AgentNode {
62
+ filePath: string;
63
+ agentPath: string;
64
+ name: string;
65
+ }
66
+
67
+ declare function scanServerRoutes(serverDir: string): ServerRouteNode[];
68
+
69
+ interface WebSocketRouteNode {
70
+ filePath: string;
71
+ wsPath: string;
72
+ }
73
+ declare function scanWebSocketRoutes(serverDir: string): WebSocketRouteNode[];
74
+
75
+ interface ManifestRoute {
76
+ filePath: string;
77
+ routePath: string;
78
+ paramNames: string[];
79
+ /** HTTP methods (uppercase) the route file exports. Optional — manifests
80
+ * generated before G1 omit this; loaders treat absence as "unknown". */
81
+ methods?: string[];
82
+ }
83
+ interface ManifestAction {
84
+ filePath: string;
85
+ actionPath: string;
86
+ }
87
+ interface ManifestWebSocket {
88
+ filePath: string;
89
+ wsPath: string;
90
+ }
91
+ /** M2 — a top-level `agents/*.ts` convention entry. `filePath` is relative to the
92
+ * project root (agents live OUTSIDE `serverDir`), unlike routes/actions/ws. */
93
+ interface ManifestAgent {
94
+ filePath: string;
95
+ agentPath: string;
96
+ name: string;
97
+ }
98
+ interface TheoManifest {
99
+ version: 1;
100
+ generatedAt: string;
101
+ routes: ManifestRoute[];
102
+ actions: ManifestAction[];
103
+ websockets: ManifestWebSocket[];
104
+ /** M2 — optional for backward compat: manifests generated before M2 omit it. */
105
+ agents?: ManifestAgent[];
106
+ }
107
+ interface LoadedManifest {
108
+ routes: ServerRouteNode[];
109
+ actions: ActionNode[];
110
+ websockets: WebSocketRouteNode[];
111
+ agents: AgentNode[];
112
+ }
113
+ declare function generateManifest(serverDir: string, projectRoot?: string): TheoManifest;
114
+ declare function writeManifest(manifest: TheoManifest, outputDir: string): void;
115
+ declare function loadManifest(distDir: string, serverDir: string): LoadedManifest;
116
+
117
+ /**
118
+ * Scan the server/middleware/ directory for middleware files.
119
+ * Files are returned sorted alphabetically — use numeric prefixes
120
+ * (e.g. 01-cors.ts, 02-auth.ts) to control execution order.
121
+ *
122
+ * Files starting with '_' or '.' are ignored (helpers, hidden files).
123
+ */
124
+ declare function scanMiddlewares(serverDir: string): string[];
125
+
126
+ export { type ActionManifestEntry, type ActionNode, ActionScanError, type LoadedManifest, type ManifestAction, type ManifestAgent, type ManifestRoute, type ManifestWebSocket, ServerRouteNode, type TheoManifest, type WebSocketRouteNode, generateManifest, loadManifest, scanMiddlewares, scanServerActions, scanServerActionsEnriched, scanServerRoutes, scanWebSocketRoutes, writeManifest };
@@ -14,7 +14,7 @@ import {
14
14
  scanServerRoutes,
15
15
  scanWebSocketRoutes,
16
16
  writeManifest
17
- } from "../../chunk-223EFY5X.js";
17
+ } from "../../chunk-2J7XU3PW.js";
18
18
  import "../../chunk-WSJKACWB.js";
19
19
  import {
20
20
  scanMiddlewares
@@ -0,0 +1,193 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { A as AuditLogger } from '../../audit-log-BQWM5YLG.js';
3
+ export { C as CSRF_WARN_CODE, a as CSRF_WARN_DOCS_URL, b as CsrfLogger, c as CsrfMode, d as CsrfWarnPayload, D as DisallowedConfig, e as enforceCsrf, m as matchDisallowed, v as validateCsrf, f as validateCsrfRequest } from '../../csrf-BBrEZSBW.js';
4
+ import { C as CsrfReadinessStore } from '../../csrf-readiness-store-CjIoub3U.js';
5
+ export { a as CsrfReadinessRouteSummary, b as CsrfReadinessSummary, c as CsrfWarnRecord } from '../../csrf-readiness-store-CjIoub3U.js';
6
+
7
+ /**
8
+ * T5.1 — Built-in CSP report endpoint.
9
+ *
10
+ * Browsers POST violation reports to `report-uri` (legacy `application/csp-report`)
11
+ * or `Reporting API` (`application/reports+json`). Framework auto-registers this
12
+ * endpoint so `cspMode: 'report-only'` is actually useful out of the box.
13
+ *
14
+ * Forwards normalized violations to:
15
+ * - audit logger (`csp.violation`)
16
+ * - devtools dispatcher (dev only, for Errors tab)
17
+ * - optional user hook (Sentry, etc.)
18
+ *
19
+ * EC-2: browser MAY send `{"csp-report": null}`, empty `{}`, or
20
+ * reports+json entries lacking `body`. Handler MUST short-circuit to
21
+ * 204 (valid format, no violation), NEVER crash via null deref.
22
+ */
23
+ declare const CSP_REPORT_PATH = "/__theo/csp-report";
24
+ interface CspViolation {
25
+ blockedUrl: string;
26
+ documentUrl: string;
27
+ violatedDirective: string;
28
+ effectiveDirective?: string;
29
+ originalPolicy?: string;
30
+ disposition?: 'enforce' | 'report';
31
+ statusCode?: number;
32
+ sourceFile?: string;
33
+ lineNumber?: number;
34
+ columnNumber?: number;
35
+ }
36
+ interface CspReportHandlerOptions {
37
+ auditLogger?: AuditLogger;
38
+ devtoolsDispatcher?: {
39
+ onCspViolation?: (v: CspViolation) => void;
40
+ };
41
+ /** Optional user-provided sink (Sentry, custom log router). Errors here are swallowed. */
42
+ onViolation?: (v: CspViolation) => void;
43
+ }
44
+ declare function normalizeLegacy(raw: Record<string, unknown>): CspViolation;
45
+ /**
46
+ * Map a `reports+json` entry to the internal shape. Returns `null` if
47
+ * the entry lacks a usable `body` object (EC-2).
48
+ */
49
+ declare function normalizeNew(entry: unknown): CspViolation | null;
50
+ declare function handleCspReport(req: IncomingMessage, res: ServerResponse, opts: CspReportHandlerOptions): Promise<void>;
51
+ declare function handleCspReportRequest(request: Request, opts: CspReportHandlerOptions): Promise<Response>;
52
+
53
+ /**
54
+ * T2.2 — `/__theo/csrf-readiness` endpoint.
55
+ *
56
+ * GET /__theo/csrf-readiness → 200 + JSON summary
57
+ * POST /__theo/csrf-readiness/reset → 204; clears the store
58
+ *
59
+ * The reset endpoint enforces CSRF (own dog food) — requires
60
+ * `X-Theo-Action: 1` AND a matching Origin header (EC-15). This avoids
61
+ * the endpoint being weaponizable from a cross-origin page when the
62
+ * endpoint is opt-in exposed in production.
63
+ *
64
+ * Mount opt-in: in dev mode, the host wires this in unconditionally. In
65
+ * production, only mount when `config.security.csrfTelemetry.exposeReadinessEndpoint === true`.
66
+ * EC-10 parallel: returns 404 (via boolean false return) when the URL
67
+ * does not match — the caller continues normal request handling.
68
+ */
69
+
70
+ declare const CSRF_READINESS_PATH = "/__theo/csrf-readiness";
71
+ declare const CSRF_READINESS_RESET_PATH = "/__theo/csrf-readiness/reset";
72
+ declare function handleCsrfReadiness(req: IncomingMessage, res: ServerResponse, store: CsrfReadinessStore): Promise<boolean>;
73
+ declare function handleCsrfReadinessRequest(request: Request, store: CsrfReadinessStore): Promise<Response | null>;
74
+
75
+ /**
76
+ * Phase 6 — Default Security Headers (D4 / EC-2).
77
+ *
78
+ * Per-response security baseline. The framework applies these BEFORE the
79
+ * route handler runs so a handler can still override via `res.setHeader`.
80
+ *
81
+ * EC-2 backward-compatibility: CSP ships in `report-only` mode by default
82
+ * for 0.2.0. Existing apps with inline scripts or third-party CDN scripts
83
+ * keep working but consumers see violation reports via their CSP report
84
+ * collector (or browser DevTools). 0.3.0 will flip the default to
85
+ * `enforce` after a release of visibility.
86
+ */
87
+ /**
88
+ * Default Content-Security-Policy. Conservative-but-not-paralyzing:
89
+ *
90
+ * - default-src 'self' — every fetch falls back to same-origin
91
+ * - script-src 'self' — T6.1 (0.3.0): `'unsafe-inline'`
92
+ * dropped. The SSR pipeline issues a
93
+ * per-request nonce that REPLACES
94
+ * this directive at runtime
95
+ * (`'nonce-<token>'`). For static /
96
+ * non-SSR contexts where no nonce is
97
+ * available, the policy is strict-
98
+ * no-inline — user inline scripts
99
+ * must be migrated to external
100
+ * `<script src="...">` or threaded
101
+ * through `ctx.nonce`.
102
+ * - style-src 'self' 'unsafe-inline' — Tailwind + TheoUI use style attrs
103
+ * in animation directives
104
+ * - img-src 'self' data: blob: — supports inline data URIs, blobs
105
+ * from canvas exports
106
+ * - font-src 'self' data: — Geist fonts inline-base64
107
+ * - connect-src 'self' ws: wss: — WebSocket dev HMR + agent streams
108
+ * - frame-ancestors 'none' — clickjacking defense
109
+ */
110
+ /**
111
+ * T5.1 — default CSP includes the built-in report endpoint so violations
112
+ * are visible without extra config. Apps that ship a custom `csp` string
113
+ * override the report-uri.
114
+ */
115
+ declare const DEFAULT_CSP: string;
116
+ /**
117
+ * T1.1 — Default Permissions-Policy header (default-deny stance).
118
+ *
119
+ * Disables sensitive Web APIs that the vast majority of apps don't use.
120
+ * Apps that DO need any of these opt in by overriding `permissionsPolicy`
121
+ * in `config.security.headers`.
122
+ *
123
+ * The seven features listed are the most-abused for: tracking
124
+ * (geolocation, accelerometer, gyroscope), spyware (camera, microphone),
125
+ * fraud (payment), and hardware exfiltration (usb).
126
+ *
127
+ * Aligns with Mozilla baseline + OWASP Secure Headers + Lighthouse PWA.
128
+ */
129
+ declare const DEFAULT_PERMISSIONS_POLICY = "geolocation=(), camera=(), microphone=(), payment=(), usb=(), accelerometer=(), gyroscope=()";
130
+ type CspMode = 'enforce' | 'report-only' | 'off';
131
+ interface SecurityHeadersConfig {
132
+ /**
133
+ * Custom CSP policy string. When set, replaces the default verbatim.
134
+ * Pass `false` to disable CSP entirely (alias for `cspMode: 'off'`).
135
+ */
136
+ csp?: string | false;
137
+ /**
138
+ * Enforcement mode for CSP. Default `report-only` for 0.2.0 (EC-2).
139
+ * 0.3.0 will default to `enforce`.
140
+ */
141
+ cspMode?: CspMode;
142
+ /**
143
+ * Strict-Transport-Security value. Defaults to
144
+ * `max-age=31536000; includeSubDomains` in production. Pass `false` to
145
+ * suppress (e.g. internal LANs without TLS).
146
+ */
147
+ hsts?: string | false;
148
+ /** X-Frame-Options. Default DENY. */
149
+ frameOptions?: 'DENY' | 'SAMEORIGIN';
150
+ /** X-Content-Type-Options. Default `nosniff`. */
151
+ contentTypeOptions?: 'nosniff';
152
+ /** Referrer-Policy. Default `strict-origin-when-cross-origin`. */
153
+ referrerPolicy?: string;
154
+ /**
155
+ * T1.1 — Permissions-Policy directive string. When set, replaces the
156
+ * default verbatim (no merge — see ADR-EC-12). Pass `false` to disable
157
+ * the header entirely. Schema-level refinement rejects any string
158
+ * containing CR/LF (EC-3 — CWE-113 HTTP Response Splitting mitigation).
159
+ */
160
+ permissionsPolicy?: string | false;
161
+ }
162
+ interface SecurityEnv {
163
+ production: boolean;
164
+ }
165
+ /**
166
+ * T4.1 — Per-request options passed by the SSR pipeline.
167
+ *
168
+ * - `nonce`: when set, the framework substitutes the `'unsafe-inline'`
169
+ * token in `script-src` with `'nonce-<nonce>'`. EC-3 forces
170
+ * `Cache-Control: private, no-store` so a CDN cannot cache the HTML
171
+ * (carrying one nonce) and re-serve it with a freshly-generated CSP
172
+ * header (carrying a different nonce).
173
+ * - `prerender`: when true, the nonce is IGNORED. Prerendered HTML is
174
+ * generated at build time with no nonce in the script tags; mixing a
175
+ * runtime nonce in the header would block every script. EC-4.
176
+ */
177
+ interface SecurityHeadersOptions {
178
+ nonce?: string;
179
+ prerender?: boolean;
180
+ }
181
+ /**
182
+ * Build the security headers map for a given config + env. Pure function —
183
+ * returned object can be inspected, logged, or applied to a response.
184
+ */
185
+ declare function buildSecurityHeaders(config: SecurityHeadersConfig, env: SecurityEnv, options?: SecurityHeadersOptions): Record<string, string>;
186
+ /**
187
+ * Apply security headers to a Node ServerResponse. Called by the
188
+ * api-middleware before the route handler runs. The handler can override
189
+ * any header via `res.setHeader()` — last write wins by Node convention.
190
+ */
191
+ declare function applySecurityHeaders(res: ServerResponse, config: SecurityHeadersConfig, env: SecurityEnv, options?: SecurityHeadersOptions): void;
192
+
193
+ export { CSP_REPORT_PATH, CSRF_READINESS_PATH, CSRF_READINESS_RESET_PATH, type CspMode, type CspReportHandlerOptions, type CspViolation, CsrfReadinessStore, DEFAULT_CSP, DEFAULT_PERMISSIONS_POLICY, type SecurityEnv, type SecurityHeadersConfig, type SecurityHeadersOptions, applySecurityHeaders, buildSecurityHeaders, handleCspReport, handleCspReportRequest, handleCsrfReadiness, handleCsrfReadinessRequest, normalizeLegacy, normalizeNew };
@@ -0,0 +1,22 @@
1
+ export { P as PostgresFactory, R as RedisFactory, S as StorageManager, g as getStorageManager } from '../../storage-manager-C4jsO0Tp.js';
2
+ export { G as GenericFactory, a as PoolLike, P as PostgresDatabaseConfig, c as RedisLike, R as RedisServerConfig, S as ServerConfig, d as StorageAdapter, b as StorageConfig, T as TlsConfig } from '../../storage-types-DsDTCPbp.js';
3
+
4
+ interface UnstorageInstance<T> {
5
+ getItem(key: string): Promise<T | null>;
6
+ setItem(key: string, value: T): Promise<void>;
7
+ removeItem(key: string): Promise<void>;
8
+ keys(prefix?: string): Promise<string[]>;
9
+ hasItem(key: string): Promise<boolean>;
10
+ clear(prefix?: string): Promise<void>;
11
+ dispose?(): Promise<void>;
12
+ }
13
+ declare function useUnstorage<T = unknown>(name: string, driver?: unknown): Promise<UnstorageInstance<T>>;
14
+
15
+ interface Db0Database {
16
+ exec: (sql: string) => Promise<unknown>;
17
+ prepare: (sql: string) => unknown;
18
+ sql: (strings: TemplateStringsArray, ...args: unknown[]) => Promise<unknown>;
19
+ }
20
+ declare function useDatabase(name: string, connector: unknown): Promise<Db0Database>;
21
+
22
+ export { type Db0Database, type UnstorageInstance, useDatabase, useUnstorage };
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Constant-time byte comparison.
3
+ *
4
+ * Wraps `node:crypto.timingSafeEqual` when available (Node 6.6+) and falls
5
+ * back to a constant-time XOR loop for runtimes without `node:crypto`
6
+ * (Cloudflare Workers, Deno, Bun edge). Required to defeat timing attacks
7
+ * on webhook signature verification — a naive `===` or `Buffer.equals`
8
+ * would short-circuit on first mismatch byte and leak signature position
9
+ * via wall-clock timing.
10
+ *
11
+ * Web Crypto's `crypto.subtle.verify` would also work, but requires a
12
+ * `CryptoKey` object and is asymmetric (verify a signature against a key).
13
+ * For our case — comparing two pre-computed digests — raw byte equality
14
+ * is the correct primitive.
15
+ *
16
+ * @see https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b
17
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify
18
+ */
19
+ /**
20
+ * Returns true iff `a` and `b` have identical bytes. Takes time
21
+ * proportional to `a.length` regardless of where bytes differ.
22
+ *
23
+ * @throws TypeError if either argument is not a Uint8Array.
24
+ */
25
+ declare function timingSafeEqual(a: Uint8Array, b: Uint8Array): boolean;
26
+
27
+ /**
28
+ * Read a Web `Request` body as a raw string EXACTLY ONCE and expose it
29
+ * alongside the original request (which remains readable by downstream
30
+ * code). Enforces a configurable `maxBodyBytes` cap to prevent OOM via
31
+ * pathological POST.
32
+ *
33
+ * MUST be called FIRST in the webhook pipeline, before any other code
34
+ * touches the body (`request.text()`, `request.json()`, parsers). Once
35
+ * the body is consumed, `Request.clone()` throws and this function fails.
36
+ *
37
+ * EC-101: default `maxBodyBytes = 1_000_000` (1 MB) covers Stripe
38
+ * (256 KB max), Slack (4 MB but compressed), and is well below Node
39
+ * memory thresholds. GitHub webhooks up to 25 MB MUST opt in
40
+ * (`maxBodyBytes: 25_000_000`).
41
+ *
42
+ * @see https://docs.stripe.com/webhooks/signatures
43
+ * @see https://docs.github.com/en/webhooks/using-webhooks/best-practices-for-using-webhooks
44
+ */
45
+ declare const DEFAULT_MAX_BODY_BYTES = 1000000;
46
+ interface ReadRawBodyOptions {
47
+ /** Maximum bytes to read before throwing `BodyTooLargeError`. Defaults to 1 MB. */
48
+ maxBodyBytes?: number;
49
+ }
50
+ interface RawBodyResult {
51
+ /** UTF-8 decoded body (or empty string when no body present). */
52
+ rawBody: string;
53
+ /** The ORIGINAL request, still readable by downstream code. */
54
+ bodyClone: Request;
55
+ }
56
+ /**
57
+ * Thrown when the request body exceeds `maxBodyBytes`. Carries status
58
+ * 413 (Payload Too Large) and stable code `BODY_TOO_LARGE` so callers
59
+ * can map it to an HTTP response without sniffing the message.
60
+ */
61
+ declare class BodyTooLargeError extends Error {
62
+ readonly limit: number;
63
+ readonly actualSeen: number;
64
+ readonly status = 413;
65
+ readonly code = "BODY_TOO_LARGE";
66
+ constructor(limit: number, actualSeen: number);
67
+ }
68
+ declare function readRawBody(request: Request, options?: ReadRawBodyOptions): Promise<RawBodyResult>;
69
+
70
+ /**
71
+ * Webhook primitive types (R0.5.10).
72
+ *
73
+ * @see docs/adr/0005-webhook-verify-inline-function.md
74
+ */
75
+ type VerifyResult = {
76
+ ok: true;
77
+ } | {
78
+ ok: false;
79
+ reason: string;
80
+ };
81
+ /**
82
+ * A verify function — pure, async-or-sync. Takes the cloned request
83
+ * (raw body NOT yet consumed by handler), returns ok/notOk + reason.
84
+ *
85
+ * Per ADR-0005, helper factories (`stripe`, `github`, `slack`) return
86
+ * this shape. Users can also write inline `verify: async (req) => ...`
87
+ * for custom providers.
88
+ */
89
+ type VerifyFn = (req: Request) => Promise<VerifyResult> | VerifyResult;
90
+ interface WebhookContext {
91
+ /** The cloned Request (still readable by user code). */
92
+ readonly request: Request;
93
+ /** Raw body bytes as UTF-8 string — already-verified at this point. */
94
+ readonly rawBody: string;
95
+ /** W3C trace_id propagated from request. */
96
+ readonly traceId: string;
97
+ /** Abort signal triggered by client disconnect or server stop. */
98
+ readonly signal: AbortSignal;
99
+ }
100
+ interface DefineWebhookOptions {
101
+ verify: VerifyFn;
102
+ handler: (ctx: WebhookContext) => unknown;
103
+ /** Override `readRawBody` body size cap (EC-101). Default 1MB. */
104
+ maxBodyBytes?: number;
105
+ }
106
+ interface WebhookDefinition {
107
+ readonly verify: VerifyFn;
108
+ readonly handler: (ctx: WebhookContext) => unknown;
109
+ readonly maxBodyBytes?: number;
110
+ /** Discriminator for runtime dispatch. */
111
+ readonly __theokit_kind: 'webhook';
112
+ }
113
+
114
+ /**
115
+ * Declare a webhook handler with first-class signature verification
116
+ * (R0.5.10, ADR-0005). Pure identity helper — returns the definition
117
+ * unchanged for downstream dispatch.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * // server/webhooks/stripe.ts
122
+ * import { defineWebhook } from 'theokit/server'
123
+ * import { stripe } from 'theokit/server/webhook/providers'
124
+ *
125
+ * export default defineWebhook({
126
+ * verify: stripe({ secret: process.env.STRIPE_WEBHOOK_SECRET! }),
127
+ * async handler({ rawBody }) {
128
+ * const event = JSON.parse(rawBody)
129
+ * // ...
130
+ * return new Response('ok')
131
+ * },
132
+ * })
133
+ * ```
134
+ */
135
+ declare function defineWebhook(opts: DefineWebhookOptions): WebhookDefinition;
136
+ /**
137
+ * Dispatch a webhook request through the definition's verify → handler
138
+ * pipeline. Returns the handler's `Response` (or a wrapped one), or a
139
+ * 401/413 response when verification or body size guards trip.
140
+ *
141
+ * EC-101: enforces `maxBodyBytes` (default 1MB via readRawBody).
142
+ * EC-103: every throw from `verify` (sync or async) is treated as
143
+ * `{ok: false, reason: 'verify threw: <message>'}`. Handler NEVER
144
+ * invoked on verify failure.
145
+ */
146
+ declare function dispatchWebhook(def: WebhookDefinition, request: Request): Promise<Response>;
147
+
148
+ export { BodyTooLargeError, DEFAULT_MAX_BODY_BYTES, type DefineWebhookOptions, type RawBodyResult, type ReadRawBodyOptions, type VerifyFn, type VerifyResult, type WebhookContext, type WebhookDefinition, defineWebhook, dispatchWebhook, readRawBody, timingSafeEqual };