datanotes 2.0.1 → 3.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/NOTICE +9 -0
- package/README.md +207 -28
- package/SECURITY.md +92 -45
- package/dist/THIRD-PARTY-NOTICES.txt +682 -0
- package/dist/api/catalog.d.cts +69 -0
- package/dist/api/catalog.d.ts +50 -2
- package/dist/api/cli-options.d.cts +39 -0
- package/dist/api/cli-options.d.ts +39 -0
- package/dist/api/client.d.cts +89 -0
- package/dist/api/client.d.ts +19 -30
- package/dist/api/docs.d.cts +211 -0
- package/dist/api/docs.d.ts +211 -0
- package/dist/api/guidance.d.cts +81 -0
- package/dist/api/guidance.d.ts +81 -0
- package/dist/api/index.cjs +6610 -2247
- package/dist/api/index.d.cts +13 -0
- package/dist/api/index.d.ts +10 -7
- package/dist/api/index.js +6610 -2247
- package/dist/api/local.cjs +118 -6
- package/dist/api/local.d.cts +95 -0
- package/dist/api/local.d.ts +70 -6
- package/dist/api/local.js +104 -6
- package/dist/api/mcp.cjs +17384 -0
- package/dist/api/mcp.d.cts +108 -0
- package/dist/api/mcp.d.ts +108 -0
- package/dist/api/mcp.js +17334 -0
- package/dist/api/otlp.d.cts +65 -0
- package/dist/api/redact.d.cts +17 -0
- package/dist/api/redact.d.ts +17 -0
- package/dist/api/requests.d.cts +26 -0
- package/dist/api/requests.d.ts +14 -16
- package/dist/api/results.d.cts +16 -0
- package/dist/api/results.d.ts +2 -1
- package/dist/api/tokens.d.cts +7 -0
- package/dist/datanotes.cjs +62511 -28069
- package/dist/docs/administration/configuration.md +59 -0
- package/dist/docs/administration/docker.md +80 -0
- package/dist/docs/administration/git-sync.md +71 -0
- package/dist/docs/administration/limits.md +69 -0
- package/dist/docs/administration/run-the-service.md +219 -0
- package/dist/docs/administration/status.md +61 -0
- package/dist/docs/administration/use-with-obsidian.md +75 -0
- package/dist/docs/api/operations/add_column.md +49 -0
- package/dist/docs/api/operations/add_constraint.md +55 -0
- package/dist/docs/api/operations/adopt_rows.md +50 -0
- package/dist/docs/api/operations/align_relations.md +41 -0
- package/dist/docs/api/operations/alter_column.md +46 -0
- package/dist/docs/api/operations/alter_table.md +67 -0
- package/dist/docs/api/operations/batch.md +48 -0
- package/dist/docs/api/operations/changes_stream.md +28 -0
- package/dist/docs/api/operations/check_table.md +29 -0
- package/dist/docs/api/operations/clone_table.md +48 -0
- package/dist/docs/api/operations/comment_on.md +42 -0
- package/dist/docs/api/operations/configure_database.md +52 -0
- package/dist/docs/api/operations/create_table.md +78 -0
- package/dist/docs/api/operations/create_view.md +54 -0
- package/dist/docs/api/operations/create_webhook.md +37 -0
- package/dist/docs/api/operations/define_base.md +52 -0
- package/dist/docs/api/operations/delete_rows.md +43 -0
- package/dist/docs/api/operations/delete_webhook.md +31 -0
- package/dist/docs/api/operations/describe_database.md +30 -0
- package/dist/docs/api/operations/describe_history.md +40 -0
- package/dist/docs/api/operations/describe_semantic_index.md +24 -0
- package/dist/docs/api/operations/describe_table.md +38 -0
- package/dist/docs/api/operations/docs.md +13 -0
- package/dist/docs/api/operations/drop_column.md +41 -0
- package/dist/docs/api/operations/drop_constraint.md +39 -0
- package/dist/docs/api/operations/drop_table.md +43 -0
- package/dist/docs/api/operations/drop_view.md +38 -0
- package/dist/docs/api/operations/engine_status.md +23 -0
- package/dist/docs/api/operations/graph_neighbors.md +32 -0
- package/dist/docs/api/operations/graph_path.md +32 -0
- package/dist/docs/api/operations/graph_traverse.md +43 -0
- package/dist/docs/api/operations/identify_session.md +24 -0
- package/dist/docs/api/operations/infer_table.md +43 -0
- package/dist/docs/api/operations/insert_row.md +48 -0
- package/dist/docs/api/operations/list_changes.md +35 -0
- package/dist/docs/api/operations/list_folder.md +28 -0
- package/dist/docs/api/operations/list_link_targets.md +44 -0
- package/dist/docs/api/operations/list_migrations.md +35 -0
- package/dist/docs/api/operations/list_tables.md +32 -0
- package/dist/docs/api/operations/list_webhooks.md +23 -0
- package/dist/docs/api/operations/manual_index.md +14 -0
- package/dist/docs/api/operations/manual_page.md +22 -0
- package/dist/docs/api/operations/merge_rows.md +44 -0
- package/dist/docs/api/operations/move_rows.md +52 -0
- package/dist/docs/api/operations/openapi.md +13 -0
- package/dist/docs/api/operations/openapi_post.md +20 -0
- package/dist/docs/api/operations/read_note.md +29 -0
- package/dist/docs/api/operations/recompute_columns.md +44 -0
- package/dist/docs/api/operations/record_tool_call.md +36 -0
- package/dist/docs/api/operations/rename_column.md +44 -0
- package/dist/docs/api/operations/rename_value.md +45 -0
- package/dist/docs/api/operations/restore_database.md +51 -0
- package/dist/docs/api/operations/restore_table.md +46 -0
- package/dist/docs/api/operations/search_notes.md +28 -0
- package/dist/docs/api/operations/select_rows.md +61 -0
- package/dist/docs/api/operations/semantic_search.md +34 -0
- package/dist/docs/api/operations/semantic_search_docs.md +26 -0
- package/dist/docs/api/operations/set_table_bases.md +44 -0
- package/dist/docs/api/operations/status.md +13 -0
- package/dist/docs/api/operations/stop_engine.md +23 -0
- package/dist/docs/api/operations/sync_semantic_index.md +33 -0
- package/dist/docs/api/operations/table_changes.md +31 -0
- package/dist/docs/api/operations/tags/auxiliary.md +14 -0
- package/dist/docs/api/operations/tags/change-feed.md +8 -0
- package/dist/docs/api/operations/tags/history.md +17 -0
- package/dist/docs/api/operations/tags/queries.md +15 -0
- package/dist/docs/api/operations/tags/rows-dml.md +16 -0
- package/dist/docs/api/operations/tags/schema-ddl.md +22 -0
- package/dist/docs/api/operations/tags/service.md +15 -0
- package/dist/docs/api/operations/tags/tokens.md +13 -0
- package/dist/docs/api/operations/tokens_create.md +34 -0
- package/dist/docs/api/operations/tokens_delete.md +29 -0
- package/dist/docs/api/operations/tokens_list.md +21 -0
- package/dist/docs/api/operations/tokens_me.md +20 -0
- package/dist/docs/api/operations/tokens_rotate.md +29 -0
- package/dist/docs/api/operations/tokens_update.md +34 -0
- package/dist/docs/api/operations/undo_migration.md +46 -0
- package/dist/docs/api/operations/update_row.md +60 -0
- package/dist/docs/api/operations/update_rows.md +46 -0
- package/dist/docs/api/operations/vacuum_table.md +37 -0
- package/dist/docs/api.md +135 -0
- package/dist/docs/develop/build-an-app.md +320 -0
- package/dist/docs/develop/build-on-datanotes.md +138 -0
- package/dist/docs/develop/change-feed-and-webhooks.md +70 -0
- package/dist/docs/develop/client.md +116 -0
- package/dist/docs/develop/concurrency.md +153 -0
- package/dist/docs/develop/http-api.md +79 -0
- package/dist/docs/develop/telemetry.md +86 -0
- package/dist/docs/guides/agents/docs-offline.md +99 -0
- package/dist/docs/guides/agents/how-agents-use-datanotes.md +124 -0
- package/dist/docs/guides/agents/prompts.md +495 -0
- package/dist/docs/guides/agents/reading-errors.md +112 -0
- package/dist/docs/guides/data-quality/check-constraints.md +379 -0
- package/dist/docs/guides/data-quality/check-table.md +63 -0
- package/dist/docs/guides/data-quality/hand-edits.md +507 -0
- package/dist/docs/guides/data-quality/sync-between-devices.md +51 -0
- package/dist/docs/guides/data-quality/validation.md +90 -0
- package/dist/docs/guides/database-objects/bases.md +480 -0
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +897 -0
- package/dist/docs/guides/database-objects/columns.md +1332 -0
- package/dist/docs/guides/database-objects/relations.md +1454 -0
- package/dist/docs/guides/database-objects/tables.md +1404 -0
- package/dist/docs/guides/database-objects/views.md +1003 -0
- package/dist/docs/guides/history/back-up.md +195 -0
- package/dist/docs/guides/history/change-data-feed.md +247 -0
- package/dist/docs/guides/history/journal-and-undo.md +262 -0
- package/dist/docs/guides/history/restore.md +341 -0
- package/dist/docs/guides/history/table-history.md +657 -0
- package/dist/docs/guides/history/vacuum.md +35 -0
- package/dist/docs/guides/read-and-write/automatic-links.md +768 -0
- package/dist/docs/guides/read-and-write/batch.md +139 -0
- package/dist/docs/guides/read-and-write/import-notes.md +896 -0
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +251 -0
- package/dist/docs/guides/read-and-write/read-and-filter.md +536 -0
- package/dist/docs/guides/read-and-write/write-rows.md +573 -0
- package/dist/docs/guides/search/link-graph.md +146 -0
- package/dist/docs/guides/search/semantic.md +133 -0
- package/dist/docs/guides/search/text.md +142 -0
- package/dist/docs/guides/security/security-model.md +110 -0
- package/dist/docs/guides/security/tokens.md +60 -0
- package/dist/docs/guides/security/who-did-what.md +42 -0
- package/dist/docs/index.md +113 -0
- package/dist/docs/llms.txt +33 -0
- package/dist/docs/reference/cli.md +136 -0
- package/dist/docs/reference/compatibility.md +63 -0
- package/dist/docs/reference/errors.md +72 -0
- package/dist/docs/reference/glossary.md +161 -0
- package/dist/docs/reference/operations/auxiliary.md +116 -0
- package/dist/docs/reference/operations/history.md +168 -0
- package/dist/docs/reference/operations/queries.md +169 -0
- package/dist/docs/reference/operations/rows.md +185 -0
- package/dist/docs/reference/operations/schema.md +316 -0
- package/dist/docs/reference/operations.md +96 -0
- package/dist/docs/reference/settings.md +31 -0
- package/dist/docs/release-notes.md +67 -0
- package/dist/docs/start/connect-agents.md +204 -0
- package/dist/docs/start/how-it-works.md +317 -0
- package/dist/docs/start/quick-start.md +126 -0
- package/package.json +58 -14
package/NOTICE
CHANGED
|
@@ -2,3 +2,12 @@ Datanotes
|
|
|
2
2
|
Copyright 2026 Davide Fornelli
|
|
3
3
|
|
|
4
4
|
This product is licensed under the Apache License, Version 2.0 (see LICENSE).
|
|
5
|
+
|
|
6
|
+
The `datanotes` command (dist/datanotes.cjs) bundles third-party software, each under its own
|
|
7
|
+
license: dist/THIRD-PARTY-NOTICES.txt lists every package with its license and copyright.
|
|
8
|
+
|
|
9
|
+
It includes Swagger UI (https://github.com/swagger-api/swagger-ui), licensed under the Apache
|
|
10
|
+
License, Version 2.0, whose NOTICE reads:
|
|
11
|
+
|
|
12
|
+
swagger-ui
|
|
13
|
+
Copyright 2020-2021 SmartBear Software Inc.
|
package/README.md
CHANGED
|
@@ -1,53 +1,232 @@
|
|
|
1
1
|
# Datanotes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Datanotes is the open-source database engine for Markdown: it runs a folder of notes as typed, validated tables that your programs and AI agents query, write and undo over MCP or HTTP, while every row stays a plain file you own.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/datanotes)
|
|
6
|
+
[](https://github.com/davidefornelli/datanotes/actions/workflows/ci.yml)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
<!-- Hero GIF goes here: an agent writes a row over MCP, the engine refuses a bad value and explains the fix, then the note opens as plain Markdown. -->
|
|
9
10
|
|
|
10
11
|
**Documentation: [datanotes.dev](https://datanotes.dev)**
|
|
11
12
|
|
|
13
|
+
## Why Datanotes
|
|
14
|
+
|
|
15
|
+
- **Agents can't write garbage.** Every write is checked against its table: types, links, unique values and CHECK constraints. A refused write changes nothing. Its answer says which value broke which rule and how to fix it.
|
|
16
|
+
- **Every change can be undone.** The engine journals every write it makes. It records who made it: the agent, its session and its token. `undo_migration` takes any change back.
|
|
17
|
+
- **It's still just Markdown.** A row is a note, and its front matter keys are the columns. Read it, edit it, grep it or commit it to Git. The engine reads your hand edits and checks them too.
|
|
18
|
+
- **Local first.** Datanotes is Apache-2.0 and runs on your machine. Nothing leaves it unless you turn that feature on.
|
|
19
|
+
|
|
20
|
+
## When not to use it
|
|
21
|
+
|
|
22
|
+
Datanotes keeps every row as a file, so it isn't a replacement for SQLite or Postgres. Choose a classic database for:
|
|
23
|
+
|
|
24
|
+
- Large analytical datasets
|
|
25
|
+
- High write throughput
|
|
26
|
+
- Many concurrent writers on one folder
|
|
27
|
+
|
|
28
|
+
Datanotes is comfortable at 10,000 notes. At 50,000 notes, the engine takes 22 to 115 seconds to start.
|
|
29
|
+
|
|
12
30
|
## Quick start
|
|
13
31
|
|
|
14
|
-
|
|
32
|
+
You need Node.js 22 or newer. On Windows, use Node.js 24.16 or newer, or 26.1 or newer.
|
|
33
|
+
|
|
34
|
+
Start the engine on a folder, which becomes your database. It can be empty, or hold notes already:
|
|
15
35
|
|
|
16
36
|
```bash
|
|
17
|
-
npx -y datanotes serve --
|
|
37
|
+
npx -y datanotes serve --database your_database_folder
|
|
18
38
|
```
|
|
19
39
|
|
|
20
|
-
|
|
21
|
-
Local-REST-API-style `/vault/*` and `/search/simple/`), with the owner's token in
|
|
22
|
-
`<vault>/.datanotes/service.json`. From code:
|
|
40
|
+
[Run Datanotes on your notes](https://datanotes.dev/start/quick-start/) walks you through your first table.
|
|
23
41
|
|
|
24
|
-
|
|
25
|
-
import { DatanotesClient } from "datanotes/client";
|
|
42
|
+
## Connect your agents
|
|
26
43
|
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
Agents reach the engine through its Model Context Protocol (MCP) server, `datanotes mcp`. It uses the engine that runs on the folder, or starts one. Every client runs the same command:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx -y datanotes mcp --database your_database_folder
|
|
29
48
|
```
|
|
30
49
|
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
<details>
|
|
51
|
+
<summary>Claude Code</summary>
|
|
33
52
|
|
|
34
|
-
|
|
53
|
+
```bash
|
|
54
|
+
claude mcp add datanotes -- \
|
|
55
|
+
npx -y datanotes mcp --database your_database_folder
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
</details>
|
|
59
|
+
|
|
60
|
+
<details>
|
|
61
|
+
<summary>Claude Desktop</summary>
|
|
62
|
+
|
|
63
|
+
Add the server to `claude_desktop_config.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"datanotes": {
|
|
69
|
+
"command": "npx",
|
|
70
|
+
"args": [
|
|
71
|
+
"-y", "datanotes", "mcp", "--database", "your_database_folder"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
</details>
|
|
79
|
+
|
|
80
|
+
<details>
|
|
81
|
+
<summary>Cursor</summary>
|
|
35
82
|
|
|
36
|
-
|
|
37
|
-
- [Operations](https://datanotes.dev/reference/tools/)
|
|
38
|
-
- [Connect agents (datanotes-mcp)](https://datanotes.dev/start/connect-agents/)
|
|
39
|
-
- [JavaScript client](https://datanotes.dev/guides/client/)
|
|
40
|
-
- [Apps](https://datanotes.dev/guides/apps/)
|
|
41
|
-
- [Obsidian client](https://datanotes.dev/guides/obsidian/)
|
|
83
|
+
Add the server to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json`:
|
|
42
84
|
|
|
43
|
-
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"datanotes": {
|
|
89
|
+
"command": "npx",
|
|
90
|
+
"args": [
|
|
91
|
+
"-y", "datanotes", "mcp", "--database", "your_database_folder"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
</details>
|
|
99
|
+
|
|
100
|
+
<details>
|
|
101
|
+
<summary>VS Code</summary>
|
|
102
|
+
|
|
103
|
+
Add the server to `.vscode/mcp.json` in your workspace:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"servers": {
|
|
108
|
+
"datanotes": {
|
|
109
|
+
"type": "stdio",
|
|
110
|
+
"command": "npx",
|
|
111
|
+
"args": [
|
|
112
|
+
"-y", "datanotes", "mcp", "--database", "your_database_folder"
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
44
118
|
|
|
45
|
-
|
|
46
|
-
which data leaves the machine (only what you turn on).
|
|
119
|
+
</details>
|
|
47
120
|
|
|
48
|
-
|
|
121
|
+
<details>
|
|
122
|
+
<summary>Codex</summary>
|
|
123
|
+
|
|
124
|
+
Add the server to `~/.codex/config.toml`:
|
|
125
|
+
|
|
126
|
+
```toml
|
|
127
|
+
[mcp_servers.datanotes]
|
|
128
|
+
command = "npx"
|
|
129
|
+
args = ["-y", "datanotes", "mcp", "--database", "your_database_folder"]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
</details>
|
|
133
|
+
|
|
134
|
+
<details>
|
|
135
|
+
<summary>Windows</summary>
|
|
136
|
+
|
|
137
|
+
On Windows, clients start `npx` through `cmd /c`. For Claude Code, outside Windows Subsystem for Linux (WSL):
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
claude mcp add datanotes -- cmd /c npx -y datanotes mcp --database C:\Notes
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
In a JSON file, the command is `cmd` and the backslashes are escaped:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"mcpServers": {
|
|
148
|
+
"datanotes": {
|
|
149
|
+
"command": "cmd",
|
|
150
|
+
"args": [
|
|
151
|
+
"/c", "npx", "-y", "datanotes", "mcp", "--database", "C:\\Notes"
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
</details>
|
|
159
|
+
|
|
160
|
+
[Connect your agents](https://datanotes.dev/start/connect-agents/) covers HTTP transport and named tokens.
|
|
161
|
+
|
|
162
|
+
## Use it from TypeScript
|
|
163
|
+
|
|
164
|
+
Install the package with `npm install datanotes`. This script finds the engine on your folder, creates a table and queries it:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
import { DatanotesClient } from "datanotes/client";
|
|
168
|
+
import { localEngine } from "datanotes/local";
|
|
169
|
+
|
|
170
|
+
const engine = localEngine("your_database_folder");
|
|
171
|
+
if (!engine) throw new Error("Start the engine on the folder first");
|
|
172
|
+
const db = new DatanotesClient({ url: engine.url, token: engine.token });
|
|
173
|
+
|
|
174
|
+
const created = await db.call("create_table", {
|
|
175
|
+
name: "film",
|
|
176
|
+
description: "Classic films I watched or want to watch",
|
|
177
|
+
filename: "{title}",
|
|
178
|
+
columns: [
|
|
179
|
+
{
|
|
180
|
+
name: "title",
|
|
181
|
+
type: "string",
|
|
182
|
+
required: true,
|
|
183
|
+
unique: true,
|
|
184
|
+
description: "The film's title, as on its poster",
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "minutes",
|
|
188
|
+
type: "integer",
|
|
189
|
+
min: 1,
|
|
190
|
+
description: "Running time in minutes",
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
if (!created.ok) throw new Error(String(created.value));
|
|
195
|
+
|
|
196
|
+
await db.call("insert_row", {
|
|
197
|
+
table: "film",
|
|
198
|
+
values: { title: "Nosferatu", minutes: 94 },
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Refused: nothing is written, and the answer explains why
|
|
202
|
+
const bad = await db.call("insert_row", {
|
|
203
|
+
table: "film",
|
|
204
|
+
values: { title: "Metropolis", minutes: 0 },
|
|
205
|
+
});
|
|
206
|
+
if (!bad.ok) console.log(bad.value);
|
|
207
|
+
|
|
208
|
+
const films = await db.call("select_rows", {
|
|
209
|
+
table: "film",
|
|
210
|
+
where: { minutes: { gt: 90 } },
|
|
211
|
+
});
|
|
212
|
+
console.log(films.value);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Each film is now a note, `main/public/film/Nosferatu.md`, with the values in its front matter. The [JavaScript client](https://datanotes.dev/develop/client/) page covers the rest of the client.
|
|
216
|
+
|
|
217
|
+
## Stability: Datanotes 3 stays 3
|
|
218
|
+
|
|
219
|
+
Every 3.x version adds to what you use and never takes it away. Operations, arguments, answer fields, routes, commands and settings keep working the same way. [Compatibility](https://datanotes.dev/reference/compatibility/) explains the promise and how the tests enforce it.
|
|
220
|
+
|
|
221
|
+
## Learn more
|
|
49
222
|
|
|
50
|
-
|
|
223
|
+
- [Documentation](https://datanotes.dev)
|
|
224
|
+
- [How it works](https://datanotes.dev/start/how-it-works/)
|
|
225
|
+
- [Operations](https://datanotes.dev/reference/operations/)
|
|
226
|
+
- [Use Datanotes with Obsidian](https://datanotes.dev/administration/use-with-obsidian/)
|
|
227
|
+
- [Contributing](CONTRIBUTING.md)
|
|
228
|
+
- [Security](SECURITY.md)
|
|
229
|
+
- [License](LICENSE)
|
|
51
230
|
|
|
52
231
|
## License
|
|
53
232
|
|
package/SECURITY.md
CHANGED
|
@@ -1,61 +1,108 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Datanotes is an engine that reads and writes a folder of Markdown notes, the vault. It runs on your own machine, for you and the agents you choose. This page explains:
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
- How to report a vulnerability
|
|
6
|
+
- Which versions get security fixes
|
|
7
|
+
- What the engine exposes on the network
|
|
8
|
+
- What each token can do
|
|
9
|
+
- How the engine guards your files and its store
|
|
10
|
+
- How to limit what an agent can do
|
|
11
|
+
- Which features send data off your machine
|
|
8
12
|
|
|
9
|
-
##
|
|
13
|
+
## Report a vulnerability
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
run on your own machine, for you and the agents you choose.
|
|
15
|
+
Report vulnerabilities only through GitHub Private Vulnerability Reporting. Open a [new private advisory](https://github.com/davidefornelli/datanotes/security/advisories/new) on the repository. It’s the one channel for security reports. Don’t report them in public issues or discussions. You’ll get an answer within a week.
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
Include these details in your report:
|
|
15
18
|
|
|
16
|
-
- The
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
`/datanotes/docs` (an interactive console over it, with its script and stylesheet) answer without
|
|
20
|
-
a token. They contain no data from the vault: the same description is published on the website.
|
|
21
|
-
The console's page loads nothing from other hosts (Content-Security-Policy: same origin only);
|
|
22
|
-
its calls need a token, which it keeps in the browser's local storage until you log out.
|
|
23
|
-
- To reach it from outside (a phone, a hosted assistant), publish it through a reverse proxy or a
|
|
24
|
-
tunnel, over HTTPS, and give each device or agent its own app token. Publish the MCP server
|
|
25
|
-
(`datanotes-mcp serve`) the same way: it holds no credentials and passes each agent's token on.
|
|
19
|
+
- The Datanotes version
|
|
20
|
+
- How to reproduce the problem
|
|
21
|
+
- What an attacker gains
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
## Supported versions
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
| --- | --- | --- |
|
|
31
|
-
| Owner token | `httpServerToken` in the settings | Everything: data, schema, apps, webhooks, undo. Keep it on the machine. |
|
|
32
|
-
| App token | created with `POST /datanotes/apps/create/` (owner only), stored hashed | Read everything; write only the tables in its `write` patterns; change the schema only with `ddl`. It cannot create webhooks, manage apps or undo; with `maintain` it may also undo, restore, vacuum, configure and rebuild the semantic index (an agent's own token). |
|
|
25
|
+
Security fixes go to the latest release of Datanotes 3.
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
| Version | Supported |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| 3.x | Yes |
|
|
30
|
+
| 2.x | No: it was a preview |
|
|
31
|
+
| 1.x | No: it was a preview |
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
and are self-reported; the credential (`auth`: `owner` or `app`, and the app's name) is set
|
|
39
|
-
by the server and cannot be claimed.
|
|
33
|
+
Update to the latest 3.x release to get a fix.
|
|
40
34
|
|
|
41
|
-
|
|
35
|
+
## What the engine exposes on the network
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
refused, both by the engine's operations and by the file host. Symbolic links inside the vault are
|
|
45
|
-
followed: do not link to folders you would not give the engine.
|
|
37
|
+
The engine’s HTTP server listens on `127.0.0.1`, so only your machine can reach it, unless you start it with `--host`. It answers no Cross-Origin Resource Sharing (CORS) preflight, so web pages can’t call it.
|
|
46
38
|
|
|
47
|
-
|
|
39
|
+
Three routes answer without a token:
|
|
48
40
|
|
|
49
|
-
|
|
41
|
+
- **`GET /`**: the status and the version
|
|
42
|
+
- **`GET /datanotes/openapi.json`**: the API’s description
|
|
43
|
+
- **`/datanotes/docs`**: an interactive console over that description, with its script and stylesheet
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
45
|
+
These routes contain no data from your vault: the website publishes the same description. The console’s page loads nothing from other hosts, because its Content Security Policy (CSP) allows the same origin only. Its calls need a token, which the browser keeps in local storage until you log out.
|
|
46
|
+
|
|
47
|
+
To reach the engine from another device, such as a phone or a hosted assistant, publish it through a reverse proxy or a tunnel, over HTTPS. Give each device or agent its own named token. Publish the Model Context Protocol (MCP) server, `datanotes mcp serve`, the same way: it holds no credentials and passes each agent’s token on to the engine.
|
|
48
|
+
|
|
49
|
+
## Credentials and what they can do
|
|
50
|
+
|
|
51
|
+
The engine accepts two kinds of token, and the owner token can do everything a named token can. Prefer a named token per device, program or agent: it has only the permissions it needs, and the journal names it. MCP clients use the same tokens, because the MCP server passes them to the engine.
|
|
52
|
+
|
|
53
|
+
### Owner token
|
|
54
|
+
|
|
55
|
+
The owner token is `httpServerToken` in the settings file. It can do everything: read and write data, change the schema, manage tokens and webhooks, undo, and read the engine’s status. `datanotes status` reads it from the settings file. Keep it on the machine.
|
|
56
|
+
|
|
57
|
+
### Named token
|
|
58
|
+
|
|
59
|
+
The owner creates a named token with `POST /datanotes/tokens/create/`, and the engine stores only its hash, in `tokens.json` in its store, outside the vault. A named token has these permissions:
|
|
60
|
+
|
|
61
|
+
- **Read**: everything
|
|
62
|
+
- **Write rows**: only the tables in its `write` patterns
|
|
63
|
+
- **Change the schema**: only with `ddl`
|
|
64
|
+
- **Maintain**: with `maintain`, it may also undo, restore, vacuum, configure the database and rebuild the semantic index; use it for an agent’s own token
|
|
65
|
+
|
|
66
|
+
A named token can’t create webhooks, manage tokens or read the engine’s status, and without `maintain` it can’t undo.
|
|
67
|
+
|
|
68
|
+
### Who made each write
|
|
69
|
+
|
|
70
|
+
The engine journals every write with its actor. The client sends the agent’s name, model and session, so they’re self-reported. The server sets the credential, `auth` (`owner`, or the named token’s name), and no client can claim another one.
|
|
71
|
+
|
|
72
|
+
## File access inside the vault
|
|
73
|
+
|
|
74
|
+
The engine resolves every path inside the vault. Both its operations and its file host refuse a path that contains `..`, a backslash, a drive letter or a NUL character.
|
|
75
|
+
|
|
76
|
+
The engine follows symbolic links inside the vault. Don’t link to folders you wouldn’t give the engine.
|
|
77
|
+
|
|
78
|
+
## A private store
|
|
79
|
+
|
|
80
|
+
The engine’s store holds its secrets: the owner token in `settings.json` and the webhooks’ secrets in `webhooks.json`. It also holds the journal and the hashes of the named tokens. On Linux and macOS, the engine keeps the store private to the user that runs it:
|
|
81
|
+
|
|
82
|
+
- **Folders**: the data home and each store are created with mode `0700`
|
|
83
|
+
- **Files**: `settings.json`, `webhooks.json` and the other files of the store are created with mode `0600`
|
|
84
|
+
- **At start**: the engine tightens a data home, a store, a settings file or a `webhooks.json` that an older version left readable by others
|
|
85
|
+
|
|
86
|
+
On Windows, the store lives in your user profile, which other users can’t read. The Docker image runs the engine with `umask 077`, so every file it creates is private too.
|
|
87
|
+
|
|
88
|
+
## Agents and prompt injection
|
|
89
|
+
|
|
90
|
+
An agent reads your notes, and a note can hold text written to manipulate it: a prompt injection. A web page you clipped or an email you saved can tell the agent to delete rows or to send your data out. The engine can’t tell such text from your own notes.
|
|
91
|
+
|
|
92
|
+
Limit what each agent can do:
|
|
93
|
+
|
|
94
|
+
- **Give it a named token**: grant only the tables it writes, and leave out `ddl` and `maintain` unless it needs them
|
|
95
|
+
- **Give it only the tools it needs**: start the MCP server with `datanotes mcp --profile`, `--tools` or `--except`
|
|
96
|
+
- **Keep the webhook tools off**: they’re off by default, because a webhook sends change events to any URL
|
|
97
|
+
|
|
98
|
+
Every write is journaled with the agent’s name, so you can review it and undo it.
|
|
99
|
+
|
|
100
|
+
## Data that leaves your machine
|
|
101
|
+
|
|
102
|
+
Nothing leaves your machine unless you turn it on. These features send data out:
|
|
103
|
+
|
|
104
|
+
- **Semantic search**: sends note text to the embedding provider you configure. It’s off by default (`semanticEnabled`), and you choose the provider with `semanticProvider` and `semanticBaseUrl`. A local provider, such as Ollama or LM Studio, keeps the text on your machine.
|
|
105
|
+
- **Telemetry**: sends logs to the OpenTelemetry Protocol (OTLP) endpoint you configure. It’s off by default (`telemetryEnabled`). The logs contain operations, routes, note paths, actors, tool names and error messages, which may quote a value, but not note bodies. The settings file stores `telemetryHeaders`, which may hold an API key; set `OTEL_EXPORTER_OTLP_HEADERS` instead to keep the key out of it.
|
|
106
|
+
- **Webhooks**: the owner creates them, and the engine posts change events to the URLs they name.
|
|
107
|
+
- **Git sync**: with `--git-sync`, the engine pushes the vault to its git remote.
|
|
108
|
+
- **Store backup**: it’s off by default (`storeBackupEnabled`). When on, the engine pushes its store to the git remote you configure. The backup holds the journal, the transaction logs, the blobs, the change feed and the named tokens’ hashes. The journal, the logs and the feed quote your notes’ values. The backup leaves out `settings.json` and `webhooks.json`, which hold the secrets. Use a private repository.
|