Skip to content

feat: add Flutter client SDK and demo app - #463

Draft
fforootd wants to merge 9 commits into
mainfrom
claude/flutter-client-sdk-plan-y4ao9i
Draft

feat: add Flutter client SDK and demo app#463
fforootd wants to merge 9 commits into
mainfrom
claude/flutter-client-sdk-plan-y4ao9i

Conversation

@fforootd

@fforootd fforootd commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

Introduces the Dart/Flutter SDK for Zitadel NextGen authentication, consisting of:

  • packages/sdk-dart (zitadel_client): Pure-Dart client for the flow and session APIs. Provides FlowClient (create/submit/current flow steps), SessionClient (handoff token exchange), and cookie/token storage abstractions. Hand-written thin client with spec-lock tests to prevent API drift.

  • packages/sdk-flutter (zitadel_flutter): Flutter widgets built on the Dart client. ZitadelLogin natively renders server-driven flow steps (BDUI) with Material widgets and localized labels. Includes ZitadelSession/ZitadelLogout widgets and secure token storage via flutter_secure_storage.

  • apps/demo-flutter: Reference Flutter app demonstrating the SDK in three modes (mock server, local Zitadel, deployed proxy). Configurable via settings UI.

The implementation mirrors the web SDK architecture: server-driven flows, native rendering, automatic cookie replay, and optional session auto-exchange. Localization covers English, German, and Italian. Includes altcha proof-of-work solver for CAPTCHA gates.

Validation

  • Unit tests for FlowClient, SessionClient, FlowController, and ZitadelLogin widget
  • Spec-lock tests verify model JSON serialization against OpenAPI schemas
  • Contract tests against live mock server (flow: identifier → done → exchange)
  • CI workflow added for Dart/Flutter SDK testing and pub.dev release

Release notes / changeset

No changeset required — these are new packages (zitadel_client v0.1.0-alpha.1, zitadel_flutter v0.1.0-alpha.1) published independently to pub.dev outside the npm lockstep train. Manual dispatch workflow added for future releases.

Notes

  • Dart packages version independently per docs/design/sdk-flutter/PLAN.md
  • Localization strings hand-ported from web components; sync tracked as deferred item
  • pubspec_overrides.yaml enables monorepo development linking
  • Moon workspace updated to include demo-flutter project
  • .gitignore and CI workflows updated for Dart/Flutter toolchain

https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF

claude added 6 commits July 6, 2026 15:31
Adds docs/design/sdk-flutter/PLAN.md describing how a Flutter client SDK
fits the nextgen architecture: a pure-Dart zitadel_client (handwritten
flow/session client with spec-lock tests against the OpenAPI spec) plus
a zitadel_flutter widget package natively rendering the BDUI flow
contract, a demo app, Moon/CI wiring, and an independent pub.dev
release path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
First milestone of the Flutter SDK plan (docs/design/sdk-flutter/PLAN.md):
a dependency-free Dart package driving the BDUI flow API (create/submit/
current with the 400-with-step unwrap), the session API (handoff exchange,
me, revoke with bearer session_token), _zflow cookie capture/replay, and
en/de/it locale dictionaries ported from @zitadel/components.

Models are hand-written against api/openapi with a spec-lock test suite
that fails when the spec and models drift. Contract tests drive a live
apps/mock-zitadel through the full login journey including the handoff
exchange.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
Second milestone of the Flutter SDK plan: ZitadelLogin renders
server-driven steps natively (ordered fields/actions from the capability
arrays, localized labels, validation hints, error banners), driven by a
FlowController that ports the <zitadel-login> orchestrator state machine
(value seeding and carry-over, current-step-only submits, rotated flow
handles, double-submit guard, optional automatic handoff exchange).
Includes ZitadelSession/ZitadelLogout, an isolate-based altcha
proof-of-work solver, secure keychain-backed token/cookie stores, a
pub-conventional example app, and controller/widget/solver test suites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
Third milestone of the Flutter SDK plan: Home (ZitadelSession card +
sign-out when signed in), full-screen ZitadelLogin with automatic handoff
exchange, and a Settings screen persisting base URL/project id via
shared_preferences. README documents the three run modes (mock-zitadel,
npx @zitadel/cli start, deployed /__nextgen proxy). AGENTS.md package map
now covers the Dart packages and their out-of-changesets release path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
…rkflow

Adds subosito/flutter-action to the full-pr CI job so the sdk-dart/
sdk-flutter/demo-flutter moon tasks (system commands) find dart/flutter
on PATH, converts their compound moon tasks to script form, links the
sdk-flutter example app to the in-repo packages via pubspec_overrides,
and adds release-flutter.yml: a manual, OIDC-authenticated pub.dev
publish (dry-run by default) that tests both packages, enforces version
lockstep, publishes zitadel_client, waits for it to resolve on pub.dev,
then publishes zitadel_flutter without the path overrides.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
The Dart packages have no package.json, so Changesets and the release
manifest already ignore them mechanically (verified via
check-changesets-status.mjs); this makes the human-facing logic match:
.changeset/README.md documents the pub.dev exception, AGENTS.md states
the Moon-vs-Changesets ownership exception plus the release procedure
(lockstep pubspec bumps, hand-maintained changelogs, release-flutter
dispatch), CONTRIBUTING.md points contributors at the Flutter toolchain
and Moon targets, and release-publish.yml excludes the Dart package
paths from its npm-publish triggers so Dart CHANGELOG merges don't fire
the changesets train.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
nextgen Ready Ready Preview, Comment Jul 8, 2026 8:21pm
nextgen-docs Ready Ready Preview, Comment Jul 8, 2026 8:21pm
nextgen-mock-zitadel Ready Ready Preview, Comment Jul 8, 2026 8:21pm

Request Review

@fforootd fforootd changed the title Add Flutter SDK and demo app for Zitadel NextGen feat: add Flutter client SDK and demo app Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

⚠️ No Changeset found

Latest commit: aad56a4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

fforootd added a commit that referenced this pull request Jul 6, 2026
## Summary

- Add a direct Moon dependency from `cli:build-release` to `cli:test` so
the production-stamped CLI build cannot clean and rewrite
`apps/cli/dist` while Vitest is exercising oclif command discovery from
that same directory.
- Keep the CLI Vitest global setup self-contained by asserting that the
tsdown-built command files exist and `oclif commands --json` discovers
`status` before any test files run.
- Remove the runtime 127 retry from the in-process CLI test helper so
the test harness fails fast instead of masking a graph/order problem.

## Validation

- `moon run cli:build-release` (runs `cli:test` before the production
CLI build; captured log shows `cli:test` 101 files / 672 tests passed
and `cli:build-release` completed)
- `moon run cli:typecheck`
- `moon run cli:lint`
- `node scripts/check-changesets-status.mjs --base origin/main
--summary`
- `corepack pnpm exec changeset status --since origin/main`
- `git diff --check origin/main...HEAD`

## Release notes / changeset

Empty changeset added: `.changeset/cli-build-release-dag.md`. This
changes package-local Moon build wiring under `@zitadel/cli`, but no
shipped CLI behavior changes and no package bump is planned.

## Notes

- The broader problem is the Moon graph/shared-output ordering, not the
PATH-sensitive server lifecycle prober.
- Blame points to the interaction between the original CLI Vitest global
setup from `0547b8c3` / #319 and the release build DAG from `b0ba758a` /
#418, which introduced `cli:build-release` as a CI-visible production
build that cleans the same `apps/cli/dist` directory.
- Live open-PR check: PR #463 reproduced the `status` exit-127 class
with `cli:build`, `cli:test`, and `cli:build-release` all building CLI
dist in the same full-pr graph. PR #462 and the older filtered failed
logs did not show this oclif/status signature.
claude added 2 commits July 8, 2026 20:10
…-sdk-plan-y4ao9i

# Conflicts:
#	.changeset/README.md
…proof opt-in

Two review findings on #463:

Formatting: CI's lint ran dart format without a resolved package config,
so the formatter fell back to the latest language version while local
runs (post pub get) pinned the package's SDK floor — different styles,
red lint. Bump the Dart floor to ^3.8.0, reformat everything in the
matching style, and make the lint tasks run pub get first so the style
is always pinned by the package config regardless of SDK version.

Gate proofs: the server currently rejects any non-empty gate_proofs as
reserved (internal/domain/flow_state_machine.go) and never emits gates.
Solving altcha gates is now behind FlowController/ZitadelLogin
enableAltchaGates (default off); by default altcha gates surface via
onUnsupportedCapability like every other provider and no proofs go on
the wire. README and plan doc updated to match; solver + tests stay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xLyz1YWAuFY8GK1scWaNF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants