@forumone/throughline-approvals 0.8.1 → 0.8.3
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,66 @@
|
|
|
1
1
|
# @forumone/throughline-approvals
|
|
2
2
|
|
|
3
|
+
## 0.8.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1f3346f: `get_approval_status` now refuses an unauthenticated caller, and answers only
|
|
8
|
+
the requester or a member of an approver group.
|
|
9
|
+
|
|
10
|
+
It had no authorization check of any kind. The handler was `async (input) =>` —
|
|
11
|
+
the signature did not accept `ctx`, so there was nothing to check against — and
|
|
12
|
+
it `findByID`d an arbitrary `approvalId` at the Local API default of
|
|
13
|
+
`overrideAccess: true`, returning the target, the requester, the approver
|
|
14
|
+
groups, the decision and the decision notes. The other four tools on this
|
|
15
|
+
server all check `ctx.user`, which made this the one approvals tool that still
|
|
16
|
+
answered when the rest correctly denied. Audit 04 F-20.
|
|
17
|
+
|
|
18
|
+
The rule is the union of what the two list tools already show a caller —
|
|
19
|
+
`list_my_requests` returns the approvals they requested, `list_pending_approvals`
|
|
20
|
+
the ones routed to their groups — so the by-id read agrees with the by-list
|
|
21
|
+
reads instead of being a way around them. No admin bypass, because
|
|
22
|
+
`respond_to_approval` has none either and a second policy on the same collection
|
|
23
|
+
is how the two drift.
|
|
24
|
+
|
|
25
|
+
A refused read returns `Approval not found`, the same sentence as a genuine
|
|
26
|
+
miss: ids are sequential, and a distinguishable refusal enumerates who is asking
|
|
27
|
+
whom to approve what.
|
|
28
|
+
|
|
29
|
+
**Behavioural change for consumers.** A `get_approval_status` call arriving with
|
|
30
|
+
no `ctx.user` now returns `{ error: 'Must be authenticated…' }` instead of the
|
|
31
|
+
approval. In practice that is every `Bearer`-authenticated MCP call, because
|
|
32
|
+
`@payloadcms/plugin-mcp` does not assign `req.user` — the same fact that made
|
|
33
|
+
the four gated tools deny and this one answer.
|
|
34
|
+
|
|
35
|
+
## 0.8.2
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- debfcd2: `system.error` now has a writer. Every MCP tool handler the suite serves is
|
|
40
|
+
wrapped, so a tool that throws records one `system.error` audit row — the
|
|
41
|
+
server, the tool, the caller, the caller's `_meta`, and the error's message —
|
|
42
|
+
before the throw propagates to the MCP client as it did before.
|
|
43
|
+
|
|
44
|
+
The row carries no stack and no arguments: `error_message` is readable by every
|
|
45
|
+
admin and editor, a stack names file paths, and a tool's input can hold a draft
|
|
46
|
+
body or a form submission. A failure inside the recording is logged and
|
|
47
|
+
swallowed, so this wrapper can never replace a tool's real error with its own.
|
|
48
|
+
|
|
49
|
+
`mcpServer` is resolved through a map rather than from the collector's own
|
|
50
|
+
server name, because the two vocabularies disagree: the components server
|
|
51
|
+
declares itself `components` and the audit enum's value is `component`. A
|
|
52
|
+
server that passes an audit writer and has no name in that map is now a
|
|
53
|
+
boot-time refusal instead of a row Payload silently rejects. New export:
|
|
54
|
+
`auditServerFor`.
|
|
55
|
+
|
|
56
|
+
Each of the six servers passes its audit writer to `collector.add`, alongside
|
|
57
|
+
the logger it already passed. A host wiring a tool by hand passes none and gets
|
|
58
|
+
the previous behaviour.
|
|
59
|
+
|
|
60
|
+
- Updated dependencies [debfcd2]
|
|
61
|
+
- @forumone/throughline-core@0.9.0
|
|
62
|
+
- @forumone/throughline-publishing@0.9.3
|
|
63
|
+
|
|
3
64
|
## 0.8.1
|
|
4
65
|
|
|
5
66
|
### Patch Changes
|
package/dist/plugin.js
CHANGED
|
@@ -70,7 +70,7 @@ export const approvalsPlugin = (rawOptions) => (incomingConfig) => {
|
|
|
70
70
|
// Payload's own MCP plugin, and the only transport these tools have.
|
|
71
71
|
// `onInit` is both the earliest they can exist and still early enough
|
|
72
72
|
// that `mcpPlugin` reads the array populated.
|
|
73
|
-
options.mcpTools?.add(tools, { serverName: 'approvals', logger });
|
|
73
|
+
options.mcpTools?.add(tools, { serverName: 'approvals', logger, audit: auditWriter });
|
|
74
74
|
registry.register({
|
|
75
75
|
id: PLUGIN_ID,
|
|
76
76
|
version: PLUGIN_VERSION,
|
package/dist/plugin.js.map
CHANGED
|
@@ -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,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAA+B,eAAe,EAAE,MAAM,cAAc,CAAA;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,kBAAkB,CAAA;AAEzB,MAAM,SAAS,GAAG,iCAAiC,CAAA;AACnD,MAAM,cAAc,GAAG,OAAO,CAAA;AAC9B,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAA;AAE1F,MAAM,CAAC,MAAM,eAAe,GAC1B,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,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,YAAY,CAAA;IACvD,MAAM,MAAM,GAAG,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC,CAAA;IAE9E,MAAM,UAAU,GAAG,yBAAyB,CAAC;QAC3C,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;KAC9C,CAAC,CAAA;IAEF;;;;;MAKE;IACF,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,0BAA0B,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAA;IAElF,OAAO;QACL,GAAG,cAAc;QACjB,WAAW,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,UAAU,CAAC;QAChE,SAAS,EAAE;YACT,GAAG,CAAC,cAAc,CAAC,SAAS,IAAI,EAAE,CAAC;YACnC;gBACE,IAAI,EAAE,GAAG,WAAW,SAAS;gBAC7B,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;oBACrB,MAAM,aAAa,GAAI,GAAG,CAAC,OAA8C,CACvE,qBAAqB,CACgC,CAAA;oBACvD,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,OAAO,IAAI,QAAQ,CAAC,0CAA0C,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;oBAClF,CAAC;oBACD,OAAO,aAAa,CAAC,GAAG,CAAC,CAAA;gBAC3B,CAAC;aACF;SACF;QACD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACxB,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC;gBAC1B,MAAM,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YACtC,CAAC;YAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;YAC3C,QAAQ,CAAC,iBAAiB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YAElD,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;YAE3C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAA;YAC7C,MAAM,QAAQ,GAAG,sBAAsB,CACrC,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAC3D,CAAA;YACD,sBAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;YAEzC,MAAM,cAAc,GAAG,oBAAoB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;YACrE,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,qBAAqB,EAAE;gBACpD,KAAK,EAAE,cAAc,CAAC,OAAO;gBAC7B,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,KAAK;gBACf,YAAY,EAAE,KAAK;aACpB,CAAC,CAAA;YAEF,MAAM,KAAK,GAAG;gBACZ,yBAAyB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;gBAC5D,2BAA2B,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;gBAC9D,2BAA2B,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;gBACjD,8BAA8B,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;gBACpD,wBAAwB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;aAC/C,CAAA;YAED,qEAAqE;YACrE,sEAAsE;YACtE,8CAA8C;YAC9C,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;YAErF,QAAQ,CAAC,QAAQ,CAAC;gBAChB,EAAE,EAAE,SAAS;gBACb,OAAO,EAAE,cAAc;gBACvB,YAAY,EAAE,CAAC,WAAW,EAAE,mBAAmB,CAAC;aACjD,CAAC,CAAA;YAEF,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE;gBACpC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzC,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,CAAC;aAC5C,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAEH,4EAA4E;AAC5E,0EAA0E;AAC1E,yEAAyE;AACzE,uCAAuC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-approval-status.d.ts","sourceRoot":"","sources":["../../src/tools/get-approval-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"get-approval-status.d.ts","sourceRoot":"","sources":["../../src/tools/get-approval-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,KAAK,EAAkB,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAE9F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAG3D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,sBAAsB,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CAC1D;AAqDD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CA2C1F"}
|
|
@@ -2,6 +2,52 @@ import { z } from 'zod';
|
|
|
2
2
|
import { unwrapRelationshipId, withMeta } from '@forumone/throughline-core';
|
|
3
3
|
import { DEFAULT_APPROVALS_SLUG } from '../collection.js';
|
|
4
4
|
import { APPROVALS_TOOLS } from './descriptors.js';
|
|
5
|
+
/*
|
|
6
|
+
Who may read one approval by id.
|
|
7
|
+
|
|
8
|
+
Audit 04 F-20. This handler was `async (input) =>` — the signature did not
|
|
9
|
+
accept `ctx` at all, so there was nothing to check against and nothing was
|
|
10
|
+
checked. It `findByID`s an arbitrary `approvalId` at the Local API default of
|
|
11
|
+
`overrideAccess: true` and returns the target, the requester, the approver
|
|
12
|
+
groups, the decision and the decision notes.
|
|
13
|
+
|
|
14
|
+
The other four tools on this server all refuse an unauthenticated caller. This
|
|
15
|
+
was the one that still answered when they denied, and that asymmetry is not
|
|
16
|
+
theoretical: `@payloadcms/plugin-mcp` never assigns `req.user`, so for a
|
|
17
|
+
`Bearer`-authenticated MCP call `ctx.user` is null and the refusal below is the
|
|
18
|
+
branch that actually fires today.
|
|
19
|
+
|
|
20
|
+
## The rule is the union of the two list tools, and deliberately nothing more
|
|
21
|
+
|
|
22
|
+
`list_my_requests` shows a caller the approvals they requested.
|
|
23
|
+
`list_pending_approvals` shows a caller the approvals routed to one of their
|
|
24
|
+
groups. Between them they already disclose every field this tool returns. So
|
|
25
|
+
the rule here is *requester or approver-group member*, which makes the by-id
|
|
26
|
+
read agree with the by-list reads rather than being a way around them.
|
|
27
|
+
|
|
28
|
+
No admin bypass, because `respond_to_approval` has none either and a second
|
|
29
|
+
policy on the same collection is how the two drift. An admin who needs an
|
|
30
|
+
arbitrary approval has the admin UI and the REST collection, both of which
|
|
31
|
+
apply `approval-requests`' own access rules — which is the thing this server
|
|
32
|
+
should not be quietly wider than.
|
|
33
|
+
|
|
34
|
+
The order of the three checks is load-bearing. Identity first, because the
|
|
35
|
+
unauthenticated refusal must not depend on the id existing; then the document;
|
|
36
|
+
then membership.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Whether this caller is a party to this approval.
|
|
40
|
+
*
|
|
41
|
+
* Group membership is compared exactly as `respond_to_approval` compares it —
|
|
42
|
+
* `approverGroups` against `ctx.user.groups`, slug by slug — so a change in how
|
|
43
|
+
* groups are named breaks both together rather than leaving this one behind.
|
|
44
|
+
*/
|
|
45
|
+
function isPartyTo(approval, user) {
|
|
46
|
+
if (unwrapRelationshipId(approval['requestedBy']) === user.id)
|
|
47
|
+
return true;
|
|
48
|
+
const approverGroups = approval['approverGroups'] ?? [];
|
|
49
|
+
return approverGroups.some((group) => user.groups.includes(group));
|
|
50
|
+
}
|
|
5
51
|
export function createGetApprovalStatusTool(deps) {
|
|
6
52
|
const inputSchema = withMeta({
|
|
7
53
|
approvalId: z.string(),
|
|
@@ -9,13 +55,23 @@ export function createGetApprovalStatusTool(deps) {
|
|
|
9
55
|
return {
|
|
10
56
|
...APPROVALS_TOOLS.getApprovalStatus,
|
|
11
57
|
inputSchema,
|
|
12
|
-
handler: async (input) => {
|
|
58
|
+
handler: async (input, ctx) => {
|
|
59
|
+
if (!ctx.user) {
|
|
60
|
+
return { error: 'Must be authenticated to read an approval request' };
|
|
61
|
+
}
|
|
13
62
|
const approval = (await deps.payload.findByID({
|
|
14
63
|
collection: deps.options.collectionSlug ?? DEFAULT_APPROVALS_SLUG,
|
|
15
64
|
id: input.approvalId,
|
|
16
65
|
}));
|
|
17
66
|
if (!approval)
|
|
18
67
|
return { error: 'Approval not found' };
|
|
68
|
+
/*
|
|
69
|
+
The same sentence as "not found", and that is the point: a caller who is
|
|
70
|
+
not a party to this request learns nothing about whether the id names one.
|
|
71
|
+
Ids are sequential, so a distinguishable refusal enumerates the collection.
|
|
72
|
+
*/
|
|
73
|
+
if (!isPartyTo(approval, ctx.user))
|
|
74
|
+
return { error: 'Approval not found' };
|
|
19
75
|
return {
|
|
20
76
|
approvalId: String(approval['id']),
|
|
21
77
|
status: approval['status'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-approval-status.js","sourceRoot":"","sources":["../../src/tools/get-approval-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAE3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAOlD,MAAM,UAAU,2BAA2B,CAAC,IAA2B;IACrE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACvB,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,eAAe,CAAC,iBAAiB;QACpC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"get-approval-status.js","sourceRoot":"","sources":["../../src/tools/get-approval-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAE3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAOlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCE;AAEF;;;;;;GAMG;AACH,SAAS,SAAS,CAChB,QAAiC,EACjC,IAAyC;IAEzC,IAAI,oBAAoB,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA;IAE1E,MAAM,cAAc,GAAI,QAAQ,CAAC,gBAAgB,CAA0B,IAAI,EAAE,CAAA;IACjF,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,IAA2B;IACrE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACvB,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,eAAe,CAAC,iBAAiB;QACpC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,EAAE,KAAK,EAAE,mDAAmD,EAAE,CAAA;YACvE,CAAC;YAED,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC5C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,sBAAsB;gBACjE,EAAE,EAAE,KAAK,CAAC,UAAU;aACrB,CAAC,CAAmC,CAAA;YACrC,IAAI,CAAC,QAAQ;gBAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAA;YAErD;;;;cAIE;YACF,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAA;YAE1E,OAAO;gBACL,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAClC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC;gBAC1B,gBAAgB,EAAE,QAAQ,CAAC,kBAAkB,CAAC;gBAC9C,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC;gBAC9B,WAAW,EAAE,QAAQ,CAAC,aAAa,CAAC;gBACpC,aAAa,EAAE,QAAQ,CAAC,eAAe,CAAC;gBACxC,WAAW,EAAE,oBAAoB,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBAC1D,WAAW,EAAE,QAAQ,CAAC,aAAa,CAAC;gBACpC,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC;gBAC1C,SAAS,EAAE,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACtD,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC;gBAChC,aAAa,EAAE,QAAQ,CAAC,eAAe,CAAC;gBACxC,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC;aACjC,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forumone/throughline-approvals",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Conversational approval workflow server for Throughline. Provides the approval resolver the publishing server consumes plus MCP tools for requesting and responding to approvals.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"zod": "^3.23.0",
|
|
45
|
-
"@forumone/throughline-core": "0.
|
|
45
|
+
"@forumone/throughline-core": "0.9.0",
|
|
46
46
|
"@forumone/throughline-plugin-contract": "0.4.1",
|
|
47
|
-
"@forumone/throughline-publishing": "0.9.
|
|
47
|
+
"@forumone/throughline-publishing": "0.9.3"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^24.13.2",
|