0.1.97 — Casdoor migration phase 3 (Flutter SDK leg)
Phase 3 of the auth migration plan. Frontend now speaks Casdoor end
to end: every app probes /auth/casdoor/config/ at boot, surfaces a
"Continue with Casdoor SSO" button when the backend reports
configured: true, redirects to the configured Casdoor signin URL,
and handles the state=casdoor round-trip via the existing
AppShellOAuthMixin.handleOAuthCallback plumbing. Shadow mode is
still the default — buttons stay hidden when env vars aren't set.
Shared (notechondria_shared)
AuthClientinterface gains two methods:getCasdoorConfig()→GET /api/v1/auth/casdoor/config/. Returns{configured: bool, ...}; the second branch fires only when configured.casdoorExchange(code, {state})→POST /api/v1/auth/casdoor/exchange/. Returns the standardauth_payloadshape so the existingapplyAuthPayloadkeeps working unchanged.
AppShellOAuthMixin.launchOAuthextended forprovider == 'casdoor': probes the config endpoint, builds a same-origin redirect URI fromUri.base, and redirects to the configuredsignin_urlwithstate=casdoor.AppShellOAuthMixin.handleOAuthCallbackrecognizesstate=casdoorand routes the code tocasdoorExchange, swallowing the legacy bind/login branches that the per-provider flows use. Casdoor bind isn't wired in this round — account linking lands later if the use case shows up.AuthHub(login dialog) + editor's_buildSignedOutAccountcard both gain anonCasdoorLoginprop. Casdoor button is rendered as aFilledButton.tonalIcon(primary) when configured; falls back to the existing Google / GitHub outlines when not.
Per-app
Editor / portal / planner each:
client.dart(orhttp_client.dart) gets the two new methods._SettingsPagegains anonCasdoorLoginprop and forwards it to its login surface (editor's_buildSignedOutAccountfor the account card; portal/planner'sAuthHub).app_shell.dartgains a_casdoorConfiguredboolean state field, populated by a fire-and-forget probe in_loadInitialData(unawaited(...)inside core/initial_data). Failures are swallowed silently — shadow mode and transient outages just leave the flag atfalse.app_shell(or editor'sbuild_helpers.dart) wiresonCasdoorLogin: _casdoorConfigured ? () => launchOAuth('casdoor', intent: 'login') : null.
Verification
flutter analyze clean across editor_app, portal_app,
planner_app. No new errors, no new warnings beyond the pre-
existing unused-* and surface-deprecation lints unrelated to this
round.
The end-to-end flow can be smoke-tested by setting CASDOOR_* env
vars on the backend, signing in via the new SSO button, and
observing the redirect-back populate Creator.casdoor_sub (the
backend phase-2 logic from 0.1.96 takes over from there).
Carryover
- Casdoor account-binding flow (link Casdoor to an existing
legacy account post-login). Out of scope for phase 3 because
the email-iexact backfill in
_resolve_useralready handles the common case automatically. - Phase 4: cutover (disable
LoginApiView/RegisterApiView, freezeSessionwrites). - Phase 5: cleanup (delete every legacy auth class / serializer /
template / helper enumerated in
docs/integrations/casdoor-migration.md). - 0.1.94 GitHub Sync items: push-side conflict resolution + asset rotation/pruning.