Skip to content

fix last commit findings#20

Merged
cobraprojects merged 2 commits into
mainfrom
update-auth-package
May 5, 2026
Merged

fix last commit findings#20
cobraprojects merged 2 commits into
mainfrom
update-auth-package

Conversation

@cobraprojects
Copy link
Copy Markdown
Owner

@cobraprojects cobraprojects commented May 5, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added remember-me token support for persistent session restoration without active session cookies.
    • Registration now automatically rolls back user creation if email verification delivery fails, ensuring data consistency.
  • Improvements

    • Enhanced request context handling in SvelteKit adapter for improved compatibility.
    • Improved header normalization and support for additional request-like objects in forms.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Warning

Rate limit exceeded

@cobraprojects has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 32 minutes and 17 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d73d7f0-7432-412d-b7a2-ee544bad9af5

📥 Commits

Reviewing files that changed from the base of the PR and between 4441db4 and 49a978f.

📒 Files selected for processing (9)
  • packages/adapter-sveltekit/tests/runtime.test.ts
  • packages/auth/src/contracts.ts
  • packages/auth/src/runtime.ts
  • packages/auth/tests/contracts.type.test.ts
  • packages/auth/tests/package.test.ts
  • packages/core/src/portable/holo.ts
  • packages/core/tests/auth-runtime.test.ts
  • packages/forms/src/contracts.ts
  • packages/forms/tests/contracts.test.ts
📝 Walkthrough

Walkthrough

This PR refactors request context handling in the SvelteKit adapter from using getRequestEvent() to an AsyncLocalStorage-backed approach with runWithSvelteKitRequestEvent(), while adding auth support for remember-me token consumption, user deletion for rollback during registration failures, header accessor normalization in forms, and corresponding CLI scaffolding updates.

Changes

Request Context & Auth Runtime

Layer / File(s) Summary
AsyncLocalStorage Architecture
packages/adapter-sveltekit/src/index.ts
Added SvelteKitRequestEvent shape, AsyncLocalStorage store for per-request context, resolveSvelteKitAuthRequestAccessors() to read cookies/headers from the store, and runWithSvelteKitRequestEvent(event, callback) to execute code within the request context.
Request Accessor Wiring
packages/adapter-sveltekit/src/index.ts
Added resolveSvelteKitOptions() to default authRequest accessors to AsyncLocalStorage-based implementations when not explicitly provided. Updated createSvelteKitHoloProject, initializeSvelteKitHoloProject, and createSvelteKitHoloHelpers to use resolveSvelteKitOptions().
Core Auth Runtime Integration
packages/core/src/portable/holo.ts
Added createRequestAwareAuthContext() that wraps auth context to enable runtime accessor mutation via setRequestAccessors(). Updated reconfigureOptionalHoloSubsystems to create request-aware auth context and expose accessor-update method. Added setAuthRequestAccessors() to main runtime object and applied it in initializeHolo for reused runtimes.
Auth Contract & Remember-Me Support
packages/auth/src/contracts.ts, packages/auth/src/runtime.ts
Added optional consumeRememberMeToken(token, options?) to AuthSessionRuntime contract. Implemented consumption during request hydration: when remember-me cookie exists and no session is set, consume the token, validate guard match, restore user from serialized payload. Added optional delete?(id) to auth provider adapter for user deletion during rollback.
Registration Rollback Logic
packages/auth/src/runtime.ts
Wrapped email verification facade creation in error handling: on failure, delete verification tokens and registered user (via createdUser.delete() or adapter.delete()), then rethrow. Added internal rollbackRegisteredUser() helper.
Forms Header Normalization
packages/forms/src/contracts.ts
Extended RequestLikeHeaders to accept header accessor objects with optional get, forEach, and entries methods. Added isHeaderAccessorObject guard. Updated normalizeRequestHeaders to populate Headers via accessor iteration when available.
Forms Sensitive Field Updates
packages/forms/src/sensitiveInput.ts
Removed token, verification_code, verificationCode, verification_token, verificationToken from DEFAULT_DONT_FLASH_FIELDS so verification/reset tokens are no longer filtered from flashed input.
SvelteKit Dependency Removal
packages/adapter-sveltekit/src/sveltekit.d.ts
Removed ambient declare module '$app/server' block that exported getRequestEvent() type signature.
CLI Scaffolding
packages/cli/src/project/registry-svelte.ts
Updated generated SvelteKit server hooks to import and use runWithSvelteKitRequestEvent(event, async () => {...}) instead of directly calling holo.getApp() within the handle hook.
Test Module Reset Patterns
packages/adapter-sveltekit/tests/adapter.type.test.ts, packages/adapter-sveltekit/tests/runtime.test.ts, packages/auth/tests/package.test.ts
Added afterEach hooks with vi.resetModules() or vi.unmock() to ensure clean module state between tests. Removed $app/server mock stub from adapter setup; replaced with explicit runWithSvelteKitRequestEvent runtime test to verify AsyncLocalStorage-based cookie/header resolution.
Integration & Verification Tests
packages/adapter-sveltekit/tests/runtime.test.ts, packages/core/tests/auth-runtime.test.ts, packages/auth/tests/package.test.ts
Added 171-line runtime test verifying authRequest accessors resolve from current SvelteKit event within runWithSvelteKitRequestEvent() and custom overrides are preserved. Added test for initializeHolo re-initialization updating auth accessors. Added tests for user deletion rollback on registration failure and remember-me token restoration when session cookie is absent.
Test Expectations & Import Path Updates
packages/adapter-nuxt/tests/module.test.ts, packages/adapter-nuxt/tests/setup.test.ts, packages/cli/tests/cli.test.ts, packages/forms/tests/contracts.test.ts
Updated Nuxt test expectations to match @holo-js/adapter-nuxt/runtime and @holo-js/adapter-nuxt/storage import paths. Added SvelteKit scaffold assertion in CLI tests. Updated forms contract tests to verify token preservation and header accessor behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • cobraprojects/holo-js#19: Both PRs implement overlapping changes to auth runtime request-accessor wiring and framework adapter patterns (SvelteKit/Nuxt request context integration).
  • cobraprojects/holo-js#16: Both PRs modify CLI scaffold generation and test assertions for framework server hooks, particularly SvelteKit module wiring.
  • cobraprojects/holo-js#10: Both PRs update Nuxt adapter test import paths and runtime expectations in similar ways.

Poem

🐰 Async stores now guard the request,
Remember-me tokens pass the test,
Headers flow through accessor gates,
No more getRequestEvent waits!
Rollback safely, restore with grace—
AsyncLocalStorage finds its place. 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'fix last commit findings' is too vague and generic to clearly convey what changes were made; it lacks specificity about which issues were addressed or what features/systems were modified. Use a more descriptive title that specifies the main changes, such as 'Refactor SvelteKit auth request handling to use AsyncLocalStorage' or 'Add remember-me token consumption and improve auth rollback handling'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch update-auth-package

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/forms/src/contracts.ts (1)

265-318: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

get-only accessor objects silently produce empty Headers

isHeaderAccessorObject returns true for objects with only get (no forEach, no entries). In normalizeRequestHeaders, neither early-return branch fires for such an object, so execution falls through to Object.entries(input). For any non-plain class instance, Object.entries returns only own enumerable string properties — typically nothing — so all headers are silently dropped.

Since isRequestLikeHeaders now returns true for such objects, they satisfy isRequestLikeInput, and a Request is constructed with a missing header. The caller has no indication that headers were lost.

🐛 Proposed fix — add an explicit early return for the `get`-only path
  if (isHeaderAccessorObject(input)) {
    if (typeof input.forEach === 'function') {
      input.forEach((value, name) => {
        headers.append(name, value)
      })
      return headers
    }

    if (typeof input.entries === 'function') {
      for (const [name, value] of input.entries()) {
        headers.append(name, value)
      }
      return headers
    }
+
+   // get-only accessor: no enumeration capability, return empty headers
+   // rather than falling through to Object.entries on a non-plain object.
+   return headers
  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/forms/src/contracts.ts` around lines 265 - 318, The
normalizeRequestHeaders function can accept objects that pass
isHeaderAccessorObject but only implement get, which cannot be iterated and
currently falls through losing headers; update normalizeRequestHeaders to detect
the "get-only" accessor (isHeaderAccessorObject(input) true && typeof
input.forEach !== 'function' && typeof input.entries !== 'function' && typeof
input.get === 'function') and handle it explicitly — either throw a clear
TypeError indicating "get-only header accessor is not iterable" (so callers know
headers were not provided) or convert it via a supported API if you have a way
to enumerate names; reference the functions/types isHeaderAccessorObject,
normalizeRequestHeaders and RequestLikeHeaders when making the change.
packages/auth/src/runtime.ts (1)

61-66: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Expose delete() on the public provider adapter contract.

The runtime implementation includes and actively invokes adapter.delete() at line 2256–2258, but AuthProviderAdapterBase does not declare this method. Typed consumers implementing the interface cannot properly expose the delete functionality without diverging from the contract.

Proposed fix
diff --git a/packages/auth/src/contracts.ts b/packages/auth/src/contracts.ts
type AuthProviderAdapterBase<TUser> = {
  findById(id: string | number): Promise<TUser | null>
  findByCredentials(credentials: Readonly<Record<string, unknown>>): Promise<TUser | null>
  create(input: Readonly<Record<string, unknown>>): Promise<TUser>
+  delete?(id: string | number): Promise<void>
  update?(user: TUser, input: Readonly<Record<string, unknown>>): Promise<TUser>
  matchesUser?(user: unknown): boolean
  getId(user: TUser): string | number
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/auth/src/runtime.ts` around lines 61 - 66, The public adapter type
ErasedAuthProviderAdapter (and the abstract/contract class
AuthProviderAdapterBase) is missing the optional delete method but the runtime
calls adapter.delete(); add delete?(id: string | number): Promise<void> to
ErasedAuthProviderAdapter and declare the same optional async delete(id: string
| number): Promise<void> signature on AuthProviderAdapterBase (or the equivalent
provider base/interface used by the runtime) so typed implementations can
implement delete() without breaking the contract; ensure the signature matches
the runtime invocation of adapter.delete().
🧹 Nitpick comments (1)
packages/adapter-sveltekit/tests/runtime.test.ts (1)

17-65: ⚡ Quick win

Extract duplicated @holo-js/core mock factory used by both tests.

The mock adapter body is duplicated almost verbatim in both tests (Line 17–65 and Line 102–150). Pulling it into a small local factory will reduce drift and simplify future updates to helper shape.

Refactor sketch
+function mockCoreWithCapture(
+  onCreateHelpers: (options: {
+    authRequest?: {
+      getCookie(name: string): Promise<string | undefined>
+      getHeader(name: string): Promise<string | undefined>
+    }
+  }) => void,
+) {
+  vi.doMock('@holo-js/core', () => ({
+    createHoloFrameworkAdapter: () => ({
+      capabilities: {},
+      async createProject() { return {} },
+      async initializeProject() { return {} },
+      createHelpers(options: { authRequest?: { getCookie(name: string): Promise<string | undefined>; getHeader(name: string): Promise<string | undefined> } }) {
+        onCreateHelpers(options)
+        return {
+          async getApp() { return {} },
+          async getProject() { return {} },
+          async getSession() { return undefined },
+          async getAuth() { return undefined },
+          async useConfig() { return undefined },
+          async config() { return undefined },
+        }
+      },
+      async resetProject() {},
+      internals: { getState() { return {} }, resolveOptions() { return {} } },
+    }),
+  }))
+}

Also applies to: 102-150

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/adapter-sveltekit/tests/runtime.test.ts` around lines 17 - 65, Pull
the duplicated mock into a local factory function and use it in both tests:
extract the object passed to vi.doMock('@holo-js/core', ...) into a helper like
makeHoloCoreMock() that returns { createHoloFrameworkAdapter: () => ({
capabilities: {}, async createProject(){}, async initializeProject(){},
createHelpers(options){ capturedAuthRequest = options.authRequest; return {
async getApp(){}, async getProject(){}, async getSession(){}, async getAuth(){},
async useConfig(){}, async config(){} } }, async resetProject(){}, internals: {
getState(){}, resolveOptions(){} } }) } and then call vi.doMock('@holo-js/core',
() => makeHoloCoreMock()) in both places; ensure capturedAuthRequest remains
writable in the test scope and update any imports/uses of
createHoloFrameworkAdapter, createHelpers, capturedAuthRequest to the shared
factory.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/adapter-sveltekit/tests/runtime.test.ts`:
- Around line 86-91: Ensure the test asserts capturedAuthRequest is defined
before using async matchers: add an explicit
expect(capturedAuthRequest).toBeDefined() (or equivalent) right before the lines
that call capturedAuthRequest.getCookie and capturedAuthRequest.getHeader, then
remove the optional chaining (capturedAuthRequest?.) so the subsequent await
expect(capturedAuthRequest.getCookie('session')).resolves... and await
expect(capturedAuthRequest.getHeader('x-request-id')).resolves... operate on a
guaranteed non-null object; repeat this for both the positive and undefined
assertions.

In `@packages/auth/src/runtime.ts`:
- Around line 2246-2258: In rollbackRegisteredUser, don't let a thrown
createdUser.delete() short-circuit the fallback: wrap the call to
createdUser.delete() (in the block checking 'delete' in createdUser) in a
try/catch, and if it throws attempt adapter.delete(serialized.id) inside the
catch (if adapter.delete exists); surface or rethrow the original or combined
error after attempting the adapter fallback so orphaned rows aren't left behind
if model-level deletion fails.

In `@packages/core/src/portable/holo.ts`:
- Around line 1405-1425: The code currently mutates the shared variable
currentAccessors (used by RequestAccessContext, resolveRequestContext, and
setRequestAccessors), producing a runtime-global accessor that can be
overwritten across concurrent requests; change this to be request-scoped by
replacing the mutable currentAccessors with a stable resolver that returns
per-request accessors instead of mutating shared state: update
setRequestAccessors to register a resolver function (or store accessors on the
per-request context) and modify resolveRequestContext/RequestAccessContext usage
so attachAuthRequestAccessors(context, ...) is invoked with the resolver result
on each call (or reads accessors off the passed-in context) so
getRequestCookie/getRequestHeader always use request-local accessors and never a
shared mutable variable; adjust references to currentAccessors,
resolveRequestContext, setRequestAccessors, and attachAuthRequestAccessors
accordingly.

---

Outside diff comments:
In `@packages/auth/src/runtime.ts`:
- Around line 61-66: The public adapter type ErasedAuthProviderAdapter (and the
abstract/contract class AuthProviderAdapterBase) is missing the optional delete
method but the runtime calls adapter.delete(); add delete?(id: string | number):
Promise<void> to ErasedAuthProviderAdapter and declare the same optional async
delete(id: string | number): Promise<void> signature on AuthProviderAdapterBase
(or the equivalent provider base/interface used by the runtime) so typed
implementations can implement delete() without breaking the contract; ensure the
signature matches the runtime invocation of adapter.delete().

In `@packages/forms/src/contracts.ts`:
- Around line 265-318: The normalizeRequestHeaders function can accept objects
that pass isHeaderAccessorObject but only implement get, which cannot be
iterated and currently falls through losing headers; update
normalizeRequestHeaders to detect the "get-only" accessor
(isHeaderAccessorObject(input) true && typeof input.forEach !== 'function' &&
typeof input.entries !== 'function' && typeof input.get === 'function') and
handle it explicitly — either throw a clear TypeError indicating "get-only
header accessor is not iterable" (so callers know headers were not provided) or
convert it via a supported API if you have a way to enumerate names; reference
the functions/types isHeaderAccessorObject, normalizeRequestHeaders and
RequestLikeHeaders when making the change.

---

Nitpick comments:
In `@packages/adapter-sveltekit/tests/runtime.test.ts`:
- Around line 17-65: Pull the duplicated mock into a local factory function and
use it in both tests: extract the object passed to vi.doMock('@holo-js/core',
...) into a helper like makeHoloCoreMock() that returns {
createHoloFrameworkAdapter: () => ({ capabilities: {}, async createProject(){},
async initializeProject(){}, createHelpers(options){ capturedAuthRequest =
options.authRequest; return { async getApp(){}, async getProject(){}, async
getSession(){}, async getAuth(){}, async useConfig(){}, async config(){} } },
async resetProject(){}, internals: { getState(){}, resolveOptions(){} } }) } and
then call vi.doMock('@holo-js/core', () => makeHoloCoreMock()) in both places;
ensure capturedAuthRequest remains writable in the test scope and update any
imports/uses of createHoloFrameworkAdapter, createHelpers, capturedAuthRequest
to the shared factory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d1394675-b9a3-4b7e-85f4-902d81d1a659

📥 Commits

Reviewing files that changed from the base of the PR and between a86cdf5 and 4441db4.

📒 Files selected for processing (17)
  • packages/adapter-nuxt/tests/module.test.ts
  • packages/adapter-nuxt/tests/setup.test.ts
  • packages/adapter-sveltekit/src/index.ts
  • packages/adapter-sveltekit/src/sveltekit.d.ts
  • packages/adapter-sveltekit/tests/adapter.test.ts
  • packages/adapter-sveltekit/tests/adapter.type.test.ts
  • packages/adapter-sveltekit/tests/runtime.test.ts
  • packages/auth/src/contracts.ts
  • packages/auth/src/runtime.ts
  • packages/auth/tests/package.test.ts
  • packages/cli/src/project/registry-svelte.ts
  • packages/cli/tests/cli.test.ts
  • packages/core/src/portable/holo.ts
  • packages/core/tests/auth-runtime.test.ts
  • packages/forms/src/contracts.ts
  • packages/forms/src/sensitiveInput.ts
  • packages/forms/tests/contracts.test.ts
💤 Files with no reviewable changes (3)
  • packages/forms/src/sensitiveInput.ts
  • packages/adapter-sveltekit/src/sveltekit.d.ts
  • packages/adapter-sveltekit/tests/adapter.test.ts

Comment thread packages/adapter-sveltekit/tests/runtime.test.ts Outdated
Comment thread packages/auth/src/runtime.ts
Comment thread packages/core/src/portable/holo.ts Outdated
@cobraprojects cobraprojects merged commit e4180bd into main May 5, 2026
1 check was pending
@coderabbitai coderabbitai Bot mentioned this pull request May 5, 2026
@cobraprojects cobraprojects deleted the update-auth-package branch May 5, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant