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.
Files changed (181) hide show
  1. package/NOTICE +9 -0
  2. package/README.md +207 -28
  3. package/SECURITY.md +92 -45
  4. package/dist/THIRD-PARTY-NOTICES.txt +682 -0
  5. package/dist/api/catalog.d.cts +69 -0
  6. package/dist/api/catalog.d.ts +50 -2
  7. package/dist/api/cli-options.d.cts +39 -0
  8. package/dist/api/cli-options.d.ts +39 -0
  9. package/dist/api/client.d.cts +89 -0
  10. package/dist/api/client.d.ts +19 -30
  11. package/dist/api/docs.d.cts +211 -0
  12. package/dist/api/docs.d.ts +211 -0
  13. package/dist/api/guidance.d.cts +81 -0
  14. package/dist/api/guidance.d.ts +81 -0
  15. package/dist/api/index.cjs +6610 -2247
  16. package/dist/api/index.d.cts +13 -0
  17. package/dist/api/index.d.ts +10 -7
  18. package/dist/api/index.js +6610 -2247
  19. package/dist/api/local.cjs +118 -6
  20. package/dist/api/local.d.cts +95 -0
  21. package/dist/api/local.d.ts +70 -6
  22. package/dist/api/local.js +104 -6
  23. package/dist/api/mcp.cjs +17384 -0
  24. package/dist/api/mcp.d.cts +108 -0
  25. package/dist/api/mcp.d.ts +108 -0
  26. package/dist/api/mcp.js +17334 -0
  27. package/dist/api/otlp.d.cts +65 -0
  28. package/dist/api/redact.d.cts +17 -0
  29. package/dist/api/redact.d.ts +17 -0
  30. package/dist/api/requests.d.cts +26 -0
  31. package/dist/api/requests.d.ts +14 -16
  32. package/dist/api/results.d.cts +16 -0
  33. package/dist/api/results.d.ts +2 -1
  34. package/dist/api/tokens.d.cts +7 -0
  35. package/dist/datanotes.cjs +62511 -28069
  36. package/dist/docs/administration/configuration.md +59 -0
  37. package/dist/docs/administration/docker.md +80 -0
  38. package/dist/docs/administration/git-sync.md +71 -0
  39. package/dist/docs/administration/limits.md +69 -0
  40. package/dist/docs/administration/run-the-service.md +219 -0
  41. package/dist/docs/administration/status.md +61 -0
  42. package/dist/docs/administration/use-with-obsidian.md +75 -0
  43. package/dist/docs/api/operations/add_column.md +49 -0
  44. package/dist/docs/api/operations/add_constraint.md +55 -0
  45. package/dist/docs/api/operations/adopt_rows.md +50 -0
  46. package/dist/docs/api/operations/align_relations.md +41 -0
  47. package/dist/docs/api/operations/alter_column.md +46 -0
  48. package/dist/docs/api/operations/alter_table.md +67 -0
  49. package/dist/docs/api/operations/batch.md +48 -0
  50. package/dist/docs/api/operations/changes_stream.md +28 -0
  51. package/dist/docs/api/operations/check_table.md +29 -0
  52. package/dist/docs/api/operations/clone_table.md +48 -0
  53. package/dist/docs/api/operations/comment_on.md +42 -0
  54. package/dist/docs/api/operations/configure_database.md +52 -0
  55. package/dist/docs/api/operations/create_table.md +78 -0
  56. package/dist/docs/api/operations/create_view.md +54 -0
  57. package/dist/docs/api/operations/create_webhook.md +37 -0
  58. package/dist/docs/api/operations/define_base.md +52 -0
  59. package/dist/docs/api/operations/delete_rows.md +43 -0
  60. package/dist/docs/api/operations/delete_webhook.md +31 -0
  61. package/dist/docs/api/operations/describe_database.md +30 -0
  62. package/dist/docs/api/operations/describe_history.md +40 -0
  63. package/dist/docs/api/operations/describe_semantic_index.md +24 -0
  64. package/dist/docs/api/operations/describe_table.md +38 -0
  65. package/dist/docs/api/operations/docs.md +13 -0
  66. package/dist/docs/api/operations/drop_column.md +41 -0
  67. package/dist/docs/api/operations/drop_constraint.md +39 -0
  68. package/dist/docs/api/operations/drop_table.md +43 -0
  69. package/dist/docs/api/operations/drop_view.md +38 -0
  70. package/dist/docs/api/operations/engine_status.md +23 -0
  71. package/dist/docs/api/operations/graph_neighbors.md +32 -0
  72. package/dist/docs/api/operations/graph_path.md +32 -0
  73. package/dist/docs/api/operations/graph_traverse.md +43 -0
  74. package/dist/docs/api/operations/identify_session.md +24 -0
  75. package/dist/docs/api/operations/infer_table.md +43 -0
  76. package/dist/docs/api/operations/insert_row.md +48 -0
  77. package/dist/docs/api/operations/list_changes.md +35 -0
  78. package/dist/docs/api/operations/list_folder.md +28 -0
  79. package/dist/docs/api/operations/list_link_targets.md +44 -0
  80. package/dist/docs/api/operations/list_migrations.md +35 -0
  81. package/dist/docs/api/operations/list_tables.md +32 -0
  82. package/dist/docs/api/operations/list_webhooks.md +23 -0
  83. package/dist/docs/api/operations/manual_index.md +14 -0
  84. package/dist/docs/api/operations/manual_page.md +22 -0
  85. package/dist/docs/api/operations/merge_rows.md +44 -0
  86. package/dist/docs/api/operations/move_rows.md +52 -0
  87. package/dist/docs/api/operations/openapi.md +13 -0
  88. package/dist/docs/api/operations/openapi_post.md +20 -0
  89. package/dist/docs/api/operations/read_note.md +29 -0
  90. package/dist/docs/api/operations/recompute_columns.md +44 -0
  91. package/dist/docs/api/operations/record_tool_call.md +36 -0
  92. package/dist/docs/api/operations/rename_column.md +44 -0
  93. package/dist/docs/api/operations/rename_value.md +45 -0
  94. package/dist/docs/api/operations/restore_database.md +51 -0
  95. package/dist/docs/api/operations/restore_table.md +46 -0
  96. package/dist/docs/api/operations/search_notes.md +28 -0
  97. package/dist/docs/api/operations/select_rows.md +61 -0
  98. package/dist/docs/api/operations/semantic_search.md +34 -0
  99. package/dist/docs/api/operations/semantic_search_docs.md +26 -0
  100. package/dist/docs/api/operations/set_table_bases.md +44 -0
  101. package/dist/docs/api/operations/status.md +13 -0
  102. package/dist/docs/api/operations/stop_engine.md +23 -0
  103. package/dist/docs/api/operations/sync_semantic_index.md +33 -0
  104. package/dist/docs/api/operations/table_changes.md +31 -0
  105. package/dist/docs/api/operations/tags/auxiliary.md +14 -0
  106. package/dist/docs/api/operations/tags/change-feed.md +8 -0
  107. package/dist/docs/api/operations/tags/history.md +17 -0
  108. package/dist/docs/api/operations/tags/queries.md +15 -0
  109. package/dist/docs/api/operations/tags/rows-dml.md +16 -0
  110. package/dist/docs/api/operations/tags/schema-ddl.md +22 -0
  111. package/dist/docs/api/operations/tags/service.md +15 -0
  112. package/dist/docs/api/operations/tags/tokens.md +13 -0
  113. package/dist/docs/api/operations/tokens_create.md +34 -0
  114. package/dist/docs/api/operations/tokens_delete.md +29 -0
  115. package/dist/docs/api/operations/tokens_list.md +21 -0
  116. package/dist/docs/api/operations/tokens_me.md +20 -0
  117. package/dist/docs/api/operations/tokens_rotate.md +29 -0
  118. package/dist/docs/api/operations/tokens_update.md +34 -0
  119. package/dist/docs/api/operations/undo_migration.md +46 -0
  120. package/dist/docs/api/operations/update_row.md +60 -0
  121. package/dist/docs/api/operations/update_rows.md +46 -0
  122. package/dist/docs/api/operations/vacuum_table.md +37 -0
  123. package/dist/docs/api.md +135 -0
  124. package/dist/docs/develop/build-an-app.md +320 -0
  125. package/dist/docs/develop/build-on-datanotes.md +138 -0
  126. package/dist/docs/develop/change-feed-and-webhooks.md +70 -0
  127. package/dist/docs/develop/client.md +116 -0
  128. package/dist/docs/develop/concurrency.md +153 -0
  129. package/dist/docs/develop/http-api.md +79 -0
  130. package/dist/docs/develop/telemetry.md +86 -0
  131. package/dist/docs/guides/agents/docs-offline.md +99 -0
  132. package/dist/docs/guides/agents/how-agents-use-datanotes.md +124 -0
  133. package/dist/docs/guides/agents/prompts.md +495 -0
  134. package/dist/docs/guides/agents/reading-errors.md +112 -0
  135. package/dist/docs/guides/data-quality/check-constraints.md +379 -0
  136. package/dist/docs/guides/data-quality/check-table.md +63 -0
  137. package/dist/docs/guides/data-quality/hand-edits.md +507 -0
  138. package/dist/docs/guides/data-quality/sync-between-devices.md +51 -0
  139. package/dist/docs/guides/data-quality/validation.md +90 -0
  140. package/dist/docs/guides/database-objects/bases.md +480 -0
  141. package/dist/docs/guides/database-objects/catalogs-and-schemas.md +897 -0
  142. package/dist/docs/guides/database-objects/columns.md +1332 -0
  143. package/dist/docs/guides/database-objects/relations.md +1454 -0
  144. package/dist/docs/guides/database-objects/tables.md +1404 -0
  145. package/dist/docs/guides/database-objects/views.md +1003 -0
  146. package/dist/docs/guides/history/back-up.md +195 -0
  147. package/dist/docs/guides/history/change-data-feed.md +247 -0
  148. package/dist/docs/guides/history/journal-and-undo.md +262 -0
  149. package/dist/docs/guides/history/restore.md +341 -0
  150. package/dist/docs/guides/history/table-history.md +657 -0
  151. package/dist/docs/guides/history/vacuum.md +35 -0
  152. package/dist/docs/guides/read-and-write/automatic-links.md +768 -0
  153. package/dist/docs/guides/read-and-write/batch.md +139 -0
  154. package/dist/docs/guides/read-and-write/import-notes.md +896 -0
  155. package/dist/docs/guides/read-and-write/joins-and-aggregates.md +251 -0
  156. package/dist/docs/guides/read-and-write/read-and-filter.md +536 -0
  157. package/dist/docs/guides/read-and-write/write-rows.md +573 -0
  158. package/dist/docs/guides/search/link-graph.md +146 -0
  159. package/dist/docs/guides/search/semantic.md +133 -0
  160. package/dist/docs/guides/search/text.md +142 -0
  161. package/dist/docs/guides/security/security-model.md +110 -0
  162. package/dist/docs/guides/security/tokens.md +60 -0
  163. package/dist/docs/guides/security/who-did-what.md +42 -0
  164. package/dist/docs/index.md +113 -0
  165. package/dist/docs/llms.txt +33 -0
  166. package/dist/docs/reference/cli.md +136 -0
  167. package/dist/docs/reference/compatibility.md +63 -0
  168. package/dist/docs/reference/errors.md +72 -0
  169. package/dist/docs/reference/glossary.md +161 -0
  170. package/dist/docs/reference/operations/auxiliary.md +116 -0
  171. package/dist/docs/reference/operations/history.md +168 -0
  172. package/dist/docs/reference/operations/queries.md +169 -0
  173. package/dist/docs/reference/operations/rows.md +185 -0
  174. package/dist/docs/reference/operations/schema.md +316 -0
  175. package/dist/docs/reference/operations.md +96 -0
  176. package/dist/docs/reference/settings.md +31 -0
  177. package/dist/docs/release-notes.md +67 -0
  178. package/dist/docs/start/connect-agents.md +204 -0
  179. package/dist/docs/start/how-it-works.md +317 -0
  180. package/dist/docs/start/quick-start.md +126 -0
  181. package/package.json +58 -14
@@ -0,0 +1,75 @@
1
+ # Use Datanotes with Obsidian
2
+
3
+ > Run the engine with --vault when an app such as Obsidian opens the whole vault: how paths and wikilinks work, and how to move between a vault and a database folder.
4
+
5
+ Datanotes runs on a database folder by default, with `--database`. Apps such as Obsidian work on a vault instead: a folder of all your notes, where the database is one folder among others. This page shows:
6
+
7
+ * When to start the engine with `--vault`
8
+ * How paths and wikilinks work in a vault
9
+ * How to move between a vault and a database folder
10
+
11
+ ## Choose between a database folder and a vault
12
+
13
+ You have two ways to use Obsidian with Datanotes:
14
+
15
+ * **Open the database folder in Obsidian**: start the engine with `--database`, and open that same folder as an Obsidian vault. The folder’s root is then the vault root, so links resolve as they are. Use it when the database is all you keep in the vault.
16
+ * **Run the engine on the vault**: start the engine with `--vault` on the folder Obsidian opens. The database is a subfolder of the vault. Use it when the vault already holds other notes, or other apps that expect a vault.
17
+
18
+ Start the engine on a vault with `--vault`, or the `DATANOTES_VAULT` variable:
19
+
20
+ ```bash
21
+ npx -y datanotes serve --vault your_vault_folder
22
+ ```
23
+
24
+ Give `--vault` or `--database`, never both: the engine refuses to start with both.
25
+
26
+ ## Find the database in the vault
27
+
28
+ The database is the folder of the vault’s one `metastore.yaml`. A new database goes to `datanotes/`, at the top of the vault. The folder can have any name and sit anywhere in the vault, also in a subfolder. [One database per vault](https://datanotes.dev/administration/run-the-service/#one-database-per-vault) explains how the engine finds it at each start.
29
+
30
+ Rows and plain notes live side by side. A plain note links to a row, and a row links to a plain note, with backlinks on both sides. The engine serves every note of the vault, not only the rows: [`read_note`](https://datanotes.dev/reference/operations/queries/#read_note), [`list_folder`](https://datanotes.dev/reference/operations/queries/#list_folder) and [`search_notes`](https://datanotes.dev/reference/operations/queries/#search_notes) reach them all.
31
+
32
+ ## Read paths and wikilinks from the vault root
33
+
34
+ With `--vault`, every path is relative to the vault. A row of the table `film`, in catalog `main` and schema `public`, has this path:
35
+
36
+ ```text
37
+ datanotes/main/public/film/Metropolis.md
38
+ ```
39
+
40
+ A note at the vault’s root is `intro.md`. Operations take and return paths in this form, and the wikilinks the engine writes start from the vault root too. Obsidian resolves links from the same root, so it follows every link the engine writes.
41
+
42
+ With `--database`, paths start from the database folder instead: the same row is `main/public/film/Metropolis.md`. When you open that folder in Obsidian, its root is the vault root, so links resolve there too.
43
+
44
+ ## Move between a vault and a database folder
45
+
46
+ [`configure_database`](https://datanotes.dev/reference/operations/auxiliary/#configure_database) with `root` moves the database within the folder the engine serves. The move rewrites every link in one operation, as for any [move of the database folder](https://datanotes.dev/start/how-it-works/#move-the-vault-or-the-database-folder).
47
+
48
+ To turn a vault into a database folder, move the database to the vault root with `root: ""`:
49
+
50
+ ```ts
51
+ await db.call("configure_database", { root: "" });
52
+ ```
53
+
54
+ The catalog folders and `metastore.yaml` then sit at the root, and paths lose their `datanotes/` prefix. From the next start, run the engine with `--database` on that folder. The engine refuses the move when a catalog folder or a `metastore.yaml` already exists at the root.
55
+
56
+ To move the database back into a subfolder, give the folder’s name:
57
+
58
+ ```ts
59
+ await db.call("configure_database", { root: "datanotes" });
60
+ ```
61
+
62
+ From the next start, run the engine with `--vault` on the same folder.
63
+
64
+ ## Pass the same option to every command
65
+
66
+ The other commands find the engine by the same folder and option you gave `datanotes serve`:
67
+
68
+ ```bash
69
+ npx -y datanotes status --vault your_vault_folder
70
+ npx -y datanotes stop --vault your_vault_folder
71
+ npx -y datanotes store path --vault your_vault_folder
72
+ npx -y datanotes mcp --vault your_vault_folder
73
+ ```
74
+
75
+ With a database folder, pass `--database your_database_folder` to each instead.
@@ -0,0 +1,49 @@
1
+ # Add a typed column. Sparse by default (written only on rows that have a value — use for
2
+
3
+ `POST /datanotes/operations/add_column/` (operation `add_column`)
4
+
5
+ Add a typed column. Sparse by default (written only on rows that have a value — use for
6
+ metrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label":
7
+ "Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`).
8
+ `description` is required: what the column holds, for the agents and people who read the schema
9
+ (the engine writes it for `identity` "uuid" / "created" columns).
10
+ `dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add
11
+ a column whose meaning an existing column (name/label/aliases/description) already covers.
12
+ Column names are permanent identifiers; only `rename_column` changes them.
13
+ Enum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", …}`): describe_table shows them and a refused value lists them.
14
+ Generated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).
15
+ Filtered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.
16
+
17
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
18
+
19
+ ## Parameters
20
+
21
+ | Name | In | Type | Required | Description |
22
+ | --- | --- | --- | --- | --- |
23
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
24
+
25
+ ## Request body
26
+
27
+ `application/json`, required
28
+
29
+ | Property | Type | Required | Default | Description |
30
+ | --- | --- | --- | --- | --- |
31
+ | `table` | `string` | yes | | |
32
+ | `column` | `object` | yes | | The column's spec: name, type, description and its other attributes; `dense: true` writes it on every row. |
33
+ | `dry_run` | `boolean` | no | `false` | |
34
+
35
+ ## Responses
36
+
37
+ | Status | Description | Body |
38
+ | --- | --- | --- |
39
+ | 200 | Done. | `OpResult` (application/json) |
40
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
41
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
42
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
43
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
44
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
45
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
46
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
47
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
48
+
49
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,55 @@
1
+ # ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,
2
+
3
+ `POST /datanotes/operations/add_constraint/` (operation `add_constraint`)
4
+
5
+ ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,
6
+ e.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL;
7
+ inside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails).
8
+ A key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}`
9
+ (further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` /
10
+ `not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row
11
+ whose parent has no parent). A link to a row that does not exist fails; on a list of links every linked
12
+ row must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a
13
+ missing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the
14
+ vault (by path, from the row's note: same-named rows in two folders stay apart); renaming or moving a
15
+ linked row keeps them (they follow it).
16
+ Refused while existing rows violate it (they are listed); then enforced on every write, by the same rule.
17
+ A write that changes a linked row re-checks the rows that link to it and is refused, listing them, when
18
+ it breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault
19
+ the earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too.
20
+ rename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.
21
+
22
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
23
+
24
+ ## Parameters
25
+
26
+ | Name | In | Type | Required | Description |
27
+ | --- | --- | --- | --- | --- |
28
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
29
+
30
+ ## Request body
31
+
32
+ `application/json`, required
33
+
34
+ | Property | Type | Required | Default | Description |
35
+ | --- | --- | --- | --- | --- |
36
+ | `table` | `string` | yes | | |
37
+ | `name` | `string` | yes | | |
38
+ | `check` | `object` | yes | | |
39
+ | `dry_run` | `boolean` | no | `false` | |
40
+
41
+ ## Responses
42
+
43
+ | Status | Description | Body |
44
+ | --- | --- | --- |
45
+ | 200 | Done. | `OpResult` (application/json) |
46
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
47
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
48
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
49
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
50
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
51
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
52
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
53
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
54
+
55
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,50 @@
1
+ # Turn existing notes (not rows of any table yet) into rows of `table`, keeping their body and
2
+
3
+ `POST /datanotes/operations/adopt_rows/` (operation `adopt_rows`)
4
+
5
+ Turn existing notes (not rows of any table yet) into rows of `table`, keeping their body and
6
+ links: `rename` keys (`{"data": "occurred_at"}`), `set` for all, `per_row` values by
7
+ note path (`{"Home/x.md": {"zone": "[[Kitchen]]"}}`), `drop` keys the table does not have.
8
+ Every note gets `table` and a system `id`; with `relocate` (default true, unlike move_rows:
9
+ notes become rows where the table keeps its rows) it moves to the table's folder, named by its filename pattern (links to it are rewritten). All notes are validated first
10
+ (as rows of `table`, so notes of the same call may link to one another):
11
+ unknown keys and bad values are listed and nothing is written. Run with `dry_run` first; undo
12
+ with `undo_migration`. Many notes: adopt them in calls of about 1,000 `paths` each, so a
13
+ stop or a crash interrupts less (each call is one journal entry).
14
+
15
+ ## Parameters
16
+
17
+ | Name | In | Type | Required | Description |
18
+ | --- | --- | --- | --- | --- |
19
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
20
+
21
+ ## Request body
22
+
23
+ `application/json`, required
24
+
25
+ | Property | Type | Required | Default | Description |
26
+ | --- | --- | --- | --- | --- |
27
+ | `table` | `string` | yes | | |
28
+ | `paths` | `string[]` | yes | | |
29
+ | `rename` | `object \| null` | no | `null` | |
30
+ | `set` | `object \| null` | no | `null` | |
31
+ | `per_row` | `object \| null` | no | `null` | |
32
+ | `drop` | `string[] \| null` | no | `null` | |
33
+ | `relocate` | `boolean` | no | `true` | |
34
+ | `dry_run` | `boolean` | no | `false` | |
35
+
36
+ ## Responses
37
+
38
+ | Status | Description | Body |
39
+ | --- | --- | --- |
40
+ | 200 | Done. | `OpResult` (application/json) |
41
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
42
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
43
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
44
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
45
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
46
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
47
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
48
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
49
+
50
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,41 @@
1
+ # Add the reciprocal links missing on a table's `inverse` link columns (e.g. Alice lists Carol
2
+
3
+ `POST /datanotes/operations/align_relations/` (operation `align_relations`)
4
+
5
+ Add the reciprocal links missing on a table's `inverse` link columns (e.g. Alice lists Carol
6
+ in `friends` but Carol does not list Alice). Run it after declaring `inverse` on existing data;
7
+ check_table reports such rows (code `inverse`). Single-value links already pointing elsewhere
8
+ are conflicts (nothing written). The links it adds are checked like other writes (CHECKs that
9
+ follow links, `ref_where` / `ref_by`). Writes through the tools already keep both sides in step.
10
+
11
+ ## Parameters
12
+
13
+ | Name | In | Type | Required | Description |
14
+ | --- | --- | --- | --- | --- |
15
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
16
+
17
+ ## Request body
18
+
19
+ `application/json`, required
20
+
21
+ | Property | Type | Required | Default | Description |
22
+ | --- | --- | --- | --- | --- |
23
+ | `table` | `string` | yes | | |
24
+ | `paths` | `string[] \| null` | no | `null` | |
25
+ | `dry_run` | `boolean` | no | `false` | |
26
+
27
+ ## Responses
28
+
29
+ | Status | Description | Body |
30
+ | --- | --- | --- |
31
+ | 200 | Done. | `OpResult` (application/json) |
32
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
33
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
34
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
35
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
36
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
37
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
38
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
39
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
40
+
41
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,46 @@
1
+ # Change a column's attributes (type, min/max/step, values, required, default, label,
2
+
3
+ `POST /datanotes/operations/alter_column/` (operation `alter_column`)
4
+
5
+ Change a column's attributes (type, min/max/step, values, required, default, label,
6
+ aliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except
7
+ `description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with
8
+ the list of violating rows when existing values do not satisfy the new definition. A
9
+ different scale means a different column: add a new one instead of rescaling. To rename one
10
+ enum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a
11
+ target level is refused, naming it.
12
+
13
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
14
+
15
+ ## Parameters
16
+
17
+ | Name | In | Type | Required | Description |
18
+ | --- | --- | --- | --- | --- |
19
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
20
+
21
+ ## Request body
22
+
23
+ `application/json`, required
24
+
25
+ | Property | Type | Required | Default | Description |
26
+ | --- | --- | --- | --- | --- |
27
+ | `table` | `string` | yes | | |
28
+ | `column` | `string` | yes | | The column's name. |
29
+ | `changes` | `object` | yes | | |
30
+ | `dry_run` | `boolean` | no | `false` | |
31
+
32
+ ## Responses
33
+
34
+ | Status | Description | Body |
35
+ | --- | --- | --- |
36
+ | 200 | Done. | `OpResult` (application/json) |
37
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
38
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
39
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
40
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
41
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
42
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
43
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
44
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
45
+
46
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,67 @@
1
+ # Alter a table: move it (`catalog`, `schema`), rename it (`name`), change
2
+
3
+ `POST /datanotes/operations/alter_table/` (operation `alter_table`)
4
+
5
+ Alter a table: move it (`catalog`, `schema`), rename it (`name`), change
6
+ `partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,
7
+ `exclude` folders, `row_template`
8
+ ("" removes it), `history` (true | false | "default"), `autolink_target`
9
+ (true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by
10
+ a date or a time) or `tags` (key/value
11
+ labels merged into the table's, e.g. `{"domain": "health"}`; a `null` value removes that tag;
12
+ `clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those),
13
+ `archive` (folder name inside the table folder) or `fields` (untyped fields, name → default; a
14
+ `null` value removes one). Rows, archive and transaction log follow; links are updated; renamed
15
+ rows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,
16
+ history, autolink_target, row_template, fields) rewrites the table entry alone: no row is moved or rewritten. Refused
17
+ when a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows
18
+ links, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not
19
+ rewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.
20
+
21
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
22
+
23
+ ## Parameters
24
+
25
+ | Name | In | Type | Required | Description |
26
+ | --- | --- | --- | --- | --- |
27
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
28
+
29
+ ## Request body
30
+
31
+ `application/json`, required
32
+
33
+ | Property | Type | Required | Default | Description |
34
+ | --- | --- | --- | --- | --- |
35
+ | `table` | `string` | yes | | |
36
+ | `catalog` | `string \| null` | no | `null` | |
37
+ | `schema` | `string \| null` | no | `null` | |
38
+ | `name` | `string \| null` | no | `null` | |
39
+ | `partition` | `string \| null` | no | `null` | |
40
+ | `filename` | `string \| null` | no | `null` | |
41
+ | `description` | `string \| null` | no | `null` | The new description: what a row records (it changes, never goes: "" is refused). |
42
+ | `aliases` | `string[] \| null` | no | `null` | |
43
+ | `history` | `boolean \| "default" \| null` | no | `null` | Keep the table's versions: true, false, or "default" (the database's setting). |
44
+ | `autolink_target` | `boolean \| "default" \| null` | no | `null` | May automatic links link the table's rows? true, false, or "default" (yes, unless its rows are named by a date or a time). |
45
+ | `exclude` | `string[] \| null` | no | `null` | |
46
+ | `row_template` | `string \| null` | no | `null` | Markdown body of new rows; "" removes it. |
47
+ | `tags` | `object \| null` | no | `null` | Tags to add or change (strings); a null value removes that tag. The other tags are kept. |
48
+ | `clear_tags` | `boolean` | no | `false` | Remove every tag first (with `tags`: the table keeps exactly those). |
49
+ | `archive` | `string \| null` | no | `null` | Archive folder: a folder name inside the table folder (e.g. "_archive"); "" = the database default (`archive_folder`). Archived rows follow. |
50
+ | `fields` | `object \| null` | no | `null` | Untyped fields to set (name → default, as in create_table `fields`); a null value removes that field. The other fields are kept; a name cannot be a column. |
51
+ | `dry_run` | `boolean` | no | `false` | |
52
+
53
+ ## Responses
54
+
55
+ | Status | Description | Body |
56
+ | --- | --- | --- |
57
+ | 200 | Done. | `OpResult` (application/json) |
58
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
59
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
60
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
61
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
62
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
63
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
64
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
65
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
66
+
67
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,48 @@
1
+ # Several writes that succeed or fail together. `operations`: `[{"op": ..., ...arguments}]` where
2
+
3
+ `POST /datanotes/operations/batch/` (operation `batch`)
4
+
5
+ Several writes that succeed or fail together. `operations`: `[{"op": ..., ...arguments}]` where
6
+ `op` is a row operation (`insert_row`, `update_row`, `update_rows`, `delete_rows`, `merge_rows`,
7
+ `move_rows`, `adopt_rows`, `recompute_columns`, `align_relations`, `restore_table`) or a DDL op
8
+ (`create_table`, `add_column`, `alter_column`, …), with the same arguments as the operation (an unknown one refuses the batch) (e.g.
9
+ `values` for insert_row, `set` for update_row / update_rows). They run in order, each seeing the previous ones; if one is
10
+ refused, the ones already applied are undone (`rolled_back`). Returns `steps` (per operation, each with its result,
11
+ where `ambiguous_mentions` is as in insert_row) and
12
+ `migration_id`: undo_migration on it reverts the whole batch. Use it when a change spans several
13
+ rows (create an event and update the people in it). `dry_run` checks each operation against the
14
+ current data only.
15
+
16
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
17
+
18
+ ## Parameters
19
+
20
+ | Name | In | Type | Required | Description |
21
+ | --- | --- | --- | --- | --- |
22
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
23
+
24
+ ## Request body
25
+
26
+ `application/json`, required
27
+
28
+ | Property | Type | Required | Default | Description |
29
+ | --- | --- | --- | --- | --- |
30
+ | `operations` | `object[]` | yes | | |
31
+ | `summary` | `string \| null` | no | `null` | |
32
+ | `dry_run` | `boolean` | no | `false` | |
33
+
34
+ ## Responses
35
+
36
+ | Status | Description | Body |
37
+ | --- | --- | --- |
38
+ | 200 | Done. | `object` (application/json) |
39
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
40
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
41
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
42
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
43
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
44
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `object` (application/json) |
45
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `object \| Error` (application/json) |
46
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `object` (application/json) |
47
+
48
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,28 @@
1
+ # The change feed as Server-Sent Events (id = sequence number). Resumes from Last-Event-ID or `since`.
2
+
3
+ `GET /datanotes/changes/stream` (operation `changes_stream`)
4
+
5
+ Same filters as list_changes (`tables`, `kinds`, `columns`: comma-separated; `exclude_actor`; `where`: JSON). A comment line every 25 s keeps proxies from closing the connection; `event: gap` tells the client events were pruned.
6
+
7
+ ## Parameters
8
+
9
+ | Name | In | Type | Required | Description |
10
+ | --- | --- | --- | --- | --- |
11
+ | `since` | query | `string` | no | |
12
+ | `tables` | query | `string` | no | |
13
+ | `kinds` | query | `string` | no | |
14
+ | `columns` | query | `string` | no | |
15
+ | `exclude_actor` | query | `string` | no | |
16
+ | `where` | query | `string` | no | |
17
+ | `Last-Event-ID` | header | `string` | no | |
18
+
19
+ ## Responses
20
+
21
+ | Status | Description | Body |
22
+ | --- | --- | --- |
23
+ | 200 | The events, one `data:` line (JSON) each. | `string` (text/event-stream) |
24
+ | 400 | `where` is not a JSON object. | `Error` (application/json) |
25
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
26
+ | 503 | The change feed is not running. | `Error` (application/json) |
27
+
28
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,29 @@
1
+ # Validate every row against the table (required, types, ranges, enums, links, unknown
2
+
3
+ `POST /datanotes/operations/check_table/` (operation `check_table`)
4
+
5
+ Validate every row against the table (required, types, ranges, enums, links, unknown
6
+ columns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)
7
+
8
+ ## Request body
9
+
10
+ `application/json`
11
+
12
+ | Property | Type | Required | Default | Description |
13
+ | --- | --- | --- | --- | --- |
14
+ | `table` | `string \| null` | no | `null` | Omit to check every table. |
15
+ | `limit` | `integer` | no | `500` | Rows with violations returned (paging). |
16
+ | `offset` | `integer` | no | `0` | Rows with violations skipped first (paging). |
17
+
18
+ ## Responses
19
+
20
+ | Status | Description | Body |
21
+ | --- | --- | --- |
22
+ | 200 | Done. | `object` (application/json) |
23
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
24
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
25
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
26
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
27
+ | 500 | Unexpected error. | `Error` (application/json) |
28
+
29
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,48 @@
1
+ # CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows
2
+
3
+ `POST /datanotes/operations/clone_table/` (operation `clone_table`)
4
+
5
+ CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows
6
+ (deep clone), optionally as of a `version` / `timestamp`. `copy_rows: false` copies the
7
+ definition only (CREATE TABLE LIKE). `target`: `catalog.schema.table`, `schema.table` (in the
8
+ source's catalog) or a name (source's catalog and schema). Useful for experiments, e.g. a sandbox copy
9
+ in the `agent` catalog. The clone is a new table, so it needs the descriptions create_table does: a
10
+ source without them is refused, naming what to describe first (alter_table, alter_column). A past
11
+ version lacking one gets the one the source has now.
12
+
13
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
14
+
15
+ ## Parameters
16
+
17
+ | Name | In | Type | Required | Description |
18
+ | --- | --- | --- | --- | --- |
19
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
20
+
21
+ ## Request body
22
+
23
+ `application/json`, required
24
+
25
+ | Property | Type | Required | Default | Description |
26
+ | --- | --- | --- | --- | --- |
27
+ | `source` | `string` | yes | | |
28
+ | `target` | `string` | yes | | |
29
+ | `version` | `integer \| null` | no | `null` | |
30
+ | `timestamp` | `string \| null` | no | `null` | |
31
+ | `copy_rows` | `boolean` | no | `true` | Copy the rows (default); false copies the definition only (CREATE TABLE LIKE). |
32
+ | `dry_run` | `boolean` | no | `false` | |
33
+
34
+ ## Responses
35
+
36
+ | Status | Description | Body |
37
+ | --- | --- | --- |
38
+ | 200 | Done. | `OpResult` (application/json) |
39
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
40
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
41
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
42
+ | 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
43
+ | 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
44
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
45
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
46
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
47
+
48
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
@@ -0,0 +1,42 @@
1
+ # COMMENT ON CATALOG / SCHEMA: set the `description` of a catalog (`catalog` alone) or of one of its
2
+
3
+ `POST /datanotes/operations/comment_on/` (operation `comment_on`)
4
+
5
+ COMMENT ON CATALOG / SCHEMA: set the `description` of a catalog (`catalog` alone) or of one of its
6
+ schemas (`catalog` and `schema`) in metastore.yaml: what it holds, so agents pick the right place.
7
+ `description` "" removes it. An unknown catalog or schema is refused with the existing ones.
8
+ describe_database and `system.information_schema.catalogs` / `schemata` show it. Undo with
9
+ `undo_migration`. A table's description: alter_table.
10
+
11
+ The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).
12
+
13
+ ## Parameters
14
+
15
+ | Name | In | Type | Required | Description |
16
+ | --- | --- | --- | --- | --- |
17
+ | `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |
18
+
19
+ ## Request body
20
+
21
+ `application/json`, required
22
+
23
+ | Property | Type | Required | Default | Description |
24
+ | --- | --- | --- | --- | --- |
25
+ | `catalog` | `string` | yes | | |
26
+ | `schema` | `string \| null` | no | `null` | A schema of the catalog; omitted, the description is the catalog's. |
27
+ | `description` | `string` | yes | | The new description; "" removes it. |
28
+ | `dry_run` | `boolean` | no | `false` | |
29
+
30
+ ## Responses
31
+
32
+ | Status | Description | Body |
33
+ | --- | --- | --- |
34
+ | 200 | Done. | `OpResult` (application/json) |
35
+ | 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
36
+ | 401 | Missing or wrong bearer token. | `Error` (application/json) |
37
+ | 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
38
+ | 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
39
+ | 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
40
+ | 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |
41
+
42
+ The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).