Skip to content

Commit 04247ae

Browse files
committed
DID refactor #1139
1 parent 7edd51c commit 04247ae

133 files changed

Lines changed: 5082 additions & 2533 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"Bash(grep -n \"pub async fn handle_get_resource\\\\|pub async fn post_commit\" /Users/joep/dev/github/atomicdata-dev/atomic-server/server/src/handlers/*.rs)",
1414
"Bash(cargo tauri --version)",
1515
"Bash(echo $ANDROID_HOME)",
16-
"Bash(adb devices)"
16+
"Bash(adb devices)",
17+
"Bash(echo $PATH)",
18+
"Bash(cargo build:*)"
1719
]
1820
}
1921
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ trace-*.json
88
artifact
99
server/assets_tmp
1010
.netlify
11+
scratchpad

.zed/settings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"terminal": {
3+
"shell": {
4+
"with_arguments": {
5+
"program": "/bin/zsh",
6+
"args": ["--login"]
7+
}
8+
}
9+
}
10+
}

.zed/tasks.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[
2+
{
3+
"label": "run atomic-server (cargo run)",
4+
"command": "cargo run --bin atomic-server",
5+
"cwd": "$ZED_WORKTREE_ROOT"
6+
},
7+
{
8+
"label": "test atomic-server (cargo nextest run)",
9+
"command": "cargo nextest run",
10+
"cwd": "$ZED_WORKTREE_ROOT"
11+
},
12+
{
13+
"label": "run data-browser dev server (pnpm start)",
14+
"command": "pnpm start",
15+
"cwd": "$ZED_WORKTREE_ROOT/browser"
16+
},
17+
{
18+
"label": "test data-browser e2e",
19+
"command": "pnpm test-e2e",
20+
"cwd": "$ZED_WORKTREE_ROOT/browser"
21+
},
22+
{
23+
"label": "test end-to-end / E2E (npm playwright)",
24+
"command": "cd server/e2e_tests/ && npm i && npm run test",
25+
"cwd": "$ZED_WORKTREE_ROOT"
26+
},
27+
{
28+
"label": "build desktop atomic-server tauri",
29+
"command": "cargo tauri build",
30+
"cwd": "$ZED_WORKTREE_ROOT/desktop"
31+
},
32+
{
33+
"label": "dev desktop atomic-server tauri",
34+
"command": "cargo tauri dev",
35+
"cwd": "$ZED_WORKTREE_ROOT/desktop"
36+
},
37+
{
38+
"label": "benchmark criterion atomic-server",
39+
"command": "cargo criterion",
40+
"cwd": "$ZED_WORKTREE_ROOT/server"
41+
},
42+
{
43+
"label": "docs atomic data (mdbook serve)",
44+
"command": "mdbook serve",
45+
"cwd": "$ZED_WORKTREE_ROOT/docs"
46+
},
47+
{
48+
"label": "run SigNoz for tracing locally (docker)",
49+
"command": "git clone https://github.com/SigNoz/signoz.git /tmp/signoz 2>/dev/null || true && cd /tmp/signoz/deploy && docker compose up",
50+
"cwd": "$ZED_WORKTREE_ROOT"
51+
},
52+
{
53+
"label": "dagger call rust-build",
54+
"command": "dagger call rust-build",
55+
"cwd": "$ZED_WORKTREE_ROOT"
56+
}
57+
]

Cargo.lock

Lines changed: 4 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@ members = [
88
"plugin-examples/test-plugin",
99
"atomic-plugin",
1010
]
11+
1112
# Tauri build is deprecated, see
12-
# https://github.com/atomicdata-dev/atomic-server/issues/718
13-
exclude = ["desktop"]

DIDS-DRIVES-ROUTING.md

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Atomic Data is moving away from a fixed "main drive" at the root `/` of a server
66
## Core Concepts
77

88
### 1. Identity vs. Alias
9-
- **Identity (Immutable)**: A Drive is identified by its DID: `did:ad:{genesis}?drive={hash}`.
9+
- **Identity (Immutable)**: A Drive is identified by its DID: `did:ad:{genesis}`.
1010
- **Alias (Mutable)**: A Domain or Subdomain (e.g., `joep.atomicdata.dev`, `localhost:9883`) is an alias that routes to a specific Drive DID.
1111

1212
### 2. Agent-First Onboarding
@@ -21,30 +21,44 @@ The server uses the HTTP `Host` header to determine which Drive to serve:
2121
- `jane.atomicdata.dev` -> Serves Jane's Drive.
2222
- `localhost:9883` -> Serves the developer's default Drive.
2323

24+
### 4. Custom Path Routing
25+
Human-readable access to resources within a Drive is handled via two strategies:
26+
- **Flat Slugs**: If a resource has a `https://atomicdata.dev/properties/path` property (e.g., `path: "/my-blog-post"`), it is served directly at that URL relative to the Drive's domain.
27+
- **Hierarchical Fallback**: If no explicit `path` is found, the server traverses the hierarchy using `PARENT` and `shortname` properties (e.g., `/folders/2026/note`).
28+
2429
---
2530

2631
## Implementation Phases
2732

2833
### Phase 1: Backend Routing & Mapping
29-
- [ ] **Mapping Store**: Implement a mechanism in `atomic-server` to store and query `Host -> Drive DID` mappings.
30-
- [ ] **Host-Based Resolution**: Update the HTTP request handler to check the `Host` header.
31-
- [ ] **Relative Pathing**: Ensure that paths like `/classes` are correctly resolved relative to the Drive DID mapped to the current Host.
34+
- [x] **Mapping Store**: Sled `drive_mapping` tree in `lib/src/db.rs``add_drive_mapping` / `get_drive_did`.
35+
- [x] **Host-Based Resolution**: `appstate.rs::get_drive_did_for_host` — checks explicit mapping, falls back to subdomain query.
36+
- [x] **Relative Pathing**: `db.rs::get_resource_at_path` — traverses hierarchy relative to a Drive DID; supports both flat `path` lookups and hierarchical fallback.
3237

3338
### Phase 2: Drive Lifecycle & Population
34-
- [ ] **Standard Initialization**: Refactor `atomic_lib::populate` so it can be applied to any Drive DID (creating `/classes`, `/tags`, etc. within that drive).
35-
- [ ] **Drive Resource**: Ensure the Drive resource itself contains the necessary metadata (Drive Public Key, Hash, Owner).
39+
- [x] **Standard Initialization**: `atomic_lib::populate::bootstrap` is drive-agnostic and reusable.
40+
- [x] **Drive Resource metadata**: `OnboardingPage.tsx` creates the genesis drive with `write` and `read` set to the agent's DID.
3641

3742
### Phase 3: Server Setup & Onboarding UI
38-
- [ ] **Node Setup State**: Detect when a server has no mappings and enter "Setup Mode".
39-
- [ ] **Setup UI**: A dedicated frontend flow for creating an Agent and the first Drive.
40-
- [ ] **Alias Registration**: A secure way for the first Agent to "claim" the server's primary domain.
43+
- [x] **Node Setup State**: `db.rs::is_uninitialized` + `get_resource.rs` injects `isUninitialized: true` on root responses.
44+
- [x] **Setup UI**: `OnboardingPage.tsx` — generate agent keypair → genesis drive commit → set `INITIAL_DRIVE` on root → show secret.
45+
- [x] **Alias Registration**: `handlers/commit.rs` — after commit, if new resource has `INITIAL_DRIVE` set, calls `store.add_drive_mapping(host, drive_did)` using the `Host` header.
46+
- [x] **Authorization during onboarding**: `handlers/commit.rs` allows unauthenticated writes to `INITIAL_DRIVE` only when the specific host is uninitialized.
4147

4248
### Phase 4: Decentralized Discovery
43-
- [ ] **JSON-AD Headers**: Include the true `did:ad` identity in HTTP responses so clients can switch to P2P resolution.
44-
- [ ] **DHT/Reticulum Announces**: Servers announce the Drive hashes they host to the P2P networks.
49+
- [x] **JSON-AD Headers**: Added `Link: <did:ad:...>; rel="canonical"` response header in `handlers/get_resource.rs` for DID subjects.
50+
- [x] **DHT/Reticulum Announces**: `dht.rs` — periodic `announce_peer(SHA1(drive_did))` every 15 min; DHT fallback resolution in `get_resource.rs`.
51+
- [x] **Explicit Subdomains**: `Subject::Internal` explicitly stores subdomains for reliable multi-tenant routing.
4552

4653
---
4754

55+
## What to work on next (priority order)
56+
57+
1. **Path Uniqueness Validation** — ensure that two resources in the same Drive cannot share the same `path` property during `commit` validation.
58+
2. **Drive-Scoped Search** — update the search endpoint to respect the resolved Drive DID so results are filtered by the current "Tenant".
59+
3. **End-to-end test** — write a server integration test that exercises the full onboarding flow: fresh DB → `isUninitialized` → genesis drive commit → `INITIAL_DRIVE` commit → drive mapping → resource resolution.
60+
4. **Reticulum Pathfinding** — implement the binary announce/resolution logic for `did:ad` over the Reticulum mesh.
61+
4862
## Success Criteria
4963
1. Running `atomic-server` for the first time leads to an Agent/Drive creation flow.
5064
2. Multiple drives can be accessed via subdomains on the same server instance.

browser/data-browser/frontend.log

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
> @tomic/data-browser@0.41.0-beta.0 start /Users/joep/dev/github/atomicdata-dev/atomic-server/browser/data-browser
3+
> vite
4+
5+
6+
VITE v8.0.0 ready in 1634 ms
7+
8+
➜ Local: http://localhost:5173/
9+
➜ Network: http://192.168.0.169:5173/
10+
➜ Network: http://192.168.139.3:5173/
11+
➜ Network: http://192.168.194.0:5173/
12+
➜ Network: http://192.168.215.0:5173/
13+
➜ press h + enter to show help
14+
node:events:485
15+
throw er; // Unhandled 'error' event
16+
^
17+
18+
Error: read EIO
19+
at TTY.onStreamRead (node:internal/stream_base_commons:216:20)
20+
Emitted 'error' event on Interface instance at:
21+
at ReadStream.onerror (node:internal/readline/interface:243:10)
22+
at ReadStream.emit (node:events:507:28)
23+
at emitErrorNT (node:internal/streams/destroy:170:8)
24+
at emitErrorCloseNT (node:internal/streams/destroy:129:3)
25+
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
26+
errno: -5,
27+
code: 'EIO',
28+
syscall: 'read'
29+
}
30+
31+
Node.js v23.11.0

browser/data-browser/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@emotion/is-prop-valid": "^1.4.0",
2020
"@floating-ui/dom": "^1.7.4",
2121
"@modelcontextprotocol/sdk": "^1.23.0",
22+
"@noble/hashes": "^0.5.9",
2223
"@oddbird/css-anchor-positioning": "^0.6.1",
2324
"@openrouter/ai-sdk-provider": "^1.2.5",
2425
"@radix-ui/react-popover": "^1.1.15",
@@ -48,8 +49,8 @@
4849
"@tiptap/suggestion": "^3.11.0",
4950
"@tiptap/y-tiptap": "^3.0.1",
5051
"@tomic/lib": "workspace:*",
51-
"@tomic/react": "workspace:*",
5252
"@tomic/plugin": "workspace:*",
53+
"@tomic/react": "workspace:*",
5354
"@uiw/codemirror-theme-github": "^4.25.3",
5455
"@uiw/react-codemirror": "^4.25.3",
5556
"@wuchale/jsx": "^0.10.1",
@@ -102,7 +103,7 @@
102103
"lint-staged": "^10.5.4",
103104
"types-wm": "^1.1.0",
104105
"typescript": "^5.9.3",
105-
"vite": "^7.3.1",
106+
"vite": "^8.0.0",
106107
"vite-plugin-prismjs": "^0.0.11",
107108
"vite-plugin-pwa": "^1.1.0",
108109
"vite-plugin-webfont-dl": "^3.11.1"

browser/data-browser/src/App.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ const store = new Store({
3333
serverUrl,
3434
});
3535

36+
import { bootstrap } from './bootstrap';
37+
bootstrap(store);
38+
3639
await enableYjs();
3740

3841
store.parseMetaTags();
@@ -44,7 +47,7 @@ declare global {
4447
}
4548

4649
// Fetch all the Properties and Classes - this helps speed up the app.
47-
store.preloadPropsAndClasses();
50+
// store.preloadPropsAndClasses();
4851

4952
registerCustomCreateActions();
5053
// Register global event handlers.

0 commit comments

Comments
 (0)