Menu
Public repository / 2d36cd6c72fc6a63a7edb87bb54a4020e50f2f8a
AkurAI-Drive / AGENTS.md
Latest change 2a704b4150242ecb374ce9d885a11e2a4b158d39 - docs: document the sync/file API + native client in AGENTS.md by olibuijr
# AGENTS.md — AkurAI Drive
A private, Iceland-hosted file cloud, part of the AkurAI platform. Live at
**https://akurai-drive.olibuijr.com** (EC2 `mail.olibuijr.com` / 3.94.46.219).
## Two components
**1. Marketing site (`site/`)** — branded landing + onboarding, served by the
**AkurAI-Framework** single binary (`akurai serve --dir site/frontend`):
```
akurai-ec2 deploy-binary akurai-drive <akurai-musl-bin> 8095 ~/Projects/AkurAI-Drive/site
```
- `site/frontend/index.html` — the whole landing (self-contained native-ESM, no build):
hero, features, how-it-works, pricing, security band. Every CTA → `/auth/login`.
- Built from the already-compiled framework binary; **do NOT modify
`~/Projects/AkurAI-Framework`** (another session owns it via `fw-*` worktrees).
**2. Backend API (`backend/`)** — `akurai-drive-api`, a Rust/axum service that mirrors
`~/Projects/akurai-idp` (axum + rusqlite + musl). Deployed by `backend/deploy.sh`:
systemd `akurai-drive-api.service` (User=drive), `127.0.0.1:8096`, env in
`/etc/akurai-drive-api.env`, DB `/data/akurai-drive/drive.sqlite`.
- `GET /auth/login` → sets a `drive_oauth_state` cookie, 302 to the IDP `/authorize`.
- `GET /auth/callback` → state check, exchanges the code at the IDP over **localhost
http (`127.0.0.1:3500`, no TLS)** with `client_secret_basic`, calls `/userinfo`,
creates a `drive_session`, 302 to `/app`.
- `GET /auth/logout`, `GET /api/me` (identity + `is_admin` = groups ∋ `drive-admins`),
`GET /api/storage` (session-scoped bucket list).
- `POST /api/storage` — **the gate**: requires header `X-Drive-Access-Code` ==
`DRIVE_ACCESS_CODE` (else 403), then a valid session (else 401), then provisions a
real bucket via `aws s3api create-bucket` (`<prefix>-<slug(org)>-<6hex>`), records it.
- `GET /app` → the logged-in dashboard (`static/app.html`, `include_str!`); 302 to
`/auth/login` without a session.
- **Sync/file API** (accepts a `drive_session` cookie OR `Authorization: Bearer <device-token>`;
every op validates the bucket is owned by the caller via the `storage` table → 404 otherwise):
- `GET /auth/device?redirect=<loopback>` → mints a ~365-day device token, 302 to
`<loopback>?token=…` (loopback-only; threads `return_to` through the OAuth state so login
resumes here). This is how the native client authenticates — no IDP client, no embedded secret.
- `GET /api/buckets` · `GET /api/files?bucket=&prefix=` (via `aws s3api list-objects-v2`)
- `POST /api/files/presign {bucket,key,op:put|get}` → an **in-house SigV4** presigned URL
(`src/sigv4.rs`; the box's `aws s3 presign` is GET-only/SigV2). Client PUTs/GETs **directly to
S3** — bytes never touch the box.
- `DELETE /api/files {bucket,key}` (via `aws s3api delete-object`).
## Native sync client (`client/`)
`akurai-drive-sync` — a Rust CLI (Dropbox-style) that syncs a local folder with the user's bucket.
`login` (browser → loopback device token), `init <folder> --bucket`, `sync` (bidirectional;
sqlite sync-state; conflict = keep-both), `daemon` (inotify + 30s poll), `status`. Files move
client ↔ S3 via presigned URLs. Install: `client/install.sh` (→ `~/.local/bin` + a `--user`
systemd service). Config + state under `~/.config/akurai-drive/`.
## Routing (nginx vhost on the box)
`/auth/*`, `/api/`, `/app`, `/healthz` → backend `:8096`; everything else (`/`, static) →
framework `:8095`. The default-server catch-all (`000-default-https`) returns a clean 404 for
unmatched hosts.
## The gate
The early-access code is enforced **in the backend** via the `DRIVE_ACCESS_CODE` env var.
Its value lives ONLY in `/etc/akurai-drive-api.env` on the box — never committed here,
never in the frontend (the user types it into the create-storage form). Change it = edit
the env file + `systemctl restart akurai-drive-api`.
## Auth / AWS
OIDC client `AkurAI Drive` (`client_id 7d0d50e0…`), admin = IDP group `drive-admins`.
S3 via a scoped IAM user `akurai-drive-s3` (create/delete + objects on `akurai-drive-*`
only), keys in the backend env. AWS CLI v2 is installed on the box.
## Conventions
- `data/` and `target/` are gitignored. Verify deploys with
`curl --resolve akurai-drive.olibuijr.com:443:3.94.46.219 …`.
- See memory `akurai-drive-project`, `idp-location-ec2`, `aws-ec2-ops`.
## Next
Files plane: browser ↔ S3 direct via SigV4 **presigned URLs** (server signs only —
HMAC-SHA256 — bytes never touch the box); a file-manager UI on `/app`; per-tenant bucket
policy/CORS; remove the early-access gate for GA.