Skip to content

[docs] Clarify expression purity, fail-loudly argument contracts, and server-side transactional authority for client-side functions #4162

Open

Description

@RandalSchwartz

Client-side functions in a2ui_core are a major architectural win—compiling deterministic local Dart functions directly into synchronous preact_signals computed() nodes removes both LLM round-trip latency and async widget glue.

However, as teams adopt this pattern in production Flutter applications, three recurring questions come up immediately in engineering reviews. Documenting these explicitly in the official GenUI / A2UI guides and sample code will prevent common anti-patterns before they ship.

Three Areas to Document

1. Expression Purity vs. Action Side Effects (execute() Synchronicity)

Because FunctionImplementation.execute() runs synchronously inside the reactive signal graph, docs should explicitly call out the physical boundary:

  • Safe in execute() (UI Expression Bindings): Pure, deterministic math, formatting, and synchronous reads against pre-warmed in-memory state (O(1) lookups).
  • Unsafe in execute(): Disk I/O (SQLite), network calls, async platform channels, or state mutations. Async lookups and side effects belong in explicit user actions (SubmitAction) or out-of-band repository updates that populate the DataModel / in-memory cache cleanly.

2. Fail Loudly on Broken Contracts (Avoid ?? 0.0 in Samples)

When an example FunctionImplementation handles missing required arguments using silent defaults like (args['unitPrice'] as num?)?.toDouble() ?? 0.0, developers copy that pattern into pricing or eligibility logic. If a DataModel path is misspelled, the UI silently displays $0.00.

  • Recommendation: Recommend asserting/throwing ArgumentError on missing required parameters inside execute() so UI error boundaries catch broken paths rather than displaying plausible-looking wrong numbers.

3. Optimistic Client Ergonomics vs. Authoritative Server Validation

Examples featuring client-side discount or pricing functions (such as applying a 20% promo code locally) immediately trigger a valid security concern: "What stops a tampered client from applying that discount repeatedly?"

  • Recommendation: Clarify in the GenUI security guidance that client-side functions provide optimistic, 120 FPS interactive previews, while final transactional authority (checkout totals, coupon eligibility, inventory) always remains server-side on action submission.

Activity

  1. added
    status: needs-triageauto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs
    on Nov 11, 2026
  2. polina-c commented on Nov 12, 2026

    @polina-c
    Collaborator

    From triage bot:

    Triage suggestion:

    For humans

    Summary:
    The issue asks for docs on client-side functions in a2ui_core: keep FunctionImplementation.execute() free of I/O and side effects, throw on missing required arguments instead of defaulting them (as in ?? 0.0), and state that the server, not the client, decides final prices and discounts.

    Why flagged for triage:
    This issue has external input but no priority label yet.

    Suggestion:
    Set P3: the advice is reasonable, but the issue reports no defect, and docs on this are not on the roadmap. Two of its premises are partly off. I found no ?? 0.0 default in the repository's samples or docs, so the pattern it warns about does not come from this repository. And execute() can return a ReadonlySignal and takes a CancellationSignal, so a function can deliver its result later, which a "synchronous only" rule would have to account for. The third point is partly covered already: Agent functions describes server-side operations such as validating a coupon code. #4161, by the same author, asks how a2ui_core should handle unresolved required arguments, the code side of the second point. #4163, also by the same author, asks for related catalog design docs.

    1. Add labels: type: feature/enhancement, P3, component: documentation, lang: dart
    2. Related issues: [dart/a2ui_core] Discussion: Unresolved (null) required arguments silently bypass argumentSchema checks during reactive evaluation #4161, [docs] Add Catalog Design Best Practices: Anti-Corruption Layer modeling, semantic grain size, and protocol vs. data versioning #4163

    To adjust and apply this suggestion, run in your a2ui checkout:

    tools/internal/triage_new/triage_ui.sh https://github.com/a2ui-project/a2ui/issues/4162
    For software
    <a2ui>
    root = TriageSuggestion(
      summary="""The issue asks for docs on client-side functions in `a2ui_core`: keep `FunctionImplementation.execute()` free of I/O and side effects, throw on missing required arguments instead of defaulting them (as in `?? 0.0`), and state that the server, not the client, decides final prices and discounts.""",
      reason="This issue has external input but no priority label yet.",
      suggestion="""Set P3: the advice is reasonable, but the issue reports no defect, and docs on this are not on the [roadmap](https://github.com/a2ui-project/a2ui/blob/8bf644a37d680a227296b8c0849a7f4b328b8b73/docs/public/roadmap.md). Two of its premises are partly off. I found no `?? 0.0` default in the repository's samples or docs, so the pattern it warns about does not come from this repository. And [`execute()`](https://github.com/a2ui-project/a2ui/blob/8bf644a37d680a227296b8c0849a7f4b328b8b73/dart/a2ui_core/lib/src/core/catalog.dart#L217-L222) can return a `ReadonlySignal` and takes a `CancellationSignal`, so a function can deliver its result later, which a "synchronous only" rule would have to account for. The third point is partly covered already: [Agent functions](https://github.com/a2ui-project/a2ui/blob/8bf644a37d680a227296b8c0849a7f4b328b8b73/docs/site/src/content/docs/concepts/actions-and-functions.mdx?plain=1#L173-L181) describes server-side operations such as validating a coupon code. #4161, by the same author, asks how `a2ui_core` should handle unresolved required arguments, the code side of the second point. #4163, also by the same author, asks for related catalog design docs.""",
      added_labels=["type: feature/enhancement", "P3", "component: documentation", "lang: dart"],
      related_issues=[4161, 4163]
    )
    </a2ui>
    

    🤖 Agent-generated

  3. added
    P2The team intends to work on this in the near future, or at a lower priority.
    and removed
    status: needs-triageauto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs
    on Nov 12, 2026
  4. self-assigned this
    on Nov 12, 2026
  5. Varun-S10 commented on Nov 12, 2026

    @Varun-S10
    Collaborator

    Hi @RandalSchwartz, Thank you for raising the issue. We appreciate you taking the time to share your thoughts with us.
    Hi @gspencergoog, could you please take a look?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions