eDB — Unified Multi-Model Database v0.1.0
eDB is a lightweight, embeddable multi-model database for EmbeddedOS that unifies SQL (relational), document (NoSQL), and key-value storage under a single Python API and REST interface. Designed for resource-constrained devices, edge computing, and rapid prototyping — with built-in JWT authentication, AES-256-GCM encryption, and an AI-powered natural language query assistant.
Language: Python 3.10+ | Package: pip install edb | License: MIT | Backend: SQLite3
SQL Engine: Full relational database powered by SQLite — CREATE, INSERT, SELECT, UPDATE, DELETE, JOINs, indexes.
Document Store: Schema-free JSON document collections with query operators ($eq, $gt, $lt, $in, $regex).
Key-Value Store: Fast in-memory key-value with optional TTL-based expiry and persistence.
REST API: FastAPI-powered HTTP interface for all three engines — serve with edb serve.
eBot AI: Natural language → SQL/NoSQL translation using rule-based NLP.
Security: JWT auth (RBAC), AES-256-GCM encryption at rest, tamper-resistant audit logging.
pip install edb
edb init myproject.sqlite # Create database
edb shell # Interactive SQL shell
edb serve --port 8080 # Launch REST API server🗃 SQL Engine
Full relational database with SQLite backend. Module: edb.core.relational
Database Initialization
RelationalDB RelationalDB(db_path: str)Create or open a SQLite database at the given file path. Creates the file and parent directories if they don’t exist.
Parameters
| db_path | str | Path to the SQLite database file (e.g., "mydb.sqlite"). |
Returns
RelationalDB instance.
Example
from edb.core.relational import RelationalDB
db = RelationalDB("mydb.sqlite")list[dict] db.execute(sql: str, params: tuple = ())Execute a raw SQL statement. For SELECT queries, returns a list of row dicts. For write operations, commits automatically and returns an empty list.
Parameters
| sql | str | SQL statement with optional ? placeholders. |
| params | tuple | Positional parameters for placeholders. |
Returns
List of dicts for SELECT; empty list for DDL/DML.
Example
db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
role TEXT DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")CRUD Operations
list[dict] db.execute("INSERT INTO ...")Insert one or more rows into a table. Use parameterized queries to prevent SQL injection.
Example
# Single insert
db.execute(
"INSERT INTO users (name, email, role) VALUES (?, ?, ?)",
("Alice", "alice@example.com", "admin")
)
# Batch insert
users = [("Bob", "bob@example.com", "user"), ("Carol", "carol@example.com", "user")]
for name, email, role in users:
db.execute("INSERT INTO users (name, email, role) VALUES (?, ?, ?)", (name, email, role))list[dict] db.execute("SELECT ...")Query rows from one or more tables. Supports WHERE, JOIN, ORDER BY, LIMIT, GROUP BY, HAVING, and aggregate functions.
Example
# Basic select
rows = db.execute("SELECT * FROM users WHERE role = ?", ("admin",))
for row in rows:
print(f"{row['name']} — {row['email']}")
# Join with aggregation
results = db.execute("""
SELECT u.name, COUNT(o.id) AS order_count
FROM users u LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id ORDER BY order_count DESC LIMIT 10
""")list[dict] db.execute("UPDATE ...")Update existing rows matching a WHERE condition.
Example
db.execute(
"UPDATE users SET role = ? WHERE email = ?",
("admin", "bob@example.com")
)list[dict] db.execute("DELETE ...")Delete rows matching a WHERE condition.
Example
db.execute("DELETE FROM users WHERE email = ?", ("carol@example.com",))Schema & Index Management
list[dict] db.execute("CREATE INDEX ...")Create indexes to accelerate queries. Supports unique indexes, composite indexes, and partial indexes.
Example
# Unique index
db.execute("CREATE UNIQUE INDEX idx_users_email ON users(email)")
# Composite index
db.execute("CREATE INDEX idx_orders_user_date ON orders(user_id, created_at)")
# List all tables
tables = db.execute("SELECT name FROM sqlite_master WHERE type='table'")Interactive Shell
$ edb shell
eDB Shell v0.1.0 (SQLite 3.39.0)
Connected to: mydb.sqlite
edb> CREATE TABLE sensors (id INTEGER PRIMARY KEY, name TEXT, value REAL);
OK
edb> INSERT INTO sensors VALUES (1, 'temperature', 23.5);
OK (1 row affected)
edb> SELECT * FROM sensors;
+----+-------------+-------+
| id | name | value |
+----+-------------+-------+
| 1 | temperature | 23.5 |
+----+-------------+-------+
1 row(s)
edb> .tables
sensors
users
edb> .schema sensors
CREATE TABLE sensors (id INTEGER PRIMARY KEY, name TEXT, value REAL);
edb> .quit📄 Document Store
Schema-free JSON document collections with query operators. Module: edb.core.document
Collection Management
DocumentStore DocumentStore(db_path: str)Initialize the document store engine. Uses the same SQLite file as the SQL engine — documents are stored as JSON blobs with auto-generated UUIDs.
Parameters
| db_path | str | Path to the database file. |
Example
from edb.core.document import DocumentStore
docs = DocumentStore("mydb.sqlite")Collection docs.collection(name: str)Get or create a named collection. Collections are created lazily on first insert.
Parameters
| name | str | Collection name (alphanumeric, underscores). |
Returns
Collection handle.
Example
sensors = docs.collection("sensors")
users = docs.collection("users")Document Operations
str collection.insert(doc: dict)Insert a JSON document into the collection. Auto-generates a UUID _id field if not provided.
Parameters
| doc | dict | JSON-serializable document. |
Returns
Document _id string (UUID).
Example
doc_id = sensors.insert({
"type": "temperature",
"value": 23.5,
"unit": "celsius",
"location": "lab-1",
"tags": ["indoor", "calibrated"],
"metadata": {"firmware": "v2.1", "battery": 85}
})
print(f"Inserted: {doc_id}")list[str] collection.insert_many(docs: list[dict])Bulk insert multiple documents. Runs in a single transaction for atomicity.
Parameters
| docs | list[dict] | List of documents to insert. |
Returns
List of inserted _id strings.
Example
ids = sensors.insert_many([
{"type": "humidity", "value": 65.2, "unit": "percent"},
{"type": "pressure", "value": 1013.25, "unit": "hPa"},
{"type": "temperature", "value": 19.8, "unit": "celsius"}
])list[dict] collection.find(query: dict = {})Query documents matching filter criteria. Supports operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $regex, $exists.
Parameters
| query | dict | Filter document. Empty dict returns all documents. |
Returns
List of matching documents (dicts with _id).
Example
# Exact match
temps = sensors.find({"type": "temperature"})
# Comparison operators
hot = sensors.find({"value": {"$gt": 30}, "type": "temperature"})
# Regex match
lab_sensors = sensors.find({"location": {"$regex": "^lab-"}})
# $in operator
specific = sensors.find({"type": {"$in": ["temperature", "humidity"]}})
# Nested field access
old_fw = sensors.find({"metadata.firmware": {"$lt": "v2.0"}})dict | None collection.find_one(query: dict)Find the first document matching the query. Returns None if no match.
Parameters
| query | dict | Filter document. |
Returns
Matching document or None.
Example
doc = sensors.find_one({"_id": doc_id})
if doc:
print(f"Value: {doc['value']} {doc['unit']}")int collection.update(query: dict, update: dict)Update all documents matching the query. Supports $set, $unset, $inc, $push, $pull operators.
Parameters
| query | dict | Filter to select documents. |
| update | dict | Update operations to apply. |
Returns
Number of documents modified.
Example
# Set fields
sensors.update(
{"type": "temperature", "location": "lab-1"},
{"$set": {"value": 24.1, "updated_at": "2025-01-15T10:30:00Z"}}
)
# Increment a numeric field
sensors.update({"_id": doc_id}, {"$inc": {"metadata.battery": -1}})
# Push to an array
sensors.update({"_id": doc_id}, {"$push": {"tags": "verified"}})int collection.delete(query: dict)Delete all documents matching the query.
Parameters
| query | dict | Filter to select documents for deletion. |
Returns
Number of documents deleted.
Example
deleted = sensors.delete({"type": "pressure", "value": {"$lt": 900}})
print(f"Removed {deleted} documents")int collection.count(query: dict = {})Count documents matching the query. Empty query counts all documents in the collection.
Parameters
| query | dict | Optional filter. |
Returns
Number of matching documents.
Example
total = sensors.count()
temp_count = sensors.count({"type": "temperature"})
print(f"{temp_count}/{total} are temperature readings")Query Operators Reference
Supported Query Operators
$eq | dict | Equals (implicit when using direct value match) |
$ne | dict | Not equal |
$gt / $gte | dict | Greater than / greater than or equal |
$lt / $lte | dict | Less than / less than or equal |
$in / $nin | dict | Value in / not in array |
$regex | dict | Regular expression match |
$exists | dict | Field exists (true) or not (false) |
Supported Update Operators
$set | dict | Set field values (create if missing) |
$unset | dict | Remove fields from document |
$inc | dict | Increment numeric fields |
$push | dict | Append value to array field |
$pull | dict | Remove value from array field |
🔑 Key-Value Store
Fast in-memory key-value store with optional TTL expiry and disk persistence. Module: edb.core.keyvalue
KeyValueStore KeyValueStore(db_path: str)Initialize the key-value store. Keys are strings; values are any JSON-serializable type. Supports optional TTL-based expiry for cache-like behavior.
Parameters
| db_path | str | Path to the persistence file. Values are loaded into memory at startup. |
Example
from edb.core.keyvalue import KeyValueStore
kv = KeyValueStore("mydb.sqlite")None kv.set(key: str, value: Any, ttl: int | None = None)Store a key-value pair. If the key already exists, its value is overwritten. Optional TTL in seconds causes automatic expiry.
Parameters
| key | str | Key string (max 512 bytes). |
| value | Any | JSON-serializable value (str, int, float, dict, list, bool, None). |
| ttl | int | None | Time-to-live in seconds. None = no expiry. |
Example
# Permanent storage
kv.set("config:version", "2.1.0")
kv.set("device:info", {"name": "sensor-01", "firmware": "v2.1", "calibrated": True})
# Cache with TTL (expires after 5 minutes)
kv.set("cache:weather", {"temp": 22.5, "humidity": 60}, ttl=300)
# Session token (expires after 1 hour)
kv.set("session:abc123", {"user_id": 42, "role": "admin"}, ttl=3600)Any | None kv.get(key: str)Retrieve a value by key. Returns None if the key doesn’t exist or has expired.
Parameters
| key | str | Key to look up. |
Returns
Stored value or None.
Example
version = kv.get("config:version") # "2.1.0"
info = kv.get("device:info") # {"name": "sensor-01", ...}
missing = kv.get("nonexistent") # Nonebool kv.delete(key: str)Delete a key-value pair. Returns True if the key existed and was deleted.
Parameters
| key | str | Key to delete. |
Returns
True if deleted, False if key not found.
Example
kv.delete("session:abc123") # True
kv.delete("nonexistent") # Falsebool kv.exists(key: str)Check if a key exists and has not expired.
Parameters
| key | str | Key to check. |
Returns
True if key exists and is not expired.
list[str] kv.keys(pattern: str = "*")List all keys matching a glob pattern. Excludes expired keys.
Parameters
| pattern | str | Glob pattern (* = all, session:* = all sessions). |
Returns
List of matching key strings.
Example
all_keys = kv.keys() # All keys
sessions = kv.keys("session:*") # Session keys only
configs = kv.keys("config:*") # Config keys onlyNone kv.flush()Delete all key-value pairs from the store and persist the change to disk.
None kv.cleanup_expired()Remove all expired keys from the store. Called automatically on get(), but can be invoked manually for batch cleanup.
🌐 REST API
FastAPI-powered HTTP interface for all database engines. Module: edb.api
# Start the API server
edb serve --port 8080
# With authentication enabled
edb serve --port 8080 --auth
# Custom host and database
edb serve --host 0.0.0.0 --port 8080 --db /data/production.sqliteSQL Endpoints
POST /api/sql/queryExecute a SQL query and return results as JSON.
Request Body
| sql | string | SQL statement to execute. |
| params | array | Optional positional parameters. |
Example
curl -X POST http://localhost:8080/api/sql/query \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT * FROM users WHERE role = ?", "params": ["admin"]}'
# Response:
{
"columns": ["id", "name", "email", "role"],
"rows": [
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"}
],
"row_count": 1
}GET /api/sql/tablesList all tables in the database with row counts.
Response
JSON array of {"name": "...", "row_count": N} objects.
GET /api/sql/tables/{table}/schemaGet the schema (column names, types, constraints) of a specific table.
Document Endpoints
POST /api/documents/{collection}Insert a document into a collection.
Request Body
| document | object | JSON document to insert. |
Example
curl -X POST http://localhost:8080/api/documents/sensors \
-H "Content-Type: application/json" \
-d '{"document": {"type": "temperature", "value": 23.5}}'
# Response:
{"_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "inserted"}POST /api/documents/{collection}/findQuery documents with MongoDB-style filter operators.
Request Body
| query | object | Filter document with optional operators. |
Example
curl -X POST http://localhost:8080/api/documents/sensors/find \
-H "Content-Type: application/json" \
-d '{"query": {"type": "temperature", "value": {"$gt": 20}}}'PUT /api/documents/{collection}Update documents matching a query.
Request Body
| query | object | Filter to select documents. |
| update | object | Update operations ($set, $inc, etc.). |
DELETE /api/documents/{collection}Delete documents matching a query.
Request Body
| query | object | Filter to select documents for deletion. |
Key-Value Endpoints
GET /api/kv/{key}Retrieve a value by key.
Response
{"key": "...", "value": ..., "ttl_remaining": N|null}
Example
curl http://localhost:8080/api/kv/config:version
# Response:
{"key": "config:version", "value": "2.1.0", "ttl_remaining": null}PUT /api/kv/{key}Set a key-value pair with optional TTL.
Request Body
| value | any | JSON-serializable value. |
| ttl | integer | null | Optional TTL in seconds. |
Example
curl -X PUT http://localhost:8080/api/kv/cache:token \
-H "Content-Type: application/json" \
-d '{"value": "abc123xyz", "ttl": 3600}'DELETE /api/kv/{key}Delete a key-value pair.
Response
{"key": "...", "deleted": true|false}
GET /api/kvList all keys, optionally filtered by glob pattern via ?pattern=session:* query parameter.
Response
{"keys": ["key1", "key2", ...], "count": N}
🔒 Authentication
JWT-based authentication with role-based access control (RBAC). Module: edb.auth
admin: Full access — create/drop tables, manage users, read/write all data.
read_write: Read and write data, create indexes. Cannot drop tables or manage users.
read_only: Read-only access to all queries. Cannot modify any data.
Auth Endpoints
POST /api/auth/registerRegister a new user account. First registered user automatically gets admin role.
Request Body
| username | string | Unique username (3-64 chars). |
| password | string | Password (min 8 chars, hashed with bcrypt). |
| role | string | Optional: "admin", "read_write", or "read_only" (default). |
Example
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "secureP@ss123", "role": "admin"}'
# Response:
{"user_id": 1, "username": "alice", "role": "admin", "created": true}POST /api/auth/loginAuthenticate and receive access + refresh token pair. Access token expires in 15 minutes; refresh token in 7 days.
Request Body
| username | string | Registered username. |
| password | string | User password. |
Example
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "secureP@ss123"}'
# Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 900,
"role": "admin"
}POST /api/auth/refreshExchange a valid refresh token for a new access token.
Request Body
| refresh_token | string | Valid refresh token. |
Response
New access_token with fresh expiry.
GET /api/auth/meGet the currently authenticated user’s profile. Requires Authorization: Bearer <token> header.
Response
{"user_id": N, "username": "...", "role": "...", "created_at": "..."}
# All API endpoints require the Authorization header when --auth is enabled:
curl -X POST http://localhost:8080/api/sql/query \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT * FROM users"}'Token Structure
JWT Access Token Payload
sub | string | Username (subject) |
role | string | User role (admin, read_write, read_only) |
iat | integer | Issued-at timestamp (Unix epoch) |
exp | integer | Expiration timestamp (Unix epoch) |
type | string | "access" or "refresh" |
🛡 Security
Encryption at rest, audit logging, and input sanitization. Module: edb.security
Encryption
EncryptionManager EncryptionManager(key: bytes)Initialize AES-256-GCM encryption engine. All data at rest is encrypted with this key. The key must be exactly 32 bytes.
Parameters
| key | bytes | 32-byte encryption key. Generate with os.urandom(32) or derive from passphrase with PBKDF2. |
Example
from edb.security import EncryptionManager
import os
key = os.urandom(32)
enc = EncryptionManager(key)
ciphertext = enc.encrypt(b"sensitive data")
plaintext = enc.decrypt(ciphertext) # b"sensitive data"bytes enc.encrypt(plaintext: bytes)Encrypt data using AES-256-GCM. Returns nonce + ciphertext + tag (authenticated encryption).
Parameters
| plaintext | bytes | Data to encrypt. |
Returns
Encrypted bytes (12-byte nonce + ciphertext + 16-byte auth tag).
bytes enc.decrypt(ciphertext: bytes)Decrypt and verify AES-256-GCM ciphertext. Raises InvalidTag if data has been tampered with.
Parameters
| ciphertext | bytes | Encrypted data from encrypt(). |
Returns
Decrypted plaintext bytes.
Audit Logging
AuditLogger AuditLogger(db_path: str)Initialize tamper-resistant audit log. Each entry is hash-chained to the previous entry using SHA-256, forming an immutable ledger.
Parameters
| db_path | str | Path to audit log database (separate from main DB). |
Example
from edb.security import AuditLogger
audit = AuditLogger("audit.sqlite")
audit.log("alice", "QUERY", "SELECT * FROM users")
audit.log("bob", "INSERT", "INSERT INTO orders VALUES (...)")
# Verify chain integrity
is_valid = audit.verify_chain() # True if untamperedNone audit.log(user: str, action: str, detail: str)Record an audit event with timestamp, user, action type, and detail. Auto-computes hash chain.
Parameters
| user | str | Username performing the action. |
| action | str | Action type: QUERY, INSERT, UPDATE, DELETE, LOGIN, REGISTER, ADMIN. |
| detail | str | SQL statement or action description. |
bool audit.verify_chain()Verify the integrity of the entire audit chain. Returns False if any entry has been modified or deleted.
Returns
True if chain is intact.
list[dict] audit.query(user: str = None, action: str = None, limit: int = 100)Query audit log entries with optional filters.
Parameters
| user | str | Filter by username (optional). |
| action | str | Filter by action type (optional). |
| limit | int | Maximum entries to return (default 100). |
Returns
List of audit entries with id, timestamp, user, action, detail, hash.
Input Sanitization
Built-in Protections
SQL Injection | Prevention | Parameterized queries enforced; raw string interpolation rejected |
NoSQL Injection | Prevention | Query operators validated against whitelist ($eq, $gt, etc.) |
Prompt Injection | Prevention | eBot input sanitized; dangerous SQL keywords blocked from NL input |
XSS | Prevention | All REST API outputs JSON-encoded; no HTML rendering |
Path Traversal | Prevention | Database paths validated and sandboxed |
🤖 eBot AI
Natural language to SQL/NoSQL query translation. Module: edb.ebot
eBot uses rule-based NLP to translate natural language questions into SQL or NoSQL queries. It parses intent, extracts entities (table names, column names, operators), and generates safe parameterized queries. No external LLM required — runs entirely offline.
Python API
EBot EBot(db: RelationalDB, doc_store: DocumentStore = None)Initialize eBot with database references. Introspects table schemas to understand column names and types.
Parameters
| db | RelationalDB | SQL engine instance for schema introspection. |
| doc_store | DocumentStore | Optional document store for NoSQL queries. |
Example
from edb.ebot import EBot
bot = EBot(db, doc_store=docs)
result = bot.query("show me all admin users")
# Translates to: SELECT * FROM users WHERE role = 'admin'
print(result)dict bot.query(question: str)Translate a natural language question into a query and execute it. Returns both the generated query and results.
Parameters
| question | str | Natural language question (English). |
Returns
Dict with query (generated SQL/NoSQL), query_type ("sql" or "nosql"), results (data), and row_count.
Example
# SQL translation examples
bot.query("how many users are there?")
# → SELECT COUNT(*) AS count FROM users
bot.query("show the top 5 orders by amount")
# → SELECT * FROM orders ORDER BY amount DESC LIMIT 5
bot.query("what is the average temperature reading?")
# → SELECT AVG(value) AS average FROM sensors WHERE type = 'temperature'
# NoSQL translation
bot.query("find all temperature sensors in lab-1")
# → collection("sensors").find({"type": "temperature", "location": "lab-1"})str bot.explain(question: str)Translate without executing — returns the generated query string for review.
Parameters
| question | str | Natural language question. |
Returns
Generated SQL or NoSQL query string.
REST Endpoint
POST /api/ebot/querySend a natural language query via the REST API.
Request Body
| question | string | Natural language question. |
| explain_only | boolean | If true, return the generated query without executing. |
Example
curl -X POST http://localhost:8080/api/ebot/query \
-H "Content-Type: application/json" \
-d '{"question": "show me all users who registered this week"}'
# Response:
{
"question": "show me all users who registered this week",
"query_type": "sql",
"generated_query": "SELECT * FROM users WHERE created_at >= date('now', '-7 days')",
"results": [...],
"row_count": 3
}🔍 Query Engine
Full-text search, graph queries, and advanced query features. Module: edb.query
Full-Text Search
None db.create_fts_index(table: str, columns: list[str])Create a full-text search index on specified columns using SQLite FTS5. Enables fast text search with ranking.
Parameters
| table | str | Table to index. |
| columns | list[str] | Columns to include in the FTS index. |
Example
db.create_fts_index("articles", ["title", "body"])
# Search with ranking
results = db.search("articles", "embedded operating system", limit=10)
for r in results:
print(f"[{r['rank']:.2f}] {r['title']}")list[dict] db.search(table: str, query: str, limit: int = 20)Execute a full-text search query with BM25 ranking. Returns results sorted by relevance.
Parameters
| table | str | Table with FTS index. |
| query | str | Search query (supports AND, OR, NOT, phrase matching with quotes). |
| limit | int | Maximum results to return (default 20). |
Returns
List of matching rows with rank score field (lower = more relevant).
Example
# Boolean search
results = db.search("articles", "embedded AND system NOT windows")
# Phrase search
results = db.search("articles", '"real-time operating system"')
# Prefix matching
results = db.search("articles", "micro*")REST Search Endpoint
POST /api/search/{table}Full-text search via REST API.
Request Body
| query | string | Search query string. |
| limit | integer | Max results (default 20). |
Example
curl -X POST http://localhost:8080/api/search/articles \
-H "Content-Type: application/json" \
-d '{"query": "embedded database", "limit": 5}'Planned Features
Graph Data Model (v0.2.0): Vertex/edge storage with Cypher-like traversal queries — db.graph.add_vertex(), db.graph.traverse().
LLM-Powered eBot (v0.3.0): Optional LLM backend for complex natural language queries, multi-table joins, and conversational context.
Vector Search (v0.3.0): Embedding storage and approximate nearest-neighbor search for AI/ML workloads.
Replication (v0.4.0): Primary-replica replication for high availability on edge clusters.
💻 CLI Reference
edb Commands
edb init <path> | Create a new database file at the given path | |
edb shell | Open interactive SQL shell (supports .tables, .schema, .quit) | |
edb serve | Start the REST API server (FastAPI + Uvicorn) | |
edb migrate | Run pending schema migrations from migrations/ directory |
edb serve Options
--host | string | Bind address (default: 127.0.0.1) |
--port | integer | Listen port (default: 8080) |
--db | string | Database file path (default: ./edb.sqlite) |
--auth | flag | Enable JWT authentication |
--encrypt | flag | Enable AES-256-GCM encryption at rest |
--audit | flag | Enable audit logging |
--cors | string | CORS allowed origins (default: *) |
--workers | integer | Number of Uvicorn workers (default: 1) |
edb shell Commands
.tables | List all tables | |
.schema <table> | Show CREATE statement for a table | |
.collections | List all document collections | |
.kv | List all key-value keys | |
.export <table> <file> | Export table to CSV | |
.import <file> <table> | Import CSV into table | |
.quit | Exit the shell |