@@ -152,7 +152,7 @@
-
+
@@ -457,8 +457,8 @@
// ── Navigation ────────────────────────────────────────────────────────
function navigate(page) {
// Update page titles map
- const titles = { dashboard:'Dashboard', schemas:'Schemas', entities:'Entities',
- workers:'Workers', schemas:'Schemas', apikeys:'API Keys', explorer:'Explorer' };
+ const titles = { dashboard:'Dashboard', databases:'Databases', schemas:'Schemas', entities:'Entities',
+ workers:'Workers', apikeys:'API Keys', explorer:'Explorer' };
// Hide all pages
document.querySelectorAll('.page').forEach(el => el.classList.add('hidden'));
document.getElementById('page-' + page).classList.remove('hidden');
@@ -472,7 +472,7 @@
closeSidebar();
// Load data for page
if (page === 'dashboard') loadDashboard();
- if (page === 'schemas') loadSchemas();
+ if (page === 'databases') loadDatabases();
if (page === 'entities') { populateDbSelects(); }
if (page === 'workers') loadWorkers();
if (page === 'schemas') loadSchemas();
@@ -495,7 +495,7 @@
async function refreshAll() {
const icon = document.getElementById('refreshIcon');
icon.classList.add('spin');
- await Promise.all([loadDashboard(), loadSchemas()]);
+ await Promise.all([loadDashboard(), loadDatabases()]);
icon.classList.remove('spin');
}
@@ -549,8 +549,8 @@
document.getElementById('healthBody').innerHTML = '
Server unreachable';
}
- // ── Schemas ─────────────────────────────────────────────────────────
- async function loadSchemas() {
+ // ── Databases ─────────────────────────────────────────────────────────
+ async function loadDatabases() {
try {
const r = await api('/api/schemas');
if (r.ok) {
@@ -625,7 +625,7 @@
}).then(r => r.json().then(d => {
if (r.ok) {
showAlert(alertEl, 'success', `Schema "${name}" created with entity "${key}".`);
- loadSchemas();
+ loadDatabases();
} else {
showAlert(alertEl, 'error', d.error || 'Failed.');
}
@@ -669,7 +669,7 @@
});
if (r.ok) {
showAlert(alertEl, 'success', 'Entity written successfully.');
- await loadSchemas();
+ await loadDatabases();
} else {
const d = await r.json().catch(() => ({}));
showAlert(alertEl, 'error', d.error || 'Failed.');
From 520601205f60bb74e0b15fb3b3aae9d58039feaa Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 15 Mar 2026 10:05:48 +0000
Subject: [PATCH 03/11] Remove database terminology: replace with schema
throughout UI, docs and Go code
Co-authored-by: DeltaRule <83079740+DeltaRule@users.noreply.github.com>
---
README.md | 44 +++++------
api/proto/worker.pb.go | 2 +-
api/proto/worker_grpc.pb.go | 4 +-
cmd/main-worker/static/app.html | 134 ++++++++++++++++----------------
cmd/proc-worker/server.go | 4 +-
cmd/proc-worker/server_test.go | 2 +-
pkg/fs/storage.go | 4 +-
pkg/fs/storage_test.go | 6 +-
tools/manual_verify_fs.go | 2 +-
9 files changed, 101 insertions(+), 101 deletions(-)
diff --git a/README.md b/README.md
index 974d8fc..4477369 100644
--- a/README.md
+++ b/README.md
@@ -45,8 +45,8 @@
## Overview
DeltaDatabase stores arbitrary JSON documents — called **entities** — inside
-**schema-databases** identified by a `schema_id`. The schema IS the database —
-there is no separate database namespace. Every entity is stored under its
+**schemas** identified by a `schema_id`. The schema is the namespace —
+there is no separate grouping above it. Every entity is stored under its
`schema_id`, which also acts as the JSON Schema template identifier for
validation. Every entity is:
@@ -418,8 +418,8 @@ Requires `admin` permission.
### `PUT /entity/{schema_id}`
-Create or update one or more entities in the schema-database identified by `schema_id`.
-The schema IS the database — `schema_id` serves as both the storage namespace and the
+Create or update one or more entities in the schema identified by `schema_id`.
+The schema is the namespace — `schema_id` serves as both the storage namespace and the
JSON Schema template used for validation (if a template with that ID exists).
**Path parameter:** `schema_id` — schema identifier (e.g., `chat.v1`).
@@ -468,7 +468,7 @@ Retrieve a single entity.
### `DELETE /entity/{schema_id}?key={entityKey}`
-Delete a single entity by key from a schema-database. Requires `write` permission.
+Delete a single entity by key from a schema. Requires `write` permission.
**Path parameter:** `schema_id` — schema identifier.
@@ -626,20 +626,20 @@ curl http://127.0.0.1:8080/schema/chat.v1
The web management UI exposes a **📋 Schemas** tab where you can list, load,
and edit schemas through a form — no `curl` or file editing needed.
-### Using a schema-database via the REST API
+### Using a schema via the REST API
The `schema_id` in the URL path is both the storage namespace and the schema
validator. When a JSON Schema template with the given `schema_id` exists, each
PUT is validated before storage.
```bash
-# Store entities in the "chat.v1" schema-database
+# Store entities in the "chat.v1" schema
curl -X PUT http://127.0.0.1:8080/entity/chat.v1 \
-H "Authorization: Bearer $ADMIN_KEY" \
-H 'Content-Type: application/json' \
-d '{"session_001": {"messages": [{"role":"user","content":"Hello!"}]}}'
-# Retrieve an entity from the "chat.v1" schema-database
+# Retrieve an entity from the "chat.v1" schema
curl "http://127.0.0.1:8080/entity/chat.v1?key=session_001" \
-H "Authorization: Bearer $ADMIN_KEY"
```
@@ -647,7 +647,7 @@ curl "http://127.0.0.1:8080/entity/chat.v1?key=session_001" \
### Using a schema on a PUT (gRPC)
When calling the gRPC `Process` RPC directly, set the `schema_id` field of
-`ProcessRequest` to the desired schema-database identifier (e.g. `"chat.v1"`).
+`ProcessRequest` to the desired schema identifier (e.g. `"chat.v1"`).
The Processing Worker will:
1. Store the entity under that namespace.
2. Validate the payload against the `chat.v1` JSON Schema template (if it exists).
@@ -761,7 +761,7 @@ http://127.0.0.1:8080/


-
+
**Pages:**
@@ -769,10 +769,10 @@ http://127.0.0.1:8080/
|------|-------------|
| **Login** | Beautiful sign-in card — enter your admin key, API key, or a dev-mode Client ID |
| **Dashboard** | Live health status, worker counts, schema count, and cache statistics |
-| **Schemas** | Dropdown + card grid of all schema-databases; click any card to explore its entities |
+| **Schemas** | Dropdown + card grid of all schemas; click any card to explore its entities |
| **Entities** | GET, PUT, and DELETE entities with a schema dropdown pre-populated from `GET /api/schemas` |
| **Workers** | Table of all registered Processing Workers with status, key ID, last-seen, and tags |
-| **Schemas** | List, load, create, and edit JSON Schema templates; export as Pydantic or TypeScript |
+| **Templates** | List, load, create, and edit JSON Schema templates; export as Pydantic or TypeScript |
| **API Keys** | Create and delete RBAC API keys (admin only) with permissions and optional expiry |
| **Explorer** | Send arbitrary HTTP requests to any endpoint with quick-access buttons |
@@ -780,7 +780,7 @@ http://127.0.0.1:8080/
| Endpoint | Description |
|----------|-------------|
-| `GET /api/schemas` | Returns a sorted list of schema-databases currently in the entity cache (requires `read`) |
+| `GET /api/schemas` | Returns a sorted list of schemas currently in the entity cache (requires `read`) |
| `GET /api/me` | Returns the caller's `client_id`, `permissions`, and `is_admin` flag |
The UI is **fully responsive** — on mobile a hamburger menu opens the sidebar as an overlay.
@@ -794,7 +794,7 @@ No additional installation is required — the UI is embedded directly in the
The following examples demonstrate a complete **chat session backend** where:
-* Each user session is stored under database `chatdb`.
+* Each user session is stored in schema `chatdb`.
* The entity key is the session ID (e.g., `session_001`).
* The entity value is a JSON object containing the conversation history.
@@ -814,7 +814,7 @@ import (
const (
baseURL = "http://127.0.0.1:8080"
- database = "chatdb"
+ schema = "chatdb"
)
// Message represents a single chat turn.
@@ -860,7 +860,7 @@ func (c *ChatClient) doRequest(method, path string, body io.Reader) (*http.Respo
// GetSession retrieves the conversation history for a session.
// Returns an empty session if the session does not yet exist.
func (c *ChatClient) GetSession(sessionID string) (Session, error) {
- path := fmt.Sprintf("/entity/%s?key=%s", database, url.QueryEscape(sessionID))
+ path := fmt.Sprintf("/entity/%s?key=%s", schema, url.QueryEscape(sessionID))
resp, err := c.doRequest(http.MethodGet, path, nil)
if err != nil {
return Session{}, err
@@ -896,7 +896,7 @@ func (c *ChatClient) AppendMessage(sessionID string, msg Message) error {
return err
}
- path := fmt.Sprintf("/entity/%s", database)
+ path := fmt.Sprintf("/entity/%s", schema)
resp, err := c.doRequest(http.MethodPut, path, bytes.NewReader(payload))
if err != nil {
return err
@@ -977,7 +977,7 @@ import requests
import json
BASE_URL = "http://127.0.0.1:8080"
-DATABASE = "chatdb"
+SCHEMA = "chatdb"
class DeltaChatClient:
@@ -994,7 +994,7 @@ class DeltaChatClient:
def get_session(self, session_id: str) -> dict:
"""Return the conversation dict; empty if session does not exist yet."""
resp = self.session.get(
- f"{self.base_url}/entity/{DATABASE}",
+ f"{self.base_url}/entity/{SCHEMA}",
params={"key": session_id},
timeout=10,
)
@@ -1009,7 +1009,7 @@ class DeltaChatClient:
data.setdefault("messages", []).append({"role": role, "content": content})
resp = self.session.put(
- f"{self.base_url}/entity/{DATABASE}",
+ f"{self.base_url}/entity/{SCHEMA}",
json={session_id: data},
timeout=10,
)
@@ -1238,7 +1238,7 @@ for a complete Docker Compose and Kubernetes walkthrough.
| Schema validation | JSON Schema draft-07 enforced before every write |
| Log redaction | No plaintext entity data or key material is emitted in logs |
| Token expiry | Worker tokens: 1 h (configurable). Client tokens: 24 h (configurable) |
-| Path traversal | Entity keys, database names and schema IDs are validated to reject `/`, `\`, and `..` |
+| Path traversal | Entity keys and schema IDs are validated to reject `/`, `\`, and `..` |
| Request body limit | REST PUT/schema endpoints reject bodies larger than 1 MiB |
| Admin endpoints | `GET /admin/workers` requires a valid Bearer token; `GET /admin/schemas` is public |
| Write durability (FS) | `fdatasync` before atomic rename guarantees no data loss on worker crash |
@@ -1327,7 +1327,7 @@ For full build instructions, prerequisites, and testing setup, see
│ ├── main-worker/ # Main Worker entry point & server
│ │ ├── main.go
│ │ ├── server.go # gRPC + REST handler
-│ │ ├── frontend.go # Embedded web UI + /api/login, /api/databases, /api/me
+│ │ ├── frontend.go # Embedded web UI + /api/login, /api/schemas, /api/me
│ │ └── static/
│ │ ├── index.html # Login page
│ │ ├── app.html # Multi-page management SPA
diff --git a/api/proto/worker.pb.go b/api/proto/worker.pb.go
index ef4ea9e..8af12d0 100644
--- a/api/proto/worker.pb.go
+++ b/api/proto/worker.pb.go
@@ -67,7 +67,7 @@ func (x *SubscribeResponse) GetKeyId() string {
// ProcessRequest requests a GET or PUT operation on an entity.
// SchemaId serves as both the storage namespace and the JSON Schema identifier —
-// the schema IS the database.
+// the schema is the namespace for all its entities.
type ProcessRequest struct {
SchemaId string `json:"schema_id,omitempty"`
EntityKey string `json:"entity_key,omitempty"`
diff --git a/api/proto/worker_grpc.pb.go b/api/proto/worker_grpc.pb.go
index 1e772ac..e0ca7f7 100644
--- a/api/proto/worker_grpc.pb.go
+++ b/api/proto/worker_grpc.pb.go
@@ -14,7 +14,7 @@ import (
type MainWorkerClient interface {
// Subscribe registers a Processing Worker and returns a token and wrapped key material.
Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (*SubscribeResponse, error)
- // Process performs internal GET/PUT operations for database entities.
+ // Process performs internal GET/PUT operations for schema entities.
Process(ctx context.Context, in *ProcessRequest, opts ...grpc.CallOption) (*ProcessResponse, error)
}
@@ -49,7 +49,7 @@ func (c *mainWorkerClient) Process(ctx context.Context, in *ProcessRequest, opts
type MainWorkerServer interface {
// Subscribe registers a Processing Worker and returns a token and wrapped key material.
Subscribe(context.Context, *SubscribeRequest) (*SubscribeResponse, error)
- // Process performs internal GET/PUT operations for database entities.
+ // Process performs internal GET/PUT operations for schema entities.
Process(context.Context, *ProcessRequest) (*ProcessResponse, error)
}
diff --git a/cmd/main-worker/static/app.html b/cmd/main-worker/static/app.html
index 6a5cd19..15a8209 100644
--- a/cmd/main-worker/static/app.html
+++ b/cmd/main-worker/static/app.html
@@ -33,8 +33,8 @@
-