* feat(deploy): support Vercel Hobby alongside Docker
* fix(deploy): include PDFKit runtime font assets
* docs(deploy): document Vercel and Docker setup
* docs(deploy): record storage persistence checks
* refactor(deploy): drop scheduled staging cleanup
Staging uploads are deleted after finalization and expired ones are swept
on each new upload, so the Vercel cron job, its route, and CRON_SECRET are
no longer needed. The Deploy with Vercel wizard now asks for two secrets.
* docs(deploy): restructure Vercel guides
Split the Vercel page into a how-to with its environment reference, move the
large RPC staging protocol to an API reference page, and move CI deployment
checks to the contributing section. Point Deploy with Vercel buttons at main.
* chore: remove agent planning records and fix web app description
Delete superpowers plans/specs, ADRs, issue plans, execution briefs, domain
context maps, and Europass research. Describe apps/web as a TanStack Router
SPA served by apps/server.
* refactor(deploy): simplify Vercel support code
- Share one Redis client and key namespace through @reactive-resume/db/redis
for API and auth instead of a second auth-only client.
- Drop the auth seeding retry; the provider already treats concurrent inserts
as no-ops and deployment preparation seeds before runtime.
- Detect staging support from POST /api/storage/stage (404 on Docker) instead
of a separate GET probe.
- Read staged bodies directly; the signed upload already caps their size.
- Close per-subscription Redis connections with disconnect() alone.
- Check Blob health with one list call instead of write/read/delete.
- Remove redundant tsdown onlyBundle list, dead namespace fallbacks, and the
conditional spread in the health status.
* fix(deploy): heal stopped runs with dead owners and keep auth up without Redis
- Run owners refresh a Redis heartbeat until they release their claim. Stop
requests reap the run immediately when the owner has stopped heartbeating,
instead of leaving the thread blocked until the 15-minute TTL reaper.
- Auth and oRPC rate limiters fall back to per-instance memory limits when
Redis errors, instead of rejecting every login or failing requests.
* ci: allow esbuild build for Vercel CLI and register deployment deps with knip
pnpm 12 fails dlx installs with ignored build scripts, so allow esbuild
explicitly. The server bundle keeps @vercel/blob, ioredis, and jose external,
and api/index.mjs is the Vercel Function entry.
* fix(web): send buffered RPC bodies instead of teed streams
Reading a request clone turned the original body into a stream, which
browsers send without inspectable request data and which needs duplex
mode. Send the already buffered Blob for direct requests.
* fix(web): send direct RPC bodies as bytes
Blob request bodies are sent as data pipes, so browser tooling cannot
inspect them. Buffer the original request as an ArrayBuffer and send those
bytes; this restores the e2e save assertions that match on request data.
The Lapras section marginTop added in c0c658c0 shifted every date marker in
that template down the page, but the date-layout characterization baseline
was not regenerated, so packages/pdf has been failing on main since. The
delta is geometry-only: same page count (2), same text item count (87), same
markers, x and width unchanged; 17 markers move on y and the raster hashes
follow.
Nothing caught it because the workflow ran test:ci for only server and
tooling, leaving 17 packages uncovered. Replace that filter list with the
full workspace run so a package cannot silently lose coverage again, and
move it after the migration and storage steps that the api suite needs.
Serial execution is deliberate. Running the packages in parallel oversubscribes
the runner and starves the PDF rasterization and API rate-limit suites past
their timeouts; 19/19 pass consistently at --concurrency=1.
Remove the Semantic CSS acceptance suite (six specs, fifteen visual
baselines, and its fixtures) along with the --grep-invert that excluded it
from CI. With the serial PDF preflight gone, Playwright can run four
workers in CI instead of one.
Also drop the slowest and most redundant specs: PDF raster direction,
thumbnail resolution, import reproduction, imported tables, picture
rendering, and literal whitespace, plus the basic authored-page guidance,
settings profile, and resume lifecycle checks already covered elsewhere.
Trim the OAuth consent matrix to allow and deny on an existing session.
Rewrites the landing page, in-app microcopy, and public docs, then fixes what the rewrite exposed: stale template counts, a broken quickstart anchor, out-of-sync FAQ structured data, dead error-hint branches in the MCP tools, and wrong-sense translations across all 53 locales. Adds GLOSSARY.md so translators get the right sense of the ambiguous UI terms.
Upgrades to Better Auth 1.7, expands Custom Styles coverage of item headers, and adds a human-approval step to the AI agent's resume edits.
Breaking for self-hosters using a custom OAuth provider: the callback path changes from /api/auth/oauth2/callback/custom to /api/auth/callback/custom, and installs using OAUTH_DISCOVERY_URL need one additional UPDATE after upgrading. Both are documented in docs/self-hosting/sso.mdx.
- Better Auth 1.7, with the account issuer migration and the jwks alg/crv columns the 1.7 jwt plugin requires
- Agent edits gated behind an approval step, with crash-safe runs and context pruning
- item-header now covers every section header row on every template; adds the item-header-row part
- Fixes provider unlinking, auth error messages, and version conflicts on freshly created resumes
- New /auth/error page, translated across all 53 target locales
- DeepSeek Harness plugin moved into packages/dsh-plugin
- Dependency bumps across the workspace
context.issue spreads to { owner, repo, number }, but Octokit v9 requires
issue_number. The request hit /repos/.../issues//labels and returned 404,
so no opened issue was ever labeled.
* feat(mcp): add OAuth 2.1 authentication for claude.ai MCP connector
Enable OAuth 2.1 (RFC 8414 + RFC 7591) for the MCP endpoint using
better-auth's MCP plugin. This allows claude.ai and other MCP clients
to authenticate via Dynamic Client Registration and Authorization Code
flow with PKCE, using the existing login page.
- Add `mcp()` plugin to better-auth config with login page redirect
- Add `.well-known/oauth-authorization-server` discovery endpoint
- Add `.well-known/oauth-protected-resource` metadata endpoint
- Update MCP handler to accept Bearer tokens via `getMcpSession`
- Retain `x-api-key` fallback for backward compatibility
- Return proper HTTP 401 + WWW-Authenticate header for unauthed requests
- Add `oauthApplication`, `oauthAccessToken`, `oauthConsent` tables
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): use typed AuthError and suppress noisy verifyApiKey throws
- Replace string-matching error detection with instanceof AuthError
- Wrap verifyApiKey in try-catch to avoid logging malformed key errors
- Move console.error below auth check so 401s don't pollute logs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(mcp): add database migration for OAuth tables
Creates oauth_application, oauth_access_token, and oauth_consent tables
required for MCP OAuth 2.1 Dynamic Client Registration flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): resolve OAuth Bearer token auth for oRPC tool calls
The oRPC context only checked session cookies and API keys, causing
MCP tool calls from OAuth clients (claude.ai) to fail with Unauthorized
even though the MCP endpoint itself authenticated successfully.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): look up user by userId from OAuth access token
getMcpSession returns OAuthAccessToken (with userId), not a session
object with a user property. Must query the user table by userId.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(mcp): migrate from deprecated mcp() plugin to @better-auth/oauth-provider
The better-auth MCP plugin is marked for deprecation in favor of the
OAuth Provider plugin. This refactors the entire OAuth 2.1 flow to use
@better-auth/oauth-provider with JWT-based token verification, replacing
the opaque token lookup via getMcpSession().
Key changes:
- Replace mcp() with jwt() + oauthProvider() in auth config
- Replace getMcpSession() with verifyAccessToken() (JWT/JWKS)
- Replace oauthApplication table with oauthClient (RFC 7591 compliant)
- Add oauthRefreshToken table and jwks table for JWT signing keys
- Extract shared authBaseUrl and verifyOAuthToken helper
- Hoist McpServer to module scope (avoid per-request reconstruction)
- Update .well-known discovery endpoints for OAuth Provider
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): resolve OAuth 2.1 flow for claude.ai MCP connector
Multiple fixes required to make the full MCP OAuth flow work with
claude.ai's implementation:
- Add RFC 8414 discovery route at /.well-known/oauth-authorization-server/api/auth
(claude.ai appends the issuer path per spec)
- Add /auth/oauth server route to handle login/consent flow
(generates auth codes directly, bypassing h3 cookie issues)
- Default token_endpoint_auth_method to "none" via onRequest plugin hook
(claude.ai omits this field, causing confidential client rejection)
- Strip prompt=consent from authorize requests via onRequest hook
(better-auth checks prompt before skipConsent, causing redirect loops)
- Add validAudiences for MCP resource URL
(JWT aud claim contains the MCP URL, not the base URL)
- Disable CSRF check for cross-origin OAuth flows
- Log token endpoint errors for debugging
- Set skipConsent on OAuth clients via /auth/oauth route
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(mcp): harden OAuth security and enforce lock on delete
- Scope CSRF bypass to OAuth2 paths only instead of disabling globally
- Validate redirect_uri against registered client URIs (prevents code interception)
- Use pathname matching instead of fragile url.includes() for route guards
- Replace biased modulo code generation with crypto.randomBytes
- Enforce resume lock check on delete (previously silently ignored)
- Remove debug console.error logging of OAuth token response bodies
- Use Response.json() consistently for MCP 401 response
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update dependencies, refine ignore patterns, and enhance documentation
- Updated various dependencies in package.json and pnpm-lock.yaml for improved stability and features.
- Adjusted ignore patterns in knip.json to include specific component directories.
- Enhanced documentation for the MCP server, clarifying authentication methods and configuration options.
- Made minor adjustments to VSCode settings for better code organization.
* fix(mcp): resolve OAuth client registration and stale token handling
Claude.ai sends token_endpoint_auth_method: "client_secret_post" without
a client_secret during Dynamic Client Registration, causing Better Auth to
reject it as an unauthenticated confidential client. Force to "none" for
unauthenticated registrations.
Also catch JWKS verification errors (e.g. key rotation after redeployment)
so stale Bearer tokens return 401 instead of 200 with an error body,
allowing clients to re-initiate the OAuth flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* reiterate on tests
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
* feat: add job listings feature with JSearch API integration, resume tailoring, and per-user rate limiting
* feat(jobs): add search filters UI, filter helper functions with tests, and job_search_quota DB migration
* feat(jobs): add pagination with 30 results per page and prev/next navigation
* refactor(job-detail): Adjust sheet width and scroll area height
* feat(ai): Add resume tailoring feature and prompt
* refactor(ai): Revise tailoring prompts and schema for full skill rewrite
* feat(ai): Add reference tailoring and output sanitization
* feat(testing): Add Vitest testing framework
* fix: address PR review - atomic rate limiting, calendar-month quota, skill sync warning, gitignore routeTree.gen.ts
* feat(jobs): Add location filter to job listings
* feat(job-listings): Add DOCX document generation
* feat(job-listings): Enable search by location and on Enter key
* feat(job-listings): Split location filter into city, state, and country
* feat(jobs): Implement job search adapter and JSearch
* Update 'locale/' directory
* feat(resume): Simplify filename generation and add tests
* fix(JSearch): reduce JSearch API usage to 1 request per search to prevent quota exhaustion
* fix(JSearch): Displayed quota amounts on Job Search functionality and settings fixed to pull from RapidAPI/JSearch response
* fix(internal rate limit): Removed internal rate limit and .env.example addition, cloud based implementation handles.
* style(job-filters): Adjust layout of switch filters
* fix(typecheck): Fixed typecheck issues introduced to sync with origin
* feat(jobs): Enhance tailor dialog with apply link and tags
* feat(locale files): updated locale files with the latest build
* feat(jobs): Add job search provider and integrate testing functionality
- Introduced `createJobSearchProvider` function to instantiate a JSearchProvider.
- Enhanced job search provider with methods for searching jobs, retrieving job details, and testing connection.
- Updated `vite.config.ts` to include new testing configurations and plugins.
- Added new dependencies in `package.json` for testing and document generation.
- Removed obsolete `vitest.config.ts` file.
- Improved job search provider tests for better coverage and reliability.
* refactor: Update job search routes and remove obsolete test configurations
- Removed the test configuration from `vite.config.ts`.
- Updated localization files to reflect changes in job search routes, renaming references from `jobs` to `job-search` across multiple languages.
- Adjusted autofix workflow to run formatting without the `--fix` flag for better control over code style adjustments.
* chore: Update dependencies and improve animation performance
- Added `jsdom` as a new dependency in `package.json`.
- Updated `vite-plus` and `vitest` to the latest versions for better compatibility.
- Enhanced animation components with `willChange` styles to optimize rendering performance.
- Adjusted various UI components to improve responsiveness and visual effects.
- Removed obsolete job details functionality from the job search provider and related tests.
* chore(locales): Update localization files for job search improvements
- Modified job search related strings to remove references to "this month" for a more concise format.
- Updated file references in localization entries to reflect changes in the job search component structure.
- Added new strings for API usage, quota remaining, and job fetching error messages across multiple languages.
- Removed obsolete "Monthly Usage" string from localization files.
* chore(dependencies): Update @typescript/native-preview to version 7.0.0-dev.20260319.1
---------
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
* Migrate from Biome to Oxlint/Oxfmt
* pin version of autofix
* set version of autofix
* pin version of autofix
* [autofix.ci] apply automated fixes
* better comments, test formatter
* [autofix.ci] apply automated fixes
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>