release: development → main (OG fix + MCP/CLI Eden + foundation refactors)#2438
Conversation
…ompt and fix Apple model tool call response
…type inference
Add response: { 200: Schema } to all remaining routes so Eden Treaty
stops returning unknown for API responses. Convert return status() error
paths to throw so handler return types stay clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
…types/index.ts Move enum constants, Zod schemas, and inferred types to a dedicated constants.ts file. Convert types/index.ts to a pure re-export barrel. Update all api-internal importers to use @packrat/api/types/constants directly. Expo app imports continue working via the re-export barrel. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…api/schemas Replace duplicated schema definitions in packages/app entities with direct re-exports from the canonical API schemas. Fix CatalogItemSchema to use datetimeString preprocess (consistent with PackItemSchema) so dates serialize to string instead of Date at the API boundary. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…templates
- catalog POST/PUT: parse through CatalogItemSchema before returning, stripping
the embedding vector from API responses and adding response: { 200: Schema }
for Eden Treaty type inference
- catalog POST/PUT: convert return status() error paths to throws so handler
return type matches the declared response schema
- packTemplates generate-from-online-content: switch from manual role check to
adminAuthPlugin macro (isAdmin: true) for consistent access control
…API constants Delete apps/expo/types/index.ts which duplicated type definitions already in @packrat/api/types/constants. Redirect all 15 importing files to the canonical source so there is one definition for PackItem, Pack, User, WeightUnit, and PackCategory across the codebase. Also fix constants.ts utility schemas: userId fields were z.number() but better-auth uses string UUIDs; update to z.string() and fix corresponding test mock data.
- upload.ts: return 400/403 instead of throw Error() for validation/auth
- trips/index.ts: soft-delete (deleted=true) scoped by userId; return 404
when no row matched (replaces hard DELETE + separate ownership check)
- guides/index.ts: return 400 for missing q param instead of throw Error()
- user/index.ts: return 409 for duplicate email instead of throw Error()
- weather.ts: return 400 for missing location ID instead of throw Error()
- packs/index.ts: return 403 for access denied; use computePackWeights()
directly instead of computePacksWeights([])[0] (noUncheckedIndexedAccess);
remove redundant try/catch that only re-threw
- schemas/upload.ts: restore z.string().url() validation on presigned URLs
- routeParams.ts: update stale comment to match .pipe() implementation
Routes that needed to return error status codes inline had their
response: { 200: Schema } maps removed to satisfy Elysia type constraints
(Eden Treaty typing preserved on all other routes).
Create two new workspace packages: - @packrat/db: Drizzle table definitions, raw constants (no Zod), ValidationError interface, drizzle-zod generated schemas - @packrat/schemas: All route-level Zod schemas, depends on @packrat/db packages/api keeps 100% backward-compatible re-export shims so all existing import paths continue to work unchanged. drizzle.config.ts and migration infra are untouched. @packrat/app entities now import from @packrat/schemas directly. Resolves duplicate ErrorResponseSchema/SuccessResponseSchema across schema files (consolidated into @packrat/schemas/shared). Fixes pre-existing type mismatches surfaced by stricter Drizzle-inferred types: User.avatar→image/avatarUrl, Pack→PackWithItems for compute-pack utility, test factories updated to provide all required Drizzle model fields. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…ckrat/db and @packrat/schemas Replace all import paths that went through the @packrat/api re-export shims: - @packrat/api/types/constants → @packrat/db (Pack, PackItem, User, CatalogItem, etc.) - @packrat/api/schemas/* → @packrat/schemas/* - @packrat/api/types → @packrat/schemas/constants Adds @packrat/db and @packrat/schemas as direct workspace deps in apps/expo. Migrates apps/expo features, utils, and packages/api/src/utils to source from canonical packages rather than the backward-compat shims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Introduce a clean 4-layer architecture: @packrat/constants (zero dep) raw arrays, TS unions, plain interfaces @packrat/db Drizzle tables + inferred model types @packrat/schemas Zod schemas built on constants + db @packrat/types re-exports model types from db for frontend consumption - @packrat/constants: PACK_CATEGORIES, WEIGHT_UNITS, ITEM_CATEGORIES, WeightUnit, PackCategory, ItemLink, ItemReview, etc. - @packrat/types: Pack, PackItem, User, CatalogItem, PackWithItems, Trip, etc. - @packrat/db/constants.ts becomes a re-export shim (backward compat) - @packrat/units now sources WeightUnit/WEIGHT_UNITS from @packrat/constants instead of defining its own duplicate - Consumer imports in apps/expo and packages/api updated accordingly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Remove 21 shim files that existed solely to forward imports to their
new canonical homes after the @packrat/db and @packrat/schemas extraction:
- packages/db/src/constants.ts (→ @packrat/constants)
- packages/api/src/db/schema.ts (→ @packrat/db/schema)
- packages/api/src/db/zod-schemas.ts (→ @packrat/db/zod-schemas)
- packages/api/src/schemas/{ai,auth,catalog,chat,feed,guides,
imageDetection,packTemplates,packs,seasonSuggestions,
trailConditions,trips,upload,users,weather}.ts (→ @packrat/schemas/*)
- packages/api/src/types/{validation,constants,index}.ts
All consumers updated to import directly from canonical sources:
@packrat/constants, @packrat/db, @packrat/schemas, @packrat/types.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
…subpath resolution Metro does not use the package.json exports field by default; without unstable_enablePackageExports the bundler cannot resolve subpath imports like @packrat/schemas/constants, causing the E2E APK build to fail.
…lution Metro's unstable_enablePackageExports resolves the exports map to an exact path. Without the .ts extension, ./src/constants resolves to a non-existent file and Metro warns + falls back, ultimately failing to find the module. Explicit ./src/*.ts makes Metro find the source file directly.
Bun and Metro resolve exports map paths exactly — ./src/* (extensionless) produces a path that doesn't exist, causing module resolution failures. Apply ./src/*.ts to @packrat/db, @packrat/api, @packrat/osm-db, and @packrat/overpass to match the same fix already applied to @packrat/schemas.
…/schemas - packages/schemas/src/admin.ts: full Zod conversion of all TypeBox schemas (AdminStats, AdminUser, AdminPack, AdminCatalog, ETL, analytics, trails) - packages/api/src/schemas/admin.ts: deleted (no longer a shim, no longer needed) - Admin routes now import from @packrat/schemas/admin - apps/admin/lib/api.ts: Static<typeof XSchema> → z.infer<typeof XSchema>, import path updated to @packrat/schemas/admin - TrailConditionReportSchema in admin renamed AdminTrailConditionReportSchema to avoid barrel collision with trailConditions.ts variant 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Extract shared datetimeString helper to packages/schemas/src/utils.ts
- Add inferred types to @packrat/schemas/admin so consumers import types directly
- Clean up apps/admin/lib/api.ts to re-export from schema types instead of re-inferring
- Normalize UserAvatar.tsx to single avatarUrl field; update mockData accordingly
- Use typed cast in compute-pack.test.ts instead of `as any`
- Remove unused with:{ pack/catalogItem } eager loads in trips and packs routes
- Return structured 404 with code field in user and weather routes
…rectly - Add `export type Env = ValidatedEnv` to env-validation.ts - Delete packages/api/src/types/env.ts (was a pure re-export shim) - Update all 13 consumers to import Env from @packrat/api/utils/env-validation - Remove ValidationError re-export from etl.ts; consumers import from @packrat/schemas/validation
…ve dead middleware aliases - UserAvatar prop type uses Pick<MockUser, 'name' | 'avatarUrl'> instead of local duplicate - variables.ts: userId was number, should be string (users.id is string via Better Auth) - Delete adminMiddleware.ts and apiKeyAuth.ts (re-export alias files with no importers)
… code regressions - @packrat/types now re-exports z.infer<> types from @packrat/schemas instead of raw Drizzle InferSelectModel types (wire-safe ISO strings vs Date objects) - Added type exports (Pack, PackItem, PackWithItems, Trip, User, CatalogItem) directly to their schema files - Added PackWithItemsSchema with required items array to packs.ts - Removed re-export block from schemas/constants.ts; packs.ts and catalog.ts now import WEIGHT_UNITS/PACK_CATEGORIES directly from @packrat/constants - Fixed duplicate Trip type export in trips.ts - Fixed status code regressions in packs and catalog routes: throw new Error() → return status(400/500, ...) for client/server errors - Added ApiErrorSchema to affected route response maps so Elysia types resolve - Fixed test fixture: createdAt/updatedAt now use ISO strings not Date objects
…chemas Every named Zod schema now lives in packages/schemas/src/ — route and service files only import, never define. New schema files: - packages/schemas/src/trails.ts — OsmMemberSchema, RouteBaseRowSchema, RouteSearchRowSchema, RouteDetailRowSchema - packages/schemas/src/wildlife.ts — WildlifeIdentifyRequestSchema Schema additions to existing files: - trailConditions: CreateTrailConditionReportRequestSchema, UpdateTrailConditionReportRequestSchema - admin: AnalyticsPeriodSchema - catalog: CatalogETLSchema - packs: AddPackItemBodySchema - packTemplates: AIPackAnalysisSchema, AIPackAnalysisItemSchema; replace local datetimeString with import from ./utils Route/service cleanup: - All top-level const XxxSchema = z. removed from routes/ and services/ - 10 route files and services/trails.ts updated to import from @packrat/schemas Enforcement: - packages/checks/src/check-route-schemas.ts — new script that fails if any named schema is defined at module level in routes/ or services/ (4 internal AI-parsing files allowlisted) - Wired as check:route-schemas:strict in pre-push clean-checks
Runtime-portable: same helper works in Node, Workers, browser. Useful if this ever moves out of @packrat/cli (e.g., shared with @packrat/mcp on Cloudflare Workers, which doesn't have Bun's globals). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(guides): build OG images for all 504 posts (was 39)
MCP + CLI: Eden Treaty migration, admin tools, ACL
chore(guides): harden OG image generation + add web-build CI
…cores fix: improve Lighthouse LCP scores for guides and landing apps
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| 🔵 In progress View logs |
packrat-admin | dd81e3f | May 17 2026, 07:26 AM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| 🔵 In progress View logs |
packrat-api-dev | dd81e3f | May 17 2026, 07:26 AM |
|
Important Review skippedToo many files! This PR contains 299 files, which is 149 over the limit of 150. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (299)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
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>
Coverage Report for API Unit Tests Coverage (./packages/api)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Coverage Report for Expo Unit Tests Coverage (./apps/expo)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||
Adds a follow-up to #2437 that asserts the OG / Twitter meta tags expected by social previewers actually land in the built HTML, and optionally re-checks them over the wire against a deployed URL. - New `apps/guides/__tests__/og-meta.test.ts` runs `bun run build` (if `out/` is missing) and walks every `out/guide/<slug>.html` plus `out/index.html`, parsing with cheerio. It asserts the full meta set (og:title, og:description, og:image, og:image:width, og:image:height, og:type, og:url, og:site_name, twitter:card, twitter:title, twitter:description, twitter:image) on a 3-post random sample, that every post has an absolute `https://` og:image pointing at `/og/<slug>.png`, and that the root page uses the site-wide image (not a per-post one). Sampling keeps the suite fast across 500+ posts. - Optional live pass via `open-graph-scraper` is gated on `OG_LIVE_CHECK_URL`. Same shape, fetched over the wire — useful after a deploy to catch CF transforms / cache layers that a built-HTML check can miss. - New `test:og-meta` script and wired into the `Builds` workflow after the guides build, before the artifact upload — a meta-tag regression fails the workflow check on the PR. - `cheerio` and `open-graph-scraper` added as devDependencies of `apps/guides` (test-only, not runtime deps). - README documents both passes and lists the manual debugger URLs (opengraph.xyz, microlink, FB Sharing Debugger, LinkedIn Post Inspector) for post-deploy verification. Antecedents: #2436 (build-order fix) and #2437 (OG hardening + Builds workflow). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…flow
Extends the guides OG meta validation pattern to the landing marketing
site, and wires Lighthouse CI into the Builds workflow for both apps.
Per the team mandate: every web app gets programmatic OG and Lighthouse
evaluation, surfaced in PR checks before deploy.
Landing-side OG meta:
- apps/landing/__tests__/og-meta.test.ts walks built HTML in out/
(top-level *.html + nested <slug>/index.html, skipping 404/500),
asserts the same 12-tag OG/Twitter set as guides, requires absolute
https og:image pointing at the site-wide image, and includes the
same OG_LIVE_CHECK_URL-gated open-graph-scraper block.
- Adds cheerio + open-graph-scraper as devDependencies (matching guides).
- Adds test:og-meta script.
Lighthouse CI in Builds workflow:
- Adds lighthouse:ci script (lhci autorun, no rebuild) to both apps.
- Builds workflow gains a Lighthouse CI step after OG validation in
each job, with continue-on-error so perf regressions yellow-check
rather than block, and a Step Summary block so reviewers see the
output without clicking into job logs.
- Uses existing .lighthouserc.{js,mobile.js} budgets unchanged.
Docs:
- New apps/landing/README.md documents the build pipeline + OG +
Lighthouse validation layers + manual debugger links.
- Updates apps/guides/README.md to cross-reference the shared pattern
and document the new Lighthouse CI integration.
.gitignore: adds .lighthouseci/ output dir.
packages/env/scripts/no-raw-process-env.ts auto-updated by postinstall
env script to allow OG_LIVE_CHECK_URL reads in the two new test files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Was >=24.0.0 which allowed non-LTS jumps (e.g. 26). ^24.0.0 restricts to the 24.x series — current Node LTS, supported through 2027. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nto chore/og-meta-validation
…ove continue-on-error Three real issues from the latest #2439 CI run: - 404.html and 500.html were dragging Lighthouse runs down — they inherently lack <title>/<html lang>/meta description by design. Used assertMatrix with a regex pattern to exclude them; full assertion set still runs against every other HTML. - continue-on-error: true on the Lighthouse step meant failures didn't fail CI. Removed both (guides + landing). Lighthouse is now a real gate. - LHCI reports were going to temporary-public-storage URLs only. Added actions/upload-artifact steps for apps/<name>/.lighthouseci with 14-day retention so reviewers can click through after the PR run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore(web): programmatic OG meta validation + Lighthouse CI for guides + landing
chore(engines): pin node to ^24.0.0 (current LTS)
Release roll-up
Promoting development → main (254 commits ahead). Production deploys from `main`, so this is what gets the recent foundation + OG work in front of users.
Headline items
Foundation refactors
Open Graph (fixes the prod-OG issue specifically)
Web
Smaller wins
Why now
The OG previews on `guides.packratai.com` are currently empty in production because all the OG/metadata work lives on `development`. Promoting closes the deploy gap — once Cloudflare Pages rebuilds production, OG previews appear within minutes. Re-scrape via the Facebook OG Debugger to bust caches after deploy.
Risk
This is a large release; the foundation refactors are intentionally additive (re-export shims preserve every existing import path), but the MCP/CLI migration is genuinely new behavior. Mobile + landing prod traffic is unaffected (they don't consume the MCP/CLI directly).
Recommend a CI watch + a quick smoke check of:
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com