Skip to content

feat(auth): provision signup with listee libs#4

Merged
gentamura merged 3 commits intomainfrom
auth-lib-integration
Oct 21, 2025
Merged

feat(auth): provision signup with listee libs#4
gentamura merged 3 commits intomainfrom
auth-lib-integration

Conversation

@gentamura
Copy link
Member

@gentamura gentamura commented Oct 21, 2025

Summary

  • provision Supabase signup confirmations by calling @listee/auth
  • reuse listee db client to grant default categories during signup
  • enable skipLibCheck to avoid external type errors during build

Summary by CodeRabbit

  • New Features

    • Automated account provisioning now runs during signup completion
    • Stronger token payload verification and validation in auth flows
  • Refactor

    • Removed some exported type aliases from the public auth surface
    • Added local-linked packages to support auth and types
    • Adjusted TypeScript compiler settings to improve library compatibility

@coderabbitai
Copy link

coderabbitai bot commented Oct 21, 2025

Walkthrough

Adds two local Bun-linked packages, enables skipLibCheck in TypeScript, and extends the auth service with token decoding helpers, a cached AccountProvisioner, and an account provisioning step during signup completion; also removes some exported type aliases.

Changes

Cohort / File(s) Summary
Dependency linking
package.json
Added local-linked dependencies @listee/auth and @listee/types using Bun link: spec.
Auth service provisioning integration
src/services/auth-service.ts
Imported AccountProvisioner, createAccountProvisioner, and SupabaseToken; added cached singleton getAccountProvisioner(); added token helpers (isSupabaseTokenPayload, decodeSupabaseToken, extractSubjectFromTokenPayload, extractEmailFromAccessToken); added provisionSignupAccount() and invoke it in completeSignupFromFragment() prior to storing refresh token; removed exported type aliases (AccessTokenResult, AuthStatus, SignupRedirect).
TypeScript config
tsconfig.json
Set skipLibCheck: true in compilerOptions to skip type checking of library declaration files.

Sequence Diagram

sequenceDiagram
    participant User
    participant SignupFlow
    participant AuthService
    participant ProvisionerLib

    User->>SignupFlow: complete signup (fragment)
    SignupFlow->>AuthService: completeSignupFromFragment(result)
    AuthService->>AuthService: parse fragment & extract tokens
    AuthService->>AuthService: decodeSupabaseToken(accessToken)
    AuthService->>ProvisionerLib: getAccountProvisioner() (cached)
    AuthService->>ProvisionerLib: provision(userId, tokenPayload, email)
    ProvisionerLib-->>AuthService: provisioning result
    AuthService->>AuthService: store refresh token
    AuthService-->>SignupFlow: return signup completion
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through tokens, quick and bright,

linked local paths and set types right.
A cached provisioner tends the door,
decoding claims to welcome more.
Signup done — I munch a carrot, light. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "feat(auth): provision signup with listee libs" accurately captures the primary change in the pull request. The substantial modifications are in auth-service.ts, which introduces provisioning functionality that is invoked during signup completion by integrating with @listee/auth. The supporting changes in package.json (adding @listee/auth and @listee/types dependencies) and tsconfig.json (adding skipLibCheck configuration) enable this core functionality. The title is concise, specific, and clear—a teammate scanning the repository history would immediately understand that this PR adds signup provisioning capability through external listee libraries.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch auth-lib-integration

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.

@gentamura gentamura self-assigned this Oct 21, 2025
Copy link

@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: 2

🧹 Nitpick comments (4)
package.json (1)

17-18: Confirm portability of "link:" deps; consider workspace:/file: instead.

"link:" is tool-specific and may not install under npm/pnpm without Bun. If this CLI is used outside your monorepo or by contributors without Bun, prefer:

  • workspaces: "@listee/auth": "workspace:*" / "@listee/types": "workspace:*", or
  • explicit local paths: "file:../auth".

If Bun-only is intentional, ignore. Otherwise, adjust for wider compatibility.

tsconfig.json (1)

16-16: Avoid global skipLibCheck; it masks real type errors.

This disables checks for all .d.ts (including your linked libs), weakening safety and IDE feedback.

  • Prefer moving it to a build-only config (tsconfig.build.json) and keep strict checks in the editor.
  • Or fix the offending library types; if only default libs are noisy, use skipDefaultLibCheck instead.

Minimal change if you keep single config:

-    "skipLibCheck": true,
+    "skipLibCheck": false,
src/services/auth-service.ts (2)

18-25: Singleton is fine; add a test reset or DI hook.

  • Expose a small internal reset (for tests) or allow injecting a provisioner to improve testability.
  • Confirm createAccountProvisioner() is synchronous; if it ever becomes async, guard against concurrent initialization.

Example (optional):

// Only in test builds:
export const __resetProvisionerForTests = () => { cachedAccountProvisioner = null; };

453-453: Be explicit about provisioning failure behavior.

Provisioning runs before storing the refresh token. If provisioning fails, the user may need to re-trigger confirmation. If that’s intended (atomic signup), fine; otherwise consider storing the token first and rolling back on failure.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 633f990 and 5d32b12.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/services/auth-service.ts (5 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/services/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/services/**/*.ts: Place Supabase-facing logic under src/services/
Read SUPABASE_URL and SUPABASE_ANON_KEY from environment variables or .env; never hardcode credentials
Default Keytar service name to "listee-cli"; allow overrides via env vars or CLI flags

Files:

  • src/services/auth-service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript strict practices: forbid any, forbid as assertions, no implicit any; implement type guards for narrowing
Use two-space indentation and LF line endings
Use camelCase for identifiers
Keep comments purposeful; add brief context only for non-trivial flows
Maintain ASCII in files unless the file already uses Unicode

Files:

  • src/services/auth-service.ts
src/**/[a-z0-9-]*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use kebab-case filenames for modules under src/

Files:

  • src/services/auth-service.ts
🧬 Code graph analysis (1)
src/services/auth-service.ts (1)
src/types/auth.ts (1)
  • SignupRedirect (37-40)
🔇 Additional comments (4)
src/services/auth-service.ts (4)

2-6: Imports look good; type-only used correctly.

Verify that the linked packages resolve under your chosen package manager on CI and for contributors.


224-231: LGTM.

Subject extraction with sanity checks is correct.


233-235: Consolidation through decodeSupabaseToken is good.

Single decode path improves consistency.


357-361: LGTM.

Path construction with encodeURIComponent is correct and safe.

Copy link

@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: 0

🧹 Nitpick comments (5)
src/services/auth-service.ts (5)

2-6: Private packages and skipLibCheck: confirm install/runtime plan.

Using @listee/auth and @listee/types via local links is fine for dev, but will break for consumers unless these are resolvable in their env. Also, relying on skipLibCheck can hide real type issues bubbling from these packages. Please confirm distribution strategy (publish, vend, or feature‑gate), and consider minimal local .d.ts shims for only the types you consume to avoid broad skipLibCheck.


18-25: Provisioner singleton: add a small test hook/DI seam.

The cache is good. For tests, consider a tiny setter to inject/reset the provisioner and avoid cross‑test bleed.

Example (outside this hunk):

export const setAccountProvisionerForTests = (prov: AccountProvisioner | null): void => {
  cachedAccountProvisioner = prov;
};

242-249: Clarify expired-token vs malformed-token error.

Currently any failure in isSupabaseTokenPayload yields “payload structure is invalid,” which also covers expiry. Emit a distinct message for expired tokens to guide users.

 const decodeSupabaseToken = (token: string): SupabaseToken => {
-  const payload = decodeJwtPayload(token);
-  if (!isSupabaseTokenPayload(payload)) {
-    throw new Error("Access token payload structure is invalid.");
-  }
-  return payload;
+  const payload = decodeJwtPayload(token);
+  // Offer a clearer path when only expiry is the problem
+  if (isRecord(payload) && isNumber((payload as any).exp)) {
+    const now = Math.floor(Date.now() / 1000);
+    if ((payload as any).exp <= now) {
+      throw new Error("Access token has expired. Please restart signup with a fresh link.");
+    }
+  }
+  if (!isSupabaseTokenPayload(payload)) {
+    throw new Error("Access token payload structure is invalid.");
+  }
+  return payload;
 };

476-483: Ordering: provision before storing refresh token—verify intent.

This avoids a “logged‑in but unprovisioned” state, which is reasonable for CLI UX. Confirm this trade‑off is desired (users must re-trigger signup if provisioning fails). Alternative: store first and rollback on failure to enable retry with the stored session.


485-505: Avoid console.error in service; propagate structured error instead.

Elsewhere the pattern is to throw enriched Errors without direct logging. Consider removing the side‑effect log and include account context in the thrown message.

   try {
     await provisioner.provision({
       userId,
       token: tokenPayload,
       email: result.account,
     });
   } catch (error) {
-    const message = toErrorMessage(error);
-    console.error(
-      `Account provisioning failed for ${result.account}: ${message}`,
-    );
-    throw new Error(`Account provisioning failed: ${message}`);
+    throw new Error(
+      `Account provisioning failed for ${result.account}: ${toErrorMessage(error)}`
+    );
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 618bd73 and 31bffef.

📒 Files selected for processing (1)
  • src/services/auth-service.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/services/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/services/**/*.ts: Place Supabase-facing logic under src/services/
Read SUPABASE_URL and SUPABASE_ANON_KEY from environment variables or .env; never hardcode credentials
Default Keytar service name to "listee-cli"; allow overrides via env vars or CLI flags

Files:

  • src/services/auth-service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript strict practices: forbid any, forbid as assertions, no implicit any; implement type guards for narrowing
Use two-space indentation and LF line endings
Use camelCase for identifiers
Keep comments purposeful; add brief context only for non-trivial flows
Maintain ASCII in files unless the file already uses Unicode

Files:

  • src/services/auth-service.ts
src/**/[a-z0-9-]*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use kebab-case filenames for modules under src/

Files:

  • src/services/auth-service.ts
🧬 Code graph analysis (1)
src/services/auth-service.ts (1)
src/types/auth.ts (1)
  • SignupRedirect (37-40)
🔇 Additional comments (4)
src/services/auth-service.ts (4)

211-241: Stricter token payload guard — LGTM.

Validates sub, email, iat, exp, and rejects expired tokens.


251-258: Subject extraction — LGTM.

Clear checks and precise error.


260-268: Email extraction via decoded payload — LGTM.

Consistent with the stricter decode path.


383-388: Signup endpoint path construction — LGTM.

Correct handling of optional redirect_to with encoding.

@gentamura gentamura merged commit 5133211 into main Oct 21, 2025
1 check passed
@gentamura gentamura deleted the auth-lib-integration branch October 21, 2025 14:20
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