Repository navigation
feat: brew.send(key, payload) and fire by key (13.1.0) - #55
Open
thedogwiththedataonit wants to merge 7 commits into
Open
thedogwiththedataonit wants to merge 7 commits into
thedogwiththedataonit wants to merge 7 commits into
Conversation
This was referenced Oct 13, 2026
Open
thedogwiththedataonit
added a commit
to GetBrew/brew-cli
that referenced
this pull request
Oct 16, 2026
package.json goes to 0.17.0 and the Unreleased notes (mcp install, browser sign-in, send and app-emails, the canvas SDK methods) become 0.17.0. RELEASING.md gains the app email SDK gate: `send` and `app-emails` need the SDK release carrying GetBrew/typescript-sdk#55 and #64, which is not on npm yet, so the dependency and bun.lock stay on main's pin until it publishes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thedogwiththedataonit
added a commit
to GetBrew/brew-cli
that referenced
this pull request
Oct 16, 2026
package.json goes to 0.17.0 and the Unreleased notes (mcp install, browser sign-in, send and app-emails, the canvas SDK methods) become 0.17.0. RELEASING.md gains the app email SDK gate: `send` and `app-emails` need the SDK release carrying GetBrew/typescript-sdk#55 and #64, which is not on npm yet, so the dependency and bun.lock stay on main's pin until it publishes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thedogwiththedataonit
added a commit
to GetBrew/brew-cli
that referenced
this pull request
Oct 16, 2026
package.json goes to 0.17.0 and the Unreleased notes (mcp install, browser sign-in, send and app-emails, the canvas SDK methods) become 0.17.0. RELEASING.md gains the app email SDK gate: `send` and `app-emails` need the SDK release carrying GetBrew/typescript-sdk#55 and #64, which is not on npm yet, so the dependency and bun.lock stay on main's pin until it publishes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- automations.triggers.fireByKey({ triggerKey, payload }, options?) for
POST /v1/automations/triggers/by-key/{triggerKey}/fire, mirroring fire
(TPayload generic, { raw: true } overload); empty/dot-segment keys throw
a TypeError before any request.
- brew.send(key, payload, options?) on every client (and withBrand
clients), typed by the augmentable BrewTriggerKeyRegistry: any string
key while it is empty, exactly its keys and payloads once augmented.
- Regenerated spec from brew-v2#2017: trigger rows carry key + appEmail,
create/patch take key, the fire body gains triggerKey, new
TRIGGER_KEY_* error codes.
- README "Send your first app email", docs/send.md, automations.md trigger
keys, AGENTS.md two-positional exception, CHANGELOG 12.2.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- `brew.send(key, payload)` with `key: 'auth.password-reset' | 'order.paid'`
no longer accepts a password-reset payload: `BrewSendPayloadFor<TKey>`
takes a literal key's own payload and, for a union key, the intersection
of its members' payloads. Literal-key errors stay on the offending
property (a union-of-tuples rest signature moved every one of them to
"No overload matches this call" on the call line).
- `FireTriggerByKeyResponse.triggerKey` is required: a by-key fire,
accepted or replayed, always names the key.
- With an empty registry a payload field may be `undefined`; `JSON.stringify`
leaves it out of the body.
- Type tests: union key refused (with and without `{ raw: true }`), a
payload fitting every member accepted, narrowed pairs accepted,
`string | undefined` fields accepted, `email: undefined` refused.
Mutation-checked against the old payload type. The 404 test mocks the
API's real TRIGGER_KEY_NOT_FOUND suggestion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…elog - README and docs/send.md use the canonical kit keys and the shared auth payload (`appName` optional); no "receipts", no `npx brew.new init`. - docs/send.md: the by-key route needs the brew-v2 #2013 + #2017 deploy before 12.2.0 is released; union-key and `undefined` field rules. - CHANGELOG: the missing 12.1.0 entry (#50); 12.2.0 names the vendored spec commit and what else shipped since 12.1.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's Unreleased section (canvas revoke response) is planned as 13.0.0 under the method-signature version policy, and 12.2.0/12.3.0 are already published. brew.send and fireByKey therefore ship as 13.1.0. The vendored spec is brew-v2 main 8c7020e535 plus #2013 (d556eaf50d) and #2017 (104d635e70); package.json stays at main's version for the release commit to bump. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thedogwiththedataonit
force-pushed
the
claude/send-by-key
branch
from
October 16, 2026 16:12
3a1259b to
8bae73f
Compare
…e rebase AGENTS.md links to docs/development.md#the-brewsend-exception; the section lived in the old merge commit and did not survive the rebase onto main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2017 was rebased onto #2013 (d556eaf50d) on brew-v2 main 8c7020e535, so the vendored spec is now byte-identical to its own. New since 104d635e70: a Brew-event trigger refuses a by-key fire with 409 TRIGGER_NOT_FIREABLE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thedogwiththedataonit
added a commit
that referenced
this pull request
Oct 16, 2026
- CHANGELOG: this ships as 13.2.0, after 13.1.0 (#55) and main's planned 13.0.0; the payload merge order reads `{ ...variables, email: to }` (the recipient wins), as the code does; error and warning codes listed are only those in the vendored spec; new: import modes (#2064), Better Auth invites, the migrate command. - Spec: brew-v2 main 8c7020e535 + #2013 d556eaf50d + #2017 104d635e70 + #2066 c72bb45467 + #2064 70fb35dd71 (team sandbox #2059 not included). - Packaging checks cover main's /embed and /react: typesVersions entries, smoke loads both (with react linked in), `npm pack --ignore-scripts` (main added a prepare script), and the only allowed peer is the optional react. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BrewSendPayloadFor intersected the payloads after distributing over them, so a key whose registered payload is itself a union required every alternative at once (Greptile P2 on #55): with 'invite.sent' as { channel: 'link', … } | { channel: 'code', … }, a key typed 'invite.sent' | 'auth.password-reset' collapsed to never. Distribute over the keys only: (A1 | A2) & B. Type test added to the augmented registry program (fails before the fix). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thedogwiththedataonit
added a commit
that referenced
this pull request
Oct 16, 2026
- CHANGELOG: this ships as 13.2.0, after 13.1.0 (#55) and main's planned 13.0.0; the payload merge order reads `{ ...variables, email: to }` (the recipient wins), as the code does; error and warning codes listed are only those in the vendored spec; new: import modes (#2064), Better Auth invites, the migrate command. - Spec: brew-v2 main 8c7020e535 + #2013 d556eaf50d + #2017 104d635e70 + #2066 c72bb45467 + #2064 70fb35dd71 (team sandbox #2059 not included). - Packaging checks cover main's /embed and /react: typesVersions entries, smoke loads both (with react linked in), `npm pack --ignore-scripts` (main added a prepare script), and the only allowed peer is the optional react. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 of 9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
App email by trigger key, the SDK half of the DX push (
brew.send). Rebased onmaind804502(10-16).brew.send(key, payload, options?)on every client, includingwithBrand(...)clients:brew.send('auth.password-reset', { email, confirmationUrl, appName })firesPOST /v1/automations/triggers/by-key/{triggerKey}/firewith{ payload }and resolves to the accepted fire(
triggerInstanceId,automationRunIds,triggerKey, ...).{ idempotencyKey }is forwarded as theIdempotency-Keyheader;{ raw: true }passes through.brew.automations.triggers.fireByKey({ triggerKey, payload }, options?): the object form, mirroringfire(
TPayloadgeneric,rawoverload). An unknown key throwsBrewApiError404TRIGGER_KEY_NOT_FOUND, a Brew-eventtrigger 409
TRIGGER_NOT_FIREABLE; an empty,.or..key throws aTypeErrorbefore any request (dot segmentswould otherwise resolve to another route).
FireTriggerByKeyResponse.triggerKeyis required.BrewTriggerKeyRegistry(augment withdeclare module '@brew.new/sdk'): empty by default, sosendtakes anystring key and
{ email: string } & { [k: string]: SendPayloadValue | undefined }. Once augmented, unknown keys andwrong payloads stop compiling; a key typed as a union must carry a payload that fits every key in it, and a key whose
payload is itself a union is satisfied by any one of its alternatives (Greptile P2, fixed in
d073ec7).main8c7020e535plus exactly the operations and schemas of GetBrew/brew-v2#2013 (d556eaf50d)and #2017 (
63736f0f99). With #2017 now stacked on #2013 on current main, the vendored file is byte-identical to#2017's own spec. Trigger rows carry
key+appEmail,create/patchtakekey,TriggerFireAccepted.triggerKey,codes
TRIGGER_KEY_NOT_FOUND/TRIGGER_KEY_RESERVED/TRIGGER_KEY_TAKEN. Types regenerated withbun run generate:types.docs/send.md,docs/automations.mdtrigger keys, the two-positionalbrew.sendexception indocs/development.md#the-brewsend-exception(AGENTS.md pointer; AGENTS.md is 8,176 bytes).Version: 13.1.0 (not released)
npm already has 12.2.0 and 12.3.0. Main's
CHANGELOG"Unreleased" section (#71, canvasrevokeresponse) changes apublic method signature and is planned as 13.0.0 under RELEASING.md's version policy (brew-cli's RELEASING waits
for it). This PR only adds, so it is the next minor after that: 13.1.0. The CHANGELOG heading is
13.1.0 (not released yet), above Unreleased.package.jsonstays at main's version: the release commit(
npm version 13.1.0) sets it, so merging this before 13.0.0 is cut cannot skip 13.0.0. Cut 13.0.0 first.#64 (adapters +
appEmails) is 13.2.0. Consumers that needbrew.sendpin^13.1.0.Rebase notes
client.ts(main'scanvasresource +send, both kept),package.json(main's 12.3.0 kept),AGENTS.md (main's text + the one-line
brew.sendpointer), CHANGELOG (main's history kept; this PR's entry rewritten as13.1.0; the 12.1.0 backfill kept), spec + generated types (rebuilt, not merged).
docs/development.mdsection lived in a merge commit and was dropped by the rebase; restored in1fe8154.Publish gate
Do not tag or publish until GetBrew/brew-v2#2013 and #2017 are deployed and the live spec matches the vendored one
(the by-key operation and the trigger
key/appEmailfields). Until then the by-key route answers 404 and triggerrows carry no
key. If either PR changes its spec before merge, re-vendor and runbun run generate:types.Tests
tests/resources/automations/triggers/fire-by-key.test.ts(MSW): dotted key in the path, body{ payload }, auto andcaller idempotency header,
/and?percent-encoded,./../empty refused,{ raw: true }, 404 mapping.tests/send.test.ts(MSW viacreateBrewClient): body,undefinedfield dropped, idempotency option,X-Brand-Idfrom
withBrand, 404.tests/types/send-registry.test.ts+tests/types/augmented-registry/(a separate TypeScript program; every@ts-expect-errormust fire): unknown key, wrong payload, missing field, union key, union payload alternatives.Local on head
d073ec7:bun tsc,bun lint,bun run format:check,bun run test(124 files, 713 tests),bun run build,generate:typesfreshness,bun install --frozen-lockfile(no changes), AGENTS.md budget: all pass.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; no blocking issues remain.Summary
Adds
brew.send(key, payload, options?)andautomations.triggers.fireByKey, with brand scoping, request options, and typed trigger keys.brew.sendsends app email by its trigger key.Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR A["brew.send(key, payload, options)"] --> B["triggers.fireByKey"] C["withBrand client"] --> A B --> D["Shared HTTP client"] D --> E["POST /v1/automations/triggers/by-key/{triggerKey}/fire"] E --> F["Accepted fire or raw response"]Reviews (4) · Last reviewed commit: "fix(send): keep a union payload's altern..." · Reviewed by Greptile