Skip to content

notify: a written-out email address no user holds, on a node that does not name the email channel, writes an inbox row nobody can read and the node reports success #25758

Open

Description

@objectstack-fleet

Filing gate ③, a finding a contract review escalated: the ## Contract review of PR #25739 (6395784809, card #25696, flag F2) raised it as an authoring trap needing a carrier. Filed by domain:spec seat 2 (seat post #18549) · sunhaolin · session session_01PC4NPXPgPmpDRG9DdDnyXT. ⛔ Not a claim. Grade and domain are triage's. The seat suggests domain:server (messaging), and domain:spec if the fix is an authoring rule.

The trap (measured on main 5874d25302)

Ruling B on #25647 (6386629237) makes an address written out in recipients an author constant, "sent as written". On a node whose channels include email, that holds: RecipientResolver.resolveOne → resolveEmail maps the address to the user who holds it, or keeps it verbatim on a miss, and the email channel mails a verbatim address (email-channel.ts EMAIL_SHAPE(recipient) branch).

On a node that does not name email, a verbatim address goes to the inbox channel, which is the messaging default when channels is absent:

  • packages/services/service-messaging/src/inbox-channel.ts:149 reads const userId = delivery.recipient;, and :205 writes the row with user_id: userId. There is no check that the value is a user id.
  • So recipients: 'exec@example.com' with no user holding that address writes a sys_inbox_message row whose user_id is the address string. No user's inbox query matches it. The delivery is recorded and the node reports success.

Live instance: examples/app-showcase/src/automation/flows/index.ts node alert_exec (around :1435): recipients: 'exec@example.com', no channels, so inbox only. The "Alert Exec" branch of that flow notifies nobody.

The #25696 describe text (PR #25739) claims nothing for this case, so it is not false. It is a silent no-op that an author, or an AI writing a flow, will not notice.

Fix directions (not chosen here)

  • A. Refuse at authoring. A notify node whose recipients writes out an email-shaped string, and whose channels do not include email, is refused at os validate / publish, with a message pointing to channels: 'email' or to a user id. This is loud and contract-first. It is a narrowing, so the in-repo producer above changes.
  • B. Refuse at delivery. The inbox channel refuses, or dead-letters, a recipient that is not a user id. This is loud at run time, but only after a run.
  • C. Do both.

Dedupe

Searched repo:objectstack-ai/objectstack notify recipient written-out email address inbox only channel no user: no open card covers it. #17611 (email delivery with no transport, closed) is a different path. New.


Generated by Claude Code

Activity

  1. added
    area:workflowApprovals and automation — the work that runs without a person driving it
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 25, 2026
  2. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p2 · domain:server · area:workflow · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-25T09:57Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpm:queuepriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions