Skip to content

Issue #153: Design for triggering actions from the client#175

Open
nivethadhanakoti wants to merge 2 commits into
meerkat-lang:mainfrom
nivethadhanakoti:issue-153-client-actions
Open

Issue #153: Design for triggering actions from the client#175
nivethadhanakoti wants to merge 2 commits into
meerkat-lang:mainfrom
nivethadhanakoti:issue-153-client-actions

Conversation

@nivethadhanakoti

@nivethadhanakoti nivethadhanakoti commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Design only, per the issue: no implementation, for a round of feedback first.

Adds docs/design/client-actions.md proposing a language extension that binds an action to a user interface event, and meerkat/tests/client_button.mkt as a demonstrating test case. The .mkt file does not work today by design — event
attributes are not recognised and an Html value cannot carry an action — and should work once the design is implemented.

The proposal in short

An attribute beginning with on is an event attribute, and its interpolated expression must evaluate to an action:

pub def html = (<button onclick={bump}>increment</button>);

This reuses the existing {expr} interpolation; only what the expression evaluates to differs. Because Value::ActionClosure already carries a ServiceNetId, the action can belong to another node — a browser can hold a
handler for a server-side action, and remote_action already accepts exactly what the closure stores.

Two things worth pushing back on

The design treats the Html representation change as a prerequisite, not an optional refinement: an Html value is currently a rendered string, which has nowhere to put a handler, so it would need to become a structured tree. That is
a larger change than the syntax suggests, though the Html module documents a tree as its anticipated direction, and it also addresses the injection concern raised on #143.

Passing an input's value to an action is left unresolved. Action closures have no parameter list, so either they gain parameters or the event value is bound into the captured environment under a well known name. I have set out both
rather than picking one.

Summary by CodeRabbit

  • Documentation

    • Added a design proposal for triggering local or remote actions from browser UI events.
    • Documented event handling, action binding, input values, and open implementation questions.
  • Tests

    • Added an expected-failure example demonstrating a button click triggering a server-side counter action.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nivethadhanakoti, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 897d48a3-128f-43c9-8009-46e25f9fdd12

📥 Commits

Reviewing files that changed from the base of the PR and between cf32f32 and a0bceb7.

📒 Files selected for processing (1)
  • docs/design/client-actions.md
📝 Walkthrough

Walkthrough

Adds a design specification for triggering Meerkat actions from browser events and introduces a currently failing button test using onclick={s1.inc_x}.

Changes

Client Actions

Layer / File(s) Summary
Action binding design and button test
docs/design/client-actions.md, meerkat/tests/client_button.mkt
Documents proposed on*={action} bindings, local and remote invocation semantics, structured HTML attributes, input-value handling, and open questions; adds a failing counter button test using onclick={s1.inc_x}.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • meerkat-lang/meerkat#153 — Directly covers the client-triggered action design and button interaction test added here.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main design-focused change: enabling client-triggered actions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/client-actions.md`:
- Around line 93-97: Update the proposed Html event-attribute and DOM-rendering
design so browsers receive only opaque, server-issued handler identifiers rather
than action statements or captured environments. Bind each identifier to the
session and authorization context, and resolve it server-side to the original
closure before executing the action; do not expose or trust closure fields in
browser event listeners.
- Around line 99-104: Update the Html module design description to define the
safe-rendering boundary: interpolated text and ordinary attributes must be
emitted as data through safe DOM APIs, while trusted/raw HTML nodes must be
explicitly identified and handled separately. Clarify that adopting a structured
tree alone does not provide injection protection unless these rules are
enforced.
- Around line 75-85: Expand the browser-to-server section around remote_action
to define the end-to-end dispatch contract: specify the client transport and
request payload carrying action identity and arguments, session/authentication
handling, server routing into the existing Manager::remote_action path,
client-visible error behavior, and how resulting reactive updates are delivered
to subscribed clients. Keep the local-action path and existing reactive
machinery unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9bf58035-e0db-4116-a215-ca8a936bd2f3

📥 Commits

Reviewing files that changed from the base of the PR and between c7c035b and cf32f32.

📒 Files selected for processing (2)
  • docs/design/client-actions.md
  • meerkat/tests/client_button.mkt

Comment on lines +75 to +85
When the corresponding event fires, the runtime invokes the action. If the
action's `ServiceNetId` names the local node, it runs locally through the
ordinary action path. If it names another node, it is sent there through
`remote_action`. The captured environment and service identity supply the
execution context, so no new capture or scoping rules are required.

Any state the action changes propagates through the existing reactive
machinery. In the example above, clicking the button increments `x` on the
server, which recomputes `s1.y`, which pushes an update to the subscribed
client, which recomputes `z` and re-renders `html`. The click is the only new
step; everything after it already works.

@coderabbitai coderabbitai Bot Jul 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Define the browser-to-server dispatch contract.

remote_action in meerkat-lib/src/runtime/manager/mod.rs, Lines 1369-1473, is a node-to-node Manager method that sends an ActionRequest; a browser event cannot call it directly. Specify the client transport, action identity, session handling, error behavior, and update delivery needed to make this end-to-end flow implementable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/client-actions.md` around lines 75 - 85, Expand the
browser-to-server section around remote_action to define the end-to-end dispatch
contract: specify the client transport and request payload carrying action
identity and arguments, session/authentication handling, server routing into the
existing Manager::remote_action path, client-visible error behavior, and how
resulting reactive updates are delivered to subscribed clients. Keep the
local-action path and existing reactive machinery unchanged.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partly addressed, but I think the premise needs a correction: the browser is a Meerkat node in this architecture. PR #143 gives the wasm client a Manager with a NetworkActor, and it already calls manager methods directly, so remote_action is reachable the same way it is on a native client. The real question underneath is how a DOM event reaches the runtime and identifies which handler fired, which the new trust-boundary section covers in part — the opaque-handle approach makes the click payload just an identifier.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Current design: event/runtime/trust-boundary references =='
rg -n -C 4 -i 'remote_action|trust.boundary|opaque|handle|DOM|event' docs/design/client-actions.md || true

echo
echo '== Runtime remote_action definition and call sites =='
rg -n -C 3 '\bremote_action\s*\(' meerkat-lib meerkat 2>/dev/null || true

echo
echo '== WASM/client Manager and NetworkActor references in checked-out PR =='
rg -n -C 3 '\b(Manager|NetworkActor)\b' --glob '*.rs' . || true

echo
echo '== Pull request `#143` metadata and changed files =='
gh pr view 143 --repo meerkat-lang/meerkat --json number,title,state,mergedAt,headRefName,baseRefName,url \
  --jq '{number,title,state,mergedAt,headRefName,baseRefName,url}'
gh pr view 143 --repo meerkat-lang/meerkat --json files \
  --jq '.files[] | {path, additions, deletions}' || true

Length of output: 49506


@nivethadhanakoti, you’re right — the premise of my finding was incorrect. #143’s merged WASM client creates a Manager, attaches a NetworkActor, and participates as a Meerkat node, so it can invoke Manager::remote_action through the ordinary runtime path.

The revised design also now correctly identifies the actual boundary: mapping a DOM event to a runtime handler and ensuring the handler reference cannot be forged. The proposed opaque, session-scoped identifier is an appropriate direction; the document explicitly leaves its final form open. I’m withdrawing the finding.

🐇🔍


✏️ Learnings added
Learnt from: nivethadhanakoti
Repo: meerkat-lang/meerkat PR: 175
File: docs/design/client-actions.md:75-88
Timestamp: 2026-07-23T07:00:26.362Z
Learning: In the Meerkat WASM client architecture introduced by merged pull request `#143`, the browser runs a `Manager` with a `NetworkActor` and is a Meerkat node. Browser-originated runtime operations, including `Manager::remote_action`, use the normal node-to-node path; client-action design reviews should focus on securely bridging DOM events to runtime handler identities rather than assuming an additional browser-to-server transport is needed.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread docs/design/client-actions.md
Comment thread docs/design/client-actions.md Outdated
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.

1 participant