@karmaniverous/jeeves-server-core 0.3.0 → 0.5.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 (65) hide show
  1. package/README.md +58 -13
  2. package/dist/openapi.json.js +4038 -0
  3. package/dist/scripts/openapiInfo.d.ts +15 -0
  4. package/dist/src/catalog/browserSafe.test.d.ts +4 -0
  5. package/dist/src/catalog/contentEntries.d.ts +468 -0
  6. package/dist/src/catalog/contentEntries.js +150 -0
  7. package/dist/src/catalog/contentSchemas.d.ts +179 -0
  8. package/dist/src/catalog/contentSchemas.js +195 -0
  9. package/dist/src/catalog/descriptions.d.ts +52 -0
  10. package/dist/src/catalog/descriptions.js +54 -0
  11. package/dist/src/catalog/eventEntries.d.ts +70 -0
  12. package/dist/src/catalog/eventEntries.js +59 -0
  13. package/dist/src/catalog/fileMutateSchema.d.ts +41 -0
  14. package/dist/src/catalog/fileMutateSchema.js +77 -0
  15. package/dist/src/catalog/index.d.ts +15 -0
  16. package/dist/src/catalog/index.js +10 -0
  17. package/dist/src/catalog/oauthEntries.d.ts +125 -0
  18. package/dist/src/catalog/oauthEntries.js +92 -0
  19. package/dist/src/catalog/route.d.ts +137 -0
  20. package/dist/src/catalog/route.js +92 -0
  21. package/dist/src/catalog/runnerEntries.d.ts +145 -0
  22. package/dist/src/catalog/runnerEntries.js +69 -0
  23. package/dist/src/catalog/schemas.test.d.ts +4 -0
  24. package/dist/src/catalog/serverCatalog.d.ts +1143 -0
  25. package/dist/src/catalog/serverCatalog.js +37 -0
  26. package/dist/src/catalog/serverCatalog.test.d.ts +4 -0
  27. package/dist/src/catalog/sharingEntries.d.ts +200 -0
  28. package/dist/src/catalog/sharingEntries.js +146 -0
  29. package/dist/src/catalog/statusSchemas.d.ts +87 -0
  30. package/dist/src/catalog/statusSchemas.js +119 -0
  31. package/dist/src/catalog/utilityEntries.d.ts +151 -0
  32. package/dist/src/catalog/utilityEntries.js +62 -0
  33. package/dist/src/catalog/utilitySchemas.d.ts +98 -0
  34. package/dist/src/catalog/utilitySchemas.js +131 -0
  35. package/dist/src/configAuthSchema.d.ts +100 -0
  36. package/dist/src/configAuthSchema.js +119 -0
  37. package/dist/src/configFeatureSchemas.d.ts +43 -0
  38. package/dist/src/configFeatureSchemas.js +53 -0
  39. package/dist/src/configPrintStyles.d.ts +63 -0
  40. package/dist/src/configPrintStyles.js +98 -0
  41. package/dist/src/configPrintStyles.test.d.ts +1 -0
  42. package/dist/src/crypto.d.ts +6 -13
  43. package/dist/src/crypto.js +7 -32
  44. package/dist/src/crypto.test.d.ts +7 -0
  45. package/dist/src/errors.d.ts +51 -0
  46. package/dist/src/errors.js +97 -0
  47. package/dist/src/errors.test.d.ts +4 -0
  48. package/dist/src/index.d.ts +5 -2
  49. package/dist/src/index.js +18 -3
  50. package/dist/src/openapi.d.ts +13 -0
  51. package/dist/src/openapi.js +17 -0
  52. package/dist/src/openapi.test.d.ts +4 -0
  53. package/dist/src/schema.d.ts +21 -122
  54. package/dist/src/schema.js +39 -153
  55. package/dist/src/schema.publicUrl.test.d.ts +1 -0
  56. package/dist/src/schema.test.d.ts +1 -0
  57. package/dist/src/types.d.ts +7 -0
  58. package/dist/src/urlKey.d.ts +24 -0
  59. package/dist/src/urlKey.js +43 -0
  60. package/dist/src/urlKey.test.d.ts +1 -0
  61. package/openapi.json +3934 -0
  62. package/package.json +31 -16
  63. package/dist/src/endpoints.d.ts +0 -34
  64. package/dist/src/endpoints.js +0 -235
  65. /package/dist/src/{endpoints.test.d.ts → configAuthSchema.test.d.ts} +0 -0
@@ -1,135 +1,19 @@
1
1
  import { z } from 'zod';
2
+ import type { authModeSchema } from './configAuthSchema.js';
3
+ import { brandingSchema } from './configFeatureSchemas.js';
4
+ export { authModeSchema, authSchema, emailAuthSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, keyEntrySchema, scopesObjectSchema, scopesSchema, } from './configAuthSchema.js';
5
+ export type { LoggingConfig } from './configFeatureSchemas.js';
6
+ export { brandingSchema, loggingConfigSchema, oauthProviderSchema, oauthSchema, themeOverridesSchema, } from './configFeatureSchemas.js';
2
7
  /** Config properties deprecated in v3.6.0 (now resolved via core services). */
3
8
  export declare const DEPRECATED_CONFIG_PROPS: readonly ["host", "runnerUrl", "watcherUrl", "metaUrl"];
4
- /** Supported authentication methods */
5
- export declare const authModeSchema: z.ZodEnum<{
6
- keys: "keys";
7
- google: "google";
8
- email: "email";
9
- }>;
10
- /** Google OAuth configuration */
11
- export declare const googleAuthSchema: z.ZodObject<{
12
- clientId: z.ZodString;
13
- clientSecret: z.ZodString;
14
- }, z.core.$strip>;
15
- /** Email (magic link) authentication configuration */
16
- export declare const emailAuthSchema: z.ZodObject<{
17
- smtpUrl: z.ZodString;
18
- fromAddress: z.ZodEmail;
19
- }, z.core.$strip>;
20
- /** Auth configuration */
21
- export declare const authSchema: z.ZodObject<{
22
- modes: z.ZodArray<z.ZodEnum<{
23
- keys: "keys";
24
- google: "google";
25
- email: "email";
26
- }>>;
27
- google: z.ZodOptional<z.ZodObject<{
28
- clientId: z.ZodString;
29
- clientSecret: z.ZodString;
30
- }, z.core.$strip>>;
31
- sessionSecret: z.ZodOptional<z.ZodString>;
32
- email: z.ZodOptional<z.ZodObject<{
33
- smtpUrl: z.ZodString;
34
- fromAddress: z.ZodEmail;
35
- }, z.core.$strip>>;
36
- }, z.core.$strip>;
37
- /** Event webhook configuration */
38
- export declare const eventConfigSchema: z.ZodObject<{
39
- schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
40
- cmd: z.ZodString;
41
- map: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
42
- timeoutMs: z.ZodOptional<z.ZodNumber>;
43
- }, z.core.$strip>;
44
- /**
45
- * Scopes configuration — controls which paths a user/key can access.
46
- *
47
- * Three forms:
48
- * - `string` — single allow pattern (e.g. '/d/*')
49
- * - `string[]` — array of allow patterns (shorthand for \{ allow: [...] \})
50
- * - `\{ allow?: string[], deny?: string[] \}` — explicit allow/deny rules
51
- *
52
- * Semantics:
53
- * - Path must match at least one allow rule AND NOT match any deny rule
54
- * - Omitting `allow` = implicit ['/*'] (allow everything)
55
- * - Omitting `deny` = no exclusions
56
- * - Omitting scopes entirely = unrestricted access
57
- */
58
- export declare const scopesObjectSchema: z.ZodObject<{
59
- allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
- deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
- }, z.core.$strip>;
62
- export declare const scopesSchema: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
63
- allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
64
- deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
65
- }, z.core.$strip>]>;
66
- /** Insider entry (identity + scopes + optional persisted seed) */
67
- export declare const insiderEntrySchema: z.ZodObject<{
68
- scopes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
69
- allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
- deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
71
- }, z.core.$strip>]>>;
72
- allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
73
- deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
74
- seed: z.ZodOptional<z.ZodString>;
75
- keyCreatedAt: z.ZodOptional<z.ZodString>;
76
- }, z.core.$strip>;
77
- /** Key entry — plain string (seed, no scopes) or object with key + optional scopes */
78
- export declare const keyEntrySchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
79
- key: z.ZodString;
80
- scopes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
81
- allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
82
- deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
83
- }, z.core.$strip>]>>;
84
- allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
85
- deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
86
- }, z.core.$strip>]>;
87
- /** Check if a string is a named scope identifier (not a path glob). */
88
- export declare function isScopeName(v: string): boolean;
89
- /** Logging configuration. Not hot-reloadable — changes require service restart. */
90
- export declare const loggingConfigSchema: z.ZodObject<{
91
- level: z.ZodOptional<z.ZodString>;
92
- file: z.ZodOptional<z.ZodString>;
93
- }, z.core.$strip>;
94
- /** Inferred logging config type. */
95
- export type LoggingConfig = z.infer<typeof loggingConfigSchema>;
96
- /** OAuth provider configuration */
97
- export declare const oauthProviderSchema: z.ZodObject<{
98
- authUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
99
- tokenUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
100
- pkce: z.ZodDefault<z.ZodBoolean>;
101
- defaultScopes: z.ZodDefault<z.ZodArray<z.ZodString>>;
102
- }, z.core.$strip>;
103
- /** OAuth configuration */
104
- export declare const oauthSchema: z.ZodObject<{
105
- credentialDir: z.ZodString;
106
- providers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
107
- authUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
108
- tokenUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
109
- pkce: z.ZodDefault<z.ZodBoolean>;
110
- defaultScopes: z.ZodDefault<z.ZodArray<z.ZodString>>;
111
- }, z.core.$strip>>>;
112
- }, z.core.$strip>;
113
- /** Theme overrides for light and dark modes */
114
- export declare const themeOverridesSchema: z.ZodRecord<z.ZodString, z.ZodString>;
115
- /** Instance branding configuration */
116
- export declare const brandingSchema: z.ZodObject<{
117
- name: z.ZodDefault<z.ZodString>;
118
- emoji: z.ZodDefault<z.ZodString>;
119
- theme: z.ZodOptional<z.ZodObject<{
120
- light: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
121
- dark: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
122
- }, z.core.$strip>>;
123
- emailTemplate: z.ZodOptional<z.ZodString>;
124
- }, z.core.$strip>;
125
9
  /** Top-level Jeeves Server configuration */
126
10
  export declare const jeevesConfigSchema: z.ZodObject<{
127
11
  port: z.ZodDefault<z.ZodNumber>;
128
12
  chromePath: z.ZodString;
129
13
  auth: z.ZodObject<{
130
14
  modes: z.ZodArray<z.ZodEnum<{
131
- keys: "keys";
132
15
  google: "google";
16
+ keys: "keys";
133
17
  email: "email";
134
18
  }>>;
135
19
  google: z.ZodOptional<z.ZodObject<{
@@ -141,6 +25,7 @@ export declare const jeevesConfigSchema: z.ZodObject<{
141
25
  smtpUrl: z.ZodString;
142
26
  fromAddress: z.ZodEmail;
143
27
  }, z.core.$strip>>;
28
+ accessContact: z.ZodOptional<z.ZodString>;
144
29
  }, z.core.$strip>;
145
30
  scopes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
146
31
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -182,6 +67,19 @@ export declare const jeevesConfigSchema: z.ZodObject<{
182
67
  servers: z.ZodOptional<z.ZodArray<z.ZodURL>>;
183
68
  }, z.core.$strip>>;
184
69
  diagramCachePath: z.ZodOptional<z.ZodString>;
70
+ exportCachePath: z.ZodOptional<z.ZodString>;
71
+ printStyles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
72
+ css: z.ZodString;
73
+ page: z.ZodOptional<z.ZodObject<{
74
+ format: z.ZodOptional<z.ZodString>;
75
+ width: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
76
+ height: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
77
+ margin: z.ZodOptional<z.ZodString>;
78
+ }, z.core.$strip>>;
79
+ headerTemplate: z.ZodOptional<z.ZodString>;
80
+ footerTemplate: z.ZodOptional<z.ZodString>;
81
+ assets: z.ZodOptional<z.ZodString>;
82
+ }, z.core.$strip>>>;
185
83
  outsiderPolicy: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
186
84
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
187
85
  deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -212,6 +110,7 @@ export declare const jeevesConfigSchema: z.ZodObject<{
212
110
  eventQueue: z.ZodOptional<z.ZodString>;
213
111
  eventQueueConcurrency: z.ZodDefault<z.ZodNumber>;
214
112
  publicUrl: z.ZodOptional<z.ZodURL>;
113
+ trustProxyHeaders: z.ZodDefault<z.ZodBoolean>;
215
114
  }, z.core.$strip>;
216
115
  /** Inferred config type */
217
116
  export type JeevesConfig = z.infer<typeof jeevesConfigSchema>;
@@ -1,5 +1,10 @@
1
1
  import { SERVER_PORT } from '@karmaniverous/jeeves';
2
2
  import { z } from 'zod';
3
+ import { authSchema, scopesSchema, eventConfigSchema, keyEntrySchema, insiderEntrySchema, scopesObjectSchema, getScopeRefs } from './configAuthSchema.js';
4
+ export { authModeSchema, emailAuthSchema, googleAuthSchema, isScopeName } from './configAuthSchema.js';
5
+ import { brandingSchema, oauthSchema, loggingConfigSchema } from './configFeatureSchemas.js';
6
+ export { oauthProviderSchema, themeOverridesSchema } from './configFeatureSchemas.js';
7
+ import { absolutePathSchema, printStylesSchema } from './configPrintStyles.js';
3
8
 
4
9
  /** Config properties deprecated in v3.6.0 (now resolved via core services). */
5
10
  const DEPRECATED_CONFIG_PROPS = [
@@ -8,151 +13,6 @@ const DEPRECATED_CONFIG_PROPS = [
8
13
  'watcherUrl',
9
14
  'metaUrl',
10
15
  ];
11
- /** Supported authentication methods */
12
- const authModeSchema = z.enum(['google', 'keys', 'email']);
13
- /** Google OAuth configuration */
14
- const googleAuthSchema = z.object({
15
- clientId: z.string().min(1),
16
- clientSecret: z.string().min(1),
17
- });
18
- /** Email (magic link) authentication configuration */
19
- const emailAuthSchema = z.object({
20
- /** SMTP connection string (e.g. smtps://user:pass\@smtp.example.com:465) */
21
- smtpUrl: z.string().min(1),
22
- /** Sender email address for magic link emails */
23
- fromAddress: z.email(),
24
- });
25
- /** Auth configuration */
26
- const authSchema = z.object({
27
- /** Active authentication methods. Order determines priority. */
28
- modes: z
29
- .array(authModeSchema)
30
- .min(1, { message: 'At least one auth mode is required' }),
31
- /** Google OAuth config. Required if modes includes "google". */
32
- google: googleAuthSchema.optional(),
33
- /** Session cookie signing secret. Required if modes includes "google". */
34
- sessionSecret: z.string().min(1).optional(),
35
- /** Email (magic link) auth config. Required if modes includes "email". */
36
- email: emailAuthSchema.optional(),
37
- });
38
- /** Event webhook configuration */
39
- const eventConfigSchema = z.object({
40
- schema: z.record(z.string(), z.unknown()),
41
- cmd: z.string(),
42
- map: z.record(z.string(), z.unknown()).optional(),
43
- timeoutMs: z.number().positive().optional(),
44
- });
45
- /**
46
- * Scopes configuration — controls which paths a user/key can access.
47
- *
48
- * Three forms:
49
- * - `string` — single allow pattern (e.g. '/d/*')
50
- * - `string[]` — array of allow patterns (shorthand for \{ allow: [...] \})
51
- * - `\{ allow?: string[], deny?: string[] \}` — explicit allow/deny rules
52
- *
53
- * Semantics:
54
- * - Path must match at least one allow rule AND NOT match any deny rule
55
- * - Omitting `allow` = implicit ['/*'] (allow everything)
56
- * - Omitting `deny` = no exclusions
57
- * - Omitting scopes entirely = unrestricted access
58
- */
59
- const scopesObjectSchema = z.object({
60
- allow: z.array(z.string()).optional(),
61
- deny: z.array(z.string()).optional(),
62
- });
63
- const scopesSchema = z.union([
64
- z.string(),
65
- z.array(z.string()),
66
- scopesObjectSchema,
67
- ]);
68
- /** Insider entry (identity + scopes + optional persisted seed) */
69
- const insiderEntrySchema = z.object({
70
- scopes: scopesSchema.optional(),
71
- /** Extra allow patterns merged on top of named scope references */
72
- allow: z.array(z.string()).optional(),
73
- /** Extra deny patterns merged on top of named scope references */
74
- deny: z.array(z.string()).optional(),
75
- /** Auto-generated insider seed, persisted in config.json */
76
- seed: z.string().min(1).optional(),
77
- /** ISO timestamp of when the seed was created */
78
- keyCreatedAt: z.string().optional(),
79
- });
80
- /** Key entry — plain string (seed, no scopes) or object with key + optional scopes */
81
- const keyEntrySchema = z.union([
82
- z.string().min(1),
83
- z.object({
84
- key: z.string().min(1),
85
- scopes: scopesSchema.optional(),
86
- /** Extra allow patterns merged on top of named scope references */
87
- allow: z.array(z.string()).optional(),
88
- /** Extra deny patterns merged on top of named scope references */
89
- deny: z.array(z.string()).optional(),
90
- }),
91
- ]);
92
- /** Check if a string is a named scope identifier (not a path glob). */
93
- function isScopeName(v) {
94
- return /^[A-Za-z0-9_-]+$/.test(v);
95
- }
96
- /** Helper: collect named scope references from a scopes field value.
97
- *
98
- * Backward-compat note: `scopes` has historically accepted path globs like "/**" or ["/a","/b"].
99
- * We only treat values as *named scope references* if they look like identifiers
100
- * (e.g. "restricted", "no-vc") rather than path globs.
101
- */
102
- function getScopeRefs(scopes) {
103
- if (typeof scopes === 'string')
104
- return isScopeName(scopes) ? [scopes] : [];
105
- if (Array.isArray(scopes) && scopes.length > 0) {
106
- const strs = scopes.filter((v) => typeof v === 'string');
107
- if (strs.length !== scopes.length)
108
- return [];
109
- return strs.filter((v) => isScopeName(v));
110
- }
111
- return [];
112
- }
113
- /** Logging configuration. Not hot-reloadable — changes require service restart. */
114
- const loggingConfigSchema = z.object({
115
- /** Log level. */
116
- level: z
117
- .string()
118
- .optional()
119
- .describe('Logging level (trace, debug, info, warn, error, fatal).'),
120
- /** Log file path. */
121
- file: z
122
- .string()
123
- .optional()
124
- .describe('Path to log file (logs to stdout if omitted).'),
125
- });
126
- /** OAuth provider configuration */
127
- const oauthProviderSchema = z.object({
128
- authUrl: z.string().pipe(z.url()),
129
- tokenUrl: z.string().pipe(z.url()),
130
- pkce: z.boolean().default(false),
131
- defaultScopes: z.array(z.string()).default([]),
132
- });
133
- /** OAuth configuration */
134
- const oauthSchema = z.object({
135
- credentialDir: z.string(),
136
- providers: z.record(z.string(), oauthProviderSchema).default({}),
137
- });
138
- /** Theme overrides for light and dark modes */
139
- const themeOverridesSchema = z.record(z.string(), z.string());
140
- /** Instance branding configuration */
141
- const brandingSchema = z.object({
142
- /** Instance display name (used in page title, navbar, emails) */
143
- name: z.string().default('Jeeves Server'),
144
- /** Instance emoji (used as home icon in navbar) */
145
- emoji: z.string().default('🎩'),
146
- /** CSS variable overrides grouped by theme mode */
147
- theme: z
148
- .object({
149
- light: themeOverridesSchema.optional(),
150
- dark: themeOverridesSchema.optional(),
151
- })
152
- .optional(),
153
- /** Handlebars template for magic link emails. Supports \{\{magicLink\}\}, \{\{branding.name\}\}, \{\{branding.emoji\}\} */
154
- emailTemplate: z.string().optional(),
155
- });
156
16
  /** Top-level Jeeves Server configuration */
157
17
  const jeevesConfigSchema = z
158
18
  .object({
@@ -197,6 +57,16 @@ const jeevesConfigSchema = z
197
57
  * Defaults to `.diagram-cache` in the server working directory.
198
58
  */
199
59
  diagramCachePath: z.string().optional(),
60
+ /**
61
+ * Directory for cached PDF/DOCX exports. Defaults to `.export-cache` in
62
+ * the server working directory. Read at startup.
63
+ */
64
+ exportCachePath: z.string().optional(),
65
+ /**
66
+ * Named PDF print styles (#316): absolute paths to a stylesheet and
67
+ * optional header/footer templates and assets directory, read on use.
68
+ */
69
+ printStyles: printStylesSchema.optional(),
200
70
  /**
201
71
  * Global outsider policy — constrains which paths are eligible for outsider sharing.
202
72
  * Uses the same allow/deny model as insider scopes.
@@ -228,17 +98,17 @@ const jeevesConfigSchema = z
228
98
  /** Instance branding (name, emoji, theme overrides, email template) */
229
99
  branding: brandingSchema.optional(),
230
100
  /** Absolute path to the durable event queue JSONL file. Cursor file is derived as eventQueue + '.cursor'. */
231
- eventQueue: z
232
- .string()
233
- .min(1)
234
- .refine((p) => p.startsWith('/') ||
235
- /^[A-Za-z]:[\\/]/.test(p) ||
236
- p.startsWith('\\\\'), { message: 'eventQueue must be an absolute path' })
237
- .optional(),
101
+ eventQueue: absolutePathSchema('eventQueue').optional(),
238
102
  /** Maximum number of event queue entries processed concurrently. Defaults to 3. */
239
103
  eventQueueConcurrency: z.number().int().positive().default(3),
240
104
  /** Public base URL (e.g. https://jeeves.johngalt.id). When set, API responses include full public URLs. */
241
105
  publicUrl: z.url().optional(),
106
+ /**
107
+ * Trust `X-Forwarded-Proto` / `X-Forwarded-Host` / `Host` to build the
108
+ * public origin when `publicUrl` is unset. Enable only behind a proxy
109
+ * that sets or strips these headers itself. Default: false.
110
+ */
111
+ trustProxyHeaders: z.boolean().default(false),
242
112
  })
243
113
  .superRefine((config, ctx) => {
244
114
  // Google auth mode requires google config + sessionSecret
@@ -275,6 +145,22 @@ const jeevesConfigSchema = z
275
145
  });
276
146
  }
277
147
  }
148
+ // Login links and OAuth redirects are absolute URLs on a trusted public
149
+ // origin: publicUrl, or forwarding headers only when explicitly trusted.
150
+ const loginFlows = [
151
+ config.auth.modes.includes('email') ? 'email login' : null,
152
+ config.auth.modes.includes('google') ? 'Google login' : null,
153
+ config.oauth ? 'OAuth (oauth)' : null,
154
+ ].filter((flow) => flow !== null);
155
+ if (loginFlows.length > 0 &&
156
+ !config.publicUrl &&
157
+ !config.trustProxyHeaders) {
158
+ ctx.addIssue({
159
+ code: 'custom',
160
+ message: `publicUrl is required when ${loginFlows.join(', ')} is configured (or set trustProxyHeaders: true behind a proxy that sets X-Forwarded-* headers)`,
161
+ path: ['publicUrl'],
162
+ });
163
+ }
278
164
  // Keys auth mode requires at least one key
279
165
  if (config.auth.modes.includes('keys') &&
280
166
  Object.keys(config.keys).length === 0) {
@@ -330,4 +216,4 @@ const DEFAULT_BRANDING = {
330
216
  emoji: '🎩',
331
217
  };
332
218
 
333
- export { DEFAULT_BRANDING, DEPRECATED_CONFIG_PROPS, authModeSchema, authSchema, brandingSchema, emailAuthSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, jeevesConfigSchema, keyEntrySchema, loggingConfigSchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema, themeOverridesSchema };
219
+ export { DEFAULT_BRANDING, DEPRECATED_CONFIG_PROPS, authSchema, brandingSchema, eventConfigSchema, insiderEntrySchema, jeevesConfigSchema, keyEntrySchema, loggingConfigSchema, oauthSchema, scopesObjectSchema, scopesSchema };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -17,6 +17,11 @@ export interface ShareResponse {
17
17
  exp: string | null;
18
18
  depth?: number;
19
19
  dirs?: boolean;
20
+ /**
21
+ * Whether the shared path is an existing directory. Sent by servers from
22
+ * 3.15.0; absent from older servers.
23
+ */
24
+ isDirectory?: boolean;
20
25
  }
21
26
  /** POST /api/util/share-for request body. */
22
27
  export interface ShareForRequest {
@@ -73,6 +78,8 @@ export type FileMutationAction = 'edit-block' | 'delete-block' | 'insert-block'
73
78
  export interface RotateKeyResponse {
74
79
  ok: boolean;
75
80
  keyCreatedAt: string;
81
+ /** What stopped working: the insider key and the insider's outsider links. */
82
+ invalidates: ('insiderKey' | 'outsiderLinks')[];
76
83
  }
77
84
  /** GET /api/auth/status response. */
78
85
  export interface AuthStatusResponse {
@@ -0,0 +1,24 @@
1
+ /**
2
+ * URL auth-key query parameter names and a reader that accepts both: `k`
3
+ * (generated since 3.15.0) and the legacy `key`. Pure; no I/O.
4
+ *
5
+ * @remarks
6
+ * OpenClaw masks the value of any query parameter named `key` in
7
+ * model-visible tool output, so agents could not relay share links (#279).
8
+ * Generated URLs therefore carry the key as `k`. `key` is still accepted
9
+ * everywhere so existing links, bookmarks and webhook URLs keep working.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ /** Query parameter name used for auth keys in every generated URL. */
14
+ export declare const URL_KEY_PARAM = "k";
15
+ /** Legacy query parameter name, still accepted for backward compatibility. */
16
+ export declare const LEGACY_URL_KEY_PARAM = "key";
17
+ /**
18
+ * Read the auth key from a parsed query object or `URLSearchParams`.
19
+ * `k` wins when both names are present; empty values count as absent.
20
+ *
21
+ * @param query - Parsed query (e.g. Fastify `request.query`) or search params.
22
+ * @returns The key, or `undefined` when neither parameter carries one.
23
+ */
24
+ export declare function getUrlKey(query: unknown): string | undefined;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * URL auth-key query parameter names and a reader that accepts both: `k`
3
+ * (generated since 3.15.0) and the legacy `key`. Pure; no I/O.
4
+ *
5
+ * @remarks
6
+ * OpenClaw masks the value of any query parameter named `key` in
7
+ * model-visible tool output, so agents could not relay share links (#279).
8
+ * Generated URLs therefore carry the key as `k`. `key` is still accepted
9
+ * everywhere so existing links, bookmarks and webhook URLs keep working.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ /** Query parameter name used for auth keys in every generated URL. */
14
+ const URL_KEY_PARAM = 'k';
15
+ /** Legacy query parameter name, still accepted for backward compatibility. */
16
+ const LEGACY_URL_KEY_PARAM = 'key';
17
+ /** First non-empty string in a parsed query value (string or repeated). */
18
+ function firstString(value) {
19
+ const candidate = Array.isArray(value) ? value[0] : value;
20
+ return typeof candidate === 'string' && candidate !== ''
21
+ ? candidate
22
+ : undefined;
23
+ }
24
+ /**
25
+ * Read the auth key from a parsed query object or `URLSearchParams`.
26
+ * `k` wins when both names are present; empty values count as absent.
27
+ *
28
+ * @param query - Parsed query (e.g. Fastify `request.query`) or search params.
29
+ * @returns The key, or `undefined` when neither parameter carries one.
30
+ */
31
+ function getUrlKey(query) {
32
+ if (query instanceof URLSearchParams) {
33
+ return (firstString(query.get(URL_KEY_PARAM)) ??
34
+ firstString(query.get(LEGACY_URL_KEY_PARAM)));
35
+ }
36
+ if (query === null || typeof query !== 'object')
37
+ return undefined;
38
+ const record = query;
39
+ return (firstString(record[URL_KEY_PARAM]) ??
40
+ firstString(record[LEGACY_URL_KEY_PARAM]));
41
+ }
42
+
43
+ export { LEGACY_URL_KEY_PARAM, URL_KEY_PARAM, getUrlKey };
@@ -0,0 +1 @@
1
+ export {};