@cybermem/cli 0.8.9 → 0.9.2
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.
|
@@ -11,10 +11,37 @@
|
|
|
11
11
|
const http = require("http");
|
|
12
12
|
const crypto = require("crypto");
|
|
13
13
|
const path = require("path");
|
|
14
|
+
const sqlite3 = require("sqlite3").verbose();
|
|
14
15
|
|
|
15
16
|
const PORT = process.env.PORT || 3001;
|
|
16
17
|
const DB_PATH = process.env.OM_DB_PATH || "/data/openmemory.sqlite";
|
|
17
18
|
|
|
19
|
+
// Ensure schema exists
|
|
20
|
+
function initSchema() {
|
|
21
|
+
const db = new sqlite3.Database(DB_PATH);
|
|
22
|
+
db.serialize(() => {
|
|
23
|
+
db.run(
|
|
24
|
+
`
|
|
25
|
+
CREATE TABLE IF NOT EXISTS access_keys (
|
|
26
|
+
key_id TEXT PRIMARY KEY,
|
|
27
|
+
key_hash TEXT UNIQUE NOT NULL,
|
|
28
|
+
user_id TEXT NOT NULL,
|
|
29
|
+
name TEXT,
|
|
30
|
+
is_active INTEGER DEFAULT 1,
|
|
31
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
32
|
+
)
|
|
33
|
+
`,
|
|
34
|
+
(err) => {
|
|
35
|
+
if (err) console.error("SCHEMA ERROR:", err.message);
|
|
36
|
+
else console.log("Schema verified for access_keys");
|
|
37
|
+
db.close();
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
initSchema();
|
|
44
|
+
|
|
18
45
|
// Hash token using same PBKDF2 as CLI (for verification)
|
|
19
46
|
function hashToken(token) {
|
|
20
47
|
return new Promise((resolve, reject) => {
|
|
@@ -33,7 +60,6 @@ function hashToken(token) {
|
|
|
33
60
|
// Verify token against SQLite access_keys table
|
|
34
61
|
async function verifyToken(token) {
|
|
35
62
|
try {
|
|
36
|
-
const sqlite3 = require("sqlite3").verbose();
|
|
37
63
|
const db = new sqlite3.Database(DB_PATH);
|
|
38
64
|
|
|
39
65
|
const tokenHash = await hashToken(token);
|
|
@@ -25,7 +25,7 @@ services:
|
|
|
25
25
|
- traefik-logs:/var/log/traefik
|
|
26
26
|
labels:
|
|
27
27
|
- traefik.enable=true
|
|
28
|
-
- traefik.http.middlewares.auth-check.forwardauth.address=http://auth-sidecar:3001/
|
|
28
|
+
- traefik.http.middlewares.auth-check.forwardauth.address=http://auth-sidecar:3001/
|
|
29
29
|
- traefik.http.middlewares.auth-check.forwardauth.authResponseHeaders=X-User-Id,X-User-Email,X-User-Name,X-Auth-Method
|
|
30
30
|
restart: unless-stopped
|
|
31
31
|
|
|
@@ -52,26 +52,33 @@ services:
|
|
|
52
52
|
labels:
|
|
53
53
|
- traefik.enable=true
|
|
54
54
|
# Middleware definitions (must be on a service that starts BEFORE routes reference them)
|
|
55
|
-
- traefik.http.middlewares.strip-cybermem.stripprefix.prefixes=/cybermem
|
|
56
55
|
# Authenticated routes
|
|
57
|
-
- traefik.http.routers.mcp.rule=PathPrefix(`/
|
|
56
|
+
- traefik.http.routers.mcp.rule=PathPrefix(`/mcp`) || PathPrefix(`/sse`)
|
|
58
57
|
- traefik.http.routers.mcp.entrypoints=web
|
|
59
58
|
- traefik.http.routers.mcp.priority=100
|
|
60
59
|
- traefik.http.routers.mcp.service=mcp-service
|
|
61
|
-
- traefik.http.routers.mcp.middlewares=auth-check
|
|
60
|
+
- traefik.http.routers.mcp.middlewares=auth-check
|
|
62
61
|
# Public routes (Health/Metrics)
|
|
63
|
-
- traefik.http.routers.mcp-public.rule=PathPrefix(`/
|
|
62
|
+
- traefik.http.routers.mcp-public.rule=PathPrefix(`/health`) || PathPrefix(`/metrics`)
|
|
64
63
|
- traefik.http.routers.mcp-public.entrypoints=web
|
|
65
64
|
- traefik.http.routers.mcp-public.priority=100
|
|
66
65
|
- traefik.http.routers.mcp-public.service=mcp-service
|
|
67
|
-
- traefik.http.routers.mcp-public.middlewares=strip-cybermem
|
|
68
66
|
- traefik.http.services.mcp-service.loadbalancer.server.port=8080
|
|
69
67
|
# Legacy API support (for simple REST clients)
|
|
70
|
-
- traefik.http.routers.legacy-api.rule=PathPrefix(`/
|
|
68
|
+
- traefik.http.routers.legacy-api.rule=PathPrefix(`/add`) || PathPrefix(`/query`) || PathPrefix(`/all`)
|
|
71
69
|
- traefik.http.routers.legacy-api.entrypoints=web
|
|
72
70
|
- traefik.http.routers.legacy-api.priority=100
|
|
73
71
|
- traefik.http.routers.legacy-api.service=mcp-service
|
|
74
|
-
- traefik.http.routers.legacy-api.middlewares=auth-check
|
|
72
|
+
- traefik.http.routers.legacy-api.middlewares=auth-check
|
|
73
|
+
|
|
74
|
+
# Support legacy /cybermem redirect to root
|
|
75
|
+
- traefik.http.middlewares.cybermem-redirect.redirectregex.regex=^https?://[^/]+/cybermem(/.*)?$$
|
|
76
|
+
- traefik.http.middlewares.cybermem-redirect.redirectregex.replacement=/$${1}
|
|
77
|
+
- traefik.http.middlewares.cybermem-redirect.redirectregex.permanent=false
|
|
78
|
+
- traefik.http.routers.cybermem-legacy.rule=PathPrefix(`/cybermem`)
|
|
79
|
+
- traefik.http.routers.cybermem-legacy.entrypoints=web
|
|
80
|
+
- traefik.http.routers.cybermem-legacy.middlewares=cybermem-redirect
|
|
81
|
+
- traefik.http.routers.cybermem-legacy.priority=50
|
|
75
82
|
|
|
76
83
|
# Auth sidecar for JWT/API key validation (ForwardAuth)
|
|
77
84
|
auth-sidecar:
|
|
@@ -83,7 +90,7 @@ services:
|
|
|
83
90
|
API_KEY_FILE: /.env
|
|
84
91
|
volumes:
|
|
85
92
|
- ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/.env:ro
|
|
86
|
-
- ${HOME}/.cybermem/data:/data
|
|
93
|
+
- ${HOME}/.cybermem/data:/data
|
|
87
94
|
labels:
|
|
88
95
|
- traefik.enable=true
|
|
89
96
|
healthcheck:
|
|
@@ -185,11 +192,11 @@ services:
|
|
|
185
192
|
- ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/app/shared.env
|
|
186
193
|
labels:
|
|
187
194
|
- traefik.enable=true
|
|
188
|
-
# Dashboard route:
|
|
195
|
+
# Dashboard route: root -> dashboard on port 3000
|
|
189
196
|
- traefik.http.routers.dashboard.entrypoints=web
|
|
190
|
-
- traefik.http.routers.dashboard.rule=PathPrefix(
|
|
191
|
-
- traefik.http.routers.dashboard.priority=
|
|
192
|
-
- traefik.http.routers.dashboard.middlewares=auth-check
|
|
197
|
+
- traefik.http.routers.dashboard.rule=PathPrefix(`/`)
|
|
198
|
+
- traefik.http.routers.dashboard.priority=1
|
|
199
|
+
- traefik.http.routers.dashboard.middlewares=auth-check
|
|
193
200
|
- traefik.http.services.dashboard.loadbalancer.server.port=3000
|
|
194
201
|
restart: unless-stopped
|
|
195
202
|
depends_on:
|
package/package.json
CHANGED
|
@@ -11,10 +11,37 @@
|
|
|
11
11
|
const http = require("http");
|
|
12
12
|
const crypto = require("crypto");
|
|
13
13
|
const path = require("path");
|
|
14
|
+
const sqlite3 = require("sqlite3").verbose();
|
|
14
15
|
|
|
15
16
|
const PORT = process.env.PORT || 3001;
|
|
16
17
|
const DB_PATH = process.env.OM_DB_PATH || "/data/openmemory.sqlite";
|
|
17
18
|
|
|
19
|
+
// Ensure schema exists
|
|
20
|
+
function initSchema() {
|
|
21
|
+
const db = new sqlite3.Database(DB_PATH);
|
|
22
|
+
db.serialize(() => {
|
|
23
|
+
db.run(
|
|
24
|
+
`
|
|
25
|
+
CREATE TABLE IF NOT EXISTS access_keys (
|
|
26
|
+
key_id TEXT PRIMARY KEY,
|
|
27
|
+
key_hash TEXT UNIQUE NOT NULL,
|
|
28
|
+
user_id TEXT NOT NULL,
|
|
29
|
+
name TEXT,
|
|
30
|
+
is_active INTEGER DEFAULT 1,
|
|
31
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
32
|
+
)
|
|
33
|
+
`,
|
|
34
|
+
(err) => {
|
|
35
|
+
if (err) console.error("SCHEMA ERROR:", err.message);
|
|
36
|
+
else console.log("Schema verified for access_keys");
|
|
37
|
+
db.close();
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
initSchema();
|
|
44
|
+
|
|
18
45
|
// Hash token using same PBKDF2 as CLI (for verification)
|
|
19
46
|
function hashToken(token) {
|
|
20
47
|
return new Promise((resolve, reject) => {
|
|
@@ -33,7 +60,6 @@ function hashToken(token) {
|
|
|
33
60
|
// Verify token against SQLite access_keys table
|
|
34
61
|
async function verifyToken(token) {
|
|
35
62
|
try {
|
|
36
|
-
const sqlite3 = require("sqlite3").verbose();
|
|
37
63
|
const db = new sqlite3.Database(DB_PATH);
|
|
38
64
|
|
|
39
65
|
const tokenHash = await hashToken(token);
|
|
@@ -25,7 +25,7 @@ services:
|
|
|
25
25
|
- traefik-logs:/var/log/traefik
|
|
26
26
|
labels:
|
|
27
27
|
- traefik.enable=true
|
|
28
|
-
- traefik.http.middlewares.auth-check.forwardauth.address=http://auth-sidecar:3001/
|
|
28
|
+
- traefik.http.middlewares.auth-check.forwardauth.address=http://auth-sidecar:3001/
|
|
29
29
|
- traefik.http.middlewares.auth-check.forwardauth.authResponseHeaders=X-User-Id,X-User-Email,X-User-Name,X-Auth-Method
|
|
30
30
|
restart: unless-stopped
|
|
31
31
|
|
|
@@ -52,26 +52,33 @@ services:
|
|
|
52
52
|
labels:
|
|
53
53
|
- traefik.enable=true
|
|
54
54
|
# Middleware definitions (must be on a service that starts BEFORE routes reference them)
|
|
55
|
-
- traefik.http.middlewares.strip-cybermem.stripprefix.prefixes=/cybermem
|
|
56
55
|
# Authenticated routes
|
|
57
|
-
- traefik.http.routers.mcp.rule=PathPrefix(`/
|
|
56
|
+
- traefik.http.routers.mcp.rule=PathPrefix(`/mcp`) || PathPrefix(`/sse`)
|
|
58
57
|
- traefik.http.routers.mcp.entrypoints=web
|
|
59
58
|
- traefik.http.routers.mcp.priority=100
|
|
60
59
|
- traefik.http.routers.mcp.service=mcp-service
|
|
61
|
-
- traefik.http.routers.mcp.middlewares=auth-check
|
|
60
|
+
- traefik.http.routers.mcp.middlewares=auth-check
|
|
62
61
|
# Public routes (Health/Metrics)
|
|
63
|
-
- traefik.http.routers.mcp-public.rule=PathPrefix(`/
|
|
62
|
+
- traefik.http.routers.mcp-public.rule=PathPrefix(`/health`) || PathPrefix(`/metrics`)
|
|
64
63
|
- traefik.http.routers.mcp-public.entrypoints=web
|
|
65
64
|
- traefik.http.routers.mcp-public.priority=100
|
|
66
65
|
- traefik.http.routers.mcp-public.service=mcp-service
|
|
67
|
-
- traefik.http.routers.mcp-public.middlewares=strip-cybermem
|
|
68
66
|
- traefik.http.services.mcp-service.loadbalancer.server.port=8080
|
|
69
67
|
# Legacy API support (for simple REST clients)
|
|
70
|
-
- traefik.http.routers.legacy-api.rule=PathPrefix(`/
|
|
68
|
+
- traefik.http.routers.legacy-api.rule=PathPrefix(`/add`) || PathPrefix(`/query`) || PathPrefix(`/all`)
|
|
71
69
|
- traefik.http.routers.legacy-api.entrypoints=web
|
|
72
70
|
- traefik.http.routers.legacy-api.priority=100
|
|
73
71
|
- traefik.http.routers.legacy-api.service=mcp-service
|
|
74
|
-
- traefik.http.routers.legacy-api.middlewares=auth-check
|
|
72
|
+
- traefik.http.routers.legacy-api.middlewares=auth-check
|
|
73
|
+
|
|
74
|
+
# Support legacy /cybermem redirect to root
|
|
75
|
+
- traefik.http.middlewares.cybermem-redirect.redirectregex.regex=^https?://[^/]+/cybermem(/.*)?$$
|
|
76
|
+
- traefik.http.middlewares.cybermem-redirect.redirectregex.replacement=/$${1}
|
|
77
|
+
- traefik.http.middlewares.cybermem-redirect.redirectregex.permanent=false
|
|
78
|
+
- traefik.http.routers.cybermem-legacy.rule=PathPrefix(`/cybermem`)
|
|
79
|
+
- traefik.http.routers.cybermem-legacy.entrypoints=web
|
|
80
|
+
- traefik.http.routers.cybermem-legacy.middlewares=cybermem-redirect
|
|
81
|
+
- traefik.http.routers.cybermem-legacy.priority=50
|
|
75
82
|
|
|
76
83
|
# Auth sidecar for JWT/API key validation (ForwardAuth)
|
|
77
84
|
auth-sidecar:
|
|
@@ -83,7 +90,7 @@ services:
|
|
|
83
90
|
API_KEY_FILE: /.env
|
|
84
91
|
volumes:
|
|
85
92
|
- ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/.env:ro
|
|
86
|
-
- ${HOME}/.cybermem/data:/data
|
|
93
|
+
- ${HOME}/.cybermem/data:/data
|
|
87
94
|
labels:
|
|
88
95
|
- traefik.enable=true
|
|
89
96
|
healthcheck:
|
|
@@ -185,11 +192,11 @@ services:
|
|
|
185
192
|
- ${CYBERMEM_ENV_PATH:-${HOME}/.cybermem/.env}:/app/shared.env
|
|
186
193
|
labels:
|
|
187
194
|
- traefik.enable=true
|
|
188
|
-
# Dashboard route:
|
|
195
|
+
# Dashboard route: root -> dashboard on port 3000
|
|
189
196
|
- traefik.http.routers.dashboard.entrypoints=web
|
|
190
|
-
- traefik.http.routers.dashboard.rule=PathPrefix(
|
|
191
|
-
- traefik.http.routers.dashboard.priority=
|
|
192
|
-
- traefik.http.routers.dashboard.middlewares=auth-check
|
|
197
|
+
- traefik.http.routers.dashboard.rule=PathPrefix(`/`)
|
|
198
|
+
- traefik.http.routers.dashboard.priority=1
|
|
199
|
+
- traefik.http.routers.dashboard.middlewares=auth-check
|
|
193
200
|
- traefik.http.services.dashboard.loadbalancer.server.port=3000
|
|
194
201
|
restart: unless-stopped
|
|
195
202
|
depends_on:
|