@forumone/throughline-audit 0.3.1 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # @forumone/throughline-audit
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3140ea0: One MCP transport, not seven
8
+
9
+ Every plugin served its own `POST /<prefix>/mcp` on a 146-line JSON-RPC subset of
10
+ the protocol that spoke `tools/list` and `tools/call` and nothing else. Payload
11
+ ships an MCP server built on the official SDK — streamable HTTP, sessions, per-key
12
+ capability checkboxes — and the tools were never the transport. They now reach a
13
+ client through the host's `@payloadcms/plugin-mcp`, on one `/api/mcp`, via the
14
+ collector `createMcpToolCollector` already provided.
15
+
16
+ **Breaking.** Removed from `@forumone/throughline-core`: `createMcpHandler`,
17
+ `McpHandlerOptions`, `createApiKeysCollection`, `ApiKeysCollectionOptions`,
18
+ `DEFAULT_API_KEYS_SLUG`, `createBearerTokenAuthenticator`,
19
+ `BearerTokenAuthenticatorOptions`, `generateApiKey`. Removed from
20
+ `@forumone/throughline-plugin-contract`: `McpAuthenticator`, `McpAuthResult`.
21
+ `sha256Hex` stays exported, from `./utils` rather than `./auth`.
22
+
23
+ `routePrefix` is gone from `auditQueryPlugin`, `componentsPlugin` and
24
+ `integrationsPlugin` — omitted from their options types, so passing one is a
25
+ compile error rather than config that reads as if it does something. `/mcp` was
26
+ the only endpoint any of the three served. `publishingPlugin`, `approvalsPlugin`
27
+ and `formsPlugin` keep theirs; they still serve admin controls, the approval
28
+ action link and the public form post.
29
+
30
+ **A host that passes no `mcpTools` collector now has no MCP surface.** There is no
31
+ per-server endpoint left as a fallback. This is a config change of one line per
32
+ plugin, and `createMcpToolCollector`'s own docs carry the shape.
33
+
34
+ **What this costs, stated plainly.** `requiredScope` is now read by nothing —
35
+ `plugin-mcp` gates on checkboxes generated at config time, which this suite cannot
36
+ fill because every tool is built at `onInit`. So a key that authenticates reaches
37
+ every collected tool, exactly as an all-or-nothing per-server key did. The
38
+ declarations are kept because they are the mapping those checkboxes need; #78
39
+ tracks restoring enforcement, and the type's own doc comment says so.
40
+
41
+ Also drops the key collection from the playground, which leaves that app with no
42
+ MCP surface at all until `mcpPlugin` can be wired there — #79, blocked on moving
43
+ it off `payload@^3.83.0`.
44
+
45
+ ### Patch Changes
46
+
47
+ - Updated dependencies [3140ea0]
48
+ - @forumone/throughline-plugin-contract@0.4.0
49
+ - @forumone/throughline-core@0.7.0
50
+
3
51
  ## 0.3.1
4
52
 
5
53
  ### Patch Changes
package/README.md CHANGED
@@ -4,7 +4,9 @@ Read-only MCP query tools over the Throughline audit log. Pairs with the writer
4
4
 
5
5
  ## What this package provides
6
6
 
7
- Five MCP tools served at `/api/audit/mcp`. All are read-only and emit no audit events of their own.
7
+ Five MCP tools, handed to the host's collector at `onInit` and served by
8
+ `@payloadcms/plugin-mcp` on one `/api/mcp`. Pass `mcpTools` or they reach nobody.
9
+ All are read-only and emit no audit events of their own.
8
10
 
9
11
  | Tool | Use it for | Default access |
10
12
  |---|---|---|
@@ -74,7 +76,7 @@ auditQueryPlugin({
74
76
 
75
77
  | Option | Type | Default | Notes |
76
78
  |---|---|---|---|
77
- | `routePrefix` | `string` | `/audit` | Payload prepends `/api`, so the MCP endpoint lands at `/api/audit/mcp` |
79
+ | `mcpTools` | `McpToolCollector` | | The host's collector. Without it these five tools are unreachable |
78
80
  | `collectionSlug` | `string` | `audit-events` | Must match the slug used by core's `auditPlugin` |
79
81
  | `readAccess` | `(req) => boolean` | admin / editor | Custom predicate for read-side access |
80
82
  | `enabled` | `boolean` | `true` | Set to `false` to no-op the plugin |
package/dist/options.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { McpToolCollector } from '@forumone/throughline-core';
2
2
  import type { PayloadRequest } from 'payload';
3
3
  import type { BaseCorePluginOptions } from '@forumone/throughline-plugin-contract';
4
- export interface AuditQueryPluginOptions extends BaseCorePluginOptions {
4
+ export interface AuditQueryPluginOptions extends Omit<BaseCorePluginOptions, 'routePrefix'> {
5
5
  /**
6
6
  * Override the audit collection slug. Must match the slug `auditPlugin`
7
7
  * (in `@forumone/throughline-core`) writes to. Default: `'audit-events'`.
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAElF,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAA;IAE7C;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAC5B;AAED,eAAO,MAAM,6BAA6B,iBAAiB,CAAA;AAE3D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,uBAAuB,GAAG,uBAAuB,CAEzF"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAQlF,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,aAAa,CAAC;IACzF;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAA;IAE7C;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAC5B;AAED,eAAO,MAAM,6BAA6B,iBAAiB,CAAA;AAE3D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,uBAAuB,GAAG,uBAAuB,CAEzF"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AA+BA,MAAM,CAAC,MAAM,6BAA6B,GAAG,cAAc,CAAA;AAE3D;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgC;IAC9D,OAAO,OAAO,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAqCA,MAAM,CAAC,MAAM,6BAA6B,GAAG,cAAc,CAAA;AAE3D;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgC;IAC9D,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,uCAAuC,CAAA;AAG1F,OAAO,EACL,KAAK,uBAAuB,EAG7B,MAAM,cAAc,CAAA;AAerB;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,UAAU,CAAC,uBAAuB,CA6E9D,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,uCAAuC,CAAA;AAG1F,OAAO,EACL,KAAK,uBAAuB,EAG7B,MAAM,cAAc,CAAA;AAWrB;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,UAAU,CAAC,uBAAuB,CA0C9D,CAAA"}
package/dist/plugin.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import { getPluginRegistry } from '@forumone/throughline-plugin-contract';
2
- import { createMcpHandler, createNamedLogger, defaultLogger } from '@forumone/throughline-core';
2
+ import { createNamedLogger, defaultLogger } from '@forumone/throughline-core';
3
3
  import { DEFAULT_AUDIT_COLLECTION_SLUG, validateOptions, } from './options.js';
4
4
  import { createGetChangeHistoryTool, createGetRecentFailuresTool, createQueryAuditTool, createWhatChangedInRangeTool, createWhoChangedWhatTool, } from './tools/index.js';
5
5
  const PLUGIN_ID = '@forumone/throughline-audit';
6
6
  const PLUGIN_VERSION = '0.1.0';
7
- const MCP_HANDLER_SYMBOL = Symbol.for('@forumone/throughline/audit-mcp-handler');
8
7
  /**
9
8
  * Read-only MCP server over the audit log. Pairs with `auditPlugin` from
10
9
  * `@forumone/throughline-core` (which writes records). The query plugin
@@ -16,25 +15,10 @@ export const auditQueryPlugin = (rawOptions) => (incomingConfig) => {
16
15
  if (rawOptions.enabled === false)
17
16
  return incomingConfig;
18
17
  const options = validateOptions(rawOptions);
19
- const routePrefix = options.routePrefix ?? '/audit';
20
18
  const collectionSlug = options.collectionSlug ?? DEFAULT_AUDIT_COLLECTION_SLUG;
21
19
  const logger = createNamedLogger('audit-query', options.logger ?? defaultLogger);
22
20
  return {
23
21
  ...incomingConfig,
24
- endpoints: [
25
- ...(incomingConfig.endpoints ?? []),
26
- {
27
- path: `${routePrefix}/mcp`,
28
- method: 'post',
29
- handler: async (req) => {
30
- const handler = req.payload[MCP_HANDLER_SYMBOL];
31
- if (!handler) {
32
- return new Response(JSON.stringify({ error: 'Audit query MCP not initialized' }), { status: 503, headers: { 'content-type': 'application/json' } });
33
- }
34
- return handler(req);
35
- },
36
- },
37
- ],
38
22
  onInit: async (payload) => {
39
23
  if (incomingConfig.onInit)
40
24
  await incomingConfig.onInit(payload);
@@ -48,22 +32,10 @@ export const auditQueryPlugin = (rawOptions) => (incomingConfig) => {
48
32
  createWhatChangedInRangeTool(deps),
49
33
  createGetRecentFailuresTool(deps),
50
34
  ];
51
- // Payload's own MCP plugin, when the host is using it. See the option's
52
- // note — `onInit` is both the earliest these tools can exist and still
53
- // early enough that the array is read populated.
35
+ // Payload's own MCP plugin, and the only transport these tools have.
36
+ // `onInit` is both the earliest they can exist and still early enough
37
+ // that `mcpPlugin` reads the array populated.
54
38
  options.mcpTools?.add(tools, { serverName: 'audit', logger });
55
- const handler = createMcpHandler({
56
- payload,
57
- serverName: 'audit',
58
- tools,
59
- logger,
60
- });
61
- Object.defineProperty(payload, MCP_HANDLER_SYMBOL, {
62
- value: handler,
63
- enumerable: false,
64
- writable: false,
65
- configurable: false,
66
- });
67
39
  registry.register({
68
40
  id: PLUGIN_ID,
69
41
  version: PLUGIN_VERSION,
@@ -71,7 +43,6 @@ export const auditQueryPlugin = (rawOptions) => (incomingConfig) => {
71
43
  });
72
44
  logger.info('Audit query server ready', {
73
45
  collectionSlug,
74
- routePrefix,
75
46
  toolCount: tools.length,
76
47
  });
77
48
  },
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAEL,6BAA6B,EAC7B,eAAe,GAChB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AAEzB,MAAM,SAAS,GAAG,6BAA6B,CAAA;AAC/C,MAAM,cAAc,GAAG,OAAO,CAAA;AAC9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,cAAc,EAAE,EAAE;IACjC,IAAI,UAAU,CAAC,OAAO,KAAK,KAAK;QAAE,OAAO,cAAc,CAAA;IAEvD,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;IAC3C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,6BAA6B,CAAA;IAC9E,MAAM,MAAM,GAAG,iBAAiB,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC,CAAA;IAEhF,OAAO;QACL,GAAG,cAAc;QACjB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACxB,IAAI,cAAc,CAAC,MAAM;gBAAE,MAAM,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAE/D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;YAC3C,QAAQ,CAAC,iBAAiB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YAElD,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,CAAA;YACxC,MAAM,KAAK,GAAG;gBACZ,oBAAoB,CAAC,IAAI,CAAC;gBAC1B,0BAA0B,CAAC,IAAI,CAAC;gBAChC,wBAAwB,CAAC,IAAI,CAAC;gBAC9B,4BAA4B,CAAC,IAAI,CAAC;gBAClC,2BAA2B,CAAC,IAAI,CAAC;aACA,CAAA;YAEnC,qEAAqE;YACrE,sEAAsE;YACtE,8CAA8C;YAC9C,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;YAE7D,QAAQ,CAAC,QAAQ,CAAC;gBAChB,EAAE,EAAE,SAAS;gBACb,OAAO,EAAE,cAAc;gBACvB,YAAY,EAAE,CAAC,aAAa,CAAC;aAC9B,CAAC,CAAA;YAEF,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;gBACtC,cAAc;gBACd,SAAS,EAAE,KAAK,CAAC,MAAM;aACxB,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-audit",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Read-only MCP query tools over the Throughline audit log. Pairs with core's auditPlugin (which writes records).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "zod": "^3.23.0",
43
- "@forumone/throughline-core": "0.6.0",
44
- "@forumone/throughline-plugin-contract": "0.3.0"
43
+ "@forumone/throughline-core": "0.7.0",
44
+ "@forumone/throughline-plugin-contract": "0.4.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "^20.17.0",