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.
- package/dist/{actions-virtual-module-SQDY3V5X.js → actions-virtual-module-3CDQTWOC.js} +6 -6
- package/dist/{actions-virtual-module-PNPRCEOS.js → actions-virtual-module-EIPXX4ZB.js} +3 -3
- package/dist/adapters/web-shim.d.ts +67 -0
- package/dist/adapters/ws-shim.d.ts +55 -0
- package/dist/agent-events-DosDXkSV.d.ts +94 -0
- package/dist/agents-typed-client-SAWAAH7K.js +142 -0
- package/dist/agents-typed-client-SAWAAH7K.js.map +1 -0
- package/dist/agents-typed-client-UTEQUA63.js +143 -0
- package/dist/agents-typed-client-UTEQUA63.js.map +1 -0
- package/dist/{app-typed-client-5GYEOYP3.js → app-typed-client-7PBFWZUE.js} +3 -3
- package/dist/{app-typed-client-QG7BVZYW.js → app-typed-client-CSOK7NPC.js} +6 -6
- package/dist/audit-log-BQWM5YLG.d.ts +60 -0
- package/dist/body-parser-web-FV5HWCY3.js +71 -0
- package/dist/body-parser-web-FV5HWCY3.js.map +1 -0
- package/dist/boot/index.d.ts +39 -0
- package/dist/{build-QFRLSEZ4.js → build-HXND27XG.js} +11 -11
- package/dist/{chunk-223EFY5X.js → chunk-2J7XU3PW.js} +68 -27
- package/dist/chunk-2J7XU3PW.js.map +1 -0
- package/dist/{chunk-RESN62GB.js → chunk-2KZQPDYR.js} +5 -48
- package/dist/chunk-2KZQPDYR.js.map +1 -0
- package/dist/chunk-3S3BNW5K.js +445 -0
- package/dist/chunk-3S3BNW5K.js.map +1 -0
- package/dist/{chunk-6FYD34NX.js → chunk-BQDGES7C.js} +28 -28
- package/dist/{chunk-6FYD34NX.js.map → chunk-BQDGES7C.js.map} +1 -1
- package/dist/chunk-EXP56GFQ.js +52 -0
- package/dist/chunk-EXP56GFQ.js.map +1 -0
- package/dist/chunk-F4YUPDJ2.js +115 -0
- package/dist/chunk-F4YUPDJ2.js.map +1 -0
- package/dist/{chunk-NAZ4E2GT.js → chunk-KXA37ONC.js} +2 -2
- package/dist/chunk-NHJMZCAS.js +32 -0
- package/dist/chunk-NHJMZCAS.js.map +1 -0
- package/dist/{chunk-43D6XNDR.js → chunk-O62MW4MT.js} +91 -18
- package/dist/chunk-O62MW4MT.js.map +1 -0
- package/dist/chunk-RSVN727G.js +1 -0
- package/dist/{chunk-7CBRKNQA.js → chunk-RYTZYFSD.js} +198 -6
- package/dist/chunk-RYTZYFSD.js.map +1 -0
- package/dist/chunk-UNLA45FY.js +235 -0
- package/dist/chunk-UNLA45FY.js.map +1 -0
- package/dist/{chunk-GFMQJHXX.js → chunk-WR4F4EEZ.js} +1082 -1074
- package/dist/chunk-WR4F4EEZ.js.map +1 -0
- package/dist/{chunk-AD74EAK3.js → chunk-ZSTZXR2D.js} +1 -30
- package/dist/chunk-ZSTZXR2D.js.map +1 -0
- package/dist/cli/index.js +5 -5
- package/dist/client/index.d.ts +418 -0
- package/dist/client/index.js +84 -3
- package/dist/client/index.js.map +1 -1
- package/dist/csrf-BBrEZSBW.d.ts +107 -0
- package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
- package/dist/define-websocket-CdK94O-D.d.ts +64 -0
- package/dist/{dev-GBXOTXUP.js → dev-OWW4XVIH.js} +10 -10
- package/dist/{dev-emit-FEFEDLZF.js → dev-emit-5MDSBP5D.js} +3 -3
- package/dist/{dev-emit-O4EGOSNV.js → dev-emit-QH2YGZXN.js} +2 -2
- package/dist/devtools/entry.d.ts +5 -0
- package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
- package/dist/health-route-C0hk64_U.d.ts +57 -0
- package/dist/index-B40qUSrQ.d.ts +575 -0
- package/dist/index.d.ts +361 -0
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/internal-api-4YTJDITC.js +83 -0
- package/dist/internal-api-EFKZWIYZ.js +66 -0
- package/dist/internal-api-EFKZWIYZ.js.map +1 -0
- package/dist/job-backend-CgC8Xf33.d.ts +68 -0
- package/dist/match-CfbEFRG4.d.ts +26 -0
- package/dist/{openapi-VR6AFBLJ.js → openapi-FHY6HC6I.js} +7 -7
- package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
- package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
- package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
- package/dist/rate-limit-store-BEJnhWdw.d.ts +72 -0
- package/dist/react-query/index.d.ts +33 -0
- package/dist/{registry-Q2TZQLUH.js → registry-34LL7NF4.js} +1 -1
- package/dist/{routes-LRYOIIAI.js → routes-EW7TP7NJ.js} +2 -2
- package/dist/schema-BpH6ivDY.d.ts +74 -0
- package/dist/server/agent/index.d.ts +229 -0
- package/dist/server/agent/index.js +2 -1
- package/dist/server/auth/index.d.ts +419 -0
- package/dist/server/cost/index.d.ts +177 -0
- package/dist/server/cron/index.d.ts +208 -0
- package/dist/server/define/index.d.ts +313 -0
- package/dist/server/define/index.js +4 -2
- package/dist/server/http/index.d.ts +11 -0
- package/dist/server/index.d.ts +848 -0
- package/dist/server/index.js +9 -294
- package/dist/server/index.js.map +1 -1
- package/dist/server/jobs/index.d.ts +348 -0
- package/dist/server/observability/index.d.ts +324 -0
- package/dist/server/plugins/index.d.ts +17 -0
- package/dist/server/rate-limit/index.d.ts +105 -0
- package/dist/server/realtime/index.d.ts +15 -0
- package/dist/server/scan/index.d.ts +126 -0
- package/dist/server/scan/index.js +1 -1
- package/dist/server/security/index.d.ts +193 -0
- package/dist/server/storage/index.d.ts +22 -0
- package/dist/server/webhook/index.d.ts +148 -0
- package/dist/{start-3ZHAXSJE.js → start-KIQ5TTLR.js} +76 -13
- package/dist/start-KIQ5TTLR.js.map +1 -0
- package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
- package/dist/storage-types-DsDTCPbp.d.ts +96 -0
- package/dist/vite-plugin/index.d.ts +115 -0
- package/dist/vite-plugin/index.js +6 -4
- package/dist/{vite-plugin-WO72VLYR.js → vite-plugin-RK66K26Z.js} +7 -7
- package/dist/vite-plugin-RK66K26Z.js.map +1 -0
- package/package.json +4 -4
- package/dist/chunk-223EFY5X.js.map +0 -1
- package/dist/chunk-3LVRAGAZ.js +0 -73
- package/dist/chunk-3LVRAGAZ.js.map +0 -1
- package/dist/chunk-43D6XNDR.js.map +0 -1
- package/dist/chunk-7CBRKNQA.js.map +0 -1
- package/dist/chunk-AD74EAK3.js.map +0 -1
- package/dist/chunk-GFMQJHXX.js.map +0 -1
- package/dist/chunk-PBEH6NXR.js +0 -44
- package/dist/chunk-PBEH6NXR.js.map +0 -1
- package/dist/chunk-PIVX3DYW.js +0 -142
- package/dist/chunk-PIVX3DYW.js.map +0 -1
- package/dist/chunk-PPPR5DGR.js +0 -1
- package/dist/chunk-RESN62GB.js.map +0 -1
- package/dist/start-3ZHAXSJE.js.map +0 -1
- /package/dist/{actions-virtual-module-SQDY3V5X.js.map → actions-virtual-module-3CDQTWOC.js.map} +0 -0
- /package/dist/{actions-virtual-module-PNPRCEOS.js.map → actions-virtual-module-EIPXX4ZB.js.map} +0 -0
- /package/dist/{app-typed-client-5GYEOYP3.js.map → app-typed-client-7PBFWZUE.js.map} +0 -0
- /package/dist/{app-typed-client-QG7BVZYW.js.map → app-typed-client-CSOK7NPC.js.map} +0 -0
- /package/dist/{build-QFRLSEZ4.js.map → build-HXND27XG.js.map} +0 -0
- /package/dist/{chunk-NAZ4E2GT.js.map → chunk-KXA37ONC.js.map} +0 -0
- /package/dist/{chunk-PPPR5DGR.js.map → chunk-RSVN727G.js.map} +0 -0
- /package/dist/{dev-GBXOTXUP.js.map → dev-OWW4XVIH.js.map} +0 -0
- /package/dist/{dev-emit-FEFEDLZF.js.map → dev-emit-5MDSBP5D.js.map} +0 -0
- /package/dist/{dev-emit-O4EGOSNV.js.map → dev-emit-QH2YGZXN.js.map} +0 -0
- /package/dist/{vite-plugin-WO72VLYR.js.map → internal-api-4YTJDITC.js.map} +0 -0
- /package/dist/{openapi-VR6AFBLJ.js.map → openapi-FHY6HC6I.js.map} +0 -0
- /package/dist/{registry-Q2TZQLUH.js.map → registry-34LL7NF4.js.map} +0 -0
- /package/dist/{routes-LRYOIIAI.js.map → routes-EW7TP7NJ.js.map} +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { a as AgentErrorEvent, A as AgentEvent } from '../../agent-events-DosDXkSV.js';
|
|
2
|
+
export { b as AgentMessageEvent, f as AgentRunErrorCode, c as AgentThinkingEvent, d as AgentToolCallEvent, e as AgentToolResultEvent } from '../../agent-events-DosDXkSV.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Item #4 — `streamAgentRun`
|
|
6
|
+
*
|
|
7
|
+
* Adapter that consumes the `@theokit/sdk` `Run.stream()` async generator
|
|
8
|
+
* (SDKMessage variants) and yields TheoKit `AgentEvent`s suitable for SSE
|
|
9
|
+
* via `defineAgentEndpoint`. One line at the consumer side:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const run = await agent.send(message)
|
|
13
|
+
* yield* streamAgentRun(run)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Mapping table (SDK → AgentEvent):
|
|
17
|
+
*
|
|
18
|
+
* | SDK message | AgentEvent yielded |
|
|
19
|
+
* |---|---|
|
|
20
|
+
* | assistant.content[].type==='text' | { type: 'message', content } |
|
|
21
|
+
* | assistant.content[].type==='tool_use'| (none — covered by tool_call below) |
|
|
22
|
+
* | tool_call(status='running') | { type: 'tool_call', name, args, id } |
|
|
23
|
+
* | tool_call(status='completed') | { type: 'tool_result', name, data, id }|
|
|
24
|
+
* | tool_call(status='error') | { type: 'error', message, id } |
|
|
25
|
+
* | run.wait() status==='error' | { type: 'error', message } |
|
|
26
|
+
* | run.wait() status==='cancelled' | (none — cancel ≠ error) |
|
|
27
|
+
* | system / user / thinking / status / | (none — internal SDK telemetry) |
|
|
28
|
+
* | task / request / object_delta | |
|
|
29
|
+
*
|
|
30
|
+
* Abort semantics: when the consumer calls `generator.return()` on the
|
|
31
|
+
* outer `defineAgentEndpoint` generator, `streamAgentRun` exits the
|
|
32
|
+
* `for await` loop and does NOT call `run.wait()`. Cleanup of in-flight
|
|
33
|
+
* SDK resources is the SDK consumer's responsibility (`run.cancel()`).
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* Local mirror of the SDK's `Run` interface — only the surfaces we consume.
|
|
37
|
+
* The message contract is minimal (just `{ type: string }`) so the SDK's
|
|
38
|
+
* `SDKMessage` discriminated union IS structurally assignable without any
|
|
39
|
+
* cast at the consumer site (covariant — TS accepts the SDK's typed message
|
|
40
|
+
* as the wider `{ type: string }`). Property access inside `streamAgentRun`
|
|
41
|
+
* narrows via runtime type guards.
|
|
42
|
+
*
|
|
43
|
+
* `import type` from `@theokit/sdk` would couple TheoKit to the SDK at type-
|
|
44
|
+
* resolution time even for consumers who never use the agent surface.
|
|
45
|
+
*/
|
|
46
|
+
interface AgentRunLike {
|
|
47
|
+
stream: () => AsyncIterable<{
|
|
48
|
+
type: string;
|
|
49
|
+
}>;
|
|
50
|
+
wait: () => Promise<AgentRunResult>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Re-exported as a convenience for test fixtures. Production code typically
|
|
54
|
+
* passes an SDK `Run` directly (structural match via `{ type: string }`).
|
|
55
|
+
*/
|
|
56
|
+
type AgentRunStreamMessage = {
|
|
57
|
+
type: 'assistant';
|
|
58
|
+
message: {
|
|
59
|
+
role: 'assistant';
|
|
60
|
+
content: {
|
|
61
|
+
type: string;
|
|
62
|
+
text?: string;
|
|
63
|
+
}[];
|
|
64
|
+
};
|
|
65
|
+
} | {
|
|
66
|
+
type: 'tool_call';
|
|
67
|
+
name: string;
|
|
68
|
+
status: 'running' | 'completed' | 'error';
|
|
69
|
+
args?: unknown;
|
|
70
|
+
result?: unknown;
|
|
71
|
+
call_id: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: string;
|
|
74
|
+
[k: string]: unknown;
|
|
75
|
+
};
|
|
76
|
+
/** Subset of the SDK `RunResult` we consume. */
|
|
77
|
+
interface AgentRunResult {
|
|
78
|
+
status: 'finished' | 'error' | 'cancelled';
|
|
79
|
+
error?: {
|
|
80
|
+
message: string;
|
|
81
|
+
code?: string;
|
|
82
|
+
cause?: unknown;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Map an SDK error to the AgentErrorEvent shape. Pure function — easy to test.
|
|
87
|
+
*
|
|
88
|
+
* Backward compat (D4): non-AgentRunError throws yield only `message` field
|
|
89
|
+
* (legacy shape); discriminated fields stay `undefined`.
|
|
90
|
+
*
|
|
91
|
+
* Return type is the specific `AgentErrorEvent` (not the union) for ergonomic
|
|
92
|
+
* call-site access — `errorToEvent(err).code` works without narrowing.
|
|
93
|
+
*/
|
|
94
|
+
declare function errorToEvent(err: unknown, id?: string): AgentErrorEvent;
|
|
95
|
+
declare function streamAgentRun(run: AgentRunLike): AsyncGenerator<AgentEvent, void, unknown>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Item #5 — `createConversationHistory`
|
|
99
|
+
*
|
|
100
|
+
* Orchestrator that resolves a stable `agentId` from (explicit → session →
|
|
101
|
+
* cookie → fresh UUID), then returns an `@theokit/sdk` `Agent` via
|
|
102
|
+
* `Agent.getOrCreate(agentId, options)`. Conversation turns auto-persist in
|
|
103
|
+
* `<cwd>/.theokit/agents/<agentId>/messages.jsonl` — SDK owns the storage
|
|
104
|
+
* (ADR D1). `MemorySettings` (facts recall layer) is opt-in passthrough via
|
|
105
|
+
* `options.memory` (ADR D2).
|
|
106
|
+
*
|
|
107
|
+
* Security: agentId from cookie/explicit is attacker-controlled. The SDK
|
|
108
|
+
* uses it as a filesystem path component AND we serialize it into Set-Cookie.
|
|
109
|
+
* EC-1 enforces a strict regex `^[a-zA-Z0-9_-]{1,128}$` at every entry point;
|
|
110
|
+
* invalid values fall through (treated as "missing") rather than throw.
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* Minimum surface of an SDK Agent that consumers care about post-creation.
|
|
114
|
+
* Structural match — any object with `send` + `dispose` of compatible
|
|
115
|
+
* shape works. `send` returns a `SdkRunLike` (a Run-shaped object) that
|
|
116
|
+
* `streamAgentRun` can consume. Permissive `unknown` for now; consumers
|
|
117
|
+
* who want stricter types can cast to the SDK's own types.
|
|
118
|
+
*
|
|
119
|
+
* **T5.2 (architecture-cleanup) — DP-7 decision: KEEP (Opt B).** The 5 duck-typed
|
|
120
|
+
* mirrors below were flagged as "over-engineered" by the 2026-05-27 architecture
|
|
121
|
+
* review. Decision: KEEP them because `@theokit/sdk` is `devDependency` (not
|
|
122
|
+
* required at runtime for consumers that don't use agent features). Removing
|
|
123
|
+
* the mirrors would force a hard runtime dep on the SDK, breaking consumers
|
|
124
|
+
* who build TheoKit apps without the agent layer.
|
|
125
|
+
*
|
|
126
|
+
* @kept Defensive duck-type. Do NOT replace with direct SDK type imports unless
|
|
127
|
+
* `@theokit/sdk` is promoted from devDependency to dependency. If promoting,
|
|
128
|
+
* ALSO drop the mirrors (Opt A from the architecture-cleanup plan T5.2).
|
|
129
|
+
*/
|
|
130
|
+
interface SdkRunLike {
|
|
131
|
+
stream: () => AsyncIterable<{
|
|
132
|
+
type: string;
|
|
133
|
+
}>;
|
|
134
|
+
wait: () => Promise<{
|
|
135
|
+
status: 'finished' | 'error' | 'cancelled';
|
|
136
|
+
error?: {
|
|
137
|
+
message: string;
|
|
138
|
+
};
|
|
139
|
+
}>;
|
|
140
|
+
}
|
|
141
|
+
interface SdkAgent {
|
|
142
|
+
send: (message: string, options?: unknown) => Promise<SdkRunLike>;
|
|
143
|
+
dispose: () => Promise<void>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Phase 2 — structural duck-type of `@theokit/sdk`'s `ConversationStorageAdapter`.
|
|
147
|
+
*
|
|
148
|
+
* D2 (decoupling): we mirror the SDK's shape locally rather than hard-import
|
|
149
|
+
* the SDK type. This lets consumers pass any object matching the structural
|
|
150
|
+
* contract (own implementation, SDK's `FileSystemConversationStorage`,
|
|
151
|
+
* `InMemoryConversationStorage`, or a Postgres/Redis recipe).
|
|
152
|
+
*
|
|
153
|
+
* EC-5 (SHOULD TEST — sync drift detection): the SDK type MUST be assignable
|
|
154
|
+
* to this interface AND vice-versa. A contract test asserts both directions.
|
|
155
|
+
*
|
|
156
|
+
* `unknown` for the message payload avoids coupling to the SDK's `SDKMessage`
|
|
157
|
+
* shape. Real consumers cast at the call site if they need stricter types.
|
|
158
|
+
*/
|
|
159
|
+
interface ConversationStorageLike {
|
|
160
|
+
getMessages(conversationId: string): Promise<readonly unknown[]>;
|
|
161
|
+
appendMessage(conversationId: string, message: unknown): Promise<void>;
|
|
162
|
+
deleteConversation(conversationId: string): Promise<void>;
|
|
163
|
+
listConversationIds?(opts?: {
|
|
164
|
+
limit?: number;
|
|
165
|
+
}): Promise<readonly string[] | undefined>;
|
|
166
|
+
dispose?(): Promise<void>;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Minimum surface of `AgentOptions` accepted by `Agent.getOrCreate`. Forward-
|
|
170
|
+
* compatible: callers pass whatever the SDK supports (memory, tools, etc.).
|
|
171
|
+
*
|
|
172
|
+
* Phase 2 adds typed `conversationStorage` slot. The index signature still
|
|
173
|
+
* passes everything else opaquely.
|
|
174
|
+
*/
|
|
175
|
+
interface SdkAgentOptions {
|
|
176
|
+
apiKey?: string;
|
|
177
|
+
model?: {
|
|
178
|
+
id: string;
|
|
179
|
+
};
|
|
180
|
+
tools?: readonly unknown[];
|
|
181
|
+
memory?: Record<string, unknown>;
|
|
182
|
+
/**
|
|
183
|
+
* Phase 2 (Production-Readiness #1) — pluggable conversation persistence.
|
|
184
|
+
* Default (when omitted): SDK falls back to `FileSystemConversationStorage`.
|
|
185
|
+
* Required for serverless / multi-host deploys.
|
|
186
|
+
*/
|
|
187
|
+
conversationStorage?: ConversationStorageLike;
|
|
188
|
+
[key: string]: unknown;
|
|
189
|
+
}
|
|
190
|
+
interface ConversationHistoryArgs {
|
|
191
|
+
/** Request — for reading the conversation cookie. */
|
|
192
|
+
request: Request | {
|
|
193
|
+
headers?: {
|
|
194
|
+
cookie?: string;
|
|
195
|
+
} | Headers;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Response-like surface that accepts a `Set-Cookie` header. The primitive
|
|
199
|
+
* appends a Set-Cookie line when issuing a new conversation id. If absent,
|
|
200
|
+
* the primitive still reads the existing cookie but cannot issue a new
|
|
201
|
+
* one — useful for read-only contexts.
|
|
202
|
+
*/
|
|
203
|
+
response?: {
|
|
204
|
+
headers: Headers;
|
|
205
|
+
};
|
|
206
|
+
/** Explicit override — wins over session/cookie/uuid (ADR D3 step 1). */
|
|
207
|
+
agentId?: string;
|
|
208
|
+
/** Auth session containing a `conversationId` field — ADR D3 step 2. */
|
|
209
|
+
session?: {
|
|
210
|
+
conversationId?: string;
|
|
211
|
+
} | null;
|
|
212
|
+
/** SDK AgentOptions forwarded to Agent.getOrCreate. apiKey + model required. */
|
|
213
|
+
options: SdkAgentOptions;
|
|
214
|
+
/** Cookie name override. Default: 'theo_conversation'. */
|
|
215
|
+
cookieName?: string;
|
|
216
|
+
/** Cookie max-age in seconds. Default + min: 30 days. Non-positive coerced to default (EC-4). */
|
|
217
|
+
cookieMaxAge?: number;
|
|
218
|
+
}
|
|
219
|
+
interface ConversationHistoryResult {
|
|
220
|
+
/** The SDK Agent, ready to receive `agent.send(message)`. */
|
|
221
|
+
agent: SdkAgent;
|
|
222
|
+
/** The resolved conversation id (useful for logging / debugging). */
|
|
223
|
+
conversationId: string;
|
|
224
|
+
/** True when the id was newly generated (no prior cookie / session). */
|
|
225
|
+
isNew: boolean;
|
|
226
|
+
}
|
|
227
|
+
declare function createConversationHistory(args: ConversationHistoryArgs): Promise<ConversationHistoryResult>;
|
|
228
|
+
|
|
229
|
+
export { AgentErrorEvent, AgentEvent, type AgentRunLike, type AgentRunResult, type AgentRunStreamMessage, type ConversationHistoryArgs, type ConversationHistoryResult, type ConversationStorageLike, type SdkAgent, type SdkAgentOptions, type SdkRunLike, createConversationHistory, errorToEvent, streamAgentRun };
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { R as RateLimitStore } from '../../rate-limit-store-BEJnhWdw.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* T4.1 — Per-request CSP nonce generation.
|
|
6
|
+
*
|
|
7
|
+
* Returns a 22–24 character base64-encoded string carrying 16 bytes of
|
|
8
|
+
* cryptographic entropy. Used by the SSR pipeline to nonce the inline
|
|
9
|
+
* hydration data script so the default CSP can drop `'unsafe-inline'`
|
|
10
|
+
* from `script-src` in 0.3.0.
|
|
11
|
+
*
|
|
12
|
+
* Runtime portability: prefers Web Crypto (`globalThis.crypto`) because
|
|
13
|
+
* it is available on every target runtime (Node 19+, Bun, Deno, Vercel
|
|
14
|
+
* Edge, Cloudflare Workers). Falls back to `node:crypto` for older Node
|
|
15
|
+
* builds where `globalThis.crypto` is absent.
|
|
16
|
+
*
|
|
17
|
+
* NOT a security primitive in the cryptographic sense — the nonce is a
|
|
18
|
+
* one-shot, single-request value that defeats trivial XSS injection by
|
|
19
|
+
* making the attacker guess a 128-bit string per request. It is NOT
|
|
20
|
+
* suitable for signing or session tokens.
|
|
21
|
+
*/
|
|
22
|
+
declare function generateNonce(): string;
|
|
23
|
+
|
|
24
|
+
declare class AuthRequiredError extends Error {
|
|
25
|
+
code: "AUTH_REQUIRED";
|
|
26
|
+
status: number;
|
|
27
|
+
constructor(message?: string);
|
|
28
|
+
}
|
|
29
|
+
declare function requireAuth<T>(session: T | null | undefined): asserts session is T;
|
|
30
|
+
|
|
31
|
+
interface SessionConfig {
|
|
32
|
+
/**
|
|
33
|
+
* Session secret. Either a single string (legacy) or an array of strings
|
|
34
|
+
* where index 0 is the newest. The array form enables dual-key rotation
|
|
35
|
+
* (T3.1 / ADR D5): encrypt always uses `secrets[0]`, decrypt walks the
|
|
36
|
+
* array, transparent re-encrypt on legacy hits (T3.2).
|
|
37
|
+
*
|
|
38
|
+
* EC-1: array length capped at 5 — enforced via throw at construction.
|
|
39
|
+
*/
|
|
40
|
+
secret: string | string[];
|
|
41
|
+
cookieName?: string;
|
|
42
|
+
maxAge?: number;
|
|
43
|
+
}
|
|
44
|
+
interface SessionMeta {
|
|
45
|
+
/** Index of the secret that decrypted the session. 0 = newest; > 0 = legacy. */
|
|
46
|
+
secretIndex: number;
|
|
47
|
+
/** True when the decrypt used a legacy secret and the cookie should be re-encrypted. */
|
|
48
|
+
needsReencrypt: boolean;
|
|
49
|
+
}
|
|
50
|
+
interface SessionManager<TSession> {
|
|
51
|
+
getSession(req: IncomingMessage): Promise<TSession | null>;
|
|
52
|
+
/**
|
|
53
|
+
* T3.2 — Variant of `getSession` that surfaces decrypt metadata.
|
|
54
|
+
* Used by `api-middleware.ts` to wire transparent re-encrypt BEFORE
|
|
55
|
+
* the handler runs (so streaming SSR routes don't miss the Set-Cookie
|
|
56
|
+
* window — EC-4).
|
|
57
|
+
*/
|
|
58
|
+
getSessionWithMeta(req: IncomingMessage): Promise<{
|
|
59
|
+
data: TSession | null;
|
|
60
|
+
meta: SessionMeta;
|
|
61
|
+
}>;
|
|
62
|
+
createSession(res: ServerResponse, data: TSession): Promise<void>;
|
|
63
|
+
destroySession(res: ServerResponse): void;
|
|
64
|
+
/**
|
|
65
|
+
* T3.3 — OWASP A07:2021 session fixation mitigation. Re-encrypts the
|
|
66
|
+
* current session with a fresh IV and refreshed expiry. No-op when no
|
|
67
|
+
* session is present.
|
|
68
|
+
*/
|
|
69
|
+
rotateSession(req: IncomingMessage, res: ServerResponse): Promise<TSession | null>;
|
|
70
|
+
}
|
|
71
|
+
declare function createSessionManager<TSession>(config: SessionConfig): SessionManager<TSession>;
|
|
72
|
+
/**
|
|
73
|
+
* T5a.2 Phase D slice 3/3 — Web-Standards session manager.
|
|
74
|
+
*
|
|
75
|
+
* Mirror of `SessionManager<TSession>` for the Web `Request` + `Headers`
|
|
76
|
+
* shape. Same `SessionConfig`, same encryption (`encrypt`/`decrypt` from
|
|
77
|
+
* `./crypto.js`), same dual-key rotation logic (CR-002 constant-time
|
|
78
|
+
* decrypt fallback walk + transparent re-encrypt), same OWASP A07
|
|
79
|
+
* `rotateSession` invariant.
|
|
80
|
+
*
|
|
81
|
+
* **Signature differences vs `SessionManager`:**
|
|
82
|
+
* - Read methods take `Request` (instead of `IncomingMessage`).
|
|
83
|
+
* - Write methods take a `Headers` instance to mutate (instead of
|
|
84
|
+
* `ServerResponse`) — caller passes the headers they're building
|
|
85
|
+
* for their `Response` constructor.
|
|
86
|
+
*
|
|
87
|
+
* Uses `getCookieFromRequest` / `appendCookieToHeaders` /
|
|
88
|
+
* `appendDeleteCookieToHeaders` from Phase B slice 6/6.
|
|
89
|
+
*/
|
|
90
|
+
interface SessionManagerWeb<TSession> {
|
|
91
|
+
getSession(request: Request): Promise<TSession | null>;
|
|
92
|
+
getSessionWithMeta(request: Request): Promise<{
|
|
93
|
+
data: TSession | null;
|
|
94
|
+
meta: SessionMeta;
|
|
95
|
+
}>;
|
|
96
|
+
createSession(target: Headers, data: TSession): Promise<void>;
|
|
97
|
+
destroySession(target: Headers): void;
|
|
98
|
+
rotateSession(request: Request, target: Headers): Promise<TSession | null>;
|
|
99
|
+
}
|
|
100
|
+
declare function createSessionManagerWeb<TSession>(config: SessionConfig): SessionManagerWeb<TSession>;
|
|
101
|
+
/**
|
|
102
|
+
* T5a.2 Phase D slice 3/3 — Web-Standards transparent re-encrypt helper.
|
|
103
|
+
*
|
|
104
|
+
* Mirror of `rotateIfNeeded(sm, req, res)` for the Web Request + Headers
|
|
105
|
+
* shape. Reads session via `getSessionWithMeta`; if the cookie was
|
|
106
|
+
* decrypted with a legacy secret (index > 0), re-issues the cookie with
|
|
107
|
+
* the newest secret via `createSession(target, data)`.
|
|
108
|
+
*
|
|
109
|
+
* **EC-4 honest framing:** unlike the IncomingMessage path where the
|
|
110
|
+
* timing constraint is "before `res.writeHead` fires", the Web Request
|
|
111
|
+
* path's constraint is "before the `Response` object is constructed and
|
|
112
|
+
* returned to the runtime". Caller MUST invoke `rotateIfNeededWeb`
|
|
113
|
+
* BEFORE building the final `Response(body, { headers: target })` so the
|
|
114
|
+
* re-encrypted Set-Cookie lands on the wire.
|
|
115
|
+
*/
|
|
116
|
+
declare function rotateIfNeededWeb<TSession>(sm: SessionManagerWeb<TSession>, request: Request, target: Headers): Promise<TSession | null>;
|
|
117
|
+
/**
|
|
118
|
+
* T3.2 — Transparent re-encrypt helper (EC-4 timing-safe wrapper).
|
|
119
|
+
*
|
|
120
|
+
* Call this in your `createContext` (before any rendering / streaming
|
|
121
|
+
* starts). It:
|
|
122
|
+
* 1. Reads the session via `getSessionWithMeta`.
|
|
123
|
+
* 2. If the cookie was decrypted with a legacy secret (index > 0), it
|
|
124
|
+
* immediately re-issues the cookie with `secrets[0]` so the next
|
|
125
|
+
* request lands on the newest key.
|
|
126
|
+
* 3. Returns the session data (or null) for use downstream.
|
|
127
|
+
*
|
|
128
|
+
* EC-4: this MUST run before `renderToPipeableStream` / `res.writeHead`
|
|
129
|
+
* fires. Calling it inside an SSR component or handler body that has
|
|
130
|
+
* already streamed bytes makes the re-encrypt a silent no-op (Set-Cookie
|
|
131
|
+
* is locked once headers commit), trapping users on the legacy secret
|
|
132
|
+
* forever once it's removed from the array.
|
|
133
|
+
*/
|
|
134
|
+
declare function rotateIfNeeded<TSession>(sm: SessionManager<TSession>, req: IncomingMessage, res: ServerResponse): Promise<TSession | null>;
|
|
135
|
+
declare function assertProductionSecret(secret: string | string[]): void;
|
|
136
|
+
|
|
137
|
+
declare function encrypt<T>(data: T, secret: string): Promise<string>;
|
|
138
|
+
declare function decrypt<T>(token: string, secret: string): Promise<T | null>;
|
|
139
|
+
/**
|
|
140
|
+
* Reset the derived-key cache. Test helper — never call from production code.
|
|
141
|
+
* Used by Vitest to guarantee isolation between tests that use distinct
|
|
142
|
+
* secrets and want to confirm the derivation path runs.
|
|
143
|
+
*/
|
|
144
|
+
declare function _resetKeyCacheForTests(): void;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* T6.2 — RFC 6238 TOTP primitive.
|
|
148
|
+
*
|
|
149
|
+
* Reference: https://datatracker.ietf.org/doc/html/rfc6238
|
|
150
|
+
* HMAC-based one-time password (HOTP) base: https://datatracker.ietf.org/doc/html/rfc4226
|
|
151
|
+
*
|
|
152
|
+
* Pure-function, dependency-free implementation via Web Crypto. Secrets
|
|
153
|
+
* may be passed as Uint8Array (preferred) or base32 string.
|
|
154
|
+
*
|
|
155
|
+
* SECURITY NOTES (documented per EC-13):
|
|
156
|
+
* - TOTP secrets are equivalent to passwords. Encrypt at rest using a
|
|
157
|
+
* separate KMS key from the session secret. If your DB leaks, ALL
|
|
158
|
+
* 2FA codes are compromised — rotate by forcing all users to re-enroll.
|
|
159
|
+
* - Use `verifyTotp` constant-time (we use crypto.timingSafeEqual internally).
|
|
160
|
+
*/
|
|
161
|
+
/** Supported HMAC algorithms per RFC 6238 §1.2. Default SHA-1. */
|
|
162
|
+
type TotpAlgorithm = 'SHA-1' | 'SHA-256' | 'SHA-512';
|
|
163
|
+
interface TotpOptions {
|
|
164
|
+
/** Shared secret — bytes (preferred) OR base32 string. */
|
|
165
|
+
secret: Uint8Array | string;
|
|
166
|
+
/** Time step in seconds. Default 30 (RFC 6238 §5.2 recommended). */
|
|
167
|
+
step?: number;
|
|
168
|
+
/** Code length: 6, 7, or 8 digits. Default 6. */
|
|
169
|
+
digits?: 6 | 7 | 8;
|
|
170
|
+
/** HMAC algorithm. Default SHA-1 (RFC default). */
|
|
171
|
+
algorithm?: TotpAlgorithm;
|
|
172
|
+
/** Time in ms since epoch. Default Date.now(). */
|
|
173
|
+
time?: number;
|
|
174
|
+
}
|
|
175
|
+
interface VerifyTotpOptions extends TotpOptions {
|
|
176
|
+
/**
|
|
177
|
+
* Drift tolerance in number of steps on each side. Default 1
|
|
178
|
+
* (RFC 6238 §5.2 recommends ±1 step = 90s total window).
|
|
179
|
+
*/
|
|
180
|
+
window?: number;
|
|
181
|
+
}
|
|
182
|
+
/** Generate a TOTP code for a given time. */
|
|
183
|
+
declare function generateTotp(opts: TotpOptions): Promise<string>;
|
|
184
|
+
/**
|
|
185
|
+
* Verify a TOTP code against the current window ± `window` steps.
|
|
186
|
+
*
|
|
187
|
+
* Returns `false` for malformed tokens (non-digit, wrong length) without
|
|
188
|
+
* throwing — defensive against accidental user-input passthrough.
|
|
189
|
+
*/
|
|
190
|
+
declare function verifyTotp(token: string, opts: VerifyTotpOptions): Promise<boolean>;
|
|
191
|
+
/** Generate a cryptographically random TOTP secret. Default 20 bytes (RFC minimum). */
|
|
192
|
+
declare function generateTotpSecret(bytes?: number): Uint8Array;
|
|
193
|
+
/**
|
|
194
|
+
* Build an `otpauth://` URI for QR code enrollment. Format follows the
|
|
195
|
+
* de facto Google Authenticator spec adopted by every major TOTP app.
|
|
196
|
+
* otpauth://totp/<issuer>:<account>?secret=<base32>&issuer=<issuer>&algorithm=<alg>&digits=<n>&period=<sec>
|
|
197
|
+
*/
|
|
198
|
+
interface TotpUriOptions {
|
|
199
|
+
secret: Uint8Array;
|
|
200
|
+
issuer: string;
|
|
201
|
+
account: string;
|
|
202
|
+
algorithm?: TotpAlgorithm;
|
|
203
|
+
digits?: 6 | 7 | 8;
|
|
204
|
+
step?: number;
|
|
205
|
+
}
|
|
206
|
+
declare function totpUri(opts: TotpUriOptions): string;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* T6.3 — Backup codes for 2FA recovery.
|
|
210
|
+
*
|
|
211
|
+
* generateBackupCodes returns N plaintexts (display once to user) + hashes
|
|
212
|
+
* (store in DB). verifyBackupCode constant-time-walks all hashes and
|
|
213
|
+
* returns the matchedHash so caller can delete the used code from storage
|
|
214
|
+
* — replay protection lives at the caller (we can't see their database).
|
|
215
|
+
*
|
|
216
|
+
* SECURITY NOTES:
|
|
217
|
+
* - Codes have ~40 bits entropy (8 chars × 5 bits per char from a
|
|
218
|
+
* 32-char alphabet excluding I/L/O/0/1). Single-use → argon2id
|
|
219
|
+
* overhead is unnecessary; SHA-256 of the normalized code suffices.
|
|
220
|
+
* - The caller MUST atomically delete the matched hash on successful
|
|
221
|
+
* verify. Without that, the code is replayable. We surface
|
|
222
|
+
* matchedHash explicitly so this step is conspicuous.
|
|
223
|
+
* - Pair this with throttleLoginAttempts (T6.1) on the verify endpoint
|
|
224
|
+
* to prevent online brute-force against the 40-bit space.
|
|
225
|
+
*/
|
|
226
|
+
interface BackupCodeOptions {
|
|
227
|
+
/** How many codes to generate. Default 10. */
|
|
228
|
+
count?: number;
|
|
229
|
+
/** Length in chars (excluding separator). Default 8. */
|
|
230
|
+
length?: number;
|
|
231
|
+
/** Separator inserted at the midpoint. Default '-'; pass null to omit. */
|
|
232
|
+
separator?: '-' | null;
|
|
233
|
+
/** Custom alphabet. Default excludes ambiguous chars (I, L, O, 0, 1). */
|
|
234
|
+
alphabet?: string;
|
|
235
|
+
}
|
|
236
|
+
interface BackupCode {
|
|
237
|
+
plaintext: string;
|
|
238
|
+
hash: string;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Generate cryptographically random backup codes + their SHA-256 hashes.
|
|
242
|
+
*
|
|
243
|
+
* Plaintext is uppercase alphanumeric (default alphabet excludes ambiguous
|
|
244
|
+
* chars). Separator inserted at the midpoint (default `-`).
|
|
245
|
+
*/
|
|
246
|
+
declare function generateBackupCodes(opts?: BackupCodeOptions): Promise<BackupCode[]>;
|
|
247
|
+
/**
|
|
248
|
+
* Verify a code against a list of stored hashes. Walks all hashes
|
|
249
|
+
* constant-time (no early exit). Returns `valid:true` + matchedHash on
|
|
250
|
+
* hit; `valid:false` otherwise.
|
|
251
|
+
*
|
|
252
|
+
* `matchedHash` is the EXACT string the caller stored, ready to be passed
|
|
253
|
+
* to a `DELETE FROM backup_codes WHERE hash = ?` query.
|
|
254
|
+
*/
|
|
255
|
+
declare function verifyBackupCode(code: string, hashes: readonly string[]): Promise<{
|
|
256
|
+
valid: boolean;
|
|
257
|
+
matchedHash?: string;
|
|
258
|
+
}>;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* T6.1 — Login throttling primitive.
|
|
262
|
+
*
|
|
263
|
+
* Per-credential failure counter backed by any `RateLimitStore`. After
|
|
264
|
+
* `maxAttempts` failures within `windowMs`, the identifier is locked
|
|
265
|
+
* for `lockoutMs`. Successful login resets the counter.
|
|
266
|
+
*
|
|
267
|
+
* Usage in a login handler:
|
|
268
|
+
*
|
|
269
|
+
* const state = await checkThrottle({ store, identifier: hash(email) })
|
|
270
|
+
* if (!state.allowed) return 429
|
|
271
|
+
* const valid = await verifyPassword(creds)
|
|
272
|
+
* await recordAttempt({ store, identifier: hash(email) }, valid)
|
|
273
|
+
* if (!valid) return 401
|
|
274
|
+
*
|
|
275
|
+
* SECURITY:
|
|
276
|
+
* - NEVER pass raw email/username as `identifier`. Hash or normalize
|
|
277
|
+
* first (e.g. SHA-256 of the lowercased email). This prevents PII
|
|
278
|
+
* from landing in the rate-limit store or audit logs.
|
|
279
|
+
* - Combine with the per-route IP rate limit (T2.2) for layered defense:
|
|
280
|
+
* IP-level limits stop scripted floods; credential-level limits stop
|
|
281
|
+
* distributed brute force.
|
|
282
|
+
*/
|
|
283
|
+
interface ThrottleOptions {
|
|
284
|
+
store: RateLimitStore;
|
|
285
|
+
/**
|
|
286
|
+
* Stable identifier per credential. Hash raw emails/usernames before
|
|
287
|
+
* passing in — never leak PII to the rate-limit key space.
|
|
288
|
+
*/
|
|
289
|
+
identifier: string;
|
|
290
|
+
/** Failures before lockout. Default 5. */
|
|
291
|
+
maxAttempts?: number;
|
|
292
|
+
/** Sliding window for counting failures. Default 15 minutes. */
|
|
293
|
+
windowMs?: number;
|
|
294
|
+
/** Lockout duration after maxAttempts hit. Default 1 hour. */
|
|
295
|
+
lockoutMs?: number;
|
|
296
|
+
}
|
|
297
|
+
interface ThrottleState {
|
|
298
|
+
allowed: boolean;
|
|
299
|
+
remainingAttempts: number;
|
|
300
|
+
/** Set when `allowed === false`. Absolute timestamp when the lockout expires. */
|
|
301
|
+
lockedUntil?: Date;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Read the current throttle state for an identifier WITHOUT modifying
|
|
305
|
+
* the counter. Call before validating credentials so locked attempts
|
|
306
|
+
* are rejected fast.
|
|
307
|
+
*/
|
|
308
|
+
declare function checkThrottle(opts: ThrottleOptions): Promise<ThrottleState>;
|
|
309
|
+
/**
|
|
310
|
+
* Record an attempt outcome. On success → reset the counter. On failure
|
|
311
|
+
* → increment within the sliding window. Returns the new throttle state.
|
|
312
|
+
*
|
|
313
|
+
* Storage model: the store entry's TTL is `lockoutMs` (which doubles as
|
|
314
|
+
* the failure-accumulation window). When `lockoutMs` is short — common
|
|
315
|
+
* in tests or for soft lockouts — the entry auto-expires and the next
|
|
316
|
+
* attempt starts fresh.
|
|
317
|
+
*/
|
|
318
|
+
declare function recordAttempt(opts: ThrottleOptions, success: boolean): Promise<ThrottleState>;
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* T7.3 — RFC 7636 PKCE primitive.
|
|
322
|
+
*
|
|
323
|
+
* Reference: https://datatracker.ietf.org/doc/html/rfc7636
|
|
324
|
+
*
|
|
325
|
+
* Pure-function, dependency-free implementation using Web Crypto.
|
|
326
|
+
*
|
|
327
|
+
* Usage in an OAuth authorization-code flow:
|
|
328
|
+
*
|
|
329
|
+
* const { codeVerifier, codeChallenge, codeChallengeMethod } = await generatePkceChallenge()
|
|
330
|
+
* // Store codeVerifier in the user's session
|
|
331
|
+
* // Send codeChallenge + codeChallengeMethod in the /authorize redirect
|
|
332
|
+
* // ... user authenticates with provider ...
|
|
333
|
+
* // On /callback, send codeVerifier with the code → token exchange
|
|
334
|
+
*/
|
|
335
|
+
interface PkceChallenge {
|
|
336
|
+
codeVerifier: string;
|
|
337
|
+
codeChallenge: string;
|
|
338
|
+
codeChallengeMethod: 'S256';
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Compute the code_challenge from a code_verifier per RFC 7636 §4.2.
|
|
342
|
+
* Exported separately to enable RFC 7636 Appendix B vector testing.
|
|
343
|
+
*/
|
|
344
|
+
declare function pkceChallengeFromVerifier(verifier: string): Promise<string>;
|
|
345
|
+
/**
|
|
346
|
+
* Generate a fresh PKCE challenge pair.
|
|
347
|
+
*
|
|
348
|
+
* Verifier: 32 cryptographically random bytes → 43-char base64url string.
|
|
349
|
+
* RFC 7636 §4.1 allows 43–128 chars; we ship the minimum-safe default.
|
|
350
|
+
*
|
|
351
|
+
* Method: 'S256' only — no 'plain' fallback. RFC 7636 §7.2 strongly
|
|
352
|
+
* discourages plain and modern providers reject it.
|
|
353
|
+
*/
|
|
354
|
+
declare function generatePkceChallenge(): Promise<PkceChallenge>;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* T7.4 — OAuth `state` parameter helpers (RFC 6749 §10.12).
|
|
358
|
+
*
|
|
359
|
+
* `state` is a cryptographically random anti-CSRF token. The client
|
|
360
|
+
* stores it (in session/cookie/db) before redirecting to the
|
|
361
|
+
* authorization endpoint and verifies it on the callback. Without it,
|
|
362
|
+
* an attacker can authorize on the user's account using a captured code.
|
|
363
|
+
*/
|
|
364
|
+
/**
|
|
365
|
+
* Generate a cryptographically random state token. Default 32 bytes
|
|
366
|
+
* (~43 base64url chars). Increase for higher entropy if your provider
|
|
367
|
+
* supports it.
|
|
368
|
+
*/
|
|
369
|
+
declare function generateOAuthState(opts?: {
|
|
370
|
+
bytes?: number;
|
|
371
|
+
}): string;
|
|
372
|
+
/**
|
|
373
|
+
* Verify a state token. Constant-time compare. Empty inputs always fail
|
|
374
|
+
* (defensive — never accept empty as "they match").
|
|
375
|
+
*
|
|
376
|
+
* CR-012 fix: `constantTimeEquals` does not early-exit on length mismatch,
|
|
377
|
+
* so the comparison time is independent of how the input was forged.
|
|
378
|
+
*/
|
|
379
|
+
declare function verifyOAuthState(provided: string, stored: string): boolean;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* T7.4 — OpenID Connect Discovery 1.0 metadata fetcher.
|
|
383
|
+
*
|
|
384
|
+
* Reference: https://openid.net/specs/openid-connect-discovery-1_0.html
|
|
385
|
+
*
|
|
386
|
+
* Caches metadata in module scope. Cache key is the exact issuer string
|
|
387
|
+
* (trailing-slash sensitive per RFC 8414 §3). Failures are NOT cached —
|
|
388
|
+
* subsequent calls retry the fetch.
|
|
389
|
+
*
|
|
390
|
+
* EC-7 — HTTPS enforced. RFC 8414 §3 requires HTTPS for OIDC issuers.
|
|
391
|
+
* Localhost (loopback) is allowed for development.
|
|
392
|
+
*/
|
|
393
|
+
interface OidcMetadata {
|
|
394
|
+
issuer: string;
|
|
395
|
+
authorization_endpoint: string;
|
|
396
|
+
token_endpoint: string;
|
|
397
|
+
jwks_uri?: string;
|
|
398
|
+
userinfo_endpoint?: string;
|
|
399
|
+
end_session_endpoint?: string;
|
|
400
|
+
scopes_supported?: string[];
|
|
401
|
+
response_types_supported?: string[];
|
|
402
|
+
grant_types_supported?: string[];
|
|
403
|
+
id_token_signing_alg_values_supported?: string[];
|
|
404
|
+
[key: string]: unknown;
|
|
405
|
+
}
|
|
406
|
+
/** Clear the discovery cache. Used by tests. */
|
|
407
|
+
declare function clearOidcCache(): void;
|
|
408
|
+
/**
|
|
409
|
+
* Fetch (or return cached) OIDC provider metadata.
|
|
410
|
+
*
|
|
411
|
+
* Throws when:
|
|
412
|
+
* - Issuer URL is malformed
|
|
413
|
+
* - Issuer is HTTP and not a loopback host (EC-7)
|
|
414
|
+
* - HTTP response is non-OK
|
|
415
|
+
* - Metadata lacks `authorization_endpoint` (sanity check)
|
|
416
|
+
*/
|
|
417
|
+
declare function discoverOidcProvider(issuer: string | URL): Promise<OidcMetadata>;
|
|
418
|
+
|
|
419
|
+
export { AuthRequiredError, type BackupCode, type BackupCodeOptions, type OidcMetadata, type PkceChallenge, type SessionConfig, type SessionManager, type SessionManagerWeb, type SessionMeta, type ThrottleOptions, type ThrottleState, type TotpAlgorithm, type TotpOptions, type TotpUriOptions, type VerifyTotpOptions, _resetKeyCacheForTests, assertProductionSecret, checkThrottle, clearOidcCache, createSessionManager, createSessionManagerWeb, decrypt, discoverOidcProvider, encrypt, generateBackupCodes, generateNonce, generateOAuthState, generatePkceChallenge, generateTotp, generateTotpSecret, pkceChallengeFromVerifier, recordAttempt, requireAuth, rotateIfNeeded, rotateIfNeededWeb, totpUri, verifyBackupCode, verifyOAuthState, verifyTotp };
|