@soulcraft/sdk 1.0.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 (149) hide show
  1. package/dist/client/index.d.ts +62 -0
  2. package/dist/client/index.d.ts.map +1 -0
  3. package/dist/client/index.js +60 -0
  4. package/dist/client/index.js.map +1 -0
  5. package/dist/index.d.ts +33 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +17 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/modules/ai/index.d.ts +55 -0
  10. package/dist/modules/ai/index.d.ts.map +1 -0
  11. package/dist/modules/ai/index.js +263 -0
  12. package/dist/modules/ai/index.js.map +1 -0
  13. package/dist/modules/ai/types.d.ts +216 -0
  14. package/dist/modules/ai/types.d.ts.map +1 -0
  15. package/dist/modules/ai/types.js +30 -0
  16. package/dist/modules/ai/types.js.map +1 -0
  17. package/dist/modules/auth/backchannel.d.ts +85 -0
  18. package/dist/modules/auth/backchannel.d.ts.map +1 -0
  19. package/dist/modules/auth/backchannel.js +168 -0
  20. package/dist/modules/auth/backchannel.js.map +1 -0
  21. package/dist/modules/auth/config.d.ts +122 -0
  22. package/dist/modules/auth/config.d.ts.map +1 -0
  23. package/dist/modules/auth/config.js +158 -0
  24. package/dist/modules/auth/config.js.map +1 -0
  25. package/dist/modules/auth/middleware.d.ts +146 -0
  26. package/dist/modules/auth/middleware.d.ts.map +1 -0
  27. package/dist/modules/auth/middleware.js +204 -0
  28. package/dist/modules/auth/middleware.js.map +1 -0
  29. package/dist/modules/auth/types.d.ts +162 -0
  30. package/dist/modules/auth/types.d.ts.map +1 -0
  31. package/dist/modules/auth/types.js +14 -0
  32. package/dist/modules/auth/types.js.map +1 -0
  33. package/dist/modules/billing/types.d.ts +7 -0
  34. package/dist/modules/billing/types.d.ts.map +1 -0
  35. package/dist/modules/billing/types.js +7 -0
  36. package/dist/modules/billing/types.js.map +1 -0
  37. package/dist/modules/brainy/auth.d.ts +104 -0
  38. package/dist/modules/brainy/auth.d.ts.map +1 -0
  39. package/dist/modules/brainy/auth.js +144 -0
  40. package/dist/modules/brainy/auth.js.map +1 -0
  41. package/dist/modules/brainy/errors.d.ts +118 -0
  42. package/dist/modules/brainy/errors.d.ts.map +1 -0
  43. package/dist/modules/brainy/errors.js +142 -0
  44. package/dist/modules/brainy/errors.js.map +1 -0
  45. package/dist/modules/brainy/events.d.ts +63 -0
  46. package/dist/modules/brainy/events.d.ts.map +1 -0
  47. package/dist/modules/brainy/events.js +14 -0
  48. package/dist/modules/brainy/events.js.map +1 -0
  49. package/dist/modules/brainy/proxy.d.ts +48 -0
  50. package/dist/modules/brainy/proxy.d.ts.map +1 -0
  51. package/dist/modules/brainy/proxy.js +95 -0
  52. package/dist/modules/brainy/proxy.js.map +1 -0
  53. package/dist/modules/brainy/types.d.ts +83 -0
  54. package/dist/modules/brainy/types.d.ts.map +1 -0
  55. package/dist/modules/brainy/types.js +21 -0
  56. package/dist/modules/brainy/types.js.map +1 -0
  57. package/dist/modules/events/index.d.ts +41 -0
  58. package/dist/modules/events/index.d.ts.map +1 -0
  59. package/dist/modules/events/index.js +53 -0
  60. package/dist/modules/events/index.js.map +1 -0
  61. package/dist/modules/events/types.d.ts +129 -0
  62. package/dist/modules/events/types.d.ts.map +1 -0
  63. package/dist/modules/events/types.js +32 -0
  64. package/dist/modules/events/types.js.map +1 -0
  65. package/dist/modules/formats/types.d.ts +7 -0
  66. package/dist/modules/formats/types.d.ts.map +1 -0
  67. package/dist/modules/formats/types.js +7 -0
  68. package/dist/modules/formats/types.js.map +1 -0
  69. package/dist/modules/hall/types.d.ts +56 -0
  70. package/dist/modules/hall/types.d.ts.map +1 -0
  71. package/dist/modules/hall/types.js +16 -0
  72. package/dist/modules/hall/types.js.map +1 -0
  73. package/dist/modules/kits/types.d.ts +7 -0
  74. package/dist/modules/kits/types.d.ts.map +1 -0
  75. package/dist/modules/kits/types.js +7 -0
  76. package/dist/modules/kits/types.js.map +1 -0
  77. package/dist/modules/license/types.d.ts +7 -0
  78. package/dist/modules/license/types.d.ts.map +1 -0
  79. package/dist/modules/license/types.js +7 -0
  80. package/dist/modules/license/types.js.map +1 -0
  81. package/dist/modules/notifications/types.d.ts +7 -0
  82. package/dist/modules/notifications/types.d.ts.map +1 -0
  83. package/dist/modules/notifications/types.js +7 -0
  84. package/dist/modules/notifications/types.js.map +1 -0
  85. package/dist/modules/skills/index.d.ts +60 -0
  86. package/dist/modules/skills/index.d.ts.map +1 -0
  87. package/dist/modules/skills/index.js +253 -0
  88. package/dist/modules/skills/index.js.map +1 -0
  89. package/dist/modules/skills/types.d.ts +127 -0
  90. package/dist/modules/skills/types.d.ts.map +1 -0
  91. package/dist/modules/skills/types.js +23 -0
  92. package/dist/modules/skills/types.js.map +1 -0
  93. package/dist/modules/versions/types.d.ts +31 -0
  94. package/dist/modules/versions/types.d.ts.map +1 -0
  95. package/dist/modules/versions/types.js +9 -0
  96. package/dist/modules/versions/types.js.map +1 -0
  97. package/dist/modules/vfs/types.d.ts +26 -0
  98. package/dist/modules/vfs/types.d.ts.map +1 -0
  99. package/dist/modules/vfs/types.js +11 -0
  100. package/dist/modules/vfs/types.js.map +1 -0
  101. package/dist/server/create-sdk.d.ts +70 -0
  102. package/dist/server/create-sdk.d.ts.map +1 -0
  103. package/dist/server/create-sdk.js +125 -0
  104. package/dist/server/create-sdk.js.map +1 -0
  105. package/dist/server/hall-handlers.d.ts +195 -0
  106. package/dist/server/hall-handlers.d.ts.map +1 -0
  107. package/dist/server/hall-handlers.js +239 -0
  108. package/dist/server/hall-handlers.js.map +1 -0
  109. package/dist/server/handlers.d.ts +216 -0
  110. package/dist/server/handlers.d.ts.map +1 -0
  111. package/dist/server/handlers.js +214 -0
  112. package/dist/server/handlers.js.map +1 -0
  113. package/dist/server/index.d.ts +52 -0
  114. package/dist/server/index.d.ts.map +1 -0
  115. package/dist/server/index.js +50 -0
  116. package/dist/server/index.js.map +1 -0
  117. package/dist/server/instance-pool.d.ts +299 -0
  118. package/dist/server/instance-pool.d.ts.map +1 -0
  119. package/dist/server/instance-pool.js +359 -0
  120. package/dist/server/instance-pool.js.map +1 -0
  121. package/dist/transports/http.d.ts +86 -0
  122. package/dist/transports/http.d.ts.map +1 -0
  123. package/dist/transports/http.js +134 -0
  124. package/dist/transports/http.js.map +1 -0
  125. package/dist/transports/local.d.ts +76 -0
  126. package/dist/transports/local.d.ts.map +1 -0
  127. package/dist/transports/local.js +101 -0
  128. package/dist/transports/local.js.map +1 -0
  129. package/dist/transports/sse.d.ts +99 -0
  130. package/dist/transports/sse.d.ts.map +1 -0
  131. package/dist/transports/sse.js +192 -0
  132. package/dist/transports/sse.js.map +1 -0
  133. package/dist/transports/transport.d.ts +68 -0
  134. package/dist/transports/transport.d.ts.map +1 -0
  135. package/dist/transports/transport.js +14 -0
  136. package/dist/transports/transport.js.map +1 -0
  137. package/dist/transports/ws.d.ts +135 -0
  138. package/dist/transports/ws.d.ts.map +1 -0
  139. package/dist/transports/ws.js +331 -0
  140. package/dist/transports/ws.js.map +1 -0
  141. package/dist/types.d.ts +152 -0
  142. package/dist/types.d.ts.map +1 -0
  143. package/dist/types.js +8 -0
  144. package/dist/types.js.map +1 -0
  145. package/docs/ADR-001-sdk-design.md +282 -0
  146. package/docs/IMPLEMENTATION-PLAN.md +708 -0
  147. package/docs/USAGE.md +646 -0
  148. package/docs/kit-sdk-guide.md +474 -0
  149. package/package.json +61 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * @module modules/ai/types
3
+ * @description Type definitions for `sdk.ai.*` — the Claude AI integration module.
4
+ *
5
+ * Wraps the Anthropic Claude API with Soulcraft-specific defaults:
6
+ * - Canonical model IDs for each tier (haiku for speed, sonnet for quality, opus for complex)
7
+ * - Structured tool call handling with full type safety
8
+ * - Streaming support via async iteration
9
+ *
10
+ * The AI module does not depend on any particular transport — it calls the
11
+ * Anthropic API directly from the server process and is not proxied through Brainy.
12
+ */
13
+ /**
14
+ * Canonical Anthropic model IDs for each Soulcraft platform tier.
15
+ *
16
+ * Use these constants instead of hardcoding model strings to ensure consistency
17
+ * across products and easier future upgrades.
18
+ */
19
+ export declare const AI_MODELS: {
20
+ /** Fast, affordable — routine lookups, data extraction, simple Q&A. */
21
+ readonly haiku: "claude-haiku-4-5-20251001";
22
+ /** Balanced — most kit operations, content generation, analysis. */
23
+ readonly sonnet: "claude-sonnet-4-6";
24
+ /** Most capable — complex reasoning, long-form synthesis, multi-step planning. */
25
+ readonly opus: "claude-opus-4-6";
26
+ };
27
+ /** A valid Soulcraft Claude model tier ID. */
28
+ export type AiModel = typeof AI_MODELS[keyof typeof AI_MODELS] | string;
29
+ /**
30
+ * A single message in a Claude conversation.
31
+ */
32
+ export interface AiMessage {
33
+ /** The role of the message author. */
34
+ role: 'user' | 'assistant';
35
+ /**
36
+ * The message content.
37
+ *
38
+ * For simple text: a plain string.
39
+ * For tool results: an array of content blocks (see Anthropic API docs).
40
+ */
41
+ content: string | AiContentBlock[];
42
+ }
43
+ /**
44
+ * A content block within a message — text, image, tool use, or tool result.
45
+ */
46
+ export type AiContentBlock = {
47
+ type: 'text';
48
+ text: string;
49
+ } | {
50
+ type: 'image';
51
+ source: {
52
+ type: 'base64';
53
+ media_type: string;
54
+ data: string;
55
+ };
56
+ } | {
57
+ type: 'tool_use';
58
+ id: string;
59
+ name: string;
60
+ input: Record<string, unknown>;
61
+ } | {
62
+ type: 'tool_result';
63
+ tool_use_id: string;
64
+ content: string;
65
+ };
66
+ /**
67
+ * A tool that Claude can call during a completion.
68
+ */
69
+ export interface AiTool {
70
+ /** Machine-readable tool name (snake_case). */
71
+ name: string;
72
+ /** Human-readable description used by Claude to decide when to call this tool. */
73
+ description: string;
74
+ /** JSON Schema for the tool's input parameters. */
75
+ inputSchema: {
76
+ type: 'object';
77
+ properties: Record<string, unknown>;
78
+ required?: string[];
79
+ };
80
+ }
81
+ /**
82
+ * A tool call emitted by Claude in a completion response.
83
+ */
84
+ export interface AiToolCall {
85
+ /** Unique ID for this tool call (used when feeding results back). */
86
+ id: string;
87
+ /** The name of the tool to call. */
88
+ name: string;
89
+ /** The arguments Claude wants to pass to the tool. */
90
+ input: Record<string, unknown>;
91
+ }
92
+ /**
93
+ * Options for a single Claude completion request.
94
+ */
95
+ export interface AiCompleteOptions {
96
+ /** The conversation history, alternating user/assistant messages. */
97
+ messages: AiMessage[];
98
+ /**
99
+ * System prompt injected before the conversation.
100
+ * Typically derived from `kit.shared.aiPersona` for kit applications.
101
+ */
102
+ systemPrompt?: string;
103
+ /**
104
+ * The Claude model to use.
105
+ *
106
+ * @default AI_MODELS.sonnet
107
+ */
108
+ model?: AiModel;
109
+ /**
110
+ * Tools available to Claude during this completion.
111
+ *
112
+ * When Claude calls a tool, the response will include `toolCalls` instead of
113
+ * (or in addition to) `text`. The caller is responsible for executing the
114
+ * tool and continuing the conversation.
115
+ */
116
+ tools?: AiTool[];
117
+ /**
118
+ * Maximum tokens in the response.
119
+ *
120
+ * @default 8192
121
+ */
122
+ maxTokens?: number;
123
+ /**
124
+ * Temperature for sampling (0–1). Lower = more deterministic.
125
+ *
126
+ * @default 1 (Anthropic default)
127
+ */
128
+ temperature?: number;
129
+ }
130
+ /**
131
+ * The result of a single Claude completion.
132
+ *
133
+ * `text` and `toolCalls` may both be present if Claude includes a text
134
+ * explanation alongside tool invocations.
135
+ */
136
+ export interface AiCompleteResult {
137
+ /** The text portion of Claude's response, if any. */
138
+ text: string | null;
139
+ /** Tool calls Claude wants to make, if any. */
140
+ toolCalls: AiToolCall[] | null;
141
+ /** The reason Claude stopped generating. */
142
+ stopReason: 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence' | string;
143
+ /** Token usage for billing/metering. */
144
+ usage: {
145
+ inputTokens: number;
146
+ outputTokens: number;
147
+ };
148
+ }
149
+ /**
150
+ * Options for a streaming Claude completion.
151
+ *
152
+ * Extends {@link AiCompleteOptions} — same fields apply.
153
+ */
154
+ export type AiStreamOptions = AiCompleteOptions;
155
+ /**
156
+ * A single event emitted by a streaming Claude completion.
157
+ */
158
+ export type AiStreamEvent = {
159
+ type: 'text';
160
+ text: string;
161
+ } | {
162
+ type: 'tool_use';
163
+ toolCall: AiToolCall;
164
+ } | {
165
+ type: 'done';
166
+ result: AiCompleteResult;
167
+ };
168
+ /**
169
+ * The `sdk.ai` namespace.
170
+ *
171
+ * Provides direct access to Claude for kit applications and product backends.
172
+ * Handles model selection, tool calls, and streaming without boilerplate.
173
+ *
174
+ * @example Basic completion
175
+ * ```typescript
176
+ * const response = await sdk.ai.complete({
177
+ * messages: [{ role: 'user', content: 'What candles are low in stock?' }],
178
+ * systemPrompt: kit.shared.aiPersona,
179
+ * model: 'claude-haiku-4-5-20251001',
180
+ * tools: [searchInventoryTool],
181
+ * })
182
+ *
183
+ * if (response.toolCalls) {
184
+ * for (const call of response.toolCalls) {
185
+ * // execute tool and continue conversation
186
+ * }
187
+ * }
188
+ * ```
189
+ *
190
+ * @example Streaming
191
+ * ```typescript
192
+ * for await (const event of sdk.ai.stream({ messages, systemPrompt })) {
193
+ * if (event.type === 'text') process.stdout.write(event.text)
194
+ * if (event.type === 'done') console.log('Tokens:', event.result.usage)
195
+ * }
196
+ * ```
197
+ */
198
+ export interface AiModule {
199
+ /**
200
+ * Run a single Claude completion and return the full result.
201
+ *
202
+ * @param options - Completion options including messages, model, and tools.
203
+ * @returns The full completion result with text and/or tool calls.
204
+ * @throws {Error} If the Anthropic API returns an error.
205
+ */
206
+ complete(options: AiCompleteOptions): Promise<AiCompleteResult>;
207
+ /**
208
+ * Run a streaming Claude completion, yielding events as they arrive.
209
+ *
210
+ * @param options - Completion options (same as {@link AiModule.complete}).
211
+ * @returns An async iterable of stream events ending with a `done` event.
212
+ * @throws {Error} If the Anthropic API returns an error.
213
+ */
214
+ stream(options: AiStreamOptions): AsyncIterable<AiStreamEvent>;
215
+ }
216
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modules/ai/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @module modules/ai/types
3
+ * @description Type definitions for `sdk.ai.*` — the Claude AI integration module.
4
+ *
5
+ * Wraps the Anthropic Claude API with Soulcraft-specific defaults:
6
+ * - Canonical model IDs for each tier (haiku for speed, sonnet for quality, opus for complex)
7
+ * - Structured tool call handling with full type safety
8
+ * - Streaming support via async iteration
9
+ *
10
+ * The AI module does not depend on any particular transport — it calls the
11
+ * Anthropic API directly from the server process and is not proxied through Brainy.
12
+ */
13
+ // ─────────────────────────────────────────────────────────────────────────────
14
+ // Model tiers
15
+ // ─────────────────────────────────────────────────────────────────────────────
16
+ /**
17
+ * Canonical Anthropic model IDs for each Soulcraft platform tier.
18
+ *
19
+ * Use these constants instead of hardcoding model strings to ensure consistency
20
+ * across products and easier future upgrades.
21
+ */
22
+ export const AI_MODELS = {
23
+ /** Fast, affordable — routine lookups, data extraction, simple Q&A. */
24
+ haiku: 'claude-haiku-4-5-20251001',
25
+ /** Balanced — most kit operations, content generation, analysis. */
26
+ sonnet: 'claude-sonnet-4-6',
27
+ /** Most capable — complex reasoning, long-form synthesis, multi-step planning. */
28
+ opus: 'claude-opus-4-6',
29
+ };
30
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/modules/ai/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,uEAAuE;IACvE,KAAK,EAAE,2BAA2B;IAClC,oEAAoE;IACpE,MAAM,EAAE,mBAAmB;IAC3B,kFAAkF;IAClF,IAAI,EAAE,iBAAiB;CACf,CAAA"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @module modules/auth/backchannel
3
+ * @description OIDC back-channel logout handler factory for Soulcraft product backends.
4
+ *
5
+ * Implements the OpenID Connect Back-Channel Logout 1.0 specification. When a user
6
+ * signs out of the central IdP (`auth.soulcraft.com`), the IdP POSTs a signed
7
+ * `logout_token` (HS256 JWT) to every registered product's back-channel logout
8
+ * endpoint. This handler verifies the token and deletes all active sessions for
9
+ * the identified user, ensuring immediate logout across all products.
10
+ *
11
+ * ## Protocol
12
+ *
13
+ * 1. IdP POSTs `application/x-www-form-urlencoded` body with `logout_token` field
14
+ * 2. Handler verifies HS256 JWT signature using the OIDC client secret
15
+ * 3. Handler validates standard claims: `iss`, `aud`, `events` (must contain
16
+ * `http://schemas.openid.net/event/backchannel-logout`)
17
+ * 4. Handler deletes all better-auth sessions for the `sub` (user ID) claim
18
+ * 5. Returns 200 on success, 400 for malformed tokens, 401 for bad signatures
19
+ *
20
+ * ## Mounting (Hono)
21
+ *
22
+ * ```typescript
23
+ * import { createBackchannelLogoutHandler } from '@soulcraft/sdk/server'
24
+ *
25
+ * app.post('/api/auth/backchannel-logout', createBackchannelLogoutHandler({
26
+ * auth,
27
+ * clientSecret: process.env.SOULCRAFT_OIDC_CLIENT_SECRET!,
28
+ * idpUrl: process.env.SOULCRAFT_IDP_URL!,
29
+ * clientId: process.env.SOULCRAFT_OIDC_CLIENT_ID!,
30
+ * }))
31
+ * ```
32
+ */
33
+ import type { Context } from 'hono';
34
+ /** Minimal better-auth API surface needed for session deletion. */
35
+ export interface BackchannelAuthLike {
36
+ api: {
37
+ revokeUserSessions(opts: {
38
+ body: {
39
+ userId: string;
40
+ };
41
+ headers?: Headers;
42
+ }): Promise<unknown>;
43
+ };
44
+ }
45
+ /**
46
+ * @description Configuration for createBackchannelLogoutHandler().
47
+ */
48
+ export interface BackchannelLogoutConfig {
49
+ /** The product's better-auth instance (used to delete sessions). */
50
+ auth: BackchannelAuthLike;
51
+ /** This product's OIDC client secret — used to verify the logout_token signature. */
52
+ clientSecret: string;
53
+ /** The central IdP base URL — used to validate the `iss` claim. */
54
+ idpUrl: string;
55
+ /** This product's OIDC client ID — used to validate the `aud` claim. */
56
+ clientId: string;
57
+ }
58
+ /**
59
+ * @description Creates a Hono route handler for the OIDC back-channel logout endpoint.
60
+ *
61
+ * Mount at `POST /api/auth/backchannel-logout`. The handler:
62
+ * 1. Parses the `logout_token` from the form-encoded body
63
+ * 2. Verifies the HS256 JWT signature using the OIDC client secret
64
+ * 3. Validates `iss` (must match idpUrl), `aud` (must match clientId),
65
+ * and `events` (must contain the back-channel logout event URI)
66
+ * 4. Calls `auth.api.revokeUserSessions({ body: { userId: sub } })` to
67
+ * immediately invalidate all sessions for the identified user
68
+ * 5. Returns 200 on success, 400 for malformed/missing token, 401 for
69
+ * invalid signature or failed claims validation
70
+ *
71
+ * @param config - Auth instance, client secret, IdP URL, and client ID.
72
+ * @returns A Hono-compatible request handler function.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * app.post('/api/auth/backchannel-logout', createBackchannelLogoutHandler({
77
+ * auth,
78
+ * clientSecret: process.env.SOULCRAFT_OIDC_CLIENT_SECRET!,
79
+ * idpUrl: process.env.SOULCRAFT_IDP_URL!,
80
+ * clientId: process.env.SOULCRAFT_OIDC_CLIENT_ID!,
81
+ * }))
82
+ * ```
83
+ */
84
+ export declare function createBackchannelLogoutHandler(config: BackchannelLogoutConfig): (c: Context) => Promise<Response>;
85
+ //# sourceMappingURL=backchannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backchannel.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/backchannel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAMnC,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE;QACH,kBAAkB,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC;YAAC,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAC5F,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,IAAI,EAAE,mBAAmB,CAAA;IACzB,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAA;CACjB;AA0ED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,uBAAuB,GAC9B,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAgEnC"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * @module modules/auth/backchannel
3
+ * @description OIDC back-channel logout handler factory for Soulcraft product backends.
4
+ *
5
+ * Implements the OpenID Connect Back-Channel Logout 1.0 specification. When a user
6
+ * signs out of the central IdP (`auth.soulcraft.com`), the IdP POSTs a signed
7
+ * `logout_token` (HS256 JWT) to every registered product's back-channel logout
8
+ * endpoint. This handler verifies the token and deletes all active sessions for
9
+ * the identified user, ensuring immediate logout across all products.
10
+ *
11
+ * ## Protocol
12
+ *
13
+ * 1. IdP POSTs `application/x-www-form-urlencoded` body with `logout_token` field
14
+ * 2. Handler verifies HS256 JWT signature using the OIDC client secret
15
+ * 3. Handler validates standard claims: `iss`, `aud`, `events` (must contain
16
+ * `http://schemas.openid.net/event/backchannel-logout`)
17
+ * 4. Handler deletes all better-auth sessions for the `sub` (user ID) claim
18
+ * 5. Returns 200 on success, 400 for malformed tokens, 401 for bad signatures
19
+ *
20
+ * ## Mounting (Hono)
21
+ *
22
+ * ```typescript
23
+ * import { createBackchannelLogoutHandler } from '@soulcraft/sdk/server'
24
+ *
25
+ * app.post('/api/auth/backchannel-logout', createBackchannelLogoutHandler({
26
+ * auth,
27
+ * clientSecret: process.env.SOULCRAFT_OIDC_CLIENT_SECRET!,
28
+ * idpUrl: process.env.SOULCRAFT_IDP_URL!,
29
+ * clientId: process.env.SOULCRAFT_OIDC_CLIENT_ID!,
30
+ * }))
31
+ * ```
32
+ */
33
+ // The OIDC back-channel logout events claim URI.
34
+ const BACKCHANNEL_LOGOUT_EVENT = 'http://schemas.openid.net/event/backchannel-logout';
35
+ // ─────────────────────────────────────────────────────────────────────────────
36
+ // JWT verification helpers (Web Crypto API — no external deps)
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+ /**
39
+ * Verify an HS256 JWT using the Web Crypto API.
40
+ *
41
+ * @param token - Raw JWT string (`header.payload.signature`).
42
+ * @param secret - HMAC secret for signature verification.
43
+ * @returns The decoded payload if the signature is valid, or null.
44
+ */
45
+ async function verifyHS256JWT(token, secret) {
46
+ const parts = token.split('.');
47
+ if (parts.length !== 3)
48
+ return null;
49
+ const [headerB64, payloadB64, sigB64] = parts;
50
+ // Import the HMAC key
51
+ let key;
52
+ try {
53
+ key = await crypto.subtle.importKey('raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']);
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ // Verify signature over `header.payload`
59
+ const signingInput = `${headerB64}.${payloadB64}`;
60
+ let sigBytes;
61
+ try {
62
+ sigBytes = Uint8Array.from(atob(sigB64.replace(/-/g, '+').replace(/_/g, '/')), (c) => c.charCodeAt(0));
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ const valid = await crypto.subtle.verify('HMAC', key, sigBytes.buffer, new TextEncoder().encode(signingInput));
68
+ if (!valid)
69
+ return null;
70
+ // Decode payload
71
+ try {
72
+ const padded = payloadB64.replace(/-/g, '+').replace(/_/g, '/') +
73
+ '=='.slice(0, (4 - (payloadB64.length % 4)) % 4);
74
+ return JSON.parse(atob(padded));
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ // ─────────────────────────────────────────────────────────────────────────────
81
+ // createBackchannelLogoutHandler
82
+ // ─────────────────────────────────────────────────────────────────────────────
83
+ /**
84
+ * @description Creates a Hono route handler for the OIDC back-channel logout endpoint.
85
+ *
86
+ * Mount at `POST /api/auth/backchannel-logout`. The handler:
87
+ * 1. Parses the `logout_token` from the form-encoded body
88
+ * 2. Verifies the HS256 JWT signature using the OIDC client secret
89
+ * 3. Validates `iss` (must match idpUrl), `aud` (must match clientId),
90
+ * and `events` (must contain the back-channel logout event URI)
91
+ * 4. Calls `auth.api.revokeUserSessions({ body: { userId: sub } })` to
92
+ * immediately invalidate all sessions for the identified user
93
+ * 5. Returns 200 on success, 400 for malformed/missing token, 401 for
94
+ * invalid signature or failed claims validation
95
+ *
96
+ * @param config - Auth instance, client secret, IdP URL, and client ID.
97
+ * @returns A Hono-compatible request handler function.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * app.post('/api/auth/backchannel-logout', createBackchannelLogoutHandler({
102
+ * auth,
103
+ * clientSecret: process.env.SOULCRAFT_OIDC_CLIENT_SECRET!,
104
+ * idpUrl: process.env.SOULCRAFT_IDP_URL!,
105
+ * clientId: process.env.SOULCRAFT_OIDC_CLIENT_ID!,
106
+ * }))
107
+ * ```
108
+ */
109
+ export function createBackchannelLogoutHandler(config) {
110
+ const idpOrigin = config.idpUrl.replace(/\/$/, '');
111
+ return async function backchannelLogoutHandler(c) {
112
+ // Parse the logout_token from the form-encoded body
113
+ let logoutToken = null;
114
+ try {
115
+ const contentType = c.req.header('content-type') ?? '';
116
+ if (contentType.includes('application/x-www-form-urlencoded')) {
117
+ const body = await c.req.parseBody();
118
+ logoutToken = body['logout_token'] ?? null;
119
+ }
120
+ else {
121
+ // Also accept JSON body for easier testing
122
+ const body = await c.req.json();
123
+ logoutToken = body['logout_token'] ?? null;
124
+ }
125
+ }
126
+ catch {
127
+ return c.json({ error: 'Failed to parse request body' }, 400);
128
+ }
129
+ if (!logoutToken || typeof logoutToken !== 'string') {
130
+ return c.json({ error: 'Missing logout_token' }, 400);
131
+ }
132
+ // Verify the JWT
133
+ const payload = await verifyHS256JWT(logoutToken, config.clientSecret);
134
+ if (!payload) {
135
+ return c.json({ error: 'Invalid logout_token signature' }, 401);
136
+ }
137
+ // Validate issuer
138
+ if (payload['iss'] !== idpOrigin) {
139
+ return c.json({ error: 'Invalid issuer' }, 401);
140
+ }
141
+ // Validate audience — may be a string or array of strings
142
+ const aud = payload['aud'];
143
+ const audList = Array.isArray(aud) ? aud : [String(aud ?? '')];
144
+ if (!audList.includes(config.clientId)) {
145
+ return c.json({ error: 'Invalid audience' }, 401);
146
+ }
147
+ // Validate events claim
148
+ const events = payload['events'];
149
+ if (!events || !(BACKCHANNEL_LOGOUT_EVENT in events)) {
150
+ return c.json({ error: 'Missing backchannel logout event' }, 400);
151
+ }
152
+ // Extract the subject user ID
153
+ const sub = payload['sub'];
154
+ if (!sub || typeof sub !== 'string') {
155
+ return c.json({ error: 'Missing sub claim' }, 400);
156
+ }
157
+ // Revoke all sessions for this user
158
+ try {
159
+ await config.auth.api.revokeUserSessions({ body: { userId: sub } });
160
+ }
161
+ catch (err) {
162
+ console.error(`[SDK/backchannel] Failed to revoke sessions for user ${sub}:`, err);
163
+ return c.json({ error: 'Failed to revoke sessions' }, 500);
164
+ }
165
+ return c.json({ ok: true }, 200);
166
+ };
167
+ }
168
+ //# sourceMappingURL=backchannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backchannel.js","sourceRoot":"","sources":["../../../src/modules/auth/backchannel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @module modules/auth/config
3
+ * @description Shared constants, utilities, and environment helpers for Soulcraft
4
+ * platform authentication.
5
+ *
6
+ * Provides ONLY well-typed shared values — no `betterAuth()` wrappers. Each product
7
+ * (Workshop, Venue, Academy) assembles its own fully-typed `betterAuth()` configuration
8
+ * using these constants and utilities, keeping TypeScript inference intact end-to-end.
9
+ *
10
+ * ## Why no config factory functions?
11
+ *
12
+ * A factory returning a broad object type loses compile-time safety when passed to
13
+ * `betterAuth()`. The correct boundary is:
14
+ * - **This module** → exports typed field definitions, session config, and pure utilities
15
+ * - **Each product** → imports those exports and constructs its own `betterAuth()` call
16
+ *
17
+ * This absorbs and replaces `@soulcraft/auth/config`, which is deprecated.
18
+ *
19
+ * @example Workshop auth setup
20
+ * ```typescript
21
+ * import { betterAuth } from 'better-auth'
22
+ * import {
23
+ * SOULCRAFT_USER_FIELDS,
24
+ * SOULCRAFT_SESSION_CONFIG,
25
+ * computeEmailHash,
26
+ * } from '@soulcraft/sdk/server'
27
+ *
28
+ * export const auth = betterAuth({
29
+ * database: new Database('./auth.db'),
30
+ * secret: process.env.BETTER_AUTH_SECRET!,
31
+ * session: SOULCRAFT_SESSION_CONFIG,
32
+ * user: { additionalFields: SOULCRAFT_USER_FIELDS },
33
+ * databaseHooks: {
34
+ * user: { create: { before: async (user) => ({
35
+ * data: { ...user, emailHash: computeEmailHash(user.email), platformRole: 'creator' }
36
+ * })}}
37
+ * },
38
+ * })
39
+ * ```
40
+ */
41
+ import type { AuthMode, OIDCClientConfig } from './types.js';
42
+ /**
43
+ * Additional fields to register on the better-auth `user` table.
44
+ *
45
+ * Pass to `betterAuth({ user: { additionalFields: SOULCRAFT_USER_FIELDS } })`.
46
+ *
47
+ * `emailHash` must be populated at user-creation time via a
48
+ * `databaseHooks.user.create.before` hook. `platformRole` defaults to `'creator'`
49
+ * for Workshop; products override this in their own hook.
50
+ */
51
+ export declare const SOULCRAFT_USER_FIELDS: {
52
+ readonly platformRole: {
53
+ readonly type: "string";
54
+ readonly required: false;
55
+ readonly defaultValue: "creator";
56
+ };
57
+ readonly emailHash: {
58
+ readonly type: "string";
59
+ readonly required: false;
60
+ readonly defaultValue: "";
61
+ };
62
+ };
63
+ /**
64
+ * Session lifetime configuration shared across all Soulcraft products.
65
+ *
66
+ * Pass to `betterAuth({ session: SOULCRAFT_SESSION_CONFIG })`.
67
+ *
68
+ * - Sessions are valid for 30 days from issuance
69
+ * - Silently refreshed after 24 hours of activity, resetting the 30-day window
70
+ */
71
+ export declare const SOULCRAFT_SESSION_CONFIG: {
72
+ readonly expiresIn: number;
73
+ readonly updateAge: number;
74
+ };
75
+ /**
76
+ * Compute the SHA-256 hex digest of a canonical email address.
77
+ *
78
+ * The email is lower-cased and trimmed before hashing to ensure the same
79
+ * input always yields the same digest regardless of capitalisation or whitespace.
80
+ *
81
+ * Stored as `emailHash` on the user record. Used by Workshop to deterministically
82
+ * locate the user's Brainy data directory without exposing the raw email in paths.
83
+ *
84
+ * @param email - Raw email address (any case, may have leading/trailing whitespace).
85
+ * @returns 64-character lowercase hex SHA-256 digest.
86
+ *
87
+ * @example
88
+ * computeEmailHash('Alice@Example.COM') === computeEmailHash('alice@example.com') // true
89
+ * computeEmailHash('alice@example.com')
90
+ * // → 'b4c9a289522dd28a04617a41d7b14cf18d43d06febe513d9e27b5da67c17e52e'
91
+ */
92
+ export declare function computeEmailHash(email: string): string;
93
+ /**
94
+ * Determine the authentication mode from environment variables.
95
+ *
96
+ * - `'standalone'` — each product runs its own better-auth instance with a local
97
+ * SQLite database. No cross-product SSO. Default before `auth.soulcraft.com` is live.
98
+ * - `'oidc-client'` — set `SOULCRAFT_IDP_URL` to activate. The product's better-auth
99
+ * instance delegates all authentication to the central IdP.
100
+ *
101
+ * @returns The current auth mode derived from `SOULCRAFT_IDP_URL`.
102
+ */
103
+ export declare function getAuthMode(): AuthMode;
104
+ /**
105
+ * Read OIDC client configuration from environment variables.
106
+ *
107
+ * Returns `null` in standalone mode (when `SOULCRAFT_IDP_URL` is unset).
108
+ * Throws with a descriptive message if the URL is set but required variables
109
+ * are missing — prevents silent misconfiguration.
110
+ *
111
+ * | Variable | Required | Description |
112
+ * |------------------------------|----------|-----------------------------------------|
113
+ * | `SOULCRAFT_IDP_URL` | Yes | Central IdP base URL |
114
+ * | `SOULCRAFT_OIDC_CLIENT_ID` | Yes | This product's registered client ID |
115
+ * | `SOULCRAFT_OIDC_CLIENT_SECRET` | Yes | This product's registered client secret |
116
+ * | `SOULCRAFT_OIDC_REDIRECT_URI` | No | Deprecated — auto-derived from BETTER_AUTH_URL |
117
+ *
118
+ * @returns OIDC client config or null in standalone mode.
119
+ * @throws {Error} If `SOULCRAFT_IDP_URL` is set but client ID or secret are missing.
120
+ */
121
+ export declare function getOIDCClientConfig(): OIDCClientConfig | null;
122
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAM5D;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;CAWxB,CAAA;AAMV;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB;;;CAG3B,CAAA;AAMV;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAItD;AAMD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAuB7D"}