Skip to content

Sync with InsForge-sdk-js v1.5.1 - #8

Open
agent-zhang-beihai[bot] wants to merge 1 commit into
mainfrom
sdk-sync/v1.5.1
Open

Sync with InsForge-sdk-js v1.5.1#8
agent-zhang-beihai[bot] wants to merge 1 commit into
mainfrom
sdk-sync/v1.5.1

Conversation

@agent-zhang-beihai

@agent-zhang-beihai agent-zhang-beihai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Ports the InsForge-sdk-js v1.5.0..v1.5.1 changes into the Dart/Flutter SDK.

Ported

Auth — passwordless email OTP sign-in

  • AuthClient.signInWithOtp(email: ...) — requests a 6-digit sign-in code via POST /api/auth/email/send-otp. Returns Future<void> (matching the existing sendVerificationEmail/sendPasswordReset idiom); the server response is intentionally generic whether or not an account exists (enumeration-safe).
  • AuthClient.verifyOtp(email: ..., otp: ..., name: ...) — verifies the code via POST /api/auth/sessions with method: 'otp' (plus the existing client_type query), and establishes/persists/emits the session exactly like signIn/verifyEmail. name sets the display name only on first-time user creation.

Storage — batch object deletion

  • StorageFileApi.deleteAll(paths) now issues a single batch request (DELETE /api/storage/buckets/{bucket}/objects with {keys}, max 1000 keys — not split client-side, matching the JS SDK) instead of one DELETE per path, and returns List<DeleteObjectResult> (one result per key) instead of void.
  • New DeleteObjectResult model: key, status (deleted | notFound | failed), optional message, plus a deleted convenience getter. (Mirrors the JS remove(string[]) overload; the Dart SDK keeps its existing delete/deleteAll naming, and single-path delete is unchanged.)

Housekeeping

  • Version bumped to 0.2.0 via dart run tool/set_version.dart 0.2.0 (pubspecs + version.dart in lockstep); integration_tests and samples/twitter_app constraints updated to ^0.2.0.
  • Root + per-package CHANGELOGs and root README updated.

Skipped (JS-only)

  • PasswordSessionRequest / VerifyOtpRequest / SendOTPRequest type exports and the signInWithPassword request-type narrowing — TypeScript union gymnastics; Dart already uses named parameters, so no equivalent is needed.
  • SSR createAuthActions() mirror — the Dart SDK has no SSR layer.
  • @insforge/shared-schemas bump, tsconfig.type-tests.json, CI workflow tweaks, package.json plumbing — JS toolchain concerns.

Tests

Toolchain: Dart 3.12.2 / Flutter (local toolchain).

  • dart run tool/set_version.dart --check — in sync ✅
  • dart analyze . — no issues ✅
  • packages/insforge: dart test188/188 passed ✅ (includes new auth_client_otp_test.dart, updated file_ops_test.dart batch-delete tests, and DeleteObjectResult model tests)
  • packages/insforge_flutter: flutter test — 5/5 passed ✅
  • Live-backend integration tests not run (require a configured backend env).

🤖 Generated with Claude Code


Summary by cubic

Sync with InsForge SDK JS v1.5.1 to add passwordless email OTP sign-in and one-request batch storage deletion. Bumps insforge and insforge_flutter to 0.2.0.

  • New Features

    • Auth: AuthClient.signInWithOtp(email) sends a 6-digit code (enumeration-safe). AuthClient.verifyOtp(email, otp, name?) verifies via method: 'otp' and creates a session.
    • Storage: StorageFileApi.deleteAll(paths) now calls the batch endpoint once and returns List<DeleteObjectResult> with status: deleted | notFound | failed.
  • Migration

    • Update to insforge ^0.2.0 (and insforge_flutter ^0.2.0).
    • deleteAll now returns a list; handle or ignore the result as needed.

Written for commit 5a2c7bc. Summary will update on new commits.

Review in cubic

Port of the v1.5.0..v1.5.1 baseline changes:

- Auth: passwordless email OTP sign-in — AuthClient.signInWithOtp()
  requests a 6-digit code via POST /api/auth/email/send-otp
  (enumeration-safe generic response), and AuthClient.verifyOtp()
  verifies it via POST /api/auth/sessions with method 'otp',
  establishing/persisting/emitting a session like other flows.
- Storage: StorageFileApi.deleteAll() now uses the batch-delete
  endpoint (DELETE .../objects with {keys}, max 1000 keys) in a single
  request and returns List<DeleteObjectResult> (per-key
  deleted | notFound | failed status) instead of looping DELETEs.
- Version bumped to 0.2.0 across both packages; changelogs and README
  updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@jwfing jwfing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review: Sync with InsForge-sdk-js v1.5.1

Summary: A faithful, well-tested port of the JS SDK's passwordless email-OTP sign-in and one-request batch object deletion into the Dart/Flutter SDK — no blocking issues found.

Requirements context

The repo's spec/plan docs under docs/superpowers/{specs,plans}/ predate this change — they describe the original 0.1.0 build and explicitly state "the API has no batch delete," which this PR supersedes. Since this is a sync PR, the authoritative contract is the upstream InsForge-sdk-js v1.5.0..v1.5.1 diff. I verified the Dart implementation directly against the JS source and its own tests at tag v1.5.1 (src/modules/auth/auth.ts, src/modules/storage.ts and their __tests__). Endpoints, payloads, and response shapes all match:

  • signInWithOtpPOST /api/auth/email/send-otp body {email}
  • verifyOtpPOST /api/auth/sessions?client_type=mobile body {method:'otp', email, otp, name?}
  • deleteAllDELETE /api/storage/buckets/{bucket}/objects body {keys}, response {results:[{key,status,message?}]}

Findings

Critical

(none)

Suggestion

  • Software engineering / test coveragepackages/insforge/lib/src/storage/storage_file_api.dart:152-163: the defensive fallbacks in deleteAll (server returns a bare list instead of {results:[...]}, or a non-list/empty body → <DeleteObjectResult>[]) are not exercised by any test. The happy path ({results:[...]}) is well covered in file_ops_test.dart, but a case asserting the bare-list branch and the empty-fallback branch would lock in the parser's resilience. Low blast radius.

Information

  • Functionality / behavioral changestorage_file_api.dart:146: deleteAll changes from throwing on the first failed DELETE (the old per-path loop) to issuing one batch request where per-key failures come back as status:'failed' entries and do not throw. This matches the JS SDK and is documented in the README/CHANGELOG, but callers upgrading from 0.1.0 who relied on an exception to signal a failed delete must now inspect result.deleted / result.status. The return-type change (Future<void>Future<List<DeleteObjectResult>>) is a breaking change, appropriately gated behind the 0.1.0→0.2.0 bump (pre-1.0 semver).
  • Securitypackages/insforge/lib/src/auth/auth_client.dart:219-251: The JS SDK passes skipAuthRefresh:true on both OTP calls. In Dart, verifyOtp posts to /api/auth/sessions, which is already exempted from the reactive 401-refresh interceptor (http_client.dart:119-123) — so the equivalent protection is in place. signInWithOtp hits the non-exempt /api/auth/email/send-otp, but this is consistent with the existing sendVerificationEmail/sendPasswordReset siblings and is harmless (no active session → the refresh callback no-ops). The enumeration-safe generic server message is preserved. No secrets, tokens, OTPs, or PII are logged or newly exposed; no new dependencies.
  • Software engineering / stylepackages/insforge/test/auth/auth_client_otp_test.dart:1: the header comment references the old package layout (packages/insforge_auth/test/...) rather than the actual packages/insforge/test/auth/... path. This is consistent with the repo-wide pattern (e.g. auth_client.dart:1, storage_file_api.dart:1 carry the same stale insforge_auth/insforge_storage headers), so it's noted only for awareness, not as a defect introduced here.

Positives worth calling out: new DeleteObjectResult parsing mirrors the existing list() idiom (whereType<Map<dynamic,dynamic>>() + Map<String,dynamic>.from); verifyOtp reuses the shared _applySession/_clientTypeQuery plumbing exactly like signIn/verifyEmail; the version bump is in lockstep across both pubspecs, version.dart, integration_tests, and samples; and the OTP suite covers the invalid-code (401) error path plus the name-omitted variant. Performance: batch delete replaces N sequential DELETEs with a single request — a strict improvement.

Verdict

approved (informational — no Critical findings; explicit GitHub approval remains a human action). The two non-blocking items above are optional follow-ups.

@jwfing jwfing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM - approved.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant