@karmaniverous/jeeves-server-core 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -14,6 +14,21 @@ Shared workspace package providing cryptographic utilities and API types consume
14
14
  | `computeDeepShareKey(seed, path, params)` | HMAC-SHA256 key for deep directory shares with depth/dirs/stack/expiry |
15
15
  | `timingSafeEqual(a, b)` | Constant-time string comparison to prevent timing attacks |
16
16
 
17
+ ### Config Schema
18
+
19
+ | Export | Description |
20
+ |--------|-------------|
21
+ | `loggingConfigSchema` | Zod schema for `logging` config block (`level`, `file`, both optional) |
22
+ | `LoggingConfig` | Inferred TypeScript type from `loggingConfigSchema` |
23
+ | `jeevesConfigSchema` | Full server config Zod schema (includes `logging`, `oauth`, all other fields) |
24
+
25
+ ### Endpoint Catalog
26
+
27
+ | Export | Description |
28
+ |--------|-------------|
29
+ | `EndpointEntry` | Interface describing a single API operation (method, path, description, auth flags) |
30
+ | `serverEndpoints` | Complete declarative catalog of all jeeves-server API endpoints (38 entries) |
31
+
17
32
  ### API Types
18
33
 
19
34
  | Type | Description |
@@ -36,6 +51,9 @@ Shared workspace package providing cryptographic utilities and API types consume
36
51
  import {
37
52
  computeInsiderKey,
38
53
  computePathKey,
54
+ serverEndpoints,
55
+ type EndpointEntry,
56
+ type LoggingConfig,
39
57
  type ShareRequest,
40
58
  } from '@karmaniverous/jeeves-server-core';
41
59
  ```
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Declarative endpoint catalog — single source of truth for the jeeves-server
3
+ * API surface. Consumers (CLI, OpenClaw plugin) derive their registrations
4
+ * from this catalog.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import type { z } from 'zod';
9
+ /**
10
+ * Describes a single API operation.
11
+ */
12
+ export interface EndpointEntry {
13
+ /** HTTP method. */
14
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
15
+ /** URL path pattern (Fastify-style, e.g. '/api/file/*'). */
16
+ path: string;
17
+ /** Human-readable operation description. */
18
+ description: string;
19
+ /** Zod schema for query params (GET) or request body (POST/PUT). */
20
+ params?: z.ZodType;
21
+ /** Zod schema for the response body. */
22
+ response?: z.ZodType;
23
+ /** Whether the endpoint requires insider auth. */
24
+ insiderOnly?: boolean;
25
+ /** Whether the endpoint is unauthenticated. */
26
+ unauthenticated?: boolean;
27
+ }
28
+ /**
29
+ * Complete API endpoint catalog for jeeves-server.
30
+ *
31
+ * Keys are stable operation identifiers used by consumers to reference
32
+ * specific endpoints. Values describe the HTTP operation.
33
+ */
34
+ export declare const serverEndpoints: Record<string, EndpointEntry>;
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Declarative endpoint catalog — single source of truth for the jeeves-server
3
+ * API surface. Consumers (CLI, OpenClaw plugin) derive their registrations
4
+ * from this catalog.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ /**
9
+ * Complete API endpoint catalog for jeeves-server.
10
+ *
11
+ * Keys are stable operation identifiers used by consumers to reference
12
+ * specific endpoints. Values describe the HTTP operation.
13
+ */
14
+ const serverEndpoints = {
15
+ // --- Status & Config ---
16
+ status: {
17
+ method: 'GET',
18
+ path: '/status',
19
+ description: 'Server health: name, version, uptime, status, health details.',
20
+ unauthenticated: true,
21
+ },
22
+ config: {
23
+ method: 'GET',
24
+ path: '/config',
25
+ description: 'Query running config with optional JSONPath filter (?path=).',
26
+ unauthenticated: true,
27
+ },
28
+ 'config-apply': {
29
+ method: 'POST',
30
+ path: '/config/apply',
31
+ description: 'Push config patch to running service (deep-merge + validate + reload).',
32
+ insiderOnly: true,
33
+ },
34
+ // --- Authentication ---
35
+ 'auth-status': {
36
+ method: 'GET',
37
+ path: '/api/auth/status',
38
+ description: 'Check current authentication status (no auth required).',
39
+ unauthenticated: true,
40
+ },
41
+ 'auth-login': {
42
+ method: 'GET',
43
+ path: '/auth/login',
44
+ description: 'Redirect to Google OAuth consent screen.',
45
+ unauthenticated: true,
46
+ },
47
+ 'auth-callback': {
48
+ method: 'GET',
49
+ path: '/auth/callback',
50
+ description: 'Handle Google OAuth callback, set session cookie.',
51
+ unauthenticated: true,
52
+ },
53
+ 'auth-logout': {
54
+ method: 'GET',
55
+ path: '/auth/logout',
56
+ description: 'Clear session cookie.',
57
+ unauthenticated: true,
58
+ },
59
+ // --- File Browser ---
60
+ drives: {
61
+ method: 'GET',
62
+ path: '/api/drives',
63
+ description: 'List available root drives/labels configured on the server.',
64
+ },
65
+ path: {
66
+ method: 'GET',
67
+ path: '/api/path/*',
68
+ description: 'Get directory listing for a path.',
69
+ },
70
+ 'file-get': {
71
+ method: 'GET',
72
+ path: '/api/file/*',
73
+ description: 'Get file content with type-specific handling (markdown, csv, diagrams, etc.).',
74
+ },
75
+ 'file-put': {
76
+ method: 'PUT',
77
+ path: '/api/file/*',
78
+ description: 'Overwrite file content (insider-only; file must already exist).',
79
+ insiderOnly: true,
80
+ },
81
+ 'file-mutate': {
82
+ method: 'POST',
83
+ path: '/api/file/*',
84
+ description: 'Apply structured .md mutations: edit-block, delete-block, insert-block, edit-cell, toggle-checkbox.',
85
+ insiderOnly: true,
86
+ },
87
+ raw: {
88
+ method: 'GET',
89
+ path: '/api/raw/*',
90
+ description: 'Direct file download with appropriate content type.',
91
+ },
92
+ // --- Export ---
93
+ export: {
94
+ method: 'GET',
95
+ path: '/api/export/*',
96
+ description: 'Trigger export (PDF, DOCX, ZIP) and return download.',
97
+ },
98
+ 'export-cache-clear': {
99
+ method: 'DELETE',
100
+ path: '/api/export-cache/*',
101
+ description: 'Clear export and diagram caches for a given path.',
102
+ insiderOnly: true,
103
+ },
104
+ 'mermaid-export': {
105
+ method: 'GET',
106
+ path: '/api/mermaid-export/*',
107
+ description: 'Export Mermaid diagram (svg, png, pdf).',
108
+ },
109
+ 'plantuml-export': {
110
+ method: 'GET',
111
+ path: '/api/plantuml-export/*',
112
+ description: 'Export PlantUML diagram (svg, png, pdf, eps).',
113
+ },
114
+ // --- Diagrams ---
115
+ diagram: {
116
+ method: 'GET',
117
+ path: '/api/diagram/:type/:hash',
118
+ description: 'Fetch rendered diagram by type and content hash.',
119
+ unauthenticated: true,
120
+ },
121
+ // --- Sharing ---
122
+ share: {
123
+ method: 'POST',
124
+ path: '/api/share',
125
+ description: 'Generate HMAC-signed share link for a path.',
126
+ insiderOnly: true,
127
+ },
128
+ 'share-for': {
129
+ method: 'POST',
130
+ path: '/api/util/share-for',
131
+ description: 'Generate share link targeting specific insiders with configurable expiry/depth.',
132
+ insiderOnly: true,
133
+ },
134
+ 'readme-link': {
135
+ method: 'GET',
136
+ path: '/api/readme-link',
137
+ description: 'Pre-computed share link for the first README.md in the directory hierarchy.',
138
+ unauthenticated: true,
139
+ },
140
+ 'content-link': {
141
+ method: 'GET',
142
+ path: '/api/content-link/:file',
143
+ description: 'Pre-computed deep share URL for pinned content files (privacy, terms).',
144
+ unauthenticated: true,
145
+ },
146
+ 'link-info': {
147
+ method: 'GET',
148
+ path: '/api/link-info/*',
149
+ description: 'Query available link types for a path (page, raw, PDF, DOCX, etc.).',
150
+ },
151
+ 'rotate-key': {
152
+ method: 'POST',
153
+ path: '/api/rotate-key',
154
+ description: 'Rotate the authenticated insider API key (invalidates all existing share links).',
155
+ insiderOnly: true,
156
+ },
157
+ // --- Events ---
158
+ event: {
159
+ method: 'POST',
160
+ path: '/event',
161
+ description: 'Event gateway webhook receiver (scoped key auth).',
162
+ },
163
+ events: {
164
+ method: 'GET',
165
+ path: '/api/events',
166
+ description: 'Query recent event log entries (limit capped at 100).',
167
+ },
168
+ // --- Search ---
169
+ search: {
170
+ method: 'POST',
171
+ path: '/api/search',
172
+ description: 'Semantic search (proxied to watcher).',
173
+ },
174
+ 'search-facets': {
175
+ method: 'GET',
176
+ path: '/api/search/facets',
177
+ description: 'Search facet metadata (proxied to watcher).',
178
+ },
179
+ // --- Runner ---
180
+ runner: {
181
+ method: 'GET',
182
+ path: '/api/runner/*',
183
+ description: 'Runner API proxy (proxied to jeeves-runner).',
184
+ },
185
+ // --- OAuth ---
186
+ 'oauth-start': {
187
+ method: 'POST',
188
+ path: '/api/oauth/start',
189
+ description: 'Initiate OAuth2 authorization code flow.',
190
+ insiderOnly: true,
191
+ },
192
+ 'oauth-status': {
193
+ method: 'GET',
194
+ path: '/api/oauth/status',
195
+ description: 'Check if valid OAuth2 credentials exist for a provider/account.',
196
+ insiderOnly: true,
197
+ },
198
+ 'oauth-token': {
199
+ method: 'GET',
200
+ path: '/api/oauth/token',
201
+ description: 'Retrieve valid access token (with lazy refresh).',
202
+ insiderOnly: true,
203
+ },
204
+ 'oauth-callback': {
205
+ method: 'GET',
206
+ path: '/oauth/callback',
207
+ description: 'OAuth2 callback (browser redirect target, unauthenticated).',
208
+ unauthenticated: true,
209
+ },
210
+ // --- Keys ---
211
+ 'insider-key': {
212
+ method: 'GET',
213
+ path: '/insider-key',
214
+ description: 'Get insider key for the authenticated user.',
215
+ },
216
+ key: {
217
+ method: 'GET',
218
+ path: '/key',
219
+ description: 'Compute path-specific key.',
220
+ },
221
+ 'share-legacy': {
222
+ method: 'GET',
223
+ path: '/share',
224
+ description: 'Generate outsider share link (top-level legacy route).',
225
+ },
226
+ // --- Shortlinks ---
227
+ go: {
228
+ method: 'GET',
229
+ path: '/go/:slug',
230
+ description: 'Shortlink redirect (unauthenticated).',
231
+ unauthenticated: true,
232
+ },
233
+ };
234
+
235
+ export { serverEndpoints };
@@ -0,0 +1 @@
1
+ export {};
@@ -4,5 +4,6 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  export { computeDeepShareKey, computeInsiderKey, computeOutsiderKeyWithExpiry, computePathKey, type DeepShareParams, timingSafeEqual, } from './crypto.js';
7
- export { type AuthMode, authModeSchema, authSchema, DEPRECATED_CONFIG_PROPS, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, type JeevesConfig, jeevesConfigSchema, keyEntrySchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema, } from './schema.js';
7
+ export { type EndpointEntry, serverEndpoints } from './endpoints.js';
8
+ export { type AuthMode, authModeSchema, authSchema, DEPRECATED_CONFIG_PROPS, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, type JeevesConfig, jeevesConfigSchema, keyEntrySchema, type LoggingConfig, loggingConfigSchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema, } from './schema.js';
8
9
  export type { AuthStatusResponse, DriveEntry, ExportCacheClearResponse, ExportLink, FileMutationAction, LinkInfoResponse, OAuthStartRequest, OAuthStartResponse, RotateKeyResponse, ShareForRequest, ShareForResponse, ShareRequest, ShareResponse, } from './types.js';
package/dist/src/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { computeDeepShareKey, computeInsiderKey, computeOutsiderKeyWithExpiry, computePathKey, timingSafeEqual } from './crypto.js';
2
- export { DEPRECATED_CONFIG_PROPS, authModeSchema, authSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, jeevesConfigSchema, keyEntrySchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema } from './schema.js';
2
+ export { serverEndpoints } from './endpoints.js';
3
+ export { DEPRECATED_CONFIG_PROPS, authModeSchema, authSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, jeevesConfigSchema, keyEntrySchema, loggingConfigSchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema } from './schema.js';
@@ -3,8 +3,8 @@ import { z } from 'zod';
3
3
  export declare const DEPRECATED_CONFIG_PROPS: readonly ["host", "runnerUrl", "watcherUrl", "metaUrl"];
4
4
  /** Supported authentication methods */
5
5
  export declare const authModeSchema: z.ZodEnum<{
6
- google: "google";
7
6
  keys: "keys";
7
+ google: "google";
8
8
  }>;
9
9
  /** Google OAuth configuration */
10
10
  export declare const googleAuthSchema: z.ZodObject<{
@@ -14,8 +14,8 @@ export declare const googleAuthSchema: z.ZodObject<{
14
14
  /** Auth configuration */
15
15
  export declare const authSchema: z.ZodObject<{
16
16
  modes: z.ZodArray<z.ZodEnum<{
17
- google: "google";
18
17
  keys: "keys";
18
+ google: "google";
19
19
  }>>;
20
20
  google: z.ZodOptional<z.ZodObject<{
21
21
  clientId: z.ZodString;
@@ -75,6 +75,13 @@ export declare const keyEntrySchema: z.ZodUnion<readonly [z.ZodString, z.ZodObje
75
75
  }, z.core.$strip>]>;
76
76
  /** Check if a string is a named scope identifier (not a path glob). */
77
77
  export declare function isScopeName(v: string): boolean;
78
+ /** Logging configuration. Not hot-reloadable — changes require service restart. */
79
+ export declare const loggingConfigSchema: z.ZodObject<{
80
+ level: z.ZodOptional<z.ZodString>;
81
+ file: z.ZodOptional<z.ZodString>;
82
+ }, z.core.$strip>;
83
+ /** Inferred logging config type. */
84
+ export type LoggingConfig = z.infer<typeof loggingConfigSchema>;
78
85
  /** OAuth provider configuration */
79
86
  export declare const oauthProviderSchema: z.ZodObject<{
80
87
  authUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
@@ -98,8 +105,8 @@ export declare const jeevesConfigSchema: z.ZodObject<{
98
105
  chromePath: z.ZodString;
99
106
  auth: z.ZodObject<{
100
107
  modes: z.ZodArray<z.ZodEnum<{
101
- google: "google";
102
108
  keys: "keys";
109
+ google: "google";
103
110
  }>>;
104
111
  google: z.ZodOptional<z.ZodObject<{
105
112
  clientId: z.ZodString;
@@ -151,6 +158,10 @@ export declare const jeevesConfigSchema: z.ZodObject<{
151
158
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
152
159
  deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
153
160
  }, z.core.$strip>]>>;
161
+ logging: z.ZodOptional<z.ZodObject<{
162
+ level: z.ZodOptional<z.ZodString>;
163
+ file: z.ZodOptional<z.ZodString>;
164
+ }, z.core.$strip>>;
154
165
  oauth: z.ZodOptional<z.ZodObject<{
155
166
  credentialDir: z.ZodString;
156
167
  providers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -101,6 +101,19 @@ function getScopeRefs(scopes) {
101
101
  }
102
102
  return [];
103
103
  }
104
+ /** Logging configuration. Not hot-reloadable — changes require service restart. */
105
+ const loggingConfigSchema = z.object({
106
+ /** Log level. */
107
+ level: z
108
+ .string()
109
+ .optional()
110
+ .describe('Logging level (trace, debug, info, warn, error, fatal).'),
111
+ /** Log file path. */
112
+ file: z
113
+ .string()
114
+ .optional()
115
+ .describe('Path to log file (logs to stdout if omitted).'),
116
+ });
104
117
  /** OAuth provider configuration */
105
118
  const oauthProviderSchema = z.object({
106
119
  authUrl: z.string().pipe(z.url()),
@@ -163,6 +176,11 @@ const jeevesConfigSchema = z
163
176
  * If omitted, all paths are shareable with outsiders.
164
177
  */
165
178
  outsiderPolicy: scopesSchema.optional(),
179
+ /**
180
+ * Logging configuration.
181
+ * Not hot-reloadable — changes require a service restart.
182
+ */
183
+ logging: loggingConfigSchema.optional(),
166
184
  /** OAuth2 credential management configuration */
167
185
  oauth: oauthSchema.optional(),
168
186
  /**
@@ -249,4 +267,4 @@ const jeevesConfigSchema = z
249
267
  validateRefs(outsiderRefs, ['outsiderPolicy']);
250
268
  });
251
269
 
252
- export { DEPRECATED_CONFIG_PROPS, authModeSchema, authSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, jeevesConfigSchema, keyEntrySchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema };
270
+ export { DEPRECATED_CONFIG_PROPS, authModeSchema, authSchema, eventConfigSchema, googleAuthSchema, insiderEntrySchema, isScopeName, jeevesConfigSchema, keyEntrySchema, loggingConfigSchema, oauthProviderSchema, oauthSchema, scopesObjectSchema, scopesSchema };
package/package.json CHANGED
@@ -1,46 +1,10 @@
1
1
  {
2
- "name": "@karmaniverous/jeeves-server-core",
3
- "version": "0.1.3",
4
2
  "author": "Jeeves",
5
- "description": "Shared cryptographic utilities and API types for jeeves-server packages.",
6
- "license": "MIT",
7
- "type": "module",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/karmaniverous/jeeves-server.git",
11
- "directory": "packages/core"
12
- },
13
- "files": [
14
- "dist"
15
- ],
16
- "publishConfig": {
17
- "access": "public"
18
- },
19
- "scripts": {
20
- "prebuild": "npx rimraf dist",
21
- "build": "cross-env NO_COLOR=1 rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
22
- "lint": "eslint .",
23
- "lint:fix": "eslint --fix .",
24
- "test": "vitest run --passWithNoTests",
25
- "typecheck": "tsc --noEmit",
26
- "changelog": "git-cliff -o CHANGELOG.md",
27
- "release": "dotenvx run -f .env.local -- release-it",
28
- "release:pre": "dotenvx run -f .env.local -- release-it --no-git.requireBranch --github.prerelease --preRelease",
29
- "postbuild": "npx rimraf dist/rollup.config.d.ts dist/rollup.config.d.ts.map"
30
- },
31
- "exports": {
32
- ".": {
33
- "import": {
34
- "types": "./dist/src/index.d.ts",
35
- "default": "./dist/src/index.js"
36
- }
37
- }
38
- },
39
- "types": "dist/src/index.d.ts",
40
3
  "dependencies": {
41
- "@karmaniverous/jeeves": "^0.5.11",
4
+ "@karmaniverous/jeeves": "^0.5.12",
42
5
  "zod": "^4.4.3"
43
6
  },
7
+ "description": "Shared cryptographic utilities and API types for jeeves-server packages.",
44
8
  "devDependencies": {
45
9
  "@dotenvx/dotenvx": "^1.69.1",
46
10
  "@rollup/plugin-commonjs": "^29.0.2",
@@ -56,12 +20,28 @@
56
20
  "engines": {
57
21
  "node": ">=22"
58
22
  },
23
+ "exports": {
24
+ ".": {
25
+ "import": {
26
+ "types": "./dist/src/index.d.ts",
27
+ "default": "./dist/src/index.js"
28
+ }
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "license": "MIT",
35
+ "name": "@karmaniverous/jeeves-server-core",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
59
39
  "release-it": {
60
40
  "git": {
61
41
  "changelog": "npx git-cliff --unreleased --strip header",
62
42
  "commitMessage": "chore: release @karmaniverous/jeeves-server-core v${version}",
63
- "tagName": "core/${version}",
64
- "requireBranch": "main"
43
+ "requireBranch": "main",
44
+ "tagName": "core/${version}"
65
45
  },
66
46
  "github": {
67
47
  "release": true
@@ -73,18 +53,38 @@
73
53
  "npm run test",
74
54
  "npm run build"
75
55
  ],
76
- "before:npm:release": [
77
- "npx git-cliff -o CHANGELOG.md",
78
- "git add -A"
79
- ],
80
56
  "after:release": [
81
57
  "git switch -c release/core/${version}",
82
58
  "git push -u origin release/core/${version}",
83
59
  "git switch ${branchName}"
60
+ ],
61
+ "before:npm:release": [
62
+ "npx git-cliff -o CHANGELOG.md",
63
+ "git add -A"
84
64
  ]
85
65
  },
86
66
  "npm": {
87
67
  "publish": true
88
68
  }
89
- }
69
+ },
70
+ "repository": {
71
+ "directory": "packages/core",
72
+ "type": "git",
73
+ "url": "git+https://github.com/karmaniverous/jeeves-server.git"
74
+ },
75
+ "scripts": {
76
+ "build": "cross-env NO_COLOR=1 rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
77
+ "changelog": "git-cliff -o CHANGELOG.md",
78
+ "lint": "eslint .",
79
+ "lint:fix": "eslint --fix .",
80
+ "postbuild": "npx rimraf dist/rollup.config.d.ts dist/rollup.config.d.ts.map",
81
+ "prebuild": "npx rimraf dist",
82
+ "release": "dotenvx run -f .env.local -- release-it",
83
+ "release:pre": "dotenvx run -f .env.local -- release-it --no-git.requireBranch --github.prerelease --preRelease",
84
+ "test": "vitest run --passWithNoTests",
85
+ "typecheck": "tsc --noEmit"
86
+ },
87
+ "type": "module",
88
+ "types": "dist/src/index.d.ts",
89
+ "version": "0.1.5"
90
90
  }