Conversation
REST clients had no way to introspect plugin action schemas without
going through MCP. The MCP list_action_schemas tool exists, but a
parallel REST entry point did not — every REST integrator was forced
into MCP for schema discovery, and that gap is the upstream cause of a
class of silent-config bugs (workflow PATCHes accepted with unknown
actionTypes or invalid configs because the caller could not validate
locally).
Adds:
- GET /api/action-schemas — bearer kh_ auth, returns the same payload
shape as list_action_schemas. Supports ?category=, ?includeChains=,
and ?type=<actionType> to narrow the actions map to a single entry.
- GET /api/action-schemas/{actionType} — bearer kh_ auth, returns just
the matching action schema; 404 on unknown actionType.
Extracts the response builder out of /api/mcp/schemas/route.ts into
lib/action-schemas/builder.ts so the MCP-internal route and the new
public REST route share a single source of truth and cannot drift.
/api/mcp/schemas behaviour, response keys, and cache headers are
unchanged.
Covers the auth gate (missing header, wrong scheme, non-kh_ prefix), the full-collection response shape (actions, triggers, chains, platform, templateSyntax, builtinVariables, tips), the ?type=, ?category=, ?includeChains= filters, and the single-action lookup including the 404 path and URL-decoding of the path segment. Mocks plugins/registry, lib/mcp/workflow-schema-constants, lib/db, and lib/api-key-auth so the tests exercise the route logic and the shared builder without hitting a database or the real plugin registry.
…rapper
The condition expression resolver walked output.data directly with no
wrapper-shape fallback, so trigger node paths like "args.value" failed
with "Available fields: success, data" while the same path resolved
cleanly in action-config templates via resolveFromOutputData. Routes the
field walk through resolveFromOutputDataChecked first so trigger paths
get the same three-shape lookup (top -> { data } -> { result }) the
template engine already provides; falls back to the original strict
walk for true misses so the informative "Available fields" error
remains intact.
Also fixes the related orphan-row mis-attribution where the trigger
log row was closed with "Step did not record completion" even when a
peer step recorded the actionable error (the real failure source the
user should see in the UI). pickOrphanCloseErrorMessage detects
sibling-error rows and uses a clearer cancelled-due-to-peer message;
the legacy message is preserved when no peer carries a real error so
the worker-killed-mid-step signal is not lost.
The event worker can emit { type: 'uint256', value: 'undefined' } for
missing log fields (most commonly logIndex on pending blocks). The
prior deserializePrimitive caught the BigInt parse failure and
returned the original string, so the literal word "undefined"
propagated into the trigger output and downstream conditions either
silently mis-matched or threw an opaque BigInt error.
Now returns null for the literal strings "undefined" / "null" / "" /
actual undefined and for any value BigInt() rejects (e.g. "NaN").
Applies across all type branches because a missing field is missing
regardless of its declared ABI type. Signature widened to unknown to
match the runtime reality of values arriving from JSON over the wire.
Adds a unit-test file covering deserializePrimitive,
deserializeArg (primitive, dynamic + fixed arrays, tuples, propagation
through arrays), and deserializeEventTriggerData (happy path,
blockNumber / logIndex / transactionIndex deserialization, the
logIndex='undefined' regression, missing-args resilience). 27 cases.
…tion-resolver-event-deserializer # Conflicts: # tests/unit/condition-executor.test.ts
…er-event-deserializer fix(workflow): condition resolver + orphan-row error + event deserializer hardening
…on-schemas-rest # Conflicts: # app/api/mcp/schemas/route.ts
…rest feat(api): public REST endpoint for action schemas
Rejects sign-ups from disposable / temporary email providers on both the email+password path and OAuth (Google / GitHub) callbacks. Both paths flow through better-auth's databaseHooks.user.create, so a single before-hook in lib/auth.ts catches them. The blocklist combines a curated headline set (Mailinator, YOPmail, Guerrilla Mail, 10MinuteMail, Maildrop, EmailOnDeck, DisposableMail, Temp-Mail, Mailnesia, GetNada, Throwawaymail, Trashmail, Dispostable, Fakemail, plus aliasing services SimpleLogin, addy.io, Firefox Relay, DuckDuckGo, Burner Mail, IronVest) with the maintained disposable-email-domains.json fallback (5,488 domains, vendored from the disposable-email-domains/disposable-email-domains repo). isDisposableEmailDomain handles case folding, +alias local-parts, and multi-@ inputs via lastIndexOf. Exact-domain match only -- substring collisions like 'notmailinator.com' are intentionally checked against the full vendored list to avoid false positives or negatives.
The back/cancel control on the step-up MFA dialog navigated to /sign-in, which is not a route in this app (auth is a modal, not a page), so cancelling produced a 404. Point it at / like the other no-session navigations. Also add temporary [mfa-debug] diagnostics on the OAuth verify-mfa path and in the dual-factor TOTP check to investigate authenticator codes being rejected after OAuth sign-in on a TOTP-enrolled account.
…-totp-debug fix(auth): redirect MFA verify cancel to home instead of 404
…-signups hotfix(auth): block disposable email domains on signup
Before, the server's databaseHooks.user.create.before hook returned
false to abort, which better-auth converted into a generic "Failed to
create user" string. The signup dialog had no special case for it, so
the user saw an opaque error with no hint of what to fix.
Now the hook throws an APIError("BAD_REQUEST") carrying the shared
DISPOSABLE_EMAIL_REJECTION_MESSAGE constant. The signup dialog imports
the same constant and matches on it directly, so the surfaced text
cannot drift between server and client.
The constant lives in its own file (lib/auth-disposable-emails-message.ts)
so the client bundle does not pull in the 5,488-domain JSON or the
Set construction from lib/auth-disposable-emails.ts.
Follow-up to the ref/block-disposable-email-signups landing.
…sage refactor(auth): surface disposable-email rejection message to user
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.
No description provided.