refactor: update dependencies and remove unused code
- Added new dependencies: `adler2`, `crc32fast`, `flate2`, `miniz_oxide`, and `libredox`. - Updated existing dependencies: `tokio-rustls` to version 0.26.4 and `filetime` to version 0.2.27. - Removed the `backup.rs` file as it is no longer needed. - Introduced tests for configuration and credential management. - Enhanced the `identity` module to generate W3C compliant DID documents. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
311
docs/developer-guide.md
Normal file
311
docs/developer-guide.md
Normal file
@@ -0,0 +1,311 @@
|
||||
# Archipelago Developer Guide
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
archy/
|
||||
├── core/ # Rust backend
|
||||
│ └── archipelago/
|
||||
│ ├── src/
|
||||
│ │ ├── main.rs # Entry point, module declarations
|
||||
│ │ ├── api/rpc/ # RPC endpoint handlers
|
||||
│ │ │ ├── mod.rs # Route dispatcher
|
||||
│ │ │ ├── auth.rs # Login, session, TOTP
|
||||
│ │ │ ├── container.rs # Container lifecycle
|
||||
│ │ │ ├── package.rs # Package install/remove
|
||||
│ │ │ ├── interfaces.rs # Network interfaces, WiFi, DNS
|
||||
│ │ │ ├── federation.rs # Federation management
|
||||
│ │ │ ├── marketplace.rs # Community marketplace
|
||||
│ │ │ └── ... # Other endpoint groups
|
||||
│ │ ├── auth.rs # Password hashing, sessions
|
||||
│ │ ├── config.rs # Configuration loading
|
||||
│ │ ├── server.rs # HTTP/WS server (axum)
|
||||
│ │ ├── container/ # Podman integration
|
||||
│ │ ├── network/ # Network management
|
||||
│ │ │ ├── dns.rs # DNS configuration
|
||||
│ │ │ ├── router.rs # UPnP, diagnostics
|
||||
│ │ │ └── dwn_*.rs # DWN protocol
|
||||
│ │ ├── federation.rs # Federation protocol
|
||||
│ │ ├── marketplace.rs # Marketplace discovery
|
||||
│ │ ├── identity.rs # DID key management
|
||||
│ │ ├── vpn.rs # VPN (Tailscale/WireGuard)
|
||||
│ │ ├── mesh.rs # Meshtastic mesh networking
|
||||
│ │ └── ...
|
||||
│ ├── Cargo.toml
|
||||
│ └── tests/ # Integration tests
|
||||
├── neode-ui/ # Vue 3 frontend
|
||||
│ ├── src/
|
||||
│ │ ├── api/ # RPC client, WebSocket, container client
|
||||
│ │ │ └── rpc-client.ts # Central RPC client (all backend calls)
|
||||
│ │ ├── views/ # Page components
|
||||
│ │ │ ├── Home.vue # Dashboard with system stats
|
||||
│ │ │ ├── Marketplace.vue # App store (curated + community)
|
||||
│ │ │ ├── Server.vue # Network, VPN, DNS management
|
||||
│ │ │ ├── Federation.vue # Federation dashboard
|
||||
│ │ │ ├── Settings.vue # User settings
|
||||
│ │ │ ├── Web5.vue # DID, DWN, Nostr
|
||||
│ │ │ └── ...
|
||||
│ │ ├── stores/ # Pinia state management
|
||||
│ │ ├── components/ # Reusable UI components
|
||||
│ │ ├── composables/ # Vue composables
|
||||
│ │ ├── router/ # Vue Router with guards
|
||||
│ │ ├── types/ # TypeScript type definitions
|
||||
│ │ └── style.css # Global styles + Tailwind utilities
|
||||
│ ├── vite.config.ts
|
||||
│ └── package.json
|
||||
├── scripts/ # Deployment and utility scripts
|
||||
│ ├── deploy-to-target.sh # Main deploy script
|
||||
│ ├── first-boot-containers.sh # ISO first-boot setup
|
||||
│ └── run-tests.sh # CI test runner
|
||||
├── image-recipe/ # ISO build configuration
|
||||
│ ├── build-auto-installer-iso.sh
|
||||
│ └── configs/ # Nginx, systemd configs
|
||||
├── docs/ # Documentation
|
||||
│ ├── architecture.md
|
||||
│ ├── app-manifest-spec.md
|
||||
│ ├── marketplace-protocol.md
|
||||
│ └── multi-node-architecture.md
|
||||
├── apps/ # App manifests (YAML)
|
||||
├── CLAUDE.md # AI development instructions
|
||||
└── loop/plan.md # Project roadmap
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **macOS** (development machine): Node.js 20+, npm
|
||||
- **Linux server** (`192.168.1.228`): Rust toolchain, Podman, Nginx, Debian 12
|
||||
- SSH key: `~/.ssh/archipelago-deploy`
|
||||
|
||||
### Local Frontend Development
|
||||
|
||||
```bash
|
||||
cd neode-ui
|
||||
npm install
|
||||
npm start # Vite dev server on :8100, mock backend on :5959
|
||||
```
|
||||
|
||||
The dev server at `http://localhost:8100` uses a mock backend. Login with `password123`.
|
||||
|
||||
### Deploying Changes
|
||||
|
||||
**Never build Rust on macOS.** The deploy script rsyncs source to the Linux server and builds there.
|
||||
|
||||
```bash
|
||||
# Deploy to live server (builds backend + frontend, restarts services)
|
||||
./scripts/deploy-to-target.sh --live
|
||||
|
||||
# Deploy to both servers
|
||||
./scripts/deploy-to-target.sh --both
|
||||
```
|
||||
|
||||
The deploy script:
|
||||
1. Rsyncs source to the server
|
||||
2. Builds Rust backend on the server (`cargo build --release`)
|
||||
3. Builds Vue frontend (`npm run build`)
|
||||
4. Copies artifacts to production paths
|
||||
5. Restarts the `archipelago` systemd service
|
||||
6. Runs a health check
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Frontend tests
|
||||
cd neode-ui && npm test
|
||||
|
||||
# Backend tests (on dev server via SSH)
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
|
||||
"cd ~/archy/core && cargo test --all-features"
|
||||
|
||||
# Both
|
||||
./scripts/run-tests.sh
|
||||
```
|
||||
|
||||
## Adding a New RPC Endpoint
|
||||
|
||||
### 1. Create the Handler
|
||||
|
||||
Add a handler method in the appropriate file under `core/archipelago/src/api/rpc/`. If no existing file fits, create a new one.
|
||||
|
||||
```rust
|
||||
// core/archipelago/src/api/rpc/mymodule.rs
|
||||
use super::RpcHandler;
|
||||
use anyhow::Result;
|
||||
|
||||
impl RpcHandler {
|
||||
/// mymodule.action — description of what it does.
|
||||
pub(super) async fn handle_mymodule_action(
|
||||
&self,
|
||||
params: Option<serde_json::Value>,
|
||||
) -> Result<serde_json::Value> {
|
||||
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
|
||||
let name = params
|
||||
.get("name")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: name"))?;
|
||||
|
||||
// Your logic here
|
||||
let result = do_something(name).await?;
|
||||
|
||||
Ok(serde_json::json!({ "ok": true, "result": result }))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key patterns:**
|
||||
- Handlers are `pub(super)` — visible only to the RPC router
|
||||
- Accept `Option<serde_json::Value>` for params (omit for parameterless endpoints)
|
||||
- Return `Result<serde_json::Value>`
|
||||
- Use `self.config.data_dir` for data persistence
|
||||
- Use `anyhow::bail!()` for error responses
|
||||
|
||||
### 2. Register the Route
|
||||
|
||||
Add the module declaration and route in `core/archipelago/src/api/rpc/mod.rs`:
|
||||
|
||||
```rust
|
||||
// At the top:
|
||||
mod mymodule;
|
||||
|
||||
// In the match statement (handle_rpc_call):
|
||||
"mymodule.action" => self.handle_mymodule_action(params).await,
|
||||
```
|
||||
|
||||
### 3. Add Module (if new)
|
||||
|
||||
If your logic warrants a separate module:
|
||||
|
||||
```rust
|
||||
// core/archipelago/src/main.rs
|
||||
mod mymodule; // Add to module declarations
|
||||
```
|
||||
|
||||
### 4. Frontend Client
|
||||
|
||||
Add a convenience method to `neode-ui/src/api/rpc-client.ts`:
|
||||
|
||||
```typescript
|
||||
async myAction(params: { name: string }): Promise<{ ok: boolean; result: string }> {
|
||||
return this.call({
|
||||
method: 'mymodule.action',
|
||||
params,
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Deploy and Test
|
||||
|
||||
```bash
|
||||
./scripts/deploy-to-target.sh --live
|
||||
curl -X POST http://192.168.1.228/rpc/v1 \
|
||||
-H "Content-Type: application/json" \
|
||||
-b "archipelago_session=YOUR_SESSION" \
|
||||
-d '{"method":"mymodule.action","params":{"name":"test"}}'
|
||||
```
|
||||
|
||||
## Adding a New Vue Page
|
||||
|
||||
### 1. Create the Component
|
||||
|
||||
```vue
|
||||
<!-- neode-ui/src/views/MyPage.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="text-4xl font-bold text-white mb-2">My Page</h1>
|
||||
<div class="glass-card p-6">
|
||||
<!-- Content here -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { rpcClient } from '@/api/rpc-client'
|
||||
|
||||
// State and logic
|
||||
</script>
|
||||
```
|
||||
|
||||
### 2. Add the Route
|
||||
|
||||
In `neode-ui/src/router/index.ts`, add inside the dashboard children:
|
||||
|
||||
```typescript
|
||||
{
|
||||
path: 'my-page',
|
||||
name: 'my-page',
|
||||
component: () => import('@/views/MyPage.vue'),
|
||||
},
|
||||
```
|
||||
|
||||
### 3. Standards
|
||||
|
||||
- Always use `<script setup lang="ts">` — never Options API
|
||||
- Use `glass-card` for containers, `bg-white/5 rounded-lg` for sub-rows
|
||||
- Create global CSS classes in `src/style.css` instead of inline Tailwind
|
||||
- Use `rpcClient` from `@/api/rpc-client.ts` for all backend calls
|
||||
- Handle loading states and errors for all async operations
|
||||
|
||||
## Writing Tests
|
||||
|
||||
### Frontend (Vitest)
|
||||
|
||||
```typescript
|
||||
// neode-ui/src/api/__tests__/my-test.test.ts
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
|
||||
describe('MyFeature', () => {
|
||||
beforeEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('should do something', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ result: 'ok' }),
|
||||
}))
|
||||
|
||||
// Test your logic
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Backend (Rust)
|
||||
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_my_function() {
|
||||
let dir = tempdir().unwrap();
|
||||
let result = my_function(dir.path()).await.unwrap();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Code Quality Checklist
|
||||
|
||||
- [ ] TypeScript strict mode: no `any`, use `unknown` or proper types
|
||||
- [ ] No `unwrap()` or `expect()` in production Rust code — use `?`
|
||||
- [ ] No `console.log` — wrap in `if (import.meta.env.DEV)`
|
||||
- [ ] No empty catch blocks — log or handle errors
|
||||
- [ ] Functions under 50 lines
|
||||
- [ ] `cargo clippy` and `cargo fmt` pass
|
||||
- [ ] `npx vue-tsc --noEmit` passes
|
||||
- [ ] Security: validate all inputs, no command injection
|
||||
- [ ] Container security: readonly_root, no_new_privileges, non-root user
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Create a feature branch: `git checkout -b feature/my-feature`
|
||||
2. Make changes following the standards above
|
||||
3. Test locally: `cd neode-ui && npm test`
|
||||
4. Deploy to dev server: `./scripts/deploy-to-target.sh --live`
|
||||
5. Verify at `http://192.168.1.228`
|
||||
6. Commit with conventional format: `feat: add my feature`
|
||||
Reference in New Issue
Block a user