You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
Changed
manage_receipts: tool description now explicitly directs Claude.ai (mobile/web) clients to never pass fileContent, explains why no client-side upload workaround exists (raw file bytes are unreachable; a signed-URL upload path was tried and removed because Claude.ai's sandboxed runtime blocks outbound HTTP requests — see PR #28), and clarifies that hasFile:false from a structured-only attach is the correct, complete outcome, not a fallback. docs/TOOLS.md regenerated (also picked up pre-existing drift from PR #30's add_transaction/import_transactions describe clarifications, which had never been regenerated).
Fixed
test/setup.ts: integration tests no longer run against whatever BOOKIE_DB_URL happens to point at. They now require BOOKIE_TEST_DB_URL (a separate Neon branch) and refuse to start if it is unset or resolves to the same host+database as BOOKIE_DB_URL. Cleanup only runs in afterAll, so an interrupted run against a real ledger left rows behind — and the comments in test/setup.ts, test/oauth.test.ts, test/receipts.test.ts and test/reconcile.test.ts all claimed the suite ran against a dev branch when it followed .env. The same-database guard normalizes Neon's pooled/direct hostname pair, which address one database — comparing raw hosts would have let the live ledger through as a "test" target (caught by Copilot review on PR #54). test/db-target.test.ts asserts the substitution actually took effect and covers the comparison directly, so a refactor that drops either fails loudly instead of silently writing to the live ledger. .env.example and CONTRIBUTING.md document the new variable.
src/lib/oauth.ts: removed the 60-second setInterval that purged expired oauth_tokens rows. Querying the database every minute meant the serverless compute never accumulated the 5 idle minutes it needs to scale to zero, so it ran continuously and consumed roughly 94% of the monthly compute allowance while completely idle. Expired refresh tokens are now purged opportunistically when a new one is issued (the only event that adds rows), and expired in-memory auth codes are swept in issueAuthCode instead of on a clock. The purge is awaited but error-swallowed so housekeeping can never fail an auth exchange. rotateRefreshToken now delegates token creation to issueRefreshToken rather than duplicating it inline.
src/transports/http.ts: /.well-known/oauth-authorization-server advertised token_endpoint_auth_methods_supported: ["none"] while /token rejects any exchange without a matching client_secret — a spec-compliant client that trusted the metadata would send no credentials and fail with invalid_client. Now correctly advertises ["client_secret_post"] (RFC 6749 §2.3.1). The contradiction was latent because the deployed secret sat under a pre-0.6.3 variable name (OAUTH_AUTH_SECRET), so the enforcement branch never executed.
manage_receipts: gracefully degrade (save structured data, return hasFile:false + a fileWarning) instead of hard-failing when fileContent is provided but Railway Bucket isn't configured — matches the mobile client flow (Claude.ai vision-extracts fields, can't base64-encode raw file bytes).
server.json: version drift — the /release skill's own version bump (0.8.4 → 0.8.5) never propagated to server.json's version/package-entry version, caught by test/server-json.test.ts failing on main immediately after the v0.8.5 release merged.