Skip to content

auth: let apps declare model-level indexes on derived auth lists - #1017

Merged
borisno2 merged 4 commits into
mainfrom
claude/focused-rubin-hl7ali
Aug 22, 2026
Merged

auth: let apps declare model-level indexes on derived auth lists#1017
borisno2 merged 4 commits into
mainfrom
claude/focused-rubin-hl7ali

Conversation

@borisno2

Copy link
Copy Markdown
Member

Summary

  • authPlugin()'s per-model config (user/session/account/verification/rateLimit) now accepts an indexes option, in the same shape as a list's own db.indexes (core's ListIndex). Entries are threaded through to the derived list's db.indexes at generate time.
  • When an app-supplied entry covers a column the stack already derives an index for (e.g. User.email's derived @unique), the derived index is suppressed for that column only and the app's entry is emitted instead — the application's declaration wins over a derived default (ADR-0035). This makes two previously-unreachable cases expressible:
  • Fixes a related generator gap: db.indexes can now reference createdAt/updatedAt even when the list has no explicitly declared field for them and relies on db.timestamps for the auto-injected columns — required for the Verification composite-index case above, and generically useful for any list using db.timestamps: true.
  • Unknown-field errors reuse core's existing generator error path unchanged, and correctly name the list under its remapped modelName (e.g. AuthVerification).
  • Plugin-derived tables (from betterAuthPlugins) and adopting better-auth's own 1.7 table-level indexes option are explicitly out of scope (tracked separately as auth: upgrade better-auth to 1.7.1 — new required account.issuer column, new @@unique([issuer, accountId]), and a stale ^1.3.29 peer floor #986).

Test plan

  • New tests in packages/auth/tests/generated-fk-shape.test.ts cover: composite index + suppression, named-unique adoption on User.email, per-column suppression (other derived indexes untouched), field-key resolution through a model's column map, the auth: derived auth lists can't adopt a live constraint name, so User.email / Session.token can diff dirty #921 round-trip (User.email + Session.token), unknown-field errors (plain and under modelName remapping), and unchanged output when no indexes are configured.
  • New tests in packages/cli/src/generator/prisma.test.ts cover the generic createdAt/updatedAt auto-timestamp resolution in db.indexes, independent of auth.
  • Updated two pre-existing packages/auth/tests/config.test.ts assertions for the new indexes: [] field on normalized model config.
  • pnpm lint, pnpm manypkg fix, pnpm format all pass.
  • Full core/cli/auth package test suites pass (1175 + 381 + 279 tests).
  • Changeset added (@opensaas/stack-auth minor, @opensaas/stack-cli minor, @opensaas/stack-core patch for the TSDoc clarification).
  • Reference docs (docs/content/reference/auth.md) and how-to guide (docs/content/how-to/authentication.md) updated, cross-linked to core's db.indexes reference.

Closes #985

🤖 Generated with Claude Code

https://claude.ai/code/session_01PLqppkKWzoMZvy3aCDK6DY


Generated by Claude Code

authPlugin()'s per-model config (user/session/account/verification/rateLimit)
now accepts `indexes`, threaded through to the derived list's `db.indexes`.
An entry covering a column the stack already derives an index for suppresses
that derived index for that column and emits only the app's entry (ADR-0035),
making it possible to adopt a live constraint's real name or extend a derived
column into a composite index. Also fixes the Prisma generator to resolve
createdAt/updatedAt in db.indexes against a list's auto-timestamp columns,
not only an explicitly declared field, which the verification model's
composite-index use case depends on.

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

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

Deployment failed for project stack-docs with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/open-saas?upgradeToPro=build-rate-limit

@changeset-bot

changeset-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9fd127f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@opensaas/stack-auth Minor
@opensaas/stack-cli Minor
@opensaas/stack-core Minor
@opensaas/stack-rag Minor
@opensaas/stack-storage Minor
@opensaas/stack-tiptap Minor
@opensaas/stack-ui Minor
@opensaas/stack-storage-s3 Minor
@opensaas/stack-storage-vercel Minor

Not sure what this means? Click here to learn what changesets are.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e0e222ec4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/auth/src/config/derive-auth-lists.ts Outdated

@borisno2 borisno2 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Single-pass review at high effort (Agent tool unavailable in this session, so no multi-agent fan-out / subagent verify pass ran — this is one careful pass through the diff, cross-file callers, tests, ADR-0035, and CLAUDE.md conventions).

Verified: types (packages/core/src/config/types.ts, packages/auth/src/config/types.ts), the deriveAuthLists suppression logic (packages/auth/src/config/derive-auth-lists.ts), the generator's createdAt/updatedAt auto-timestamp resolution (packages/cli/src/generator/prisma.ts), and all associated tests all typecheck, lint clean, and pass (pnpm vitest run in both packages/auth and packages/cli, plus tsc --noEmit in both packages). The implementation matches ADR-0035 exactly, and the suppress-per-column / plugin-tables-out-of-scope claims in the new docblocks and code comments all check out against the code.

No correctness bugs found in the code itself. One finding: the general db.indexes reference doc (docs/content/reference/config-api.md) wasn't updated to reflect the new createdAt/updatedAt-via-auto-timestamps behavior this PR ships, so it now reads as stale/incomplete relative to the shipped generator behavior — flagged inline on docs/content/how-to/authentication.md since config-api.md itself has no diff lines to anchor a comment to.


Generated by Claude Code

Comment thread docs/content/how-to/authentication.md
claude added 3 commits August 22, 2026 09:52
Update the core db.indexes reference to reflect that an entry can now
name createdAt/updatedAt when a list's auto-timestamps are enabled for
that column, even with no explicitly declared field — per code review
on #1017.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PLqppkKWzoMZvy3aCDK6DY
A relationship field's own generator defaults its FK index to indexed
whenever isIndexed is omitted, unlike a scalar field. Suppressing a
relationship field's derived index therefore has to set isIndexed:
false explicitly, or the derived @@index survives and collides with
the app's own db.indexes entry. Caught by review on #1017.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PLqppkKWzoMZvy3aCDK6DY
…hl7ali

# Conflicts:
#	packages/auth/src/config/derive-auth-lists.ts
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Core Package Coverage (./packages/core)

Status Category Percentage Covered / Total
🟢 Lines 94.05% (🎯 65%) 1631 / 1734
🟢 Statements 92.32% (🎯 65%) 1768 / 1915
🟢 Functions 97.41% (🎯 62%) 264 / 271
🟢 Branches 86.18% (🎯 50%) 1279 / 1484
File CoverageNo changed files found.
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for UI Package Coverage (./packages/ui)

Status Category Percentage Covered / Total
🔵 Lines 78.45% 244 / 311
🔵 Statements 77.95% 251 / 322
🔵 Functions 69.81% 74 / 106
🔵 Branches 66.94% 160 / 239
File CoverageNo changed files found.
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for CLI Package Coverage (./packages/cli)

Status Category Percentage Covered / Total
🔵 Lines 79% 1547 / 1958
🔵 Statements 78.81% 1615 / 2049
🔵 Functions 86.11% 217 / 252
🔵 Branches 69.66% 758 / 1088
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/cli/src/generator/prisma.ts 96.22% 91.32% 100% 96.55% 62, 77, 97, 167-169, 400-402, 479, 538, 584
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Auth Package Coverage (./packages/auth)

Status Category Percentage Covered / Total
🔵 Lines 99.43% 176 / 177
🔵 Statements 97.92% 189 / 193
🔵 Functions 100% 44 / 44
🔵 Branches 90.86% 179 / 197
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/auth/src/config/derive-auth-lists.ts 96.96% 88.88% 100% 99.15% 153, 154, 341-343, 677
packages/auth/src/config/types.ts 0% 0% 0% 0%
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Package Coverage (./packages/storage)

Status Category Percentage Covered / Total
🔵 Lines 78.57% 220 / 280
🔵 Statements 80.06% 245 / 306
🔵 Functions 86.07% 68 / 79
🔵 Branches 75.88% 214 / 282
File CoverageNo changed files found.
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for RAG Package Coverage (./packages/rag)

Status Category Percentage Covered / Total
🔵 Lines 47.97% 355 / 740
🔵 Statements 48.14% 377 / 783
🔵 Functions 54.26% 70 / 129
🔵 Branches 42.55% 180 / 423
File CoverageNo changed files found.
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)

Status Category Percentage Covered / Total
🔵 Lines 100% 40 / 40
🔵 Statements 100% 40 / 40
🔵 Functions 100% 9 / 9
🔵 Branches 100% 19 / 19
File CoverageNo changed files found.
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)

Status Category Percentage Covered / Total
🔵 Lines 100% 68 / 68
🔵 Statements 100% 71 / 71
🔵 Functions 100% 15 / 15
🔵 Branches 97.87% 46 / 47
File CoverageNo changed files found.
Generated in workflow #1791 for commit 9fd127f by the Vitest Coverage Report Action

@borisno2
borisno2 merged commit b30fa61 into main Aug 22, 2026
4 of 5 checks passed
@borisno2
borisno2 deleted the claude/focused-rubin-hl7ali branch August 22, 2026 10:09
@github-actions github-actions Bot mentioned this pull request Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants