Latest Results
Merge main into the custom build branch
#6888 (post-release workflow hook) landed on main and touches the same
generated workflow, so three conflicts needed more than a textual union:
- POST_RELEASE_STEP read `needs.build.outputs.tag`/`version`. This branch
splits the old build job into prepare/build/collect, and tag-and-release
now needs [prepare, publish] — so the dispatch reads those facts from
prepare, the job that computes them. Retargeted, and its test with it.
- main's render() gained "a placeholder alone on a line is an optional
block: an empty value removes the line". @@DEFAULT_BUILD_GUARD@@ sat at
the end of the build job's `if`, so an empty value would have eaten the
newline and folded `runs-on:` into the expression. The guard is now a
line of its own, and the two optional job/step blocks let the template
carry their blank separator instead of embedding a trailing newline.
- check_custom_build_workflows rejected naming a generated workflow via
managed_workflows(), which has the hole main documents for the same guard:
it drops auto_release_internal.yml exactly when a repository has no
internal packages. Switched to main's GENERATED_WORKFLOWS, and made the
custom-build table label public so the two guards name it from one place.
Verified all four combinations of the two features render, parse as YAML
and round-trip through `sync --check`, with a test covering both at once.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E1ujR3svpGxMwm5pBMrsXhclaude/reflex-release-artifact-custom-nn2vog reflex-release: add a post-release workflow hook (#6888)
* Add a post-release workflow hook to reflex-release
`post-release-workflow` in `[tool.reflex-release]` names a workflow of the
consuming repository's own. `publish.yml` dispatches it once per published tag,
after the upload, the tag and the GitHub release all exist — the hook for
whatever has to follow a release: publishing docs, refreshing an image,
notifying a downstream repository.
The dispatch runs on the tag, so the workflow sees exactly the tree that was
published, and it is handed `tag`, `package` and `version` as
workflow_dispatch inputs. All three are required because GitHub rejects a
dispatch carrying inputs the target workflow does not declare.
The step and the `actions: write` grant it needs — in `publish.yml` and in both
workflows that call it — are rendered only when the setting is present, so a
repository that runs nothing after a release keeps the narrower permissions.
Naming a workflow this tool generates is rejected by `sync`, since handing a
published tag back to the release pipeline would either re-enter it or fail on
inputs it does not declare.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B13GVXzLdYzmqmMnaKWvyV
* Address review feedback on the post-release workflow hook
Close two holes in the guard that rejects naming a generated workflow as the
post-release hook. `gh workflow run` resolves a workflow by file name *or* by
display name, so "Publish to PyPI" walked straight past a filename-only check;
and the guard consulted `managed_workflows`, which drops
auto_release_internal.yml once a repository has no internal packages — exactly
when `sync` deletes the file, leaving the dispatch with no receiver at all. The
check now covers every workflow this tool can generate, under both names.
Validate the dispatch payload. The CLI defaults TAG/PACKAGE/VERSION to the empty
string when the environment variables are unset, and GitHub accepts a dispatch
carrying empty inputs, so a misconfigured invocation went green having told the
downstream workflow nothing. All three are now required, and the package is
checked against the repository the way the sibling publish commands do.
Name the hook's contract once. The config key and the three dispatch input names
were repeated across config parsing, the dispatch payload, the scaffolded step's
comment and its failure message; they now come from POST_RELEASE_WORKFLOW_KEY and
POST_RELEASE_INPUTS in config.py, so adding an input cannot leave the generated
workflow and the payload disagreeing.
Hoist the identical `with_post_release` test helper out of test_commands.py and
test_scaffold.py into conftest.py as `set_post_release_workflow`, alongside the
`write_lockstep` helper it mirrors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B13GVXzLdYzmqmMnaKWvyV
---------
Co-authored-by: Claude <noreply@anthropic.com> Add Auto MCP documentation for reflex-enterprise v0.9.4 (#6880)
* Document the Auto MCP feature and the new API auth model
Add a docs section for `rxe.MCPPlugin` (reflex-enterprise#198), which
publishes an app's event handlers and session state over the Model Context
Protocol:
- `enterprise/mcp/index.md`: install, quickstart, the mounted endpoints, the
`search_events` / `queue_event` / `get_pending_updates` tools, the
`reflex://` resource family, server instructions, file uploads, browserless
sessions and `pending_updates`, and a full configuration reference.
- `enterprise/mcp/authentication.md`: anonymous session tokens, the OAuth 2.1
authorization server that federates login to the `AuthPlugin` OIDC flow, the
consent page and its confused-deputy protections, app scopes, surface-aware
`auth=` checks (`ctx.surface` / `ctx.token_scopes`), and per-token rate
limiting.
- `enterprise/mcp/custom-resources.md`: the `rxe.mcp.resource` decorator.
- `enterprise/mcp/extending.md`: `configure=` and `get_mcp_server()`.
- `enterprise/mcp/deployment.md`: TLS/issuer requirements, reverse proxies,
Redis-backed storage, rate-limit tuning, and a security checklist.
Update the Event Handler API page for the same PR's interface changes:
endpoints now require an app-issued bearer from `POST /_reflex/auth/token`
(or the MCP OAuth flow) rather than a caller-invented UUID, calls are rate
limited per token with `rxe.event(rate_limit=...)` overrides, framework and
auth handlers are withheld, and state reads redact the session token. Adds
the new plugin options, refreshes the curl examples and OpenAPI excerpt, and
rewrites the security considerations.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
* Clarify how anonymous MCP sessions coexist with AuthPlugin
Anonymous access and OAuth are wired together by default when an AuthPlugin
is configured (the token verifier accepts a bearer from either authority), so
spell out what an anonymous session can and cannot reach, and both ways to
require a signed-in agent.
Also correct the shared-token-endpoint notes: `anonymous_sessions=False`
governs whether the MCP endpoint accepts anonymous bearers, but on the REST
plugin it only stops that plugin from wiring the route — REST still accepts
tokens minted by an MCPPlugin-wired endpoint.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
* Sync MCP docs with the latest PR revisions
Upstream changes since the first draft:
- OAuth endpoint paths are configurable (`registration_path`,
`authorization_path`, `token_path`, `revocation_path`), with registration
defaulting to `/register-oidc-client` instead of the SDK's bare `/register`
so it cannot shadow an app's own sign-up page. Document the new options, the
distinctness / mount-nesting constraints, and add a route-collision section
to the deployment page.
- Agent-facing var names are stripped of the framework's `_rx_state_` field
marker on the MCP delta/state surfaces and `/_reflex/retrieve_state`; the
REST ndjson event stream still carries it, so note the difference where the
stream is documented.
- Spell out the upload ticket's single-use, handler-pinned contract and the
401/403 the upload endpoint returns.
- Note that framework/auth states are dropped from state reads.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
* Drop the ndjson field-marker caveat; note the hidden auth pages
The REST event stream now strips the `_rx_state_` field marker like every
other agent-facing surface, so the response-shape example uses clean var names
and the caveat alert is gone.
Also document that the page listing (MCP `instructions` and the OpenAPI
preamble) omits the auth machinery's routes -- login, callback, logout,
forbidden, the OIDC popup pages, and the MCP consent page -- along with their
dynamic route variables.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
* Show get_mcp_server() registration inside a lifespan task
The runtime-registration example used `@rxe.get_mcp_server().tool()` at module
scope, which runs at import time and would raise the very `RuntimeError` the
alert below it warned about. Register from an `@asynccontextmanager` lifespan
task instead — it runs after compile, when the server exists — and reword the
alert to call out module scope as the case that does not work.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
* Use the kebab-case route for the lifespan tasks link
Doc URLs are kebab-cased from the file path, so the link to
docs/utility_methods/lifespan_tasks.md is /docs/utility-methods/lifespan-tasks/.
The underscored form failed test_docs_links_against_exported_sitemap.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
* Order the Auto MCP sidebar group after Authentication
#6858 added test_cross_reference_excluded_from_prev_next_chain, which pins the
enterprise auth overview's prev link to /enterprise/event-handler-api/. The
Auto MCP group sat between them and broke that adjacency.
Move it after the Authentication group, which is the better reading order
regardless: MCP OAuth federates to AuthPlugin, so the auth docs come first.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgS3a61KDaXhCWd6FHcAfA
---------
Co-authored-by: Claude <noreply@anthropic.com> Upgrade ruff, pyright, and typer; fix the resulting failures
uv.lock: ruff 0.15.12 -> 0.16.2, pyright 1.1.408 -> 1.1.411,
typer 0.25.1 -> 0.27.1. ruff 0.16.3 published inside the 7 day
exclude-newer window, so 0.16.2 is the newest resolvable release.
ruff 0.16 (preview rules are enabled repo-wide):
- D421 property-docstring-starts-with-verb: reword 53 property
docstrings from "Get the X." / "Return the X." to "The X.", per the
Google style guide the repo already follows.
- PT003: drop the redundant scope="function" from five
pytest_asyncio.fixture calls, which 0.16 now recognizes.
- ASYNC119, RUF075: ignored. Both fire on deliberate patterns --
background handlers hold `async with self` across `yield`, and the
state managers skip write-back when the `with` body raises.
- RUF105, RUF201: ignored. Both are stylistic; RUF105's own docs call
it opinionated, and migrating 190 `noqa` comments to `ruff: ignore`
would drop them for other tooling and for older ruff. RUF201 would
leave the config half codes, half names, since prefix selectors have
no name form.
pyright 1.1.411 narrows `x is None` on an `Any` value to `Any | None`,
where it previously stayed `Any`. That surfaced two dead guards, both
removed: `cls is not None` in `_isinstance()` (the line above already
returns for None) and `instruction.argval is not None` in the
dependency-tracking scanner, where the check moves inside the branch so
it stops leaking None into the sibling branches. Its bundled typeshed
also types `inspect.isgenerator`/`isasyncgen` as yielding `object`, so
`chain_updates()` now declares `events: Any`, matching the runtime
validation it delegates to. Also: annotate `Field.__init__`'s computed
default as FIELD_TYPE, cast untyped `sass.compile()` to str, and import
`ImportVar`/`unionize` from the modules that define them rather than
re-exporting them through `reflex_base.vars.base`.
typer 0.27 vendors its own copy of click, so `typer.main.get_command()`
no longer returns a nominal `click.Command`. The objects stay
structurally compatible (`reflex cloud` and the 289 hosting CLI tests
pass), so the conversion is cast at its two call sites; the six test
modules that duplicated the Typer-to-click preamble now share an
`as_click_command()` helper.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLumacyNrCZDqvyptaVxkEclaude/upgrade-ruff-pyright-typer-u3z09k Latest Branches
0%
harsh21234i:fix/shared-state-root-dirty-6392 0%
claude/reflex-release-artifact-custom-nn2vog 0%
claude/reflex-release-dev-pin-upgrades-hluw0c © 2026 CodSpeed Technology