Release/2.0.26#2427
Conversation
Main -> Development
Fix/google auth
- GearInventoryScreen: replaces mock data with usePacks(); deduplicates items across packs, filters deleted, derives categories dynamically - AIScreen: replaces MOCK_RESPONSES with DefaultChatTransport hitting /api/chat; uses sendMessage/status from @ai-sdk/react v3 API - Adds @ai-sdk/react and ai to apps/web deps 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
setup-bun v2 does not accept a 'cache' input; valid options are 'no-cache', 'bun-version', etc. Removes the invalid input from all affected workflow files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
gear-inventory: - Skip soft-deleted packs (pack.deleted) in item aggregation - Use toGrams(weight, weightUnit) for correct unit conversion - Capitalize category labels for display (first-aid → First Aid) ai-screen: - Memoize DefaultChatTransport to prevent per-render reinitialization - Concatenate all text parts instead of only the first one - Filter to user/assistant roles before rendering bubbles 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Ensures lockfile drift is caught in CI. Lighthouse already had this; adds it to checks, unit-tests, api-tests, migrations, sync-guides-r2, and e2e-tests. Skips copilot-setup-steps (needs to write lockfile). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…hemas - Replace legacy JWT auth in apps/trails with better-auth/react client (authClient.signIn/signUp/signOut/requestPasswordReset) - Add apps/trails/lib/auth-client.ts with nextCookies() SSR plugin - Rewrite AuthGate/VerifyEmail/useAuth to use Better Auth session - Fix AdminUserItem/Pack/CatalogItem TypeBox schemas to match DB selects (remove fields not selected, add nullable fields that are selected) - Align apps/admin/lib/api.ts interfaces with corrected TypeBox schemas - Fix UserSchema.id: z.number() → z.string() (Better Auth uses UUID text pk) - Fix mapToUser/applySessionUser to include emailVerified/createdAt/updatedAt - Fix ItemReviews.tsx null guards for nullable review fields - Fix web/lib/types.ts id fields: number → string throughout - Fix web/lib/data.ts mock IDs to match string type - Add queryKeys.osm used by admin trails dashboard page 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Remove useLoginMutation/useRegisterMutation from packages/app (legacy JWT endpoints no longer exist; auth is handled by Better Auth) - Add better-auth to apps/web dependencies - Create apps/web/lib/auth-client.ts with nextCookies() SSR plugin - Rewrite apps/web/app/auth/page.tsx to use authClient.signIn/signUp - Update apps/web/lib/api.ts to get session token from Better Auth - Replace clearTokens() in profile-screen with authClient.signOut() - Fix adminFetch as Promise<T> cast (res.json() returns any, no cast needed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
… state 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Package ships source .tsx files with type errors that skipLibCheck can't suppress (only applies to .d.ts files). Add // @ts-nocheck to the 3 affected files via bun patch. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
feat(web): wire gear-inventory and ai-chat screens to real API
…clusion All violations already fixed in development; only exclusion entry remains. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- convert(weight, from, to) → convert(weight, { from, to })
- displayWeight(grams, unit, precision?) → displayWeight(grams, unit) (precision always 2)
- Update all call sites in test files
chore(biome): enforce single-parameter functions
…P flow - Add passwordResetService: generates OTP, stores in verification table (15-min TTL), sends via Resend, verifies with timing-safe compare, updates credential account password (falls back to users.passwordHash for legacy users) - Add POST /api/password-reset/request and /verify routes - Wire forgotPassword/resetPassword in useAuthActions to custom endpoints - Update OTP screen from 5 to 6 characters (NIST SP 800-63B) - Update ResetPasswordRequestSchema code length to 6
…h banner getAccessToken now reads the expoClient cookie JSON from SecureStore directly instead of calling authClient.getSession() on every API request, eliminating concurrent network calls from Legend State polling intervals. onNeedsReauth now verifies the session is genuinely gone before setting needsReauthAtom, so transient 401s no longer trigger the sync-paused banner.
…pment chore: merge main into development
Better Auth prefixes session cookies with __Secure- on HTTPS (remote dev/prod) but not on HTTP (local). getAccessToken was only looking up the unprefixed key, returning null for every remote request and causing a 401 on all authenticated endpoints.
fix(auth): check __Secure- prefixed cookie when reading session token
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
packrat-admin | 9c35486 | Commit Preview URL Branch Preview URL |
May 15 2026, 05:10 PM |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (7)
WalkthroughAdds ETL chunking and progress accounting, password reset routes/services, Better Auth session refactors across apps, OG image generation with tests and metadata, CI hardening (frozen lockfile, Bun cache removal), units API breaking change, admin/client schema/type updates, and widespread package.json catalog/version updates. ChangesMonorepo functional/infrastructure update
Sequence Diagram(s)(skipped) Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 33
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (11)
.github/workflows/sync-guides-r2.yml (2)
29-34:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftPin third-party actions to full commit SHAs.
As per coding guidelines, pin third-party actions to a full commit SHA (not a mutable tag) to prevent supply-chain attacks.
🔒 Example pinning
- uses: actions/checkout@v6 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v6.2.0 - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1🤖 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 @.github/workflows/sync-guides-r2.yml around lines 29 - 34, Replace mutable action tags with immutable commit SHAs: update the two uses entries "actions/checkout@v6" and "oven-sh/setup-bun@v2" to the corresponding full commit SHA pins (e.g., actions/checkout@<full-sha> and oven-sh/setup-bun@<full-sha>) so the workflow references exact commits; keep existing inputs like "with: bun-version: latest" unchanged while swapping only the action references.
1-17: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winAdd a concurrency group to prevent redundant sync runs.
As per coding guidelines, use concurrency groups with cancel-in-progress: true to avoid redundant runs.
🔧 Suggested addition
Add after the
on:section:+concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true🤖 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 @.github/workflows/sync-guides-r2.yml around lines 1 - 17, Add a concurrency section to the GitHub Actions workflow (named "Sync Guides to R2 Bucket") right after the on: block to prevent redundant runs: define concurrency with a descriptive group (e.g., using the workflow name or branch/path context) and set cancel-in-progress: true so in-progress sync jobs are canceled when a new run starts; update the workflow's top-level keys (referencing name: "Sync Guides to R2 Bucket", the on: block, and the concurrency key) accordingly..github/workflows/migrations.yml (2)
1-25: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winConsider adding a concurrency group to prevent parallel migration runs.
This workflow runs database migrations but lacks a concurrency group. If multiple workflow runs trigger simultaneously (e.g., rapid pushes to main), migrations could run in parallel and cause database conflicts or race conditions.
🔧 Suggested addition
Add after the
on:section:+concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: falseNote: Use
cancel-in-progress: falsefor migrations to ensure in-flight migrations complete before starting new ones.As per coding guidelines, use concurrency groups with cancel-in-progress: true to avoid redundant runs.
🤖 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 @.github/workflows/migrations.yml around lines 1 - 25, The workflow "Database Migrations" currently lacks a concurrency configuration which can allow parallel runs; add a concurrency block (placed after the existing on: section) that defines a group string incorporating the workflow name and environment input (e.g., using github.ref or the workflow input environment) and set cancel-in-progress: true per guidelines to prevent redundant concurrent migration runs; reference the existing symbols "name: Database Migrations", "workflow_dispatch" and the "environment" input when constructing the group.
36-41:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftPin third-party actions to full commit SHAs.
As per coding guidelines, pin third-party actions to a full commit SHA (not a mutable tag) to prevent supply-chain attacks.
🔒 Example pinning
- - uses: actions/checkout@v6 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v6.2.0 - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1🤖 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 @.github/workflows/migrations.yml around lines 36 - 41, The workflow uses mutable tags for third-party actions ("actions/checkout@v6" and "oven-sh/setup-bun@v2"); replace these with the corresponding full commit SHAs to pin the actions. Locate the two steps referencing actions/checkout and oven-sh/setup-bun and update their "uses" values to the exact commit SHA (e.g., actions/checkout@<full-sha> and oven-sh/setup-bun@<full-sha>) fetched from each repo's releases/commit history, then commit the updated workflow..github/workflows/e2e-tests.yml (1)
64-64:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftPin all third-party actions to full commit SHAs.
This workflow uses many third-party actions with mutable tags instead of pinned commit SHAs. Each unpinned action is a potential supply-chain attack vector.
As per coding guidelines, pin third-party actions to a full commit SHA (not a mutable tag) to prevent supply-chain attacks.
Actions to pin:
actions/checkout@v6maxim-lobanov/setup-xcode@v1oven-sh/setup-bun@v2expo/expo-github-action@v8actions/setup-java@v5actions/cache@v4(multiple instances)actions/upload-artifact@v7(multiple instances)reactivecircus/android-emulator-runner@v2.37.0🔒 Pin actions to commit SHAs
Find the commit SHA for each action version on the action's GitHub releases page, then update:
- - uses: actions/checkout@v6 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v6.2.0Repeat for all third-party actions in both the
ios-e2eandandroid-e2ejobs.Also applies to: 67-69, 72-74, 90-92, 96-99, 102-109, 112-116, 134-138, 250-254, 258-262, 328-328, 331-333, 336-341, 355-358, 361-368, 372-375, 387-391, 416-422, 426-436, 446-457, 481-485, 489-493
🤖 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 @.github/workflows/e2e-tests.yml at line 64, The workflow uses mutable action tags (e.g., actions/checkout@v6, maxim-lobanov/setup-xcode@v1, oven-sh/setup-bun@v2, expo/expo-github-action@v8, actions/setup-java@v5, actions/cache@v4, actions/upload-artifact@v7, reactivecircus/android-emulator-runner@v2.37.0) and must be pinned to full commit SHAs; for each referenced action (all occurrences listed in the comment) replace the tag with the corresponding full commit SHA from that action's GitHub repo (e.g., actions/checkout@<full-sha>), ensuring you update every instance across both ios-e2e and android-e2e jobs and any repeated uses of actions/cache and actions/upload-artifact so no third-party action uses a mutable tag..github/workflows/unit-tests.yml (1)
48-52:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftPin third-party actions to full commit SHAs.
All third-party actions use mutable tags instead of commit SHAs, exposing the workflow to supply-chain attacks.
As per coding guidelines, pin third-party actions to a full commit SHA (not a mutable tag) to prevent supply-chain attacks.
🔒 Example pinning
- - uses: actions/checkout@v6 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v6.2.0 - - uses: oven-sh/setup-bun@v2 + - uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 - uses: davelosert/vitest-coverage-report-action@v2 + uses: davelosert/vitest-coverage-report-action@[SHA] # v2.x.xFind the commit SHA for each action on its GitHub releases page.
Also applies to: 64-70, 77-81, 93-99
🤖 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 @.github/workflows/unit-tests.yml around lines 48 - 52, The workflow is using mutable tags for third-party actions (e.g., "uses: actions/checkout@v6" and "uses: oven-sh/setup-bun@v2"); replace each mutable tag with the corresponding full commit SHA for the action (e.g., "uses: actions/checkout@<full-commit-sha>") so the workflow is pinned and reproducible—locate the commit SHA on each action's GitHub repo/releases page and update all occurrences (including the other uses blocks noted around lines 64-70, 77-81, 93-99) while preserving the existing inputs/keys (like with: bun-version: latest)..github/workflows/checks.yml (1)
26-27:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftPin third-party actions to full commit SHAs.
All third-party actions use mutable tags instead of commit SHAs, exposing the workflow to supply-chain attacks if upstream tags are moved or compromised.
As per coding guidelines, pin third-party actions to a full commit SHA (not a mutable tag) to prevent supply-chain attacks.
🔒 Example pinning
- - uses: actions/checkout@v6 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v6.2.0 - - uses: oven-sh/setup-bun@v2 + - uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 - uses: stefanzweifel/git-auto-commit-action@v6 + uses: stefanzweifel/git-auto-commit-action@90e3abea814c5315c597c97ee7ca5dd505f72efc # v6.0.0Also applies to: 42-44
🤖 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 @.github/workflows/checks.yml around lines 26 - 27, The workflow uses mutable tags for third-party actions (actions/checkout@v6 and oven-sh/setup-bun@v2); update those action references to their corresponding full commit SHAs instead of version tags (and do the same for the other occurrences of these actions later in the file), e.g., replace "actions/checkout@v6" and "oven-sh/setup-bun@v2" with "actions/checkout@<full-commit-sha>" and "oven-sh/setup-bun@<full-commit-sha>" respectively, ensuring you fetch the exact commit SHAs from the actions' repositories and pin every occurrence consistently..github/workflows/api-tests.yml (1)
28-28:⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftPin third-party actions to full commit SHAs.
All third-party actions in this workflow use mutable tags (
@v6,@v2,@v4) instead of pinned commit SHAs. If an upstream tag is moved or compromised, this workflow could execute malicious code.As per coding guidelines, pin third-party actions to a full commit SHA (not a mutable tag) to prevent supply-chain attacks.
🔒 Example: How to pin actions to commit SHAs
- - uses: actions/checkout@v6 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v6.2.0 - - uses: oven-sh/setup-bun@v2 + - uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0You can find commit SHAs on each action's GitHub releases page.
Also applies to: 30-32, 44-44
🤖 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 @.github/workflows/api-tests.yml at line 28, The workflow uses mutable action tags (e.g., "uses: actions/checkout@v6" and other "uses:" entries referenced at 30-32 and 44) which must be replaced with pinned full commit SHAs; find every "uses: <owner>/<repo>@<tag>" entry (notably "actions/checkout@v6", "actions/setup-node@v4", "actions/cache@v3" or similar) and replace the tag with the corresponding full commit SHA from that action's GitHub repo releases/commit history, committing the updated SHA strings so all third-party actions are pinned to immutable commits.apps/expo/app/(app)/trip/location-search.tsx (1)
41-48: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winReplace direct
fetchwith the typed API client flow.The non-OK guard is useful, but this screen still performs a direct network call in Expo code. Move this request
behind the app API client layer so request handling stays consistent and typed.As per coding guidelines, "Never call
fetch()directly — use the typed API client."🤖 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 `@apps/expo/app/`(app)/trip/location-search.tsx around lines 41 - 48, Replace the direct fetch(...) block that uses searchQuery and GOOGLE_MAPS_API_KEY with a call to the app's typed API client (e.g., a new or existing method like apiClient.getGeocode(searchQuery) or api.getGeocode) so the network request lives behind the typed client; remove direct use of fetch and the response/response.ok check and instead handle the typed client's success/error shape (throw or return based on the client's error response), and if the API key is currently embedded here move key usage to the server-side endpoint invoked by the typed client so the Expo code never contains GOOGLE_MAPS_API_KEY.apps/expo/features/auth/hooks/useAuthActions.ts (1)
95-114:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
signInWithGooglecan leave loading stuck and silently succeed without a user
setIsLoading(false)is only incatch, so successful runs keep loading true. Also, a response with noerrorand nodata.usercurrently exits without failing.Proposed fix
const signInWithGoogle = async () => { setIsLoading(true); try { @@ - if (error) throw new Error(error.message ?? t('auth.failedToSignInWithGoogle')); - if (data && 'user' in data && data.user) applySession(data.user as Record<string, unknown>); // safe-cast: Better Auth user type omits additionalFields; role/preferredWeightUnit present at runtime + if (error || !data?.user) { + throw new Error(error?.message ?? t('auth.failedToSignInWithGoogle')); + } + applySession(data.user as Record<string, unknown>); // safe-cast: Better Auth user type omits additionalFields; role/preferredWeightUnit present at runtime } catch (error) { - setIsLoading(false); - if (isErrorWithCode(error) && error.code === statusCodes.SIGN_IN_CANCELLED) { console.log(t('auth.userCancelledLogin')); @@ } throw error; + } finally { + setIsLoading(false); } };🤖 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 `@apps/expo/features/auth/hooks/useAuthActions.ts` around lines 95 - 114, The Google sign-in flow in signInWithGoogle leaves isLoading true on success and silently returns when response has no error but also no data.user; move setIsLoading(false) into a finally block or ensure it runs after both success and failure, and add explicit handling after authClient.signIn.social: if there's no error and either data is missing or 'user' is not in data or data.user is falsy, throw a descriptive Error (e.g., from t('auth.failedToSignInWithGoogle')) so applySession is only called when data.user exists; update references to authClient.signIn.social, applySession, setIsLoading and keep existing catch logic (isErrorWithCode/statusCodes) unchanged.apps/web/package.json (1)
2-4:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd the missing
versionfield to unblock release validation.The release workflow is currently failing because this manifest has no
version. Add it near Line 2 to match the release target (2.0.26).Proposed fix
{ "name": "packrat-web-app", + "version": "2.0.26", "private": true, "scripts": {🤖 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 `@apps/web/package.json` around lines 2 - 4, Add a top-level "version" field to the package.json manifest so release validation passes: insert "version": "2.0.26" at the top-level (beside "name": "packrat-web-app") in apps/web's package.json so the package has the required version metadata for the release workflow to succeed.
🤖 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 `@apps/admin/lib/api.ts`:
- Around line 338-342: The helper function adminFetch (which calls adminFetcher
and builds URLs using API_BASE) bypasses the Treaty-typed API client; replace
usages of adminFetch/adminFetcher/API_BASE with the Treaty admin client paths
(e.g., adminClient.<resource>.<action>.<method>(...)) so ETL calls go through
the typed apiClient; update each call site to use the returned shape { data,
error, status } and add the standard checks (if (error || !data) ...) before
using data. Ensure you remove or stop using adminFetch and instead call the
appropriate adminClient route methods matching the original path and payload.
In `@apps/expo/features/auth/hooks/useAuthActions.ts`:
- Around line 190-211: The forgotPassword and resetPassword functions currently
call fetch directly; replace those fetch calls with the app's typed API client
methods for the password-reset endpoints so the requests and errors go through
the centralized API contract and error handling. Update forgotPassword and
resetPassword to call the corresponding typed client methods (the password-reset
request and verify methods) and propagate/translate errors using the client's
error shape instead of manually parsing res.json(); keep the same parameters
(email, token, newPassword) so callers are unchanged. Ensure headers/body are
handled by the typed client and remove the raw fetch logic in useAuthActions'
forgotPassword and resetPassword.
In `@apps/expo/features/catalog/components/ItemReviews.tsx`:
- Around line 47-50: The expansion state uses review.title as reviewKey in the
reviews.map callback (reviewKey, expandedReviews) which can collide for
duplicate titles; change reviewKey to a deterministic unique identifier (e.g.,
combine review.id if present or fallback to `${review.title ?? ''}-${i}` or
simply `${i}-${review.title ?? ''}`) and update all uses of reviewKey (where
expandedReviews is indexed and where keys are assigned in render) so each review
has a distinct key and expansion state is independent.
In `@apps/expo/lib/api/packrat.ts`:
- Around line 18-21: The parseSessionToken function currently calls
JSON.parse(cookieJson) without guarding against malformed input; wrap the
JSON.parse call in a try/catch inside parseSessionToken and handle parse errors
by returning null (or logging) so the function does not throw; after successful
parse, pass the parsed value into fromZod(CookieStoreSchema) as before and
continue returning null if validation fails. Ensure you reference
parseSessionToken, JSON.parse, fromZod, and CookieStoreSchema when making the
change.
- Around line 41-46: Wrap the await authClient.getSession() call inside
onNeedsReauth in a try/catch to avoid propagating thrown errors; if getSession
throws, catch the error, log it (or use the app logger) and then call
store.set(needsReauthAtom, true) to ensure no unhandled rejection and the UI is
informed of reauth required; reference symbols: onNeedsReauth,
authClient.getSession, needsReauthAtom, store.set.
In `@apps/trails/lib/apiClient.ts`:
- Around line 17-20: Update getAccessToken to check the authClient.getSession()
response before dereferencing session: destructure both data and error from
authClient.getSession(), return null if error or !data, then safely return
data.session?.token ?? null; this change affects the getAccessToken async
function and ensures you don't access data.session when the call failed.
In `@apps/trails/lib/auth.ts`:
- Line 42: Update the user schema id from number to string by changing the z
schema for id to z.string() (the User/UserInfo schema where id: z.number() is
currently defined), then update the UserInfo type/any related typings so
UserInfo.id is a string; modify getUser() to detect and migrate legacy
localStorage `user` entries with numeric id (coerce number -> string) to avoid
returning null and immediate logout, and sweep code that reads UserInfo.id
(components, auth helpers) to treat it as a string (replace numeric
comparisons/uses with string-safe logic).
In `@apps/web/components/screens/ai-screen.tsx`:
- Around line 18-39: The chat transport is reading auth from
Cookies.get('access_token') which diverges from the app's centralized auth;
update the DefaultChatTransport instantiation in AIScreen so its headers are
derived from the same authClient/apiClient flow used elsewhere: replace the
current headers: () => ({ Authorization: `Bearer ${Cookies.get('access_token')
?? ''}` }) with a function that calls authClient.getSession() (or uses apiClient
to fetch a session) and returns Authorization: `Bearer ${session?.access_token
?? ''}` (handle async if DefaultChatTransport accepts a promise); ensure
DefaultChatTransport still uses API_BASE and keep the other options unchanged.
In `@apps/web/lib/api.ts`:
- Around line 5-6: The apiClient currently uses webEnv.NEXT_PUBLIC_API_URL which
bypasses the CF Worker proxy; update the createApiClient call (symbol:
apiClient) to use a same-origin or relative base URL instead of
webEnv.NEXT_PUBLIC_API_URL (set baseUrl to '/' or undefined so it uses the app
origin) to ensure requests go through the CF Worker proxy for rate limiting and
cookie-scoped auth.
In `@apps/web/lib/auth-client.ts`:
- Around line 7-10: The auth client is using a full absolute baseURL
(webEnv.NEXT_PUBLIC_API_URL) which scopes cookies to the API origin and breaks
nextCookies(); update createAuthClient usage for authClient to use a same-origin
relative path (e.g., "/api/auth" or just "/api") or omit the origin so cookies
remain scoped to the web app; make the same change for apiClient in
apps/web/lib/api.ts (adjust their baseURL values and keep nextCookies() plugin
intact).
In `@docs/plans/2026-05-13-chore-enroll-catalog-candidates-plan.md`:
- Around line 29-36: The markdown fenced code blocks in the steps that show the
JSON snippets are missing surrounding blank lines (MD031); edit the two blocks
that start with "```json" and contain the lines with "\"package-name\":
\"^x.y.z\"" and "\"package-name\": \"catalog:\"" so that there is an empty line
immediately before each opening fence and an empty line immediately after each
closing fence (i.e., add a blank line between the preceding paragraph/list item
and the ```json fence and a blank line after the ``` fence) to satisfy
markdownlint.
In `@package.json`:
- Line 55: The package.json has a mismatch between the dependency entry
"@packrat-ai/nativewindui": "2.0.3-2" and the patchedDependencies key
"@packrat-ai/nativewindui@2.0.3"; update them to match exactly by either
changing the dependency to "2.0.3" or changing the patchedDependencies key to
"@packrat-ai/nativewindui@2.0.3-2" so pnpm will apply the patch; ensure you
update the string in the package.json entries for both patchedDependencies and
dependencies/devDependencies where the package appears.
In `@packages/api/drizzle/0037_nullable_catalog_weight.sql`:
- Around line 1-5: The repository contains duplicate migrations that drop NOT
NULL on catalog_items.weight/weight_unit (see ALTER TABLE "catalog_items" ALTER
COLUMN "weight" DROP NOT NULL and ALTER COLUMN "weight_unit" DROP NOT NULL) in a
0037_* file; delete all 0037_* migration files that duplicate this change so
only the 0047_cute_bloodscream migration remains in the migration journal,
update any references to the 0037 filenames, and re-run your migration
validation/bootstrap (or migration linter) to confirm the schema changes are
tracked only by 0047_cute_bloodscream.
In `@packages/api/src/index.ts`:
- Line 37: The current CORS config allows credentialed requests for any
*.workers.dev origin (the regex /^https?:\/\/[\w-]+\.workers\.dev$/) which is
unsafe; update the CORS policy to either remove credentials: true for wildcard
worker origins or replace the broad regex with a strict allowlist of exact
origins, and ensure any route that requires auth uses the authPlugin macro
(isAuthenticated: true) and includes explicit role/ownership checks where needed
(verify handlers/middlewares that call authPlugin or check roles/owners). Locate
the CORS setup and the routes that expect credentials, change credentials to
false for wildcard patterns or narrow the origin matcher to specific hostnames,
and audit routes using protected resources to add isAuthenticated: true and
appropriate role/ownership validation.
In `@packages/api/src/routes/admin/analytics/catalog.ts`:
- Around line 419-447: The current retry flow reads etlJobs and then
unconditionally inserts a new running job, causing a TOCTOU race; replace this
with an atomic conditional update or mark to prevent duplicates: perform an
UPDATE on etlJobs (e.g., set status='retrying' and/or set retriedAt/retryJobId)
WHERE id = params.jobId AND status = 'failed' and use RETURNING to get the
updated row (instead of the current select/insert pattern), then only create the
new job (newJobId/objectKey/insert into etlJobs) and queue if the UPDATE
returned a row; alternatively, add and check a retriedAt or retryJobId column on
the original and reject the retry when that field is already set.
- Around line 277-301: The SQL extraction of err->>'field' and err->>'reason'
can produce NULLs, but the code and EtlErrorRowSchema expect non-null strings;
update the query that uses jsonb_array_elements(${invalidItemLogs.errors}) (and
the similar query at the other occurrence) to either FILTER out NULLs (e.g.,
WHERE err->>'field' IS NOT NULL AND err->>'reason' IS NOT NULL) or COALESCE
those values to a sentinel string so the returned rows conform to the typed
shape; adjust the SELECT/WHERE in the sql block that populates rows (and any
mapping that uses r.field/r.reason) so the result matches { field: string;
reason: string; count: number } and aligns with EtlErrorRowSchema.
- Around line 413-470: The retry endpoint enqueues the original objectKey as a
single chunk and thus loses the byte-range splitting used in
routes/catalog/index.ts; update the handler in the POST '/etl/:jobId/retry'
route (the code that builds chunks and calls queueCatalogETL) to reuse the same
chunking logic: perform an R2 head/metadata lookup (R2BucketService.head or the
helper used in routes/catalog/index.ts), compute byte-range sub-chunks for
objects >20MB the same way the existing splitting code does, and pass those
chunks (with range fields) into queueCatalogETL instead of a single { objectKey
} chunk; alternatively extract the splitting helper from routes/catalog/index.ts
into a shared function and call it from this retry handler so queued chunks
match the original behavior.
In `@packages/api/src/routes/admin/index.ts`:
- Around line 122-132: The origin allowlist currently returns true for any
origin ending with '.workers.dev' inside the origin: (request) => { ... }
function, which is too permissive when credentials: true; replace that broad
check with a strict match against a fixed set of allowed worker subdomains
(e.g., create an allowedWorkerOrigins Set or array and check
allowedWorkerOrigins.has(origin)) or a tightly-scoped regex for only the
specific preview prefixes you own, and ensure the credentials: true behavior is
only applied when origin exactly matches one of those allowed entries; update
the origin check in this function (and remove the generic
origin.endsWith('.workers.dev') branch) so only explicitly whitelisted worker
URLs are accepted.
In `@packages/api/src/routes/catalog/index.ts`:
- Around line 186-200: The loop serially calls r2.head for each item in chunks,
causing unnecessary latency; change it to run all HEADs in parallel by mapping
chunks to r2.head promises (e.g., use Promise.all on chunks.map) and then
iterate the resulting metas to populate queueChunks with the same logic (push
{objectKey} when meta is falsy or size<=CHUNK_BYTES, otherwise compute n and
push segments with byteStart/byteEnd using CHUNK_BYTES); reference the
variables/functions: chunks, r2.head, CHUNK_BYTES, queueChunks, byteStart,
byteEnd.
- Around line 186-200: The loop that calls r2.head(objectKey) must treat a null
meta as a hard failure instead of enqueueing the objectKey: after const meta =
await r2.head(objectKey) add a null check (meta === null) and abort the
operation (e.g., throw an error or return a 404 response) so the code does not
push the objectKey into queueChunks; only when meta is non-null proceed to the
existing size check and chunking logic. Ensure the handler updates/propagates
the error so the ETL job is not left marked as running.
In `@packages/api/src/routes/passwordReset.ts`:
- Around line 27-47: Add per-IP and per-email rate limiting and failure lockout
to the '/verify' POST handler that calls verifyOtpAndResetPassword: use the same
rate limiter config as env.TOKEN_RATE_LIMITER (key on request header
'cf-connecting-ip' and on body.email) and increment an attempt counter that
invalidates the OTP after N failed attempts, or temporarily blocks further
attempts for that key; adjust verifyOtpAndResetPassword (or wrap it) to
atomically track failures and invalidate the OTP on threshold. Also stop
returning raw error.message to clients—catch errors, log the full error
server-side, and return a user-safe generic message (e.g., "Password reset
failed") via the existing status(400) response. Ensure
ResetPasswordRequestSchema remains applied and the rate limiter is applied
before calling verifyOtpAndResetPassword.
- Around line 10-25: The /request handler calls requestPasswordReset(body.email)
without error handling which can leak account existence via different HTTP
responses; wrap the await requestPasswordReset(...) in a try/catch inside the
POST handler for '/request', catch any thrown error, log it internally (e.g.,
using the existing logger or console.error) and do not rethrow, and always
return the same { success: true, message: 'If an account exists, a reset code
has been sent.' } response so the endpoint never reveals whether the email
exists.
In `@packages/api/src/services/etl/processCatalogEtl.ts`:
- Around line 100-108: The partial-row skip branch in processCatalogEtl.ts (the
skipPartialRow block using text.indexOf('\n') and text.slice(nl + 1)) can hang
if the input uses old-Mac '\r' line endings; adjust the logic inside that block
(referencing skipPartialRow, text.indexOf, text.slice) to look for '\n' first
and if not found fall back to locating '\r' (or any of '\r\n' sequences) and
advance past whichever terminator is found so the buffer always progresses; also
add a brief comment or doc note near this code indicating the assumption about
allowed line endings (LF/CRLF) so maintainers know why '\r' is handled as a
fallback.
- Around line 50-58: The injectedHeader extraction can silently truncate when
the header line exceeds 4096 bytes: in the byteStart > 0 branch (symbols:
injectedHeader, r2Service.get, headerSlice.text(), byteStart) detect whether the
fetched headerText contains a newline; if not, either extend the range/read more
bytes (looping/fetching additional ranges until a '\n' is found) or throw a
clear error indicating the header window was too small for objectKey so the
chunk is rejected; ensure the final injectedHeader is the full header line up to
the first '\n' (or fail fast when not available).
- Around line 89-117: The producer IIFE that reads from
streamToText(r2Object.body) must be awaited and its errors propagated into the
CSV parser so they don't become unhandled rejections and leave the consumer
waiting; assign the IIFE to a variable (e.g., producer), add a .catch that
forwards the error into parser (e.g., parser.emit or parser.destroy with the
error), and after the consumer loop over "for await (const record of parser)"
await the producer so any producer-side exception is observed by the outer
try/catch; ensure parser.end() still runs in normal flow and errors from
parser.write(...) are also forwarded into parser for proper failure handling.
In `@packages/api/src/services/passwordResetService.ts`:
- Around line 17-38: The delete-then-insert in requestPasswordReset and the
update-then-delete in verifyOtpAndResetPassword are not atomic and can leave
inconsistent state if interrupted; wrap each multi-step sequence in a single
db.transaction(...) so the delete+insert (in requestPasswordReset) and the
update+delete (in verifyOtpAndResetPassword) run as one atomic unit, using the
transaction-scoped DB handle for the subsequent queries (replace direct
createDb() usages inside those flows with the transaction client) and ensure
errors roll back the transaction.
- Around line 27-35: The verification code is stored in plaintext and there is
no attempt limit; update the create-and-verify flow in passwordResetService.ts
to (1) hash the OTP before storing (e.g., use a strong one-way KDF like
bcrypt/argon2/scrypt with a per-row salt) and store hashedValue (rename from
value) plus salt if needed and initialize failedAttempts=0 on the verification
record created in the block that inserts into the verification table (id,
identifier, ...); and (2) add and enforce a maxAttempts counter on each
verification row (failedAttempts column) so that on each failed check you
increment failedAttempts and invalidate/delete the row (or mark it) when it
reaches N (e.g., 5), and on verify compare the user-supplied code by hashing it
the same way and using timing-safe comparison (instead of comparing plaintext),
deleting the record on success. Ensure fields and logic around
verification.identifier, verification.expiresAt and the insert/delete flows are
updated to use hashedValue and failedAttempts so brute-force and DB-leak risks
are mitigated.
- Around line 60-61: In verifyOtpAndResetPassword, avoid leaking account
existence by replacing the specific throw new Error('User not found') after
db.query.users.findFirst(...) with the same generic error used earlier (e.g.,
'Invalid or expired reset code' or a shared constant) so both
requestPasswordReset and verifyOtpAndResetPassword return the identical generic
message; update the error text thrown in verifyOtpAndResetPassword (around the
users.email lookup) to match the existing generic message used for bad OTPs.
- Around line 12-14: The generateOtp function currently uses Math.random() which
is not cryptographically secure; replace it with a CSPRNG approach (e.g., using
crypto.getRandomValues on Cloudflare Workers or
crypto.randomInt/crypto.randomBytes on Node) to produce OTP_LENGTH digits:
allocate a byte buffer, fill with crypto.getRandomValues, and map bytes to
digits using rejection sampling to avoid modulo bias, returning a string of
length OTP_LENGTH; update the generateOtp implementation (and any tests) to use
this secure method instead of Math.random().
- Around line 63-82: After updating the password (after the account/users update
and before deleting the verification row), revoke all active sessions for the
user by deleting from the session table: import the session schema (session)
from `@packrat/api/db/schema` and call db.delete(session).where(eq(session.userId,
user.id)) so all Better Auth sessions for user.id are removed; alternatively,
call the Better Auth session-revocation API at that same point if preferred.
In `@packages/api/test/etl.test.ts`:
- Around line 52-68: The helpers insertJob and getJob currently call
createDbClient({} as any) which bypasses type safety; update these helpers to
pass a properly typed minimal env or test client instead of using any — either
change the argument to use `unknown` or define a small TestEnv type matching
createDbClient's parameter and construct a typed empty/minimal object, or reuse
an existing pre-configured test DB client (e.g., a shared test pool) and call
createDbClient with that; ensure references to createDbClient in both insertJob
and getJob are updated so no `as any` casts remain.
- Around line 32-48: The mocks in mockR2WithCsv and mockR2WithNull use `as any`,
removing type safety; replace those casts with a properly typed mock that
conforms to the R2BucketService interface (e.g., return a
Partial<R2BucketService> or a Mocked<R2BucketService> implementation) so the
object with get: vi.fn().mockResolvedValue(...) matches the expected service
type; update the mockImplementationOnce return type to a typed shape (or cast
via `as unknown as R2BucketService` if unavoidable) and ensure the get method
signature matches the real R2BucketService.get to restore compile-time checks.
- Around line 197-228: Add an explicit module reset before the dynamic import to
ensure test isolation: call vi.resetModules() immediately before importing
generateManyEmbeddings in the test so the import returns a fresh module (then
mock generateManyEmbeddings as you already do); this change affects the test
that calls processValidItemsBatch and references generateManyEmbeddings (and
prevents the cached global mock from setup.ts from carrying state into this
test).
---
Outside diff comments:
In @.github/workflows/api-tests.yml:
- Line 28: The workflow uses mutable action tags (e.g., "uses:
actions/checkout@v6" and other "uses:" entries referenced at 30-32 and 44) which
must be replaced with pinned full commit SHAs; find every "uses:
<owner>/<repo>@<tag>" entry (notably "actions/checkout@v6",
"actions/setup-node@v4", "actions/cache@v3" or similar) and replace the tag with
the corresponding full commit SHA from that action's GitHub repo releases/commit
history, committing the updated SHA strings so all third-party actions are
pinned to immutable commits.
In @.github/workflows/checks.yml:
- Around line 26-27: The workflow uses mutable tags for third-party actions
(actions/checkout@v6 and oven-sh/setup-bun@v2); update those action references
to their corresponding full commit SHAs instead of version tags (and do the same
for the other occurrences of these actions later in the file), e.g., replace
"actions/checkout@v6" and "oven-sh/setup-bun@v2" with
"actions/checkout@<full-commit-sha>" and "oven-sh/setup-bun@<full-commit-sha>"
respectively, ensuring you fetch the exact commit SHAs from the actions'
repositories and pin every occurrence consistently.
In @.github/workflows/e2e-tests.yml:
- Line 64: The workflow uses mutable action tags (e.g., actions/checkout@v6,
maxim-lobanov/setup-xcode@v1, oven-sh/setup-bun@v2, expo/expo-github-action@v8,
actions/setup-java@v5, actions/cache@v4, actions/upload-artifact@v7,
reactivecircus/android-emulator-runner@v2.37.0) and must be pinned to full
commit SHAs; for each referenced action (all occurrences listed in the comment)
replace the tag with the corresponding full commit SHA from that action's GitHub
repo (e.g., actions/checkout@<full-sha>), ensuring you update every instance
across both ios-e2e and android-e2e jobs and any repeated uses of actions/cache
and actions/upload-artifact so no third-party action uses a mutable tag.
In @.github/workflows/migrations.yml:
- Around line 1-25: The workflow "Database Migrations" currently lacks a
concurrency configuration which can allow parallel runs; add a concurrency block
(placed after the existing on: section) that defines a group string
incorporating the workflow name and environment input (e.g., using github.ref or
the workflow input environment) and set cancel-in-progress: true per guidelines
to prevent redundant concurrent migration runs; reference the existing symbols
"name: Database Migrations", "workflow_dispatch" and the "environment" input
when constructing the group.
- Around line 36-41: The workflow uses mutable tags for third-party actions
("actions/checkout@v6" and "oven-sh/setup-bun@v2"); replace these with the
corresponding full commit SHAs to pin the actions. Locate the two steps
referencing actions/checkout and oven-sh/setup-bun and update their "uses"
values to the exact commit SHA (e.g., actions/checkout@<full-sha> and
oven-sh/setup-bun@<full-sha>) fetched from each repo's releases/commit history,
then commit the updated workflow.
In @.github/workflows/sync-guides-r2.yml:
- Around line 29-34: Replace mutable action tags with immutable commit SHAs:
update the two uses entries "actions/checkout@v6" and "oven-sh/setup-bun@v2" to
the corresponding full commit SHA pins (e.g., actions/checkout@<full-sha> and
oven-sh/setup-bun@<full-sha>) so the workflow references exact commits; keep
existing inputs like "with: bun-version: latest" unchanged while swapping only
the action references.
- Around line 1-17: Add a concurrency section to the GitHub Actions workflow
(named "Sync Guides to R2 Bucket") right after the on: block to prevent
redundant runs: define concurrency with a descriptive group (e.g., using the
workflow name or branch/path context) and set cancel-in-progress: true so
in-progress sync jobs are canceled when a new run starts; update the workflow's
top-level keys (referencing name: "Sync Guides to R2 Bucket", the on: block, and
the concurrency key) accordingly.
In @.github/workflows/unit-tests.yml:
- Around line 48-52: The workflow is using mutable tags for third-party actions
(e.g., "uses: actions/checkout@v6" and "uses: oven-sh/setup-bun@v2"); replace
each mutable tag with the corresponding full commit SHA for the action (e.g.,
"uses: actions/checkout@<full-commit-sha>") so the workflow is pinned and
reproducible—locate the commit SHA on each action's GitHub repo/releases page
and update all occurrences (including the other uses blocks noted around lines
64-70, 77-81, 93-99) while preserving the existing inputs/keys (like with:
bun-version: latest).
In `@apps/expo/app/`(app)/trip/location-search.tsx:
- Around line 41-48: Replace the direct fetch(...) block that uses searchQuery
and GOOGLE_MAPS_API_KEY with a call to the app's typed API client (e.g., a new
or existing method like apiClient.getGeocode(searchQuery) or api.getGeocode) so
the network request lives behind the typed client; remove direct use of fetch
and the response/response.ok check and instead handle the typed client's
success/error shape (throw or return based on the client's error response), and
if the API key is currently embedded here move key usage to the server-side
endpoint invoked by the typed client so the Expo code never contains
GOOGLE_MAPS_API_KEY.
In `@apps/expo/features/auth/hooks/useAuthActions.ts`:
- Around line 95-114: The Google sign-in flow in signInWithGoogle leaves
isLoading true on success and silently returns when response has no error but
also no data.user; move setIsLoading(false) into a finally block or ensure it
runs after both success and failure, and add explicit handling after
authClient.signIn.social: if there's no error and either data is missing or
'user' is not in data or data.user is falsy, throw a descriptive Error (e.g.,
from t('auth.failedToSignInWithGoogle')) so applySession is only called when
data.user exists; update references to authClient.signIn.social, applySession,
setIsLoading and keep existing catch logic (isErrorWithCode/statusCodes)
unchanged.
In `@apps/web/package.json`:
- Around line 2-4: Add a top-level "version" field to the package.json manifest
so release validation passes: insert "version": "2.0.26" at the top-level
(beside "name": "packrat-web-app") in apps/web's package.json so the package has
the required version metadata for the release workflow to succeed.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 218f4714-5085-439f-ab51-8990b3a57c90
⛔ Files ignored due to path filters (2)
apps/guides/bun.lockis excluded by!**/*.lockbun.lockis excluded by!**/*.lock,!bun.lock
📒 Files selected for processing (113)
.github/scripts/configure-deps.ts.github/workflows/api-tests.yml.github/workflows/checks.yml.github/workflows/copilot-setup-steps.yml.github/workflows/e2e-tests.yml.github/workflows/lighthouse.yml.github/workflows/migrations.yml.github/workflows/release-ios.yml.github/workflows/sync-guides-r2.yml.github/workflows/unit-tests.yml.gitignoreapps/admin/components/edit-catalog-dialog.tsxapps/admin/lib/api.tsapps/admin/lib/queryKeys.tsapps/admin/package.jsonapps/expo/app.config.tsapps/expo/app/(app)/trip/location-search.tsxapps/expo/app/auth/index.tsxapps/expo/app/auth/one-time-password.tsxapps/expo/features/auth/hooks/useAuthActions.tsapps/expo/features/auth/hooks/useAuthInit.tsapps/expo/features/catalog/components/ItemReviews.tsxapps/expo/lib/api/packrat.tsapps/expo/lib/hooks/useColorScheme.tsxapps/expo/package.jsonapps/expo/utils/__tests__/weight.test.tsapps/guides/__tests__/og-image.test.tsapps/guides/app/guide/[slug]/opengraph-image.tsxapps/guides/app/guide/[slug]/page.tsxapps/guides/app/layout.tsxapps/guides/app/opengraph-image.tsxapps/guides/app/twitter-image.tsxapps/guides/lib/metadata.tsapps/guides/lib/og-image.tsxapps/guides/package.jsonapps/guides/scripts/generate-og-images.tsapps/guides/vitest.config.tsapps/landing/__tests__/og-image.test.tsapps/landing/app/layout.tsxapps/landing/app/opengraph-image.tsxapps/landing/app/twitter-image.tsxapps/landing/lib/metadata.tsapps/landing/lib/og-image.tsxapps/landing/package.jsonapps/landing/scripts/generate-og-images.tsapps/landing/vitest.config.tsapps/trails/components/AuthGate.tsxapps/trails/components/VerifyEmail.tsxapps/trails/lib/apiClient.tsapps/trails/lib/auth-client.tsapps/trails/lib/auth.tsapps/trails/lib/useAuth.tsxapps/trails/package.jsonapps/web/app/auth/page.tsxapps/web/components/screens/ai-screen.tsxapps/web/components/screens/gear-inventory-screen.tsxapps/web/components/screens/profile-screen.tsxapps/web/lib/api.tsapps/web/lib/auth-client.tsapps/web/lib/data.tsapps/web/lib/types.tsapps/web/package.jsonbiome.jsondocs/plans/2026-05-13-chore-enroll-catalog-candidates-plan.mdpackage.jsonpackages/analytics/package.jsonpackages/api-client/package.jsonpackages/api/container_src/package.jsonpackages/api/drizzle/0037_nullable_catalog_weight.sqlpackages/api/drizzle/0037_rich_electro.sqlpackages/api/drizzle/0047_cute_bloodscream.sqlpackages/api/drizzle/meta/0047_cute_bloodscream.jsonpackages/api/drizzle/meta/_journal.jsonpackages/api/package.jsonpackages/api/src/db/schema.tspackages/api/src/index.tspackages/api/src/routes/admin/analytics/catalog.tspackages/api/src/routes/admin/index.tspackages/api/src/routes/catalog/index.tspackages/api/src/routes/index.tspackages/api/src/routes/passwordReset.tspackages/api/src/schemas/admin.tspackages/api/src/schemas/auth.tspackages/api/src/schemas/users.tspackages/api/src/services/etl/processCatalogEtl.tspackages/api/src/services/etl/processLogsBatch.tspackages/api/src/services/etl/processValidItemsBatch.tspackages/api/src/services/etl/queue.tspackages/api/src/services/etl/types.tspackages/api/src/services/etl/updateEtlJobProgress.tspackages/api/src/services/packService.tspackages/api/src/services/passwordResetService.tspackages/api/src/utils/__tests__/weight.test.tspackages/api/test/etl.test.tspackages/api/wrangler.jsoncpackages/app/package.jsonpackages/app/src/entities/user/index.tspackages/app/src/entities/user/queries.tspackages/checks/package.jsonpackages/cli/package.jsonpackages/config/package.jsonpackages/env/package.jsonpackages/guards/package.jsonpackages/mcp/package.jsonpackages/osm-db/package.jsonpackages/osm-import/package.jsonpackages/overpass/package.jsonpackages/ui/package.jsonpackages/units/package.jsonpackages/units/src/index.test.tspackages/units/src/index.tspackages/web-ui/package.jsonpatches/@packrat-ai%2Fnativewindui@2.0.3.patch
💤 Files with no reviewable changes (5)
- .github/workflows/copilot-setup-steps.yml
- packages/app/src/entities/user/index.ts
- .github/workflows/lighthouse.yml
- .github/workflows/release-ios.yml
- biome.json
Resolved 11 file conflicts from diverging auth refactors: - apps/admin/lib/queryKeys.ts: make `q` optional in osm.search/conditions (main) - apps/expo/features/auth/hooks/useAuthActions.ts: keep both clientEnvs + asBoolean/asString imports; use proper type guards in mapToUser (main) - apps/expo/features/auth/hooks/useAuthInit.ts: use asString/asBoolean in applySessionUser instead of raw String() casts (main) - apps/expo/features/catalog/components/ItemReviews.tsx: use idx variable name and review.text?.length optional chaining (main) - apps/trails/components/AuthGate.tsx: add trailsAuthClient import; call trailsAuthClient.requestPasswordReset directly in forgot-password handler; remove unused forgotPassword destructure and VerifyEmail import - apps/trails/lib/auth-client.ts (add/add): export trailsAuthClient without nextCookies plugin (main) - apps/trails/lib/useAuth.tsx: complete rewrite to main's local-state auth approach — adds pendingEmail, verifyEmail, resendVerification, token management via trails-app/lib/auth; forgotPassword implemented via trailsAuthClient to satisfy AuthActions interface - apps/trails/package.json: remove direct better-auth dep (main) - apps/web/app/auth/page.tsx: remove dead useLoginMutation/useRegisterMutation helpers; keep simple authClient-based mutations already in the component - apps/web/package.json: remove ai + better-auth direct deps (main) - bun.lock: take origin/main lockfile (latest catalog dependency resolution)
Deploying packrat-guides with
|
| Latest commit: |
9c35486
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://2755d9d4.packrat-guides-6gq.pages.dev |
| Branch Preview URL: | https://release-2-0-26.packrat-guides-6gq.pages.dev |
Coverage Report for API Unit Tests Coverage (./packages/api)
File Coverage
|
||||||||||||||||||||||||||||||||||||||
Coverage Report for Expo Unit Tests Coverage (./apps/expo)
File CoverageNo changed files found. |
Deploying packrat-landing with
|
| Latest commit: |
9c35486
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://026be429.packrat-landing.pages.dev |
| Branch Preview URL: | https://release-2-0-26.packrat-landing.pages.dev |
Main's 07d50ad (fix(trails): correct authClient import to use trailsAuthClient) overlapped with dev's broader auth refactor. Took dev's versions across: - apps/expo/features/auth/hooks/useAuthActions.ts (uses asString/asBoolean guards) - apps/trails/components/AuthGate.tsx (VerifyEmail + pendingEmail integration) - apps/trails/lib/apiClient.ts (trailsAuthClient as authClient alias) - apps/trails/lib/useAuth.tsx (pendingEmail in state shape) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This pull request introduces several improvements and fixes across the codebase, focusing on dependency management, type safety, and minor UI enhancements. The most significant changes include enforcing strict dependency installation, aligning types with backend schemas, and improving error handling and user interface consistency.
Dependency Management and CI Improvements:
bun install --frozen-lockfileto ensure deterministic dependency installation, and thecache: trueoption has been removed from theoven-sh/setup-bunstep for consistency and reliability. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12].github/scripts/configure-deps.tsscript now detects Cloudflare Pages builds and provides tailored error messages for missing tokens, improving developer experience in CI environments. [1] [2]Type Safety and API Alignment:
apps/admin/lib/api.ts, allAdminUser,AdminPack, andAdminCatalogItemtypes are now derived from their respective Zod schemas, ensuring consistency with backend validation. Related API methods have been updated to use string IDs for user operations, and new types for ETL failures are imported from schemas. [1] [2] [3] [4] [5]adminFetchhelper function is introduced for consistent admin API calls.UI and UX Improvements:
weightUnitfield is improved to avoid passing empty strings as values and ensure correct defaulting. [1] [2]Other Notable Changes:
queryKeysutility in the admin app now includes keys for OSM-related queries, supporting future enhancements.apps/admin/package.jsonare now referenced from the internalcatalog:registry for improved dependency management.apps/adminandapps/expoto2.0.26. [1] [2]Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores