Skip to content

Coerce container-valued query params and scrub handoff state on read - #456

Merged
TonsOfFun merged 1 commit into
release/1.6.2from
claude/activeagent-design-artifacts-q596yu
Sep 16, 2026
Merged

TonsOfFun merged 1 commit into
release/1.6.2from
claude/activeagent-design-artifacts-q596yu

Conversation

@TonsOfFun

Copy link
Copy Markdown
Contributor

Summary

Three hardenings the hosted platform (activeagents/activeagents) made to its own copy of the dashboard controllers in September, ported to the engine so a host that mounts it gets the same behaviour. Needed by activeagents/activeagents#132, which replaces that copy with the mounted engine.

  • Container-valued query params no longer 500. A value can arrive as a container (minutes[]=1&minutes[]=2, or page[x]=1), and neither Array nor ActionController::Parameters responds to to_i. Api::BaseController gains integer_param / clamped_param (a multi-valued param means its first value; a nested object floors to the default), applied to agent runs, agent analytics, account analytics, interactions and session recordings.
  • sandboxes#compare validates providers. A bare string or a nested object used to raise NoMethodError; it is now a 400.
  • session_recordings#show scrubs the handoff state. The response returned the visitor's cookies and web storage unscrubbed, both as its own key and nested inside metadata, while every other read path redacted. Both are stripped of cookies, session_storage and local_storage; only #handoff returns them, to the owner.

Test plan

  • New actionagent/test/param_coercion_test.rb covers each coerced endpoint and the compare rejection
  • session_recording_privacy_test.rb gains a nested handoff-state case
  • Full engine suite on gemfiles/rails8.gemfile: 405 runs, 0 failures
  • rubocop clean on the changed files

🤖 Generated with Claude Code

https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE


Generated by Claude Code

Three hardenings the hosted platform made to its own copy of the dashboard
controllers in September, ported to the engine so a host that mounts it
gets the same behaviour.

A query value can arrive as a container (`minutes[]=1&minutes[]=2`, or
`page[x]=1`), and neither Array nor ActionController::Parameters responds
to `to_i`. Every list the dashboard paginates or windows read those
params directly and turned a malformed query into a 500. Api::BaseController
gains integer_param and clamped_param: a multi-valued param means its
first value, a nested object floors to the default. Applied to agent runs,
agent analytics, the account analytics, interactions and session
recordings.

Sandboxes#compare read `providers` as a list. A bare string or a nested
object raised NoMethodError; it is now a 400.

A recording's show response returned the handoff state — a copy of the
visitor's cookies and web storage — unscrubbed, both as its own key and
nested inside metadata, while every other read path redacted. Both are
now stripped of cookies, session_storage and local_storage; only #handoff
returns them, to the owner, when they continue the session.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
TonsOfFun pushed a commit to activeagents/activeagents that referenced this pull request Sep 16, 2026
The platform's own copy of the dashboard — the React app under
app/javascript, the API controllers it read, and the models and services
behind them — is replaced by the actionagent engine mounted at /dashboard,
configured for this platform in config/initializers/action_agent.rb:
multi-tenant, sessions resolved from this app's cookie, agents per user
and keys and traces per account, plan quotas and usage metering,
per-account provider credentials, trace retention by plan, and the cloud
sandbox backends this platform operates. This app keeps what a hosted
product has and a self-hosted install does not: accounts and sessions,
plans and billing, the admin console, benchmarks, the in-container sandbox
runner, trace ingest at /v1/traces on its own TelemetryTrace subclass, and
the MCP endpoint at /mcp.

Merges claude/activeagents-local-engine-ky54n7 (the August extraction)
onto current main and repoints the gems at the engine's repository. Every
model, service and serializer the engine now owns is an alias of the
engine's class, so existing references keep working. The September
security fixes main made to the deleted controllers are carried by the
engine, whose own tests cover them; the three it lacked (container-valued
query params, compare's providers validation, the handoff-state scrub on
show) are ported in activeagents/activeagent#456, which the Gemfile pins
until it merges. Tests that exercised those controllers now do so through
the mount at /dashboard/api.

Two behaviours change with the engine's contract. It authenticates every
endpoint, so an anonymous caller gets a 401 (or, in a browser, this app's
sign-in page) rather than a scoped 404, and sandboxes no longer have an
anonymous demo pool. Compare meters one execution per provider, as run
does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
@TonsOfFun
TonsOfFun changed the base branch from main to release/1.6.2 September 16, 2026 22:48
@TonsOfFun

Copy link
Copy Markdown
Contributor Author

Retargeted to release/1.6.2, the integration branch for the 1.6.2 cut (see the top of #455 for the process). It merges cleanly onto the current release head (49a57cbf).

One thing to add before this merges: a changelog entry. On this branch the section is ## [1.6.2]## [Unreleased] is what comes after the release — under ### Fixed, alongside the MySQL and Tools-tab entries already there.

TonsOfFun pushed a commit that referenced this pull request Sep 16, 2026
The merge of #456 brings the container-valued query parameter coercion,
the compare providers validation and the recording show scrub onto the
release line; the 1.6.2 section now lists them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkXcH6XVKyD5wYnpLuH9iE
@TonsOfFun
TonsOfFun merged commit 189e3d1 into release/1.6.2 Sep 16, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants