From 834d47b93132c2abfded01240ec7fe31ee97be87 Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Wed, 6 May 2026 14:40:30 -0400 Subject: [PATCH 1/2] chore: prep repo for public release - Add LICENSE file (MIT, matching pyproject.toml license = "MIT") - Add SECURITY.md with private disclosure address (applied.ai@redis.com) - Add CONTRIBUTING.md covering bug reports, dev setup, and the auto:* label flow - Move PARAMETER_SUBSTITUTION.md design doc to docs/parameter-substitution.md - Delete PR_NOTES.md (working notes for a fix that already shipped) - Fix project URLs in pyproject.toml: redis/sql-redis -> redis-developer/sql-redis - Sync uv.lock self-version 0.4.0 -> 0.5.0 (was stale from before the release) Co-Authored-By: Claude Sonnet 4.6 --- CONTRIBUTING.md | 58 ++++++++ LICENSE | 21 +++ PR_NOTES.md | 124 ------------------ SECURITY.md | 25 ++++ .../parameter-substitution.md | 0 pyproject.toml | 4 +- uv.lock | 4 +- 7 files changed, 108 insertions(+), 128 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE delete mode 100644 PR_NOTES.md create mode 100644 SECURITY.md rename PARAMETER_SUBSTITUTION.md => docs/parameter-substitution.md (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..63a1c59 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,58 @@ +# Contributing to sql-redis + +Thanks for your interest in contributing! `sql-redis` is an early-stage, +proof-of-concept SQL-to-Redis translator and we welcome bug reports, feature +ideas, and pull requests from the community. + +## Reporting bugs and requesting features + +- Open a [GitHub issue](https://github.com/redis-developer/sql-redis/issues) + describing the problem or idea. +- For bug reports, include: + - The SQL input that misbehaved. + - The translated Redis command (`SQLQuery.redis_query_string()` output) or + the actual results, plus what you expected. + - The `sql-redis` and `redis` versions you're running. +- For security-sensitive reports, follow [SECURITY.md](./SECURITY.md) instead + of opening a public issue. + +## Development setup + +`sql-redis` uses [uv](https://docs.astral.sh/uv/) for dependency management +and [hatchling](https://hatch.pypa.io/latest/) as the build backend. + +```bash +# Clone and install +git clone https://github.com/redis-developer/sql-redis.git +cd sql-redis +uv sync + +# Common tasks (see the Makefile for the full list) +make format # black + isort +make lint # format + mypy +make test # pytest +make test-cov # pytest with coverage +make build # wheel + sdist +``` + +Tests use [`testcontainers`](https://testcontainers.com/) to spin up an +ephemeral Redis instance, so a local Docker daemon is required to run the +full suite. + +## Pull requests + +1. Fork and create a branch off `main`. +2. Make your change, including tests for any new behavior. +3. Run `make lint test` and confirm everything passes. +4. Open a pull request against `main`. Apply one of the + [`auto:` labels](./.autorc) to indicate the intended version bump + (`auto:major`, `auto:minor`, `auto:patch`, or `auto:skip-release`). + Maintainers add `auto:release` when the change is ready to ship; the + release workflow handles the version bump, tag, GitHub release, and + PyPI publish automatically. + +## Code style + +- Black and isort are enforced via `make format` and pre-commit hooks. +- Type hints required on new public APIs; `mypy` runs in CI. +- Keep new modules focused and add tests in the corresponding `tests/test_*.py`. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4734146 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025-2026 Redis, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PR_NOTES.md b/PR_NOTES.md deleted file mode 100644 index 17fdf12..0000000 --- a/PR_NOTES.md +++ /dev/null @@ -1,124 +0,0 @@ -# Fix: Token-Based Parameter Substitution - -## Summary - -Replaces naive `str.replace()` parameter substitution with token-based regex approach to fix two critical bugs discovered through TDD investigation. - -## Bugs Fixed - -### 1. Quote Escaping Bug (CRITICAL) - -Single quotes in parameters weren't escaped, breaking SQL parsing: - -```python -# Before: "WHERE name = 'O'Brien'" ❌ Breaks parsing -# After: "WHERE name = 'O''Brien'" ✅ Properly escaped -``` - -### 2. Partial Matching Bug - -`:id` incorrectly matched inside `:product_id`: - -```python -# Before: str.replace(':id', '123') → "product_123" ❌ -# After: Token-based approach → "product_id = 456" ✅ -``` - -## Solution - -Token-based approach using regex `(:[a-zA-Z_][a-zA-Z0-9_]*)`: - -``` -SQL Input: "WHERE id = :id AND product_id = :product_id" - │ │ - ▼ ▼ -Tokenize: ["WHERE id = ", ":id", " AND product_id = ", ":product_id", ""] - │ │ - ▼ ▼ -Substitute: "1" "100" - │ │ - ▼ ▼ -Result: "WHERE id = 1 AND product_id = 100" -``` - -- Splits SQL on parameter patterns -- Treats each `:identifier` as complete token -- Prevents partial matching -- Properly escapes quotes using SQL standard (`'` → `''`) - -## Why Token-Based? - -| Aspect | Token-based | sqlglot | str.replace() | -|--------|-------------|---------|---------------| -| Lines of code | ~30 | ~60 | ~3 | -| Dependencies | stdlib `re` | `sqlglot` | None | -| Performance | Fast | Slow | Fast | -| Fixes both bugs | ✅ | ✅ | ❌ | - -**Decision**: Best balance of simplicity, correctness, and performance. - -## Changes - -### Modified -- `sql_redis/executor.py` - Replaced implementation with token-based approach, added comprehensive docs - -### Added -- `tests/test_parameter_substitution.py` - 12 TDD tests validating bug fixes -- `PARAMETER_SUBSTITUTION.md` - Design document for maintainers - -### Removed -- `tests/test_edge_cases_param_substitution.py` - Edge case tests revealing translator bugs (not param substitution bugs) - -## Test Results - -``` -✅ 12/12 parameter substitution tests PASS -✅ 235/235 total tests PASS (100% pass rate) -✅ No regressions -``` - -## Quality Checks - -``` -✅ make format - black & isort -✅ make check-types - mypy clean -✅ make test - all passing -``` - -## Implementation Details - -**Regex Pattern**: `(:[a-zA-Z_][a-zA-Z0-9_]*)` -- Ensures `:id` and `:product_id` are separate tokens -- Only matches valid identifiers - -**Quote Escaping**: SQL standard (`'` → `''`) -```python -escaped = value.replace("'", "''") -result.append(f"'{escaped}'") -``` - -**Type Handling**: -- `int/float` → string -- `str` → quoted with escaping -- `bytes` → placeholder kept (for vectors) - -## Known Limitations - -**Colons in string literals**: Theoretical issue with SQL like `WHERE x = 'test:value'` - -**Why it doesn't matter**: -- Users pass values via params, not hardcoded SQL -- No real-world use cases found -- All TDD tests pass - -## Migration - -- ✅ No breaking changes -- ✅ Method signature unchanged -- ✅ Positive performance impact -- ✅ Removed `sqlglot` dependency for param substitution - ---- - -**Ready to merge** ✅ - diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..5ce7d2b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,25 @@ +# Security Policy + +## Reporting a Vulnerability + +If you believe you have discovered a security vulnerability in `sql-redis`, +please **do not open a public GitHub issue or pull request**. + +Instead, report it privately to the Redis applied AI team at +**applied.ai@redis.com**. + +Please include: + +- A description of the issue and the potential impact. +- Steps to reproduce the vulnerability (proof of concept, sample SQL, etc.). +- The version of `sql-redis` and Redis you are using. +- Any suggested mitigations, if you have them. + +We will acknowledge receipt within five business days and work with you on a +disclosure timeline. + +## Supported Versions + +Security fixes are applied to the latest minor release on PyPI. Older minor +releases are not patched; please upgrade to the latest version to receive +fixes. diff --git a/PARAMETER_SUBSTITUTION.md b/docs/parameter-substitution.md similarity index 100% rename from PARAMETER_SUBSTITUTION.md rename to docs/parameter-substitution.md diff --git a/pyproject.toml b/pyproject.toml index d31c483..2848d10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,8 +27,8 @@ dependencies = [ ] [project.urls] -Homepage = "https://github.com/redis/sql-redis" -Repository = "https://github.com/redis/sql-redis" +Homepage = "https://github.com/redis-developer/sql-redis" +Repository = "https://github.com/redis-developer/sql-redis" [build-system] requires = ["hatchling"] diff --git a/uv.lock b/uv.lock index 3623534..3036905 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.9, <3.14" resolution-markers = [ "python_full_version >= '3.10'", @@ -1014,7 +1014,7 @@ wheels = [ [[package]] name = "sql-redis" -version = "0.4.0" +version = "0.5.0" source = { editable = "." } dependencies = [ { name = "redis", version = "7.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, From e0a0bc692c3b05ca42805ba2e5b597ef348a131e Mon Sep 17 00:00:00 2001 From: Robert Shelton Date: Wed, 6 May 2026 14:41:22 -0400 Subject: [PATCH 2/2] fix: drop dead applied.ai@redis.com address; route security to GitHub PVR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The applied.ai@redis.com mailbox doesn't exist, so: - SECURITY.md now directs vulnerability reports to GitHub's Private Vulnerability Reporting (Security tab → "Report a vulnerability"), which routes privately to maintainers, and points non-security reports to public GitHub issues. - Removed the email from pyproject.toml authors metadata; kept the Redis Inc. name. Otherwise the dead address ships in PyPI metadata for every release. Co-Authored-By: Claude Sonnet 4.6 --- SECURITY.md | 24 ++++++++++++++---------- pyproject.toml | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 5ce7d2b..bf1c1ab 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,20 +3,24 @@ ## Reporting a Vulnerability If you believe you have discovered a security vulnerability in `sql-redis`, -please **do not open a public GitHub issue or pull request**. +please report it **privately** through GitHub's private vulnerability +reporting: -Instead, report it privately to the Redis applied AI team at -**applied.ai@redis.com**. +1. Go to the [Security tab](https://github.com/redis-developer/sql-redis/security) + of the repository. +2. Click **Report a vulnerability**. +3. Fill in the form with a description of the issue, reproduction steps, + affected versions, and any suggested mitigations. -Please include: +This sends the report directly to maintainers without making it public, and +gives us a place to coordinate the fix and disclosure timeline with you. -- A description of the issue and the potential impact. -- Steps to reproduce the vulnerability (proof of concept, sample SQL, etc.). -- The version of `sql-redis` and Redis you are using. -- Any suggested mitigations, if you have them. +**Please do not open a public GitHub issue or pull request** for security +reports — that would disclose the vulnerability before a fix is available. -We will acknowledge receipt within five business days and work with you on a -disclosure timeline. +For non-security bugs and feature requests, regular +[GitHub issues](https://github.com/redis-developer/sql-redis/issues) are the +right place. ## Supported Versions diff --git a/pyproject.toml b/pyproject.toml index 2848d10..c8e51c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "sql-redis" # NOTE: The version below is automatically incremented by the release workflow - do not manually adjust it. version = "0.5.0" description = "SQL to Redis command translation utility" -authors = [{ name = "Redis Inc.", email = "applied.ai@redis.com" }] +authors = [{ name = "Redis Inc." }] requires-python = ">=3.9,<3.14" readme = "README.md" license = "MIT"