Skip to content

feat(sandbox): add Flutter toolchain and a supabase_flutter port of the relational-report eval - #401

Draft
spydon wants to merge 2 commits into
claude/sdk-metadata-axis-d5c185from
feat/flutter-sdk-sandbox
Draft

spydon wants to merge 2 commits into
claude/sdk-metadata-axis-d5c185from
feat/flutter-sdk-sandbox

Conversation

@spydon

@spydon spydon commented Oct 16, 2026

Copy link
Copy Markdown

Stacked on #400 (claude/sdk-metadata-axis-d5c185), which is stacked on #399. Merge those first. Only the top commit belongs to this PR.

Summary

Does for supabase_flutter what #399 did for supabase-py: adds a Flutter toolchain to the shared sandbox image and ports the relational-report benchmark eval to Flutter.

 packages/sandbox/
 └── Dockerfile                 # node:22-slim + git, docker, psql, python3, uv
+                               #   + Flutter 3.47.6 (bundled Dart), cloned at the tag
+                               #     so x64 and arm64 both work, universal artifacts
+                               #     precached for `flutter test`

 evals/benchmark/
 ├── build-dataapi-001-relational-report/          # supabase-js
 ├── build-dataapi-001-relational-report-py/       # supabase-py
+└── build-dataapi-001-relational-report-flutter/  # supabase_flutter, sdk: flutter
+    ├── PROMPT.md              # same report, as the data layer of a staff dashboard
+    ├── EVAL.ts                # flutter test drives connect → signIn → loadSalesReport
+    └── local/
+        ├── app/               # Flutter app, no deps besides Flutter
+        │   ├── lib/main.dart          # ready-made sign-in and report pages
+        │   └── lib/sales_report.dart  # spec comment + three TODO functions
+        └── supabase/          # same schema and seed, sign-ups disabled

How it differs from the JS and Python versions

A Flutter app is client code, so it only gets the URL and the publishable key. The tables keep RLS with no policies, so the agent has to grant access and add policies that let signed-in staff read the order data without opening it to anonymous users or shipping the secret key.

Scorer flow:

score
  ctx.stackStatus()                         → API_URL, keys
  grep app/ for the secret key              → must not be shipped
  flutter pub get
  admin API: create a staff account         (sign-ups are disabled)
  write test/eval_sales_report_test.dart    → connect, signIn, loadSalesReport
  flutter test                              → JSON rows
  compare rows to SQL ground truth
  publishable key, no session, 4 tables     → reads nothing
  no package:postgres
  grep lib/ for `package:supabase_flutter/` → GATING

flutter test has no platform plugins, so the scorer's test answers the shared_preferences channel in memory and switches off the test binding's fake HttpClient.

Evidence

  • Before: the sandbox has no Flutter or Dart; no eval can target supabase_flutter.
    After: the image builds (about 1 minute, 2.6 GB); flutter and dart run as the node user.
  • A golden supabase_flutter solution (embedded select, order('name', ascending: true), policies for authenticated) passes the scorer's flutter test inside the image on arm64 against a stack seeded from the eval's migration. Anonymous reads of all four tables return nothing.
  • The untouched starter fails the gate, and the secret key and raw SQL scans are clean on both.
  • The Dart query builder's order() defaults to ascending: false, unlike supabase-js. The golden solution hit it on its first run, so expect this port to be harder than the JS one.
  • Biome, framework and sandbox typecheck, and the sandbox unit tests pass. pnpm eval:dry -- --sdk flutter lists only the new eval.
  • Not yet run: a real agent against the new eval. Labelled run-evals-changed so CI does that.

Merge Danger

Door: two-way

Revert restores the previous image tag and removes the eval folder. Nothing else depends on the Flutter layer.

Blast Radius: image-rebuild

Every runner and laptop rebuilds the sandbox image once because the Dockerfile hash in the tag changes. The image grows by the Flutter SDK. Existing evals are untouched.

…he relational-report eval

Installs Flutter 3.47.6 (with its bundled Dart) into the sandbox image,
cloned at the release tag so it works on x64 and arm64 hosts, with the
universal artifacts precached for `flutter test`. `flutter` and `dart` are
linked into the node-owned bin dir next to uv, and analytics are disabled so
no first-run notice reaches a scorer's stdout.

Adds build-dataapi-001-relational-report-flutter (sdk: flutter): the same
relational report as the JS and Python versions, as the data layer of a
Flutter staff dashboard. The starter has no dependencies besides Flutter, so
the agent has to discover and add supabase_flutter itself. A Flutter app is
client code and only gets the publishable key, so the agent also has to let
signed-in staff read the tables without opening them to anonymous users.

The scorer creates a staff account through the admin API, drops a
`flutter test` file into the app that calls connect, signIn and
loadSalesReport, and compares the result to SQL ground truth. It also checks
that anonymous reads return nothing, that the app does not contain the
secret key, that no raw Postgres driver is used, and gates on a
supabase_flutter import in lib/.
@spydon spydon added the run-evals-changed Add to a PR to refresh only the benchmark evals that have had changes label Oct 16, 2026
@vercel

vercel Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
evals Ready Ready Preview Oct 16, 2026 3:40pm UTC

Request Review

This branch was successfully deployed

1 active deployment
Preview — e70d23dd Deployed Oct 16, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-evals-changed Add to a PR to refresh only the benchmark evals that have had changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant