@forumone/throughline-publishing 0.9.1 → 0.9.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.
- package/CHANGELOG.md +36 -0
- package/dist/pipeline/types.d.ts +15 -2
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/tools/actor.d.ts +32 -0
- package/dist/tools/actor.d.ts.map +1 -0
- package/dist/tools/actor.js +40 -0
- package/dist/tools/actor.js.map +1 -0
- package/dist/tools/get-publish-status.d.ts.map +1 -1
- package/dist/tools/get-publish-status.js +5 -1
- package/dist/tools/get-publish-status.js.map +1 -1
- package/dist/tools/publish.d.ts.map +1 -1
- package/dist/tools/publish.js +12 -6
- package/dist/tools/publish.js.map +1 -1
- package/dist/tools/rollback.d.ts.map +1 -1
- package/dist/tools/rollback.js +15 -0
- package/dist/tools/rollback.js.map +1 -1
- package/dist/tools/schedule-publish.d.ts.map +1 -1
- package/dist/tools/schedule-publish.js +13 -1
- package/dist/tools/schedule-publish.js.map +1 -1
- package/dist/tools/unpublish.d.ts.map +1 -1
- package/dist/tools/unpublish.js +12 -6
- package/dist/tools/unpublish.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @forumone/throughline-publishing
|
|
2
2
|
|
|
3
|
+
## 0.9.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
|
+
- Updated dependencies [262768a]
|
|
37
|
+
- @forumone/throughline-core@0.8.2
|
|
38
|
+
|
|
3
39
|
## 0.9.1
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
package/dist/pipeline/types.d.ts
CHANGED
|
@@ -9,8 +9,21 @@ export interface PipelineActor {
|
|
|
9
9
|
/**
|
|
10
10
|
* When set, Payload reads and writes inside the pipeline run as this user
|
|
11
11
|
* with `overrideAccess: false`, so the collection's own access control
|
|
12
|
-
* applies.
|
|
13
|
-
*
|
|
12
|
+
* applies. **Both channels set it**, and anything that does not is running
|
|
13
|
+
* unauthorized writes.
|
|
14
|
+
*
|
|
15
|
+
* This used to end "the MCP path leaves it unset because the API key is its
|
|
16
|
+
* own trust boundary." It is not one. `plugin-mcp` generates a per-key
|
|
17
|
+
* checkbox for every tool and **all 27 default to `true`**
|
|
18
|
+
* (`createApiKeysCollection.js:4-15`); the `requiredScope` each tool
|
|
19
|
+
* declares is read by nothing anywhere in the tree; and the key document
|
|
20
|
+
* itself carries no `roles` field, so every role check denies while
|
|
21
|
+
* Payload's `defaultAccess` — `Boolean(user)` — allows. A key was therefore
|
|
22
|
+
* a bearer credential that could publish, unpublish, roll back or schedule
|
|
23
|
+
* any document in any collection with nothing consulted. Audit 04 F-02.
|
|
24
|
+
*
|
|
25
|
+
* `tools/actor.ts` is what sets it now, and refuses when there is no
|
|
26
|
+
* identity to set it to.
|
|
14
27
|
*/
|
|
15
28
|
enforceAccessAs?: TypedUser | undefined;
|
|
16
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,eAAe,CAAA;AAEtB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pipeline/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,eAAe,CAAA;AAEtB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,UAAU,EAAE,kBAAkB,CAAA;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,aAAa,CAAA;IACpB,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CAChC;AAED,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAElE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,aAAa,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEpF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,aAAa,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AuthenticatedUser, McpToolContext } from '@forumone/throughline-plugin-contract';
|
|
2
|
+
import type { PublishingActor } from '../service.js';
|
|
3
|
+
/** A tool result that refused before doing anything. */
|
|
4
|
+
export interface ActorRefusal {
|
|
5
|
+
error: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A publishing actor that is known to carry an identity.
|
|
9
|
+
*
|
|
10
|
+
* Both fields are non-optional, which is the invariant the guard establishes
|
|
11
|
+
* and is worth having in the type rather than only in a comment: `user` is
|
|
12
|
+
* what the audit row attributes the action to, and `enforceAccessAs` is what
|
|
13
|
+
* makes the write consult collection access. A `PublishingActor` with either
|
|
14
|
+
* absent is exactly the actor the five tools used to build, so narrowing here
|
|
15
|
+
* means the old shape no longer typechecks at these call sites.
|
|
16
|
+
*/
|
|
17
|
+
export interface EnforcedPublishingActor extends PublishingActor {
|
|
18
|
+
user: AuthenticatedUser;
|
|
19
|
+
enforceAccessAs: NonNullable<PublishingActor['enforceAccessAs']>;
|
|
20
|
+
/** Definite, because `McpToolContext` types it as a required string. */
|
|
21
|
+
apiKeyName: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The actor to run a publishing call as, or a refusal to return unchanged.
|
|
25
|
+
*
|
|
26
|
+
* Callers narrow on `'error' in resolved`. Returning the envelope rather than
|
|
27
|
+
* throwing matches every other gated tool in the suite — `query-audit.ts`'s
|
|
28
|
+
* `deniedEnvelope`, `trigger-sync.ts`, `respond-to-approval.ts` — so a refused
|
|
29
|
+
* MCP call reads as a refusal to the model rather than as a server fault.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolvePublishingActor(ctx: Pick<McpToolContext, 'user' | 'apiKeyName'>, channel?: 'mcp'): EnforcedPublishingActor | ActorRefusal;
|
|
32
|
+
//# sourceMappingURL=actor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../../src/tools/actor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AAC9F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AA8CpD,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC9D,IAAI,EAAE,iBAAiB,CAAA;IACvB,eAAe,EAAE,WAAW,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAChE,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY,CAAC,EAChD,OAAO,GAAE,KAAa,GACrB,uBAAuB,GAAG,YAAY,CAgCxC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The actor to run a publishing call as, or a refusal to return unchanged.
|
|
3
|
+
*
|
|
4
|
+
* Callers narrow on `'error' in resolved`. Returning the envelope rather than
|
|
5
|
+
* throwing matches every other gated tool in the suite — `query-audit.ts`'s
|
|
6
|
+
* `deniedEnvelope`, `trigger-sync.ts`, `respond-to-approval.ts` — so a refused
|
|
7
|
+
* MCP call reads as a refusal to the model rather than as a server fault.
|
|
8
|
+
*/
|
|
9
|
+
export function resolvePublishingActor(ctx, channel = 'mcp') {
|
|
10
|
+
if (!ctx.user) {
|
|
11
|
+
return {
|
|
12
|
+
error: 'Must be authenticated to use the publishing tools. An API key alone does not carry an ' +
|
|
13
|
+
'identity to enforce collection access against.',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
user: ctx.user,
|
|
18
|
+
apiKeyName: ctx.apiKeyName,
|
|
19
|
+
channel,
|
|
20
|
+
/*
|
|
21
|
+
The whole point. Without this the service runs at `overrideAccess: true`
|
|
22
|
+
and the collection's `update` rule — the thing that distinguishes an editor
|
|
23
|
+
from an approver — is never consulted.
|
|
24
|
+
|
|
25
|
+
One cast, and it is the kind audit 02 F-06 calls the acceptable shape: the
|
|
26
|
+
two types genuinely disagree and the comment says how. `AuthenticatedUser`
|
|
27
|
+
is this package's local shape — `{ id, email, name, roles, groups }` — while
|
|
28
|
+
`TypedUser` is generated from the consuming app's own `users` collection.
|
|
29
|
+
They describe the same row, but only the app that owns that collection can
|
|
30
|
+
say so, and this package may not import from `apps/` (see the boundary rule
|
|
31
|
+
in the repository's CLAUDE.md, enforced by `pnpm check:boundary`).
|
|
32
|
+
|
|
33
|
+
What the value is used for downstream bounds the risk: Payload passes it to
|
|
34
|
+
`update`/`findByID` as `user`, and the access functions read `id` and
|
|
35
|
+
`roles` off it. Both are present and both are the same type on either side.
|
|
36
|
+
*/
|
|
37
|
+
enforceAccessAs: ctx.user,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=actor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor.js","sourceRoot":"","sources":["../../src/tools/actor.ts"],"names":[],"mappings":"AAqEA;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAgD,EAChD,UAAiB,KAAK;IAEtB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,OAAO;YACL,KAAK,EACH,wFAAwF;gBACxF,gDAAgD;SACnD,CAAA;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO;QACP;;;;;;;;;;;;;;;;UAgBE;QACF,eAAe,EAAE,GAAG,CAAC,IAAkE;KACxF,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-publish-status.d.ts","sourceRoot":"","sources":["../../src/tools/get-publish-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"get-publish-status.d.ts","sourceRoot":"","sources":["../../src/tools/get-publish-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAI/E,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,wBAAwB,GAAG,iBAAiB,CA0C5F"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { withMeta } from '@forumone/throughline-core';
|
|
3
3
|
import { createPublishingService } from '../service.js';
|
|
4
|
+
import { resolvePublishingActor } from './actor.js';
|
|
4
5
|
import { PUBLISHING_TOOLS } from './descriptors.js';
|
|
5
6
|
export function createGetPublishStatusTool(deps) {
|
|
6
7
|
const inputSchema = withMeta({
|
|
@@ -13,10 +14,13 @@ export function createGetPublishStatusTool(deps) {
|
|
|
13
14
|
...PUBLISHING_TOOLS.getPublishStatus,
|
|
14
15
|
inputSchema,
|
|
15
16
|
handler: async (input, ctx) => {
|
|
17
|
+
const actor = resolvePublishingActor(ctx);
|
|
18
|
+
if ('error' in actor)
|
|
19
|
+
return actor;
|
|
16
20
|
const status = await service.getStatus({
|
|
17
21
|
collection: input.collection,
|
|
18
22
|
id: input.id,
|
|
19
|
-
actor
|
|
23
|
+
actor,
|
|
20
24
|
});
|
|
21
25
|
return {
|
|
22
26
|
currentStatus: status.status,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-publish-status.js","sourceRoot":"","sources":["../../src/tools/get-publish-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGrD,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AASnD,MAAM,UAAU,0BAA0B,CAAC,IAA8B;IACvE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;KACf,CAAC,CAAA;IAEF,MAAM,OAAO,GACX,IAAI,CAAC,OAAO;QACZ,uBAAuB,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAC,CAAA;IAEnE,OAAO;QACL,GAAG,gBAAgB,CAAC,gBAAgB;QACpC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,
|
|
1
|
+
{"version":3,"file":"get-publish-status.js","sourceRoot":"","sources":["../../src/tools/get-publish-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGrD,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AASnD,MAAM,UAAU,0BAA0B,CAAC,IAA8B;IACvE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;KACf,CAAC,CAAA;IAEF,MAAM,OAAO,GACX,IAAI,CAAC,OAAO;QACZ,uBAAuB,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAC,CAAA;IAEnE,OAAO;QACL,GAAG,gBAAgB,CAAC,gBAAgB;QACpC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAA;YACzC,IAAI,OAAO,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;YAElC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK;aACN,CAAC,CAAA;YAEF,OAAO;gBACL,aAAa,EAAE,MAAM,CAAC,MAAM;gBAC5B,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;gBACnD,aAAa,EAAE,MAAM,CAAC,WAAW;gBACjC,YAAY,EAAE;oBACZ,UAAU,EAAE,MAAM,CAAC,WAAW;oBAC9B,GAAG,CAAC,MAAM,CAAC,WAAW;wBACpB,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC;4BACE,SAAS,EAAE,MAAM,CAAC,QAAQ;4BAC1B,IAAI,EAAE,MAAM,CAAC,IAAI;4BACjB,MAAM,EAAE,MAAM,CAAC,MAAM;4BACrB,UAAU,EAAE,MAAM,CAAC,UAAU;4BAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;yBAC5B,CAAC;iBACP;aACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/tools/publish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/tools/publish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAI/E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;IACxB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CA8B1E"}
|
package/dist/tools/publish.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { withMeta } from '@forumone/throughline-core';
|
|
3
3
|
import { createPublishingService } from '../service.js';
|
|
4
|
+
import { resolvePublishingActor } from './actor.js';
|
|
4
5
|
import { PUBLISHING_TOOLS } from './descriptors.js';
|
|
5
6
|
export function createPublishTool(deps) {
|
|
6
7
|
const inputSchema = withMeta({
|
|
@@ -18,12 +19,17 @@ export function createPublishTool(deps) {
|
|
|
18
19
|
*/
|
|
19
20
|
requiredScope: 'publishing.execute',
|
|
20
21
|
inputSchema,
|
|
21
|
-
handler: async (input, ctx) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
handler: async (input, ctx) => {
|
|
23
|
+
const actor = resolvePublishingActor(ctx);
|
|
24
|
+
if ('error' in actor)
|
|
25
|
+
return actor;
|
|
26
|
+
return service.publish({
|
|
27
|
+
collection: input.collection,
|
|
28
|
+
id: input.id,
|
|
29
|
+
actor,
|
|
30
|
+
...(input._meta ? { meta: input._meta } : {}),
|
|
31
|
+
});
|
|
32
|
+
},
|
|
27
33
|
};
|
|
28
34
|
}
|
|
29
35
|
//# sourceMappingURL=publish.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/tools/publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGvE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAUnD,MAAM,UAAU,iBAAiB,CAAC,IAAqB;IACrD,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACrE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;KAC3C,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAA;IAE7D,OAAO;QACL,GAAG,gBAAgB,CAAC,OAAO;QAC3B;;;;;UAKE;QACF,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/tools/publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGvE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAUnD,MAAM,UAAU,iBAAiB,CAAC,IAAqB;IACrD,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACrE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;KAC3C,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAA;IAE7D,OAAO;QACL,GAAG,gBAAgB,CAAC,OAAO;QAC3B;;;;;UAKE;QACF,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAA;YACzC,IAAI,OAAO,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;YAElC,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK;gBACL,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9C,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../../src/tools/rollback.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../../src/tools/rollback.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAI/E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,iBAAiB,CAkG5E"}
|
package/dist/tools/rollback.js
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { withMeta } from '@forumone/throughline-core';
|
|
3
3
|
import { sendEventSafely } from '../events.js';
|
|
4
4
|
import { resolveCollection } from '../options.js';
|
|
5
|
+
import { resolvePublishingActor } from './actor.js';
|
|
5
6
|
import { PUBLISHING_TOOLS } from './descriptors.js';
|
|
6
7
|
export function createRollbackTool(deps) {
|
|
7
8
|
const inputSchema = withMeta({
|
|
@@ -14,7 +15,19 @@ export function createRollbackTool(deps) {
|
|
|
14
15
|
requiredScope: 'publishing.execute',
|
|
15
16
|
inputSchema,
|
|
16
17
|
handler: async (input, ctx) => {
|
|
18
|
+
const actor = resolvePublishingActor(ctx);
|
|
19
|
+
if ('error' in actor)
|
|
20
|
+
return actor;
|
|
17
21
|
const collection = resolveCollection(deps.options, input.collection);
|
|
22
|
+
/*
|
|
23
|
+
Both reads and the restore run as the caller with `overrideAccess: false`.
|
|
24
|
+
|
|
25
|
+
This tool had it worst of the five: the version lookup ran at the Local
|
|
26
|
+
API default, and `restoreVersion` was called with no user and no override
|
|
27
|
+
flag at all — so a rollback was a write to a published document that
|
|
28
|
+
consulted nothing. Audit 04 F-02.
|
|
29
|
+
*/
|
|
30
|
+
const enforce = { user: actor.enforceAccessAs, overrideAccess: false };
|
|
18
31
|
// Confirm the version belongs to this document before restoring.
|
|
19
32
|
const versions = await deps.payload.findVersions({
|
|
20
33
|
collection: collection.slug,
|
|
@@ -22,6 +35,7 @@ export function createRollbackTool(deps) {
|
|
|
22
35
|
and: [{ id: { equals: input.versionId } }, { parent: { equals: input.id } }],
|
|
23
36
|
},
|
|
24
37
|
limit: 1,
|
|
38
|
+
...enforce,
|
|
25
39
|
});
|
|
26
40
|
if (!versions.docs[0]) {
|
|
27
41
|
await deps.auditWriter({
|
|
@@ -42,6 +56,7 @@ export function createRollbackTool(deps) {
|
|
|
42
56
|
await deps.payload.restoreVersion({
|
|
43
57
|
collection: collection.slug,
|
|
44
58
|
id: input.versionId,
|
|
59
|
+
...enforce,
|
|
45
60
|
});
|
|
46
61
|
// The version is already restored; a failed emission must not undo
|
|
47
62
|
// that or lose the audit record below.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../src/tools/rollback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAgC,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAQnD,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;KAC9E,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,gBAAgB,CAAC,QAAQ;QAC5B,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;YAEpE,iEAAiE;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;gBAC/C,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,KAAK,EAAE;oBACL,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;iBAC7E;gBACD,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../src/tools/rollback.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedule-publish.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-publish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"schedule-publish.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-publish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAE9E,OAAO,EAAE,KAAK,uBAAuB,EAAqB,MAAM,eAAe,CAAA;AAK/E,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,uBAAuB,GAAG,iBAAiB,CAoH1F"}
|
|
@@ -3,6 +3,7 @@ import { withMeta } from '@forumone/throughline-core';
|
|
|
3
3
|
import { sendEventSafely } from '../events.js';
|
|
4
4
|
import { resolveCollection } from '../options.js';
|
|
5
5
|
import { runPreflightPipeline } from '../pipeline/index.js';
|
|
6
|
+
import { resolvePublishingActor } from './actor.js';
|
|
6
7
|
import { PUBLISHING_TOOLS } from './descriptors.js';
|
|
7
8
|
export function createSchedulePublishTool(deps) {
|
|
8
9
|
const inputSchema = withMeta({
|
|
@@ -18,6 +19,9 @@ export function createSchedulePublishTool(deps) {
|
|
|
18
19
|
requiredScope: 'publishing.execute',
|
|
19
20
|
inputSchema,
|
|
20
21
|
handler: async (input, ctx) => {
|
|
22
|
+
const actor = resolvePublishingActor(ctx);
|
|
23
|
+
if ('error' in actor)
|
|
24
|
+
return actor;
|
|
21
25
|
const collection = resolveCollection(deps.options, input.collection);
|
|
22
26
|
const publishAtMs = Date.parse(input.publishAt);
|
|
23
27
|
if (publishAtMs <= Date.now()) {
|
|
@@ -26,10 +30,14 @@ export function createSchedulePublishTool(deps) {
|
|
|
26
30
|
reason: 'publishAt must be in the future',
|
|
27
31
|
};
|
|
28
32
|
}
|
|
33
|
+
// As the caller, so scheduling a document they cannot read is refused
|
|
34
|
+
// here rather than at the moment the cron fires it.
|
|
29
35
|
const document = (await deps.payload.findByID({
|
|
30
36
|
collection: collection.slug,
|
|
31
37
|
id: input.id,
|
|
32
38
|
draft: true,
|
|
39
|
+
user: actor.enforceAccessAs,
|
|
40
|
+
overrideAccess: false,
|
|
33
41
|
}));
|
|
34
42
|
const preflight = await runPreflightPipeline({
|
|
35
43
|
payload: deps.payload,
|
|
@@ -38,7 +46,7 @@ export function createSchedulePublishTool(deps) {
|
|
|
38
46
|
collection,
|
|
39
47
|
document,
|
|
40
48
|
documentId: input.id,
|
|
41
|
-
actor
|
|
49
|
+
actor,
|
|
42
50
|
...(input._meta ? { meta: input._meta } : {}),
|
|
43
51
|
});
|
|
44
52
|
if (!preflight.success) {
|
|
@@ -70,6 +78,10 @@ export function createSchedulePublishTool(deps) {
|
|
|
70
78
|
data: { [collection.scheduledPublishField]: input.publishAt },
|
|
71
79
|
overrideLock: false,
|
|
72
80
|
context: { bypassPublishingServer: false },
|
|
81
|
+
// As the caller. Scheduling is a write to a published document, and it
|
|
82
|
+
// ran at `overrideAccess: true` like the other four — audit 04 F-02.
|
|
83
|
+
user: actor.enforceAccessAs,
|
|
84
|
+
overrideAccess: false,
|
|
73
85
|
});
|
|
74
86
|
// The schedule is already persisted; a failed emission must not undo
|
|
75
87
|
// that or lose the audit record below.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedule-publish.js","sourceRoot":"","sources":["../../src/tools/schedule-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAgC,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAQnD,MAAM,UAAU,yBAAyB,CAAC,IAA6B;IACrE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,8DAA8D,CAAC;KAC5E,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,gBAAgB,CAAC,eAAe;QACnC,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;YACpE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;YAC/C,IAAI,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC9B,OAAO;oBACL,SAAS,EAAE,KAAK;oBAChB,MAAM,EAAE,iCAAiC;iBAC1C,CAAA;YACH,CAAC;YAED,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC5C,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK,EAAE,IAAI;
|
|
1
|
+
{"version":3,"file":"schedule-publish.js","sourceRoot":"","sources":["../../src/tools/schedule-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAgC,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAQnD,MAAM,UAAU,yBAAyB,CAAC,IAA6B;IACrE,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,8DAA8D,CAAC;KAC5E,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,gBAAgB,CAAC,eAAe;QACnC,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAA;YACzC,IAAI,OAAO,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;YAElC,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;YACpE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;YAC/C,IAAI,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC9B,OAAO;oBACL,SAAS,EAAE,KAAK;oBAChB,MAAM,EAAE,iCAAiC;iBAC1C,CAAA;YACH,CAAC;YAED,sEAAsE;YACtE,oDAAoD;YACpD,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC5C,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,KAAK,CAAC,eAAe;gBAC3B,cAAc,EAAE,KAAK;aACtB,CAAC,CAA4B,CAAA;YAE9B,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC;gBAC3C,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,UAAU;gBACV,QAAQ;gBACR,UAAU,EAAE,KAAK,CAAC,EAAE;gBACpB,KAAK;gBACL,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9C,CAAC,CAAA;YAEF,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,WAAW,CAAC;oBACrB,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;oBAC/F,MAAM,EAAE,qBAAqB;oBAC7B,SAAS,EAAE,YAAY;oBACvB,OAAO,EAAE,kBAAkB;oBAC3B,gBAAgB,EAAE,KAAK,CAAC,UAAU;oBAClC,QAAQ,EAAE,KAAK,CAAC,EAAE;oBAClB,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU;oBAC/B,OAAO,EAAE,KAAK;oBACd,YAAY,EAAE,SAAS,CAAC,MAAM;iBAC/B,CAAC,CAAA;gBACF,OAAO;oBACL,SAAS,EAAE,KAAK;oBAChB,QAAQ,EAAE,SAAS,CAAC,QAAQ;oBAC5B,MAAM,EAAE,SAAS,CAAC,MAAM;oBACxB,IAAI,EAAE,SAAS,CAAC,IAAI;oBACpB,MAAM,EAAE,SAAS,CAAC,MAAM;oBACxB,UAAU,EAAE,SAAS,CAAC,UAAU;iBACjC,CAAA;YACH,CAAC;YAED,iEAAiE;YACjE,yEAAyE;YACzE,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;gBACxB,UAAU,EAAE,UAAU,CAAC,IAAI;gBAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE;gBAC7D,YAAY,EAAE,KAAK;gBACnB,OAAO,EAAE,EAAE,sBAAsB,EAAE,KAAK,EAAE;gBAC1C,uEAAuE;gBACvE,qEAAqE;gBACrE,IAAI,EAAE,KAAK,CAAC,eAAe;gBAC3B,cAAc,EAAE,KAAK;aACtB,CAAC,CAAA;YAEF,qEAAqE;YACrE,uCAAuC;YACvC,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;gBAC1D,IAAI,EAAE,wBAAwB;gBAC9B,IAAI,EAAE;oBACJ,UAAU,EAAE,UAAU,CAAC,IAAI;oBAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,YAAY,EAAE,KAAK,CAAC,SAAS;iBAC9B;aACF,CAAC,CAAA;YAEF,MAAM,IAAI,CAAC,WAAW,CAAC;gBACrB,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;gBAC/F,MAAM,EAAE,qBAAqB;gBAC7B,SAAS,EAAE,YAAY;gBACvB,OAAO,EAAE,kBAAkB;gBAC3B,gBAAgB,EAAE,KAAK,CAAC,UAAU;gBAClC,QAAQ,EAAE,KAAK,CAAC,EAAE;gBAClB,WAAW,EAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;gBACjF,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU;gBAC/B,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS;gBACjC,cAAc,EAAE,yBAAyB,KAAK,CAAC,SAAS,EAAE;gBAC1D,OAAO,EAAE,IAAI;aACd,CAAC,CAAA;YAEF,OAAO;gBACL,SAAS,EAAE,IAAI;gBACf,YAAY,EAAE,KAAK,CAAC,SAAS;gBAC7B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5C,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unpublish.d.ts","sourceRoot":"","sources":["../../src/tools/unpublish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"unpublish.d.ts","sourceRoot":"","sources":["../../src/tools/unpublish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAI/E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,WAAW,CAAA;IACxB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,CAwB9E"}
|
package/dist/tools/unpublish.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { withMeta } from '@forumone/throughline-core';
|
|
3
3
|
import { createPublishingService } from '../service.js';
|
|
4
|
+
import { resolvePublishingActor } from './actor.js';
|
|
4
5
|
import { PUBLISHING_TOOLS } from './descriptors.js';
|
|
5
6
|
export function createUnpublishTool(deps) {
|
|
6
7
|
const inputSchema = withMeta({
|
|
@@ -12,12 +13,17 @@ export function createUnpublishTool(deps) {
|
|
|
12
13
|
...PUBLISHING_TOOLS.unpublish,
|
|
13
14
|
requiredScope: 'publishing.execute',
|
|
14
15
|
inputSchema,
|
|
15
|
-
handler: async (input, ctx) =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
handler: async (input, ctx) => {
|
|
17
|
+
const actor = resolvePublishingActor(ctx);
|
|
18
|
+
if ('error' in actor)
|
|
19
|
+
return actor;
|
|
20
|
+
return service.unpublish({
|
|
21
|
+
collection: input.collection,
|
|
22
|
+
id: input.id,
|
|
23
|
+
actor,
|
|
24
|
+
...(input._meta ? { meta: input._meta } : {}),
|
|
25
|
+
});
|
|
26
|
+
},
|
|
21
27
|
};
|
|
22
28
|
}
|
|
23
29
|
//# sourceMappingURL=unpublish.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unpublish.js","sourceRoot":"","sources":["../../src/tools/unpublish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGvE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAUnD,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;KACf,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAA;IAE7D,OAAO;QACL,GAAG,gBAAgB,CAAC,SAAS;QAC7B,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"unpublish.js","sourceRoot":"","sources":["../../src/tools/unpublish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAoB,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGvE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAUnD,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;KACf,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAA;IAE7D,OAAO;QACL,GAAG,gBAAgB,CAAC,SAAS;QAC7B,aAAa,EAAE,oBAAoB;QACnC,WAAW;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAA;YACzC,IAAI,OAAO,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;YAElC,OAAO,OAAO,CAAC,SAAS,CAAC;gBACvB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,KAAK;gBACL,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9C,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forumone/throughline-publishing",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Policy-gated publishing server for Throughline. Wraps Payload's update operation with composition, accessibility, required-field, embargo, and approval gating.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"zod": "^3.23.0",
|
|
62
|
-
"@forumone/throughline-core": "0.8.
|
|
62
|
+
"@forumone/throughline-core": "0.8.2",
|
|
63
63
|
"@forumone/throughline-plugin-contract": "0.4.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"payload": "^3.83.0",
|
|
73
73
|
"react": "^19.2.0",
|
|
74
74
|
"typescript": "^5.6.0",
|
|
75
|
-
"vitest": "^
|
|
75
|
+
"vitest": "^4.1.10",
|
|
76
76
|
"@forumone/throughline-eslint-config": "0.0.0",
|
|
77
77
|
"@forumone/throughline-tsconfig": "0.0.0"
|
|
78
78
|
},
|