AkurAI Build
Menu

Public repository / cf42bae0c0ef14d96eaa22dacc1ca5dd68fd15ed

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.