fix: remaining 2026-07-15 audit items (GIN tag search, XFF hardening, code-blob over-fetch, CoC)#9644
Merged
Merged
Conversation
… code-blob over-fetch, CoC)
- SpecRepository.search_by_tags now uses JSONB containment (tags @> ...) on
PostgreSQL so the ix_specs_tags GIN index serves the query instead of a
cast-to-text LIKE seq scan; the SQLite test fallback escapes LIKE
metacharacters (audit Medium#17)
- MCP list_specs / search_specs_by_tags resolve code presence via a
lightweight id probe (get_ids_with_code) and /libraries/{id}/images
fetches only its own library's code (get_by_library_with_code); the
now-unused get_all_with_code() is removed (audit Medium#5, issue #7696)
- /feedback keys rate limiting and dup suppression on cf-connecting-ip or
the rightmost x-forwarded-for entry instead of the client-controlled
first entry (audit Medium#20)
- Add CODE_OF_CONDUCT.md (Contributor Covenant 2.1), linked from
docs/contributing.md (audit Medium#29)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015kWZJgpARSK68RtfeHMEsK
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kWZJgpARSK68RtfeHMEsK
The #9644 entry insertion consumed the following block's "### Fixed" header, misfiling the #9642 fixes under "### Added". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kWZJgpARSK68RtfeHMEsK
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses remaining 2026-07-15 audit items by (1) making spec tag search index-friendly and wildcard-safe, (2) removing unnecessary code-blob loading from hot listing paths, (3) hardening feedback rate-limiting IP resolution against spoofing, and (4) improving repo health documentation via a Code of Conduct.
Changes:
- Reworked
SpecRepository.search_by_tagsto use PostgreSQL JSONB containment (GIN-servable) and a SQLite fallback that escapes LIKE metacharacters. - Eliminated “load all impl code” behavior in MCP tools and
/libraries/{id}/imagesby introducing targeted queries (get_ids_with_code,get_by_library_with_code) and removingget_all_with_code(). - Updated feedback rate limiting to prefer
cf-connecting-ip, otherwise use the rightmostx-forwarded-forentry; added Code of Conduct + docs/changelog updates and unit tests for the new behaviors.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| core/database/repositories.py | Adds dialect-aware tag filters; removes get_all_with_code; adds get_by_library_with_code and get_ids_with_code to avoid over-fetching code blobs. |
| api/mcp/server.py | Switches MCP list/search to probe code presence via get_ids_with_code instead of loading code for every impl. |
| api/routers/libraries.py | Updates /libraries/{id}/images to fetch only one library’s impls with code undeferred. |
| api/routers/feedback.py | Hardens _client_ip resolution to reduce XFF spoofing impact on rate limiting / duplicate suppression. |
| tests/unit/core/database/test_repositories.py | Adds tests for tag-search SQL shape (Postgres vs SQLite) and new impl repository queries. |
| tests/unit/api/mcp/test_tools.py | Updates MCP tool tests for the new code-presence probing approach. |
| tests/unit/api/test_routers.py | Updates libraries router tests to mock ImplRepository.get_by_library_with_code behavior. |
| tests/unit/api/test_feedback_router.py | Adds unit tests for _client_ip trust-order logic. |
| docs/contributing.md | Links contribution participation to the new Code of Conduct. |
| CODE_OF_CONDUCT.md | Adds Contributor Covenant 2.1 Code of Conduct. |
| CHANGELOG.md | Adds [Unreleased] entries covering tag search, code-blob over-fetch removal, feedback hardening, and CoC addition. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…g sections
- _client_ip now takes the rightmost NON-EMPTY x-forwarded-for entry and
falls back to request.client.host, so a malformed header ("1.2.3.4, ")
can't key rate limiting on a shared empty-string bucket
- CHANGELOG [Unreleased] merged from per-PR blocks (4x Fixed, 4x Changed,
3x Added) into unique Keep-a-Changelog sections, newest entries first
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015kWZJgpARSK68RtfeHMEsK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SpecRepository.search_by_tagscast the JSONBtagscolumn to text and ran LIKE, whichix_specs_tagscan never serve (seq scan on every MCP tag search) and which let%/_in tag values wildcard-match. On PostgreSQL it now emits per-category JSONB containment (tags @> '{"<category>": ["<tag>"]}'viatype_coerce, keeping the left side a bare column so the index stays applicable); the SQLite test fallback escapes LIKE metacharacters viaautoescape(audit 2026-07-15 Medium#17).list_specs/search_specs_by_tagsand/libraries/{id}/imagesall calledget_all_with_code()(every code blob of ~3,240 impls per request). The MCP tools now resolve code presence with a lightweight id probe (ImplRepository.get_ids_with_code), the images endpoint fetches only its own library's code (get_by_library_with_code), and the now caller-lessget_all_with_code()is removed (audit Medium#5, issue perf: database access optimizations (follow-ups from #7694) #7696)./feedbackkeyed its per-IP limit and duplicate suppression on the firstx-forwarded-forentry, so a caller could evade the limit or poison a victim's bucket (5 spoofed posts = victim locked out)._client_ipnow prefers Cloudflare'scf-connecting-ipand otherwise takes the rightmost, infrastructure-appended XFF entry (audit Medium#20).CODE_OF_CONDUCT.md(Contributor Covenant 2.1) added and linked fromdocs/contributing.md— closes the last repo-health gap after fix: resolve 2026-07-15 audit findings (retry-loop fail-closed, security, SEO, dark mode) #9642 shipped the PR template and.editorconfig(audit Medium#29).Also done outside this diff (session action, user-authorized): reconciled the ~50 contradictory
impl:*labels on issue #1010 down to the 32 that match the filesystem state (8done, 7failed, watchdog history kept) so babysit-pipeline reads true state.Test plan
uv run ruff check .+ruff format --check .clean (148 files)uv run --extra typecheck mypy api corecleanuv run --extra test pytest tests/unit tests/integration— 1650 passedspecs.tags @> …(no CAST on the column), SQLite fallback matches literally with%/_in tag values,get_ids_with_codeexcludes NULL-code impls,get_by_library_with_codescopes to one library,_client_iptrust-order matrix (cf-connecting-ip > rightmost XFF > client.host)EXPLAINan MCP tag search should show a Bitmap Index Scan onix_specs_tagsChecklist
CHANGELOG.mdupdated under[Unreleased](Keep-a-Changelog categories, bold-titled bullets; PR ref to be appended)docs/contributing.mdlinks the new Code of Conduct)🤖 Generated with Claude Code
https://claude.ai/code/session_015kWZJgpARSK68RtfeHMEsK
Generated by Claude Code