sandal-db 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +318 -0
- package/dist/cli.js +2458 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SANDAL contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# SANDAL: Safe Agentic Natural-language Database Access Layer
|
|
2
|
+
|
|
3
|
+
SANDAL is an agentic command-line interface that enables software engineers, data analysts, and site reliability engineers to query, inspect, and manage databases using natural language. Powered by LangGraph and multi-provider language models, SANDAL translates natural language prompts into parameterized database queries, displays execution previews and impact estimations, and enforces multi-layered guardrails before executing any mutating statements.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- Direct Database Connectivity: Native support for PostgreSQL and MongoDB with automatic connection string parsing and schema introspection.
|
|
10
|
+
- Multi-Provider LLM Integration: Seamless switching between Google Gemini, OpenAI, and Anthropic Claude models.
|
|
11
|
+
- Multi-Stage LangGraph Pipeline: Deterministic orchestration spanning schema introspection, query generation, static safety classification, dry-run row estimation, and post-execution statistical analysis.
|
|
12
|
+
- Multi-Tier Guardrails: Automatic refusal of non-database requests, dry-run affected row count previews, explicit confirmations for destructive mutations, and hard blocking against unauthorized table or database wipes.
|
|
13
|
+
- Local Credential Security: Secure local storage in user home directory with restricted permissions, runtime credential masking, and zero telemetry.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- Node.js 18.0.0 or higher
|
|
20
|
+
- Network access to a running database instance:
|
|
21
|
+
- PostgreSQL 12 or newer
|
|
22
|
+
- MongoDB 5.0 or newer
|
|
23
|
+
- An API key from at least one supported provider:
|
|
24
|
+
- Google AI Studio (Gemini)
|
|
25
|
+
- OpenAI
|
|
26
|
+
- Anthropic
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Getting Started
|
|
31
|
+
|
|
32
|
+
### Running Without Installation (Recommended)
|
|
33
|
+
|
|
34
|
+
Run the latest version directly using `npx`:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx sandal-db@latest
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Pass a database connection URL directly as an argument:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx sandal-db@latest postgresql://postgres:secret@localhost:5432/analytics_db
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Global Installation
|
|
47
|
+
|
|
48
|
+
To install SANDAL globally on your system:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install -g sandal-db
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Once installed, invoke the CLI using `sandal-db`:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
sandal-db
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Configuration and Authentication
|
|
63
|
+
|
|
64
|
+
SANDAL resolves database connection strings and LLM API credentials through a four-tier precedence hierarchy:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
1. Command-Line Arguments (--key, --provider, [dbUrl])
|
|
68
|
+
└── 2. Environment Variables (DATABASE_URL, GEMINI_API_KEY, ...)
|
|
69
|
+
└── 3. Stored Configuration (~/.sandal/config.json)
|
|
70
|
+
└── 4. Interactive Terminal Prompts
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Method 1: Interactive Prompts
|
|
74
|
+
|
|
75
|
+
If you start SANDAL without flags or environment variables, the CLI interactively guides you through entering your connection string and API key. You will be prompted with the option to securely save these values to `~/.sandal/config.json` for subsequent runs.
|
|
76
|
+
|
|
77
|
+
### Method 2: Environment Variables
|
|
78
|
+
|
|
79
|
+
Set environment variables in your shell profile (`~/.bashrc`, `~/.zshrc`) or local `.env` file:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Database connection string (PostgreSQL or MongoDB)
|
|
83
|
+
export DATABASE_URL="postgresql://user:password@localhost:5432/my_database"
|
|
84
|
+
|
|
85
|
+
# Provide at least one provider API key:
|
|
86
|
+
export GEMINI_API_KEY="AIzaSy..."
|
|
87
|
+
export OPENAI_API_KEY="sk-proj-..."
|
|
88
|
+
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Method 3: Persistent Configuration CLI
|
|
92
|
+
|
|
93
|
+
Use the built-in `config` subcommand to store settings permanently in `~/.sandal/config.json` (stored with restrictive user-only file permissions):
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Set default database URL
|
|
97
|
+
npx sandal-db@latest config --set-db "postgresql://user:password@localhost:5432/sales_db"
|
|
98
|
+
|
|
99
|
+
# Set provider API keys
|
|
100
|
+
npx sandal-db@latest config --set-gemini "AIzaSy..."
|
|
101
|
+
npx sandal-db@latest config --set-openai "sk-proj-..."
|
|
102
|
+
npx sandal-db@latest config --set-anthropic "sk-ant-..."
|
|
103
|
+
|
|
104
|
+
# Configure default provider and model
|
|
105
|
+
npx sandal-db@latest config --set-provider google
|
|
106
|
+
npx sandal-db@latest config --set-model gemini-2.5-flash
|
|
107
|
+
|
|
108
|
+
# Review saved configuration (all credentials are automatically masked)
|
|
109
|
+
npx sandal-db@latest config --show
|
|
110
|
+
|
|
111
|
+
# Print configuration file location
|
|
112
|
+
npx sandal-db@latest config --path
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Command-Line Usage and Options
|
|
118
|
+
|
|
119
|
+
### Synopsis
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
npx sandal-db@latest [options] [dbUrl]
|
|
123
|
+
npx sandal-db@latest config [options]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Global Options
|
|
127
|
+
|
|
128
|
+
| Option | Type | Description | Default |
|
|
129
|
+
| ----------------------- | --------- | ---------------------------------------------------------------------------------- | -------------------- |
|
|
130
|
+
| `[dbUrl]` | `string` | Connection URL (`postgres://`, `postgresql://`, `mongodb://`, `mongodb+srv://`). | None |
|
|
131
|
+
| `-p, --provider <name>` | `string` | Target LLM provider: `google`, `openai`, or `anthropic`. | `google` |
|
|
132
|
+
| `-m, --model <name>` | `string` | Model identifier (e.g., `gemini-2.5-flash`, `gpt-4o`, `claude-3-5-sonnet-latest`). | Provider default |
|
|
133
|
+
| `-k, --key <key>` | `string` | API key corresponding to the selected provider. | Environment / Config |
|
|
134
|
+
| `--strict` | `boolean` | Hard-blocks full database drops and bulk table truncations. | `true` |
|
|
135
|
+
| `--no-strict` | `flag` | Disables strict safety mode. | `false` |
|
|
136
|
+
| `--allow-full-wipe` | `flag` | Explicitly permits database-level drops after interactive phrase confirmation. | `false` |
|
|
137
|
+
| `--threshold <number>` | `integer` | Row count threshold above which updates are classified as dangerous operations. | `50` |
|
|
138
|
+
| `-V, --version` | `flag` | Output the version number. | |
|
|
139
|
+
| `-h, --help` | `flag` | Display command help and exit. | |
|
|
140
|
+
|
|
141
|
+
### Default Models by Provider
|
|
142
|
+
|
|
143
|
+
| Provider | Default Model | Override Example |
|
|
144
|
+
| --------- | -------------------------- | ----------------------------------------- |
|
|
145
|
+
| Google | `gemini-2.5-flash` | `-p google -m gemini-2.5-pro` |
|
|
146
|
+
| OpenAI | `gpt-4o` | `-p openai -m gpt-4o-mini` |
|
|
147
|
+
| Anthropic | `claude-3-5-sonnet-latest` | `-p anthropic -m claude-3-5-haiku-latest` |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Interactive REPL Guide
|
|
152
|
+
|
|
153
|
+
Once connected, SANDAL initiates an interactive session with automatic schema inspection.
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
sandal [postgres]>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Dot Commands
|
|
160
|
+
|
|
161
|
+
Dot commands provide direct utility functions without issuing requests to the LLM:
|
|
162
|
+
|
|
163
|
+
| Command | Description |
|
|
164
|
+
| --------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
165
|
+
| `.tables` or `.collections` | Lists all discovered database tables or MongoDB collections with current row counts. |
|
|
166
|
+
| `.schema [name]` | Displays column names, data types, nullability constraints, and primary keys for the specified table. |
|
|
167
|
+
| `.refresh` | Invalidates cached schema metadata and re-introspects the live database. |
|
|
168
|
+
| `.clear` | Clears the terminal screen. |
|
|
169
|
+
| `.help` | Prints the interactive command reference and sample queries. |
|
|
170
|
+
| `exit` or `quit` | Closes active database connections and exits the CLI. |
|
|
171
|
+
|
|
172
|
+
### Example Natural Language Prompts
|
|
173
|
+
|
|
174
|
+
#### Data Retrieval and Aggregation
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
sandal [postgres]> Show the top 5 customers by total order amount in 2025.
|
|
178
|
+
sandal [postgres]> What is the average resolution time for support tickets grouped by priority?
|
|
179
|
+
sandal [postgres]> Find users who signed up in the last 14 days and have not completed onboarding.
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Analytical Insights
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
sandal [postgres]> Calculate standard deviation, median, and average order value across all completed orders.
|
|
186
|
+
sandal [mongodb]> Group active sessions by country code and calculate total duration per region.
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Additive Structural DDL
|
|
190
|
+
|
|
191
|
+
```text
|
|
192
|
+
sandal [postgres]> Add a concurrent index on orders(customer_id, created_at).
|
|
193
|
+
sandal [postgres]> Create a new table audit_events with id, event_name, payload jsonb, and created_at timestamp.
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### Mutation Requests
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
sandal [postgres]> Update users set status = 'dormant' where last_active_at < '2024-01-01'.
|
|
200
|
+
sandal [mongodb]> Delete error log documents created more than 90 days ago.
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Safety and Guardrail Architecture
|
|
206
|
+
|
|
207
|
+
SANDAL is designed from the ground up to prevent unintended data loss and operational incidents. Every prompt passes through multiple deterministic verification layers before any database command is executed.
|
|
208
|
+
|
|
209
|
+
### 1. Intent Pre-Processing Guard
|
|
210
|
+
|
|
211
|
+
SANDAL restricts its actions exclusively to database inspection, querying, data manipulation, and schema modification. Requests outside this scope (e.g., requests to write external code scripts, generate arbitrary essays, or execute shell commands) are rejected before reaching query planning:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
+------------------------------------------------------------------------+
|
|
215
|
+
| GUARDRAIL ENFORCEMENT |
|
|
216
|
+
| |
|
|
217
|
+
| I'm scoped to database operations on your connected DB only |
|
|
218
|
+
| (schema inspection, queries, CRUD, analysis). I can't help with that. |
|
|
219
|
+
| |
|
|
220
|
+
| Reason: Matched out-of-scope pattern |
|
|
221
|
+
+------------------------------------------------------------------------+
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 2. Read-Only Query Confirmation
|
|
225
|
+
|
|
226
|
+
Read queries (`SELECT` in PostgreSQL, `find` or `aggregate` in MongoDB) display the generated statement and await explicit confirmation:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
+--------------------------------------------------------+
|
|
230
|
+
| READ QUERY |
|
|
231
|
+
| |
|
|
232
|
+
| SELECT id, email, created_at FROM users LIMIT 10; |
|
|
233
|
+
+--------------------------------------------------------+
|
|
234
|
+
? Execute read query? (Y/n)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 3. Additive Structural DDL Review
|
|
238
|
+
|
|
239
|
+
When generating `CREATE TABLE`, `CREATE INDEX`, or `ALTER TABLE ADD COLUMN` statements, SANDAL reviews the statement for production safety and flags potential table-locking risks:
|
|
240
|
+
|
|
241
|
+
```text
|
|
242
|
+
+------------------------------------------------------------------------+
|
|
243
|
+
| STRUCTURAL DDL OPERATION |
|
|
244
|
+
| |
|
|
245
|
+
| CREATE INDEX idx_orders_customer ON orders (customer_id); |
|
|
246
|
+
| |
|
|
247
|
+
| Effect: Creates an index on orders (may lock table during build). |
|
|
248
|
+
| |
|
|
249
|
+
| Recommendation: |
|
|
250
|
+
| CREATE INDEX CONCURRENTLY idx_orders_customer ON orders (customer_id); |
|
|
251
|
+
| |
|
|
252
|
+
| - Index is not being created CONCURRENTLY. This will lock write |
|
|
253
|
+
| operations on the table during index creation. |
|
|
254
|
+
+------------------------------------------------------------------------+
|
|
255
|
+
? Apply this structural change? (Y/n)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 4. Mutation Verification with Dry-Run Row Counting
|
|
259
|
+
|
|
260
|
+
Before running mutating statements (`UPDATE`, `DELETE`), SANDAL automatically performs a non-destructive dry-run to count the precise number of records that match the query filter:
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
+--------------------------------------------------------+
|
|
264
|
+
| DANGEROUS OPERATION |
|
|
265
|
+
| |
|
|
266
|
+
| DELETE FROM users |
|
|
267
|
+
| WHERE last_login < '2024-09-13'; |
|
|
268
|
+
| |
|
|
269
|
+
| Affected rows: 14,821 |
|
|
270
|
+
| |
|
|
271
|
+
| - Mutates existing database records. |
|
|
272
|
+
+--------------------------------------------------------+
|
|
273
|
+
? Proceed with dangerous operation? (y/N)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 5. Unbounded Mutation Keyword Verification
|
|
277
|
+
|
|
278
|
+
Any mutation query lacking a filter or `WHERE` clause poses extreme operational risk. SANDAL requires typing an explicit uppercase confirmation phrase before execution:
|
|
279
|
+
|
|
280
|
+
```text
|
|
281
|
+
+--------------------------------------------------------+
|
|
282
|
+
| DANGEROUS OPERATION |
|
|
283
|
+
| |
|
|
284
|
+
| DELETE FROM users; |
|
|
285
|
+
| |
|
|
286
|
+
| Affected rows: 154,200 |
|
|
287
|
+
| |
|
|
288
|
+
| - No WHERE clause specified: EVERY row in the table |
|
|
289
|
+
| will be deleted! |
|
|
290
|
+
+--------------------------------------------------------+
|
|
291
|
+
? Destructive operation with no filter. Type "DELETE ALL" to confirm:
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### 6. Strict Mode and Full-Wipe Hard Blocking
|
|
295
|
+
|
|
296
|
+
By default, `--strict` mode is enabled. Any operation that attempts to drop an entire database or drop all tables is blocked unconditionally:
|
|
297
|
+
|
|
298
|
+
```text
|
|
299
|
+
Operation blocked by --strict mode: full database or all-table drop is prohibited.
|
|
300
|
+
To allow this, start sandal-db with --allow-full-wipe.
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
To permit database-level destructions, the user must explicitly supply `--allow-full-wipe` at startup and subsequently type the required confirmation string during interactive execution.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Security Architecture
|
|
308
|
+
|
|
309
|
+
- Credential Isolation: Passwords, tokens, and secret keys are stripped and masked across all console logs, prompts, and summaries.
|
|
310
|
+
- Local File Security: Configuration files written to `~/.sandal/config.json` are assigned restrictive file mode permissions (`0600` on POSIX systems).
|
|
311
|
+
- Direct Communication: Database traffic travels directly between your workstation and the target database over standard database protocols. Query prompts travel directly to the chosen LLM provider API endpoint.
|
|
312
|
+
- Zero Intermediate Proxies: SANDAL does not transmit telemetry, prompt data, or schema metadata to any third-party intermediary servers.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## License
|
|
317
|
+
|
|
318
|
+
SANDAL is open-source software licensed under the [MIT License](LICENSE).
|