sql-dialect-master 1.1.3__tar.gz → 1.1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/PKG-INFO +40 -47
  2. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/README.md +35 -45
  3. sql_dialect_master-1.1.5/backend/api/auth.py +29 -0
  4. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/main.py +205 -25
  5. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/middleware.py +92 -10
  6. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/readiness.py +44 -13
  7. sql_dialect_master-1.1.5/backend/api/workers.py +50 -0
  8. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/cache.py +15 -3
  9. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/config.py +9 -1
  10. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/exceptions.py +3 -0
  11. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/functions_lookup.py +62 -26
  12. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/metadata.py +2 -2
  13. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/core_extract.py +31 -8
  14. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/mappings.py +2 -2
  15. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/dialect.py +3 -1
  16. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/models.py +3 -0
  17. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/orchestrator.py +155 -20
  18. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/validation.py +4 -3
  19. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/p1_sql_scanner.py +54 -1
  20. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/parser.py +3 -50
  21. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/rules.py +68 -22
  22. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/semantic_diff.py +3 -2
  23. sql_dialect_master-1.1.5/backend/core/sql_statements.py +30 -0
  24. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/transpiler.py +457 -26
  25. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/type_mapping.py +8 -6
  26. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/utils/validators.py +27 -41
  27. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/pyproject.toml +6 -14
  28. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/PKG-INFO +40 -47
  29. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/SOURCES.txt +3 -34
  30. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/requires.txt +4 -1
  31. sql_dialect_master-1.1.5/sql_dialect_master.egg-info/top_level.txt +1 -0
  32. sql_dialect_master-1.1.3/backend/frontend_entrypoint.py +0 -22
  33. sql_dialect_master-1.1.3/frontend/__init__.py +0 -10
  34. sql_dialect_master-1.1.3/frontend/app_context_v2.py +0 -201
  35. sql_dialect_master-1.1.3/frontend/core/__init__.py +0 -33
  36. sql_dialect_master-1.1.3/frontend/core/design_tokens.py +0 -131
  37. sql_dialect_master-1.1.3/frontend/core/escaping.py +0 -13
  38. sql_dialect_master-1.1.3/frontend/core/fingerprints.py +0 -24
  39. sql_dialect_master-1.1.3/frontend/core/navigation.py +0 -157
  40. sql_dialect_master-1.1.3/frontend/core/sql_inputs.py +0 -29
  41. sql_dialect_master-1.1.3/frontend/core/state.py +0 -667
  42. sql_dialect_master-1.1.3/frontend/core/styles.py +0 -523
  43. sql_dialect_master-1.1.3/frontend/core/themes.py +0 -75
  44. sql_dialect_master-1.1.3/frontend/core/type_status.py +0 -26
  45. sql_dialect_master-1.1.3/frontend/core/viewmodels.py +0 -519
  46. sql_dialect_master-1.1.3/frontend/pages/__init__.py +0 -0
  47. sql_dialect_master-1.1.3/frontend/pages/convert.py +0 -372
  48. sql_dialect_master-1.1.3/frontend/pages/diff.py +0 -170
  49. sql_dialect_master-1.1.3/frontend/pages/functions.py +0 -99
  50. sql_dialect_master-1.1.3/frontend/pages/history.py +0 -147
  51. sql_dialect_master-1.1.3/frontend/pages/lineage.py +0 -185
  52. sql_dialect_master-1.1.3/frontend/pages/nl2sql.py +0 -305
  53. sql_dialect_master-1.1.3/frontend/pages/query_analysis.py +0 -128
  54. sql_dialect_master-1.1.3/frontend/pages/runtime.py +0 -66
  55. sql_dialect_master-1.1.3/frontend/pages/settings.py +0 -60
  56. sql_dialect_master-1.1.3/frontend/pages/templates.py +0 -86
  57. sql_dialect_master-1.1.3/frontend/pages/types.py +0 -106
  58. sql_dialect_master-1.1.3/frontend/templates_v2.py +0 -53
  59. sql_dialect_master-1.1.3/frontend/ui/__init__.py +0 -0
  60. sql_dialect_master-1.1.3/frontend/ui/command_palette.py +0 -172
  61. sql_dialect_master-1.1.3/frontend/ui/diff.py +0 -275
  62. sql_dialect_master-1.1.3/frontend/ui/editor.py +0 -102
  63. sql_dialect_master-1.1.3/frontend/ui/status.py +0 -255
  64. sql_dialect_master-1.1.3/sdm_local_v2.py +0 -219
  65. sql_dialect_master-1.1.3/sql_dialect_master.egg-info/entry_points.txt +0 -2
  66. sql_dialect_master-1.1.3/sql_dialect_master.egg-info/top_level.txt +0 -3
  67. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/LICENSE +0 -0
  68. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/__init__.py +0 -0
  69. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/__init__.py +0 -0
  70. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/api/rate_limit_store.py +0 -0
  71. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/__init__.py +0 -0
  72. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/column_hint_validation.py +0 -0
  73. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/constants.py +0 -0
  74. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/function_call_scanner.py +0 -0
  75. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/function_semantics.py +0 -0
  76. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/functions_db.json +0 -0
  77. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql.py +0 -0
  78. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/__init__.py +0 -0
  79. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/aggregations.py +0 -0
  80. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/boolean_conditions.py +0 -0
  81. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/evidence.py +0 -0
  82. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/relations.py +0 -0
  83. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/templates.py +0 -0
  84. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_components/tokenizer.py +0 -0
  85. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_legacy.py +0 -0
  86. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/__init__.py +0 -0
  87. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/aggregations.py +0 -0
  88. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/clause_extract.py +0 -0
  89. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/intent.py +0 -0
  90. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/ir.py +0 -0
  91. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/predicates.py +0 -0
  92. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/renderer.py +0 -0
  93. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/resolution.py +0 -0
  94. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/suggestions.py +0 -0
  95. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/nl2sql_pipeline/templates.py +0 -0
  96. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/p2_data_validation.py +0 -0
  97. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/post_processor.py +0 -0
  98. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/core/type_mapping.json +0 -0
  99. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/backend/utils/__init__.py +0 -0
  100. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/setup.cfg +0 -0
  101. {sql_dialect_master-1.1.3 → sql_dialect_master-1.1.5}/sql_dialect_master.egg-info/dependency_links.txt +0 -0
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-dialect-master
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: SQL Dialect Master - Multi-database SQL conversion engine
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
7
  License-File: LICENSE
8
8
  Requires-Dist: sqlglot<31.0.0,>=30.18.0
9
- Requires-Dist: streamlit>=1.38.0
10
9
  Requires-Dist: fastapi>=0.115.0
11
10
  Requires-Dist: uvicorn>=0.30.0
12
11
  Requires-Dist: pydantic>=2.9.0
@@ -21,6 +20,10 @@ Provides-Extra: qa
21
20
  Requires-Dist: ruff>=0.6; extra == "qa"
22
21
  Requires-Dist: bandit>=1.7; extra == "qa"
23
22
  Requires-Dist: pip-audit>=2.7; extra == "qa"
23
+ Requires-Dist: build>=1.2.2; extra == "qa"
24
+ Requires-Dist: twine>=5.1; extra == "qa"
25
+ Requires-Dist: setuptools>=75.0.0; extra == "qa"
26
+ Requires-Dist: wheel>=0.45; extra == "qa"
24
27
  Provides-Extra: semantic
25
28
  Requires-Dist: duckdb>=1.5.5; extra == "semantic"
26
29
  Requires-Dist: psycopg[binary]>=3.3.5; extra == "semantic"
@@ -32,12 +35,12 @@ Dynamic: license-file
32
35
 
33
36
  Enterprise-grade multi-database SQL conversion engine supporting 12 database dialects.
34
37
 
35
- Current release: 1.1.3
38
+ Current release: 1.1.5
36
39
 
37
40
  [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
38
41
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
42
  [![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-green.svg)](https://fastapi.tiangolo.com/)
40
- [![Streamlit](https://img.shields.io/badge/Streamlit-1.38+-red.svg)](https://streamlit.io/)
43
+ [![React](https://img.shields.io/badge/React-19-61DAFB.svg)](https://react.dev/)
41
44
 
42
45
  ## ✨ Features
43
46
 
@@ -54,7 +57,7 @@ Current release: 1.1.3
54
57
  | 🔧 **Rule Engine** | Deterministic priority ordering, compiled patterns, dialect-aware conflict detection |
55
58
  | 🛡️ **Security Validation** | Statement-level stacked-query detection with configurable blocking policy |
56
59
  | ⚡ **Performance** | Rule-aware cache versioning, bounded async batch conversion, and reproducible benchmark |
57
- | 🎨 **Modern UI** | Streamlit developer workspace: dark / light theme system, sidebar navigation, command palette |
60
+ | 🎨 **Modern UI** | React developer workspace with dark / light themes, responsive navigation, and command palette |
58
61
 
59
62
  ## 💾 Supported Databases
60
63
 
@@ -78,32 +81,38 @@ cd sql-dialect-master
78
81
  python -m pip install -e .
79
82
  ```
80
83
 
81
- For development and testing, install the optional development dependencies:
84
+ For development, testing, quality checks, and local builds, use the project's
85
+ Python environment and install the optional tooling:
82
86
 
83
87
  ```bash
84
- python -m pip install -e ".[dev]"
88
+ python -m venv .venv
89
+ .venv/bin/python -m pip install -e ".[dev,qa]"
85
90
  ```
86
91
 
87
92
  For database-backed semantic tests:
88
93
 
89
94
  ```bash
90
- python -m pip install -e ".[dev,semantic]"
95
+ .venv/bin/python -m pip install -e ".[dev,semantic]"
91
96
  ```
92
97
 
93
- ### Run Streamlit UI (Recommended)
98
+ ### Run the React UI
94
99
 
95
- ```bash
96
- streamlit run sdm_local_v2.py
97
- ```
98
-
99
- After installing the package, the same workspace can be launched from any
100
- working directory with:
100
+ The React workspace is the product frontend and runs independently from the
101
+ Python package. Start the API first, then run:
101
102
 
102
103
  ```bash
103
- sdm-streamlit
104
+ cd frontend-react
105
+ npm install
106
+ npm run dev
104
107
  ```
105
108
 
106
- Open http://localhost:8501 in your browser.
109
+ Open http://localhost:5174. The Vite development proxy forwards `/api`,
110
+ `/health`, and `/ready` to `http://127.0.0.1:8000`. Set `VITE_API_BASE_URL`
111
+ for a separately deployed API, or configure the URL and optional API key in
112
+ the React Settings page.
113
+
114
+ React implementation goals and gates are tracked in
115
+ [`docs/react-frontend-refactor-plan.md`](docs/react-frontend-refactor-plan.md).
107
116
 
108
117
  ### Run FastAPI Backend
109
118
 
@@ -113,6 +122,16 @@ uvicorn backend.api.main:app --reload
113
122
 
114
123
  API docs available at http://localhost:8000/docs
115
124
 
125
+ Set `SDM_API_KEY` in `.env` to require credentials for `/api/*` endpoints.
126
+ Clients may send `X-API-Key` or `Authorization: Bearer <key>`. Health probes
127
+ use the separate `SDM_HEALTH_PROBE_TOKEN` setting. An empty API key preserves
128
+ local access.
129
+
130
+ `SDM_API_WORKERS` (default 4) and `SDM_API_QUEUE_SIZE` (default 4) bound CPU
131
+ work. When all slots are occupied, requests receive HTTP 503 and a
132
+ `Retry-After` header. `SDM_REQUEST_TIMEOUT` returns HTTP 504 when a request
133
+ times out; running threads retain their capacity until they finish.
134
+
116
135
  ## 📖 Usage Examples
117
136
 
118
137
  ### Python SDK
@@ -254,42 +273,16 @@ sql-dialect-master/
254
273
  │ │ └── validators.py # Input validation
255
274
  │ │
256
275
  │ └── tests/ # Test suite and regression coverage
257
- ├── frontend/ # Streamlit UI Components (v2 architecture)
258
- │ ├── core/ # Cross-cutting concerns
259
- │ │ ├── design_tokens.py # Theme model (dark/light) + semantic status
260
- │ │ ├── navigation.py # NavigationIntent contract
261
- │ │ ├── state.py # SessionState adapter
262
- │ │ ├── themes.py # Theme switching (dark/light only)
263
- │ │ ├── styles.py # CSS generation from design tokens
264
- │ │ ├── escaping.py # HTML-safe rendering helpers
265
- │ │ └── viewmodels.py # Typed view models
266
- │ ├── pages/ # One module per workspace page
267
- │ │ ├── convert.py
268
- │ │ ├── nl2sql.py
269
- │ │ ├── diff.py
270
- │ │ ├── lineage.py
271
- │ │ ├── runtime.py
272
- │ │ ├── functions.py
273
- │ │ ├── types.py
274
- │ │ ├── templates.py
275
- │ │ ├── history.py
276
- │ │ ├── settings.py
277
- │ │ └── query_analysis.py
278
- │ ├── ui/ # Reusable UI widgets
279
- │ │ ├── command_palette.py
280
- │ │ ├── diff.py
281
- │ │ ├── editor.py
282
- │ │ └── status.py
283
- │ ├── app_context_v2.py # Shared application context (v2)
284
- │ └── templates_v2.py # SQL templates (v2)
285
276
  ├── examples/
286
277
  │ ├── api_client.py # API usage examples
287
278
  │ └── basic_usage.py # SDK usage examples
288
279
  ├── scripts/
289
280
  │ └── verify_readme_consistency.py # README source-of-truth checks
290
- ├── sdm_local_v2.py # Streamlit Application Entry (v2)
281
+ ├── frontend-react/ # React + TypeScript product frontend
282
+ │ ├── src/
283
+ │ ├── package.json
284
+ │ └── vite.config.ts
291
285
  ├── pyproject.toml # Project configuration
292
- ├── requirements.txt # Legacy/runtime dependency list
293
286
  ├── .env.example # Environment template
294
287
  ├── LICENSE # MIT License
295
288
  └── README.md
@@ -2,12 +2,12 @@
2
2
 
3
3
  Enterprise-grade multi-database SQL conversion engine supporting 12 database dialects.
4
4
 
5
- Current release: 1.1.3
5
+ Current release: 1.1.5
6
6
 
7
7
  [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
  [![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-green.svg)](https://fastapi.tiangolo.com/)
10
- [![Streamlit](https://img.shields.io/badge/Streamlit-1.38+-red.svg)](https://streamlit.io/)
10
+ [![React](https://img.shields.io/badge/React-19-61DAFB.svg)](https://react.dev/)
11
11
 
12
12
  ## ✨ Features
13
13
 
@@ -24,7 +24,7 @@ Current release: 1.1.3
24
24
  | 🔧 **Rule Engine** | Deterministic priority ordering, compiled patterns, dialect-aware conflict detection |
25
25
  | 🛡️ **Security Validation** | Statement-level stacked-query detection with configurable blocking policy |
26
26
  | ⚡ **Performance** | Rule-aware cache versioning, bounded async batch conversion, and reproducible benchmark |
27
- | 🎨 **Modern UI** | Streamlit developer workspace: dark / light theme system, sidebar navigation, command palette |
27
+ | 🎨 **Modern UI** | React developer workspace with dark / light themes, responsive navigation, and command palette |
28
28
 
29
29
  ## 💾 Supported Databases
30
30
 
@@ -48,32 +48,38 @@ cd sql-dialect-master
48
48
  python -m pip install -e .
49
49
  ```
50
50
 
51
- For development and testing, install the optional development dependencies:
51
+ For development, testing, quality checks, and local builds, use the project's
52
+ Python environment and install the optional tooling:
52
53
 
53
54
  ```bash
54
- python -m pip install -e ".[dev]"
55
+ python -m venv .venv
56
+ .venv/bin/python -m pip install -e ".[dev,qa]"
55
57
  ```
56
58
 
57
59
  For database-backed semantic tests:
58
60
 
59
61
  ```bash
60
- python -m pip install -e ".[dev,semantic]"
62
+ .venv/bin/python -m pip install -e ".[dev,semantic]"
61
63
  ```
62
64
 
63
- ### Run Streamlit UI (Recommended)
65
+ ### Run the React UI
64
66
 
65
- ```bash
66
- streamlit run sdm_local_v2.py
67
- ```
68
-
69
- After installing the package, the same workspace can be launched from any
70
- working directory with:
67
+ The React workspace is the product frontend and runs independently from the
68
+ Python package. Start the API first, then run:
71
69
 
72
70
  ```bash
73
- sdm-streamlit
71
+ cd frontend-react
72
+ npm install
73
+ npm run dev
74
74
  ```
75
75
 
76
- Open http://localhost:8501 in your browser.
76
+ Open http://localhost:5174. The Vite development proxy forwards `/api`,
77
+ `/health`, and `/ready` to `http://127.0.0.1:8000`. Set `VITE_API_BASE_URL`
78
+ for a separately deployed API, or configure the URL and optional API key in
79
+ the React Settings page.
80
+
81
+ React implementation goals and gates are tracked in
82
+ [`docs/react-frontend-refactor-plan.md`](docs/react-frontend-refactor-plan.md).
77
83
 
78
84
  ### Run FastAPI Backend
79
85
 
@@ -83,6 +89,16 @@ uvicorn backend.api.main:app --reload
83
89
 
84
90
  API docs available at http://localhost:8000/docs
85
91
 
92
+ Set `SDM_API_KEY` in `.env` to require credentials for `/api/*` endpoints.
93
+ Clients may send `X-API-Key` or `Authorization: Bearer <key>`. Health probes
94
+ use the separate `SDM_HEALTH_PROBE_TOKEN` setting. An empty API key preserves
95
+ local access.
96
+
97
+ `SDM_API_WORKERS` (default 4) and `SDM_API_QUEUE_SIZE` (default 4) bound CPU
98
+ work. When all slots are occupied, requests receive HTTP 503 and a
99
+ `Retry-After` header. `SDM_REQUEST_TIMEOUT` returns HTTP 504 when a request
100
+ times out; running threads retain their capacity until they finish.
101
+
86
102
  ## 📖 Usage Examples
87
103
 
88
104
  ### Python SDK
@@ -224,42 +240,16 @@ sql-dialect-master/
224
240
  │ │ └── validators.py # Input validation
225
241
  │ │
226
242
  │ └── tests/ # Test suite and regression coverage
227
- ├── frontend/ # Streamlit UI Components (v2 architecture)
228
- │ ├── core/ # Cross-cutting concerns
229
- │ │ ├── design_tokens.py # Theme model (dark/light) + semantic status
230
- │ │ ├── navigation.py # NavigationIntent contract
231
- │ │ ├── state.py # SessionState adapter
232
- │ │ ├── themes.py # Theme switching (dark/light only)
233
- │ │ ├── styles.py # CSS generation from design tokens
234
- │ │ ├── escaping.py # HTML-safe rendering helpers
235
- │ │ └── viewmodels.py # Typed view models
236
- │ ├── pages/ # One module per workspace page
237
- │ │ ├── convert.py
238
- │ │ ├── nl2sql.py
239
- │ │ ├── diff.py
240
- │ │ ├── lineage.py
241
- │ │ ├── runtime.py
242
- │ │ ├── functions.py
243
- │ │ ├── types.py
244
- │ │ ├── templates.py
245
- │ │ ├── history.py
246
- │ │ ├── settings.py
247
- │ │ └── query_analysis.py
248
- │ ├── ui/ # Reusable UI widgets
249
- │ │ ├── command_palette.py
250
- │ │ ├── diff.py
251
- │ │ ├── editor.py
252
- │ │ └── status.py
253
- │ ├── app_context_v2.py # Shared application context (v2)
254
- │ └── templates_v2.py # SQL templates (v2)
255
243
  ├── examples/
256
244
  │ ├── api_client.py # API usage examples
257
245
  │ └── basic_usage.py # SDK usage examples
258
246
  ├── scripts/
259
247
  │ └── verify_readme_consistency.py # README source-of-truth checks
260
- ├── sdm_local_v2.py # Streamlit Application Entry (v2)
248
+ ├── frontend-react/ # React + TypeScript product frontend
249
+ │ ├── src/
250
+ │ ├── package.json
251
+ │ └── vite.config.ts
261
252
  ├── pyproject.toml # Project configuration
262
- ├── requirements.txt # Legacy/runtime dependency list
263
253
  ├── .env.example # Environment template
264
254
  ├── LICENSE # MIT License
265
255
  └── README.md
@@ -0,0 +1,29 @@
1
+ """Optional shared API-key protection for business endpoints."""
2
+ from __future__ import annotations
3
+
4
+ import secrets
5
+
6
+ from fastapi import HTTPException, Request
7
+
8
+ from backend.core.config import settings
9
+
10
+
11
+ async def require_api_access(request: Request) -> None:
12
+ """Require a configured key for /api endpoints while keeping probes separate."""
13
+ key = settings.api_key
14
+ if key is None or not request.url.path.startswith("/api/"):
15
+ return
16
+ expected = key.get_secret_value()
17
+ if not expected:
18
+ return
19
+ supplied = request.headers.get("X-API-Key", "")
20
+ if not supplied:
21
+ scheme, _, credential = request.headers.get("Authorization", "").partition(" ")
22
+ if scheme.lower() == "bearer":
23
+ supplied = credential
24
+ if not supplied or not secrets.compare_digest(supplied.encode("utf-8"), expected.encode("utf-8")):
25
+ raise HTTPException(
26
+ status_code=401,
27
+ detail="Invalid or missing API key",
28
+ headers={"WWW-Authenticate": "Bearer"},
29
+ )