Releases: forumone/throughline
Release list
@forumone/throughline-approvals@0.8.3
Patch Changes
-
1f3346f:
get_approval_statusnow refuses an unauthenticated caller, and answers only
the requester or a member of an approver group.It had no authorization check of any kind. The handler was
async (input) =>—
the signature did not acceptctx, so there was nothing to check against — and
itfindByIDd an arbitraryapprovalIdat the Local API default of
overrideAccess: true, returning the target, the requester, the approver
groups, the decision and the decision notes. The other four tools on this
server all checkctx.user, which made this the one approvals tool that still
answered when the rest correctly denied. Audit 04 F-20.The rule is the union of what the two list tools already show a caller —
list_my_requestsreturns the approvals they requested,list_pending_approvals
the ones routed to their groups — so the by-id read agrees with the by-list
reads instead of being a way around them. No admin bypass, because
respond_to_approvalhas none either and a second policy on the same collection
is how the two drift.A refused read returns
Approval not found, the same sentence as a genuine
miss: ids are sequential, and a distinguishable refusal enumerates who is asking
whom to approve what.Behavioural change for consumers. A
get_approval_statuscall arriving with
noctx.usernow returns{ error: 'Must be authenticated…' }instead of the
approval. In practice that is everyBearer-authenticated MCP call, because
@payloadcms/plugin-mcpdoes not assignreq.user— the same fact that made
the four gated tools deny and this one answer.
@forumone/throughline-workflows@0.3.0
Minor Changes
-
7fc0c19: Every workflow factory now takes
onTerminalFailureandconcurrency.Audit 06 F-09, found in the only consumer: across that app and all seventeen
packages here,onFailure|idempotency|concurrency|singletonmatched no function
config at all. A run that exhausted its retries stopped — no dead-letter row, no
email, no page — and 12 H1 is what that cost:expire-stale-approvalsthrew at
02:00 UTC every night for eighteen days, in every environment, and nobody
noticed. A host had no way to be told, because the factories took no option.Both live on
BaseWorkflowOptions, so a host wires failure handling once rather
than per factory, andfailureOptionsis the single place the translation
happens.onTerminalFailure, notonFailure, and the collision that forced the name is
worth knowing:HealthcheckOptions.onFailurealready exists and means something
different — once per run with the checks that failed, on the first bad run,
because a probe has no retries to exhaust. Both are useful and a healthcheck can
take both. One name for two moments would have made every call site ambiguous
about which it was wiring.concurrencydefaults to 1 on the three functions that need it and is absent on
the two that do not, which is a claim about which of them race:execute-scheduled-publishesandexpire-stale-approvalsboth collect a set
of due rows and then act on them. Overlapping runs find the same row and both
act — a document published twice through a pipeline that gates on approvals,
or a requester told twice that their request lapsed.healthcheckis capped because two probes report one outage twice.revalidate-on-publishandaudit-event-echoare left uncapped. Revalidating
twice is the same as revalidating once, and one audit row is one event, so
serialising them would put a queue in front of every publish and every audited
write for no correctness gain.
A host passing
concurrencyoverrides the default; passing 0 is honoured rather
than read as absent.AuditEventEchoOptionstakes aninngestand nopayload, so it is not a
BaseWorkflowOptions. Rather than exclude it from failure handling for a reason
unrelated to failure handling,failureOptionsreads a narrower
FailureAwareOptionsand that interface extends it.New exports:
failureOptions, and the typesWorkflowFailureHandlerand
FailureAwareOptions.
@forumone/throughline-workflows@0.2.11
Patch Changes
- Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0
@forumone/throughline-publishing@0.9.3
Patch Changes
-
debfcd2:
system.errornow has a writer. Every MCP tool handler the suite serves is
wrapped, so a tool that throws records onesystem.erroraudit row — the
server, the tool, the caller, the caller's_meta, and the error's message —
before the throw propagates to the MCP client as it did before.The row carries no stack and no arguments:
error_messageis readable by every
admin and editor, a stack names file paths, and a tool's input can hold a draft
body or a form submission. A failure inside the recording is logged and
swallowed, so this wrapper can never replace a tool's real error with its own.mcpServeris resolved through a map rather than from the collector's own
server name, because the two vocabularies disagree: the components server
declares itselfcomponentsand the audit enum's value iscomponent. A
server that passes an audit writer and has no name in that map is now a
boot-time refusal instead of a row Payload silently rejects. New export:
auditServerFor.Each of the six servers passes its audit writer to
collector.add, alongside
the logger it already passed. A host wiring a tool by hand passes none and gets
the previous behaviour. -
Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0
@forumone/throughline-integrations@0.8.4
Patch Changes
-
debfcd2:
system.errornow has a writer. Every MCP tool handler the suite serves is
wrapped, so a tool that throws records onesystem.erroraudit row — the
server, the tool, the caller, the caller's_meta, and the error's message —
before the throw propagates to the MCP client as it did before.The row carries no stack and no arguments:
error_messageis readable by every
admin and editor, a stack names file paths, and a tool's input can hold a draft
body or a form submission. A failure inside the recording is logged and
swallowed, so this wrapper can never replace a tool's real error with its own.mcpServeris resolved through a map rather than from the collector's own
server name, because the two vocabularies disagree: the components server
declares itselfcomponentsand the audit enum's value iscomponent. A
server that passes an audit writer and has no name in that map is now a
boot-time refusal instead of a row Payload silently rejects. New export:
auditServerFor.Each of the six servers passes its audit writer to
collector.add, alongside
the logger it already passed. A host wiring a tool by hand passes none and gets
the previous behaviour. -
Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0
@forumone/throughline-forms@0.6.3
Patch Changes
-
debfcd2:
system.errornow has a writer. Every MCP tool handler the suite serves is
wrapped, so a tool that throws records onesystem.erroraudit row — the
server, the tool, the caller, the caller's_meta, and the error's message —
before the throw propagates to the MCP client as it did before.The row carries no stack and no arguments:
error_messageis readable by every
admin and editor, a stack names file paths, and a tool's input can hold a draft
body or a form submission. A failure inside the recording is logged and
swallowed, so this wrapper can never replace a tool's real error with its own.mcpServeris resolved through a map rather than from the collector's own
server name, because the two vocabularies disagree: the components server
declares itselfcomponentsand the audit enum's value iscomponent. A
server that passes an audit writer and has no name in that map is now a
boot-time refusal instead of a row Payload silently rejects. New export:
auditServerFor.Each of the six servers passes its audit writer to
collector.add, alongside
the logger it already passed. A host wiring a tool by hand passes none and gets
the previous behaviour. -
Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0
- @forumone/throughline-email@0.2.11
@forumone/throughline-email@0.2.11
Patch Changes
- Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0
@forumone/throughline-core@0.9.0
Minor Changes
-
debfcd2:
system.errornow has a writer. Every MCP tool handler the suite serves is
wrapped, so a tool that throws records onesystem.erroraudit row — the
server, the tool, the caller, the caller's_meta, and the error's message —
before the throw propagates to the MCP client as it did before.The row carries no stack and no arguments:
error_messageis readable by every
admin and editor, a stack names file paths, and a tool's input can hold a draft
body or a form submission. A failure inside the recording is logged and
swallowed, so this wrapper can never replace a tool's real error with its own.mcpServeris resolved through a map rather than from the collector's own
server name, because the two vocabularies disagree: the components server
declares itselfcomponentsand the audit enum's value iscomponent. A
server that passes an audit writer and has no name in that map is now a
boot-time refusal instead of a row Payload silently rejects. New export:
auditServerFor.Each of the six servers passes its audit writer to
collector.add, alongside
the logger it already passed. A host wiring a tool by hand passes none and gets
the previous behaviour.
@forumone/throughline-components@0.5.5
Patch Changes
-
debfcd2:
system.errornow has a writer. Every MCP tool handler the suite serves is
wrapped, so a tool that throws records onesystem.erroraudit row — the
server, the tool, the caller, the caller's_meta, and the error's message —
before the throw propagates to the MCP client as it did before.The row carries no stack and no arguments:
error_messageis readable by every
admin and editor, a stack names file paths, and a tool's input can hold a draft
body or a form submission. A failure inside the recording is logged and
swallowed, so this wrapper can never replace a tool's real error with its own.mcpServeris resolved through a map rather than from the collector's own
server name, because the two vocabularies disagree: the components server
declares itselfcomponentsand the audit enum's value iscomponent. A
server that passes an audit writer and has no name in that map is now a
boot-time refusal instead of a row Payload silently rejects. New export:
auditServerFor.Each of the six servers passes its audit writer to
collector.add, alongside
the logger it already passed. A host wiring a tool by hand passes none and gets
the previous behaviour. -
Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0
@forumone/throughline-audit@0.5.3
Patch Changes
-
debfcd2:
system.errornow has a writer. Every MCP tool handler the suite serves is
wrapped, so a tool that throws records onesystem.erroraudit row — the
server, the tool, the caller, the caller's_meta, and the error's message —
before the throw propagates to the MCP client as it did before.The row carries no stack and no arguments:
error_messageis readable by every
admin and editor, a stack names file paths, and a tool's input can hold a draft
body or a form submission. A failure inside the recording is logged and
swallowed, so this wrapper can never replace a tool's real error with its own.mcpServeris resolved through a map rather than from the collector's own
server name, because the two vocabularies disagree: the components server
declares itselfcomponentsand the audit enum's value iscomponent. A
server that passes an audit writer and has no name in that map is now a
boot-time refusal instead of a row Payload silently rejects. New export:
auditServerFor.Each of the six servers passes its audit writer to
collector.add, alongside
the logger it already passed. A host wiring a tool by hand passes none and gets
the previous behaviour. -
Updated dependencies [debfcd2]
- @forumone/throughline-core@0.9.0