@forumone/throughline-core 0.8.0 → 0.8.2

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 (3) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +28 -3
  3. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,83 @@
1
1
  # @forumone/throughline-core
2
2
 
3
+ ## 0.8.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 262768a: The five publishing MCP tools now refuse an unauthenticated call and run their
8
+ reads and writes as the caller.
9
+
10
+ `publish`, `unpublish`, `rollback`, `schedulePublish` and `getPublishStatus`
11
+ built their actor without `enforceAccessAs`, which is the only thing that makes
12
+ the service pass `{ user, overrideAccess: false }` to Payload. So every one of
13
+ them ran at the Local API default of `overrideAccess: true` — publish,
14
+ unpublish, roll back or schedule any document in any collection with no
15
+ authorization check. `rollback` called `restoreVersion` with no user and no
16
+ override flag at all.
17
+
18
+ `tools/actor.ts` refuses when there is no identity and hands the caller to the
19
+ service as the principal to enforce against. Deliberately not a role gate: the
20
+ admin HTTP path already requires a user, sets `enforceAccessAs`, and lets the
21
+ collection's own `update` rule decide. The MCP path now participates in that
22
+ rather than carrying a second policy.
23
+
24
+ **Behavioural change for consumers.** A tool call arriving with no `ctx.user`
25
+ now returns `{ error: 'Must be authenticated…' }` instead of performing the
26
+ operation. In practice that is every `Bearer`-authenticated MCP call, because
27
+ `@payloadcms/plugin-mcp` does not assign `req.user` — which is why the audit,
28
+ integrations and approvals servers already denied and these five did not.
29
+
30
+ `@forumone/throughline-core`'s README claimed `requiredScope` is enforced —
31
+ hidden from `tools/list` and refused unless granted. It was, by an `auth.ts`
32
+ that "one MCP transport, not seven" (#80) removed along with the six
33
+ per-server endpoints. The declarations survived; the enforcement did not. The
34
+ README now says so, and says what gates a tool instead.
35
+
36
+ ## 0.8.1
37
+
38
+ ### Patch Changes
39
+
40
+ - 957403b: One `@types/node`, so a host does not end up with two copies of `@payloadcms/ui`
41
+
42
+ Twelve packages asked for `@types/node@^20.17.0` and `design-system-payload`
43
+ asked for `^24.13.2`. Inside this repository that is untidy. Inside a host that
44
+ consumes the suite from source — which is how `forumone/forumone-2026` uses it,
45
+ as a git submodule in one pnpm workspace — it is a runtime failure.
46
+
47
+ pnpm hashes a package's identity with its resolved peers. `publishing` and
48
+ `integrations` both take `@payloadcms/ui` as a peer _and_ as a devDependency, so
49
+ each got its own copy resolved against `@types/node@20`, while the host's copy
50
+ resolved against `@types/node@24`. Same version, 3.87.1, two directories:
51
+
52
+ apps/web → @payloadcms+ui@3.87.1_…_9ce0de5c…
53
+ packages/publishing → @payloadcms+ui@3.87.1_…_13184ec4…
54
+ packages/integrations → @payloadcms+ui@3.87.1_…_13184ec4…
55
+
56
+ Two directories are two module instances. Two instances of `@payloadcms/ui` are
57
+ two `ConfigContext` objects, and `PublishButton` read the one the admin's
58
+ provider had never populated:
59
+
60
+ TypeError: Cannot destructure property 'config' of useConfig() as it is undefined
61
+
62
+ The host saw an intermittent 500 on every admin document view — `PublishButton`
63
+ is installed on each collection with a publish policy, so lists, `/admin` and
64
+ the login screen were all fine and only editing broke. Nothing caught it:
65
+ install, `--frozen-lockfile`, typecheck, lint and every test passed, because the
66
+ two copies are byte-identical and the split exists only at module resolution.
67
+ forumone/forumone-2026#498.
68
+
69
+ Aligning on `^24.13.2` collapses them to one instance. Nothing here targets a
70
+ Node 20 API deliberately; the packages typecheck and test unchanged against the
71
+ newer types.
72
+
73
+ `create-throughline` keeps `^20.17.0` on purpose. It is the one package
74
+ declaring `engines.node: >=20.9.0`, and typechecking a CLI against types newer
75
+ than the runtime it promises to support is how a Node 24-only call ships to
76
+ somebody on Node 20.
77
+
78
+ - Updated dependencies [957403b]
79
+ - @forumone/throughline-plugin-contract@0.4.1
80
+
3
81
  ## 0.8.0
4
82
 
5
83
  ### Minor Changes
package/README.md CHANGED
@@ -104,9 +104,34 @@ const publishTool: McpToolDefinition = {
104
104
  }
105
105
  ```
106
106
 
107
- A tool that declares no `requiredScope` is callable by any authenticated key, which is the right default for a read. A tool that declares one is **hidden from `tools/list`** and refused on a direct call unless the key names that scope — hidden as well as refused, because an agent shown a tool it will be turned away from will try it, fail, and report the tool as broken when what is narrow is the key.
108
-
109
- A key carrying no scopes at all passes nothing scoped. Absent is read as none, not as everything.
107
+ > **Nothing enforces this today.** The paragraphs below describe how
108
+ > `requiredScope` behaved when each server mounted its own `/api/<server>/mcp`
109
+ > endpoint behind a hand-written JSON-RPC handler. That handler and the
110
+ > `auth.ts` that held callers to their scopes — were removed by "one MCP
111
+ > transport, not seven" (#80), which consolidated every server onto Payload's
112
+ > `/api/mcp`. The scope declarations survived the refactor; the enforcement did
113
+ > not, and this section was not updated to say so. Audit 04 F-02.
114
+ >
115
+ > **What gates a tool now** is the per-key checkbox `@payloadcms/plugin-mcp`
116
+ > generates, one per tool name. Two consequences worth knowing before relying
117
+ > on either: all 27 of them **default to `true`**
118
+ > (`createApiKeysCollection.js:4-15`), and a checkbox list cannot express
119
+ > "writes off until granted, reads on" the way a scope can.
120
+ >
121
+ > The declarations are kept because they are the tool → scope mapping a
122
+ > scope-aware default would be built from — see the note on `requiredScope` in
123
+ > `@forumone/throughline-plugin-contract`, which states the same thing at the
124
+ > type. Reinstating enforcement means putting it on the surviving transport.
125
+
126
+ Historically, and as the intended design: a tool that declares no
127
+ `requiredScope` is callable by any authenticated key, which is the right
128
+ default for a read. A tool that declares one was **hidden from `tools/list`**
129
+ and refused on a direct call unless the key named that scope — hidden as well
130
+ as refused, because an agent shown a tool it will be turned away from will try
131
+ it, fail, and report the tool as broken when what is narrow is the key.
132
+
133
+ A key carrying no scopes at all passed nothing scoped. Absent was read as none,
134
+ not as everything.
110
135
 
111
136
  The consequential tools in this suite and the scopes they require:
112
137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forumone/throughline-core",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Core plumbing for Throughline: audit log, MCP authentication and handler, event taxonomy + Inngest client factory, logger, shared utilities.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -58,15 +58,15 @@
58
58
  "dependencies": {
59
59
  "zod": "^3.23.0",
60
60
  "zod-to-json-schema": "^3.25.2",
61
- "@forumone/throughline-plugin-contract": "0.4.0"
61
+ "@forumone/throughline-plugin-contract": "0.4.1"
62
62
  },
63
63
  "devDependencies": {
64
- "@types/node": "^20.17.0",
64
+ "@types/node": "^24.13.2",
65
65
  "eslint": "^9.15.0",
66
66
  "inngest": "^4.2.0",
67
67
  "payload": "^3.83.0",
68
68
  "typescript": "^5.6.0",
69
- "vitest": "^2.1.0",
69
+ "vitest": "^4.1.10",
70
70
  "@forumone/throughline-eslint-config": "0.0.0",
71
71
  "@forumone/throughline-tsconfig": "0.0.0"
72
72
  },