Skip to content

Releases: forumone/throughline

@forumone/throughline-approvals@0.8.3

Choose a tag to compare

@briangraves briangraves released this 12 Sep 00:31
9ee2a69

Patch Changes

  • 1f3346f: get_approval_status now 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 accept ctx, so there was nothing to check against — and
    it findByIDd an arbitrary approvalId at 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 check ctx.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_requests returns 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_approval has 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_status call arriving with
    no ctx.user now returns { error: 'Must be authenticated…' } instead of the
    approval. In practice that is every Bearer-authenticated MCP call, because
    @payloadcms/plugin-mcp does not assign req.user — the same fact that made
    the four gated tools deny and this one answer.

@forumone/throughline-workflows@0.3.0

Choose a tag to compare

@briangraves briangraves released this 05 Sep 16:10
f3c00ce

Minor Changes

  • 7fc0c19: Every workflow factory now takes onTerminalFailure and concurrency.

    Audit 06 F-09, found in the only consumer: across that app and all seventeen
    packages here, onFailure|idempotency|concurrency|singleton matched 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-approvals threw 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, and failureOptions is the single place the translation
    happens.

    onTerminalFailure, not onFailure, and the collision that forced the name is
    worth knowing: HealthcheckOptions.onFailure already 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.

    concurrency defaults 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-publishes and expire-stale-approvals both 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.
    • healthcheck is capped because two probes report one outage twice.
    • revalidate-on-publish and audit-event-echo are 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 concurrency overrides the default; passing 0 is honoured rather
    than read as absent.

    AuditEventEchoOptions takes an inngest and no payload, so it is not a
    BaseWorkflowOptions. Rather than exclude it from failure handling for a reason
    unrelated to failure handling, failureOptions reads a narrower
    FailureAwareOptions and that interface extends it.

    New exports: failureOptions, and the types WorkflowFailureHandler and
    FailureAwareOptions.

@forumone/throughline-workflows@0.2.11

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:44
028d6d2

Patch Changes

  • Updated dependencies [debfcd2]
    • @forumone/throughline-core@0.9.0

@forumone/throughline-publishing@0.9.3

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:44
028d6d2

Patch Changes

  • debfcd2: system.error now has a writer. Every MCP tool handler the suite serves is
    wrapped, so a tool that throws records one system.error audit 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_message is 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.

    mcpServer is resolved through a map rather than from the collector's own
    server name, because the two vocabularies disagree: the components server
    declares itself components and the audit enum's value is component. 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

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:44
028d6d2

Patch Changes

  • debfcd2: system.error now has a writer. Every MCP tool handler the suite serves is
    wrapped, so a tool that throws records one system.error audit 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_message is 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.

    mcpServer is resolved through a map rather than from the collector's own
    server name, because the two vocabularies disagree: the components server
    declares itself components and the audit enum's value is component. 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

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:44
028d6d2

Patch Changes

  • debfcd2: system.error now has a writer. Every MCP tool handler the suite serves is
    wrapped, so a tool that throws records one system.error audit 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_message is 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.

    mcpServer is resolved through a map rather than from the collector's own
    server name, because the two vocabularies disagree: the components server
    declares itself components and the audit enum's value is component. 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

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:43
028d6d2

Patch Changes

  • Updated dependencies [debfcd2]
    • @forumone/throughline-core@0.9.0

@forumone/throughline-core@0.9.0

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:43
028d6d2

Minor Changes

  • debfcd2: system.error now has a writer. Every MCP tool handler the suite serves is
    wrapped, so a tool that throws records one system.error audit 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_message is 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.

    mcpServer is resolved through a map rather than from the collector's own
    server name, because the two vocabularies disagree: the components server
    declares itself components and the audit enum's value is component. 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

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:44
028d6d2

Patch Changes

  • debfcd2: system.error now has a writer. Every MCP tool handler the suite serves is
    wrapped, so a tool that throws records one system.error audit 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_message is 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.

    mcpServer is resolved through a map rather than from the collector's own
    server name, because the two vocabularies disagree: the components server
    declares itself components and the audit enum's value is component. 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

Choose a tag to compare

@briangraves briangraves released this 04 Sep 01:44
028d6d2

Patch Changes

  • debfcd2: system.error now has a writer. Every MCP tool handler the suite serves is
    wrapped, so a tool that throws records one system.error audit 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_message is 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.

    mcpServer is resolved through a map rather than from the collector's own
    server name, because the two vocabularies disagree: the components server
    declares itself components and the audit enum's value is component. 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