AkurAI Build
Menu

Public repository / 2e9c26e6274a8310cc2db17fb9390a7af4ab0913

AkurAI-Framework / AGENTS.md

Latest change dbd1e2529b1a8875ac975415d54ef3e98e046457 - merge: worktree agent a89bbaec936462de5 by Ólafur Búi Ólafsson

# AGENTS.md — AkurAI-Framework

> The map. Read this first. Every subsystem is a small, single-responsibility
> crate; every crate is many small files. Land in the right file via the tables
> below — don't grep blind.

## What this is

A **single-binary, pure-Rust, zero-runtime-dependency** full-stack web framework
in the spirit of PocketBase: embedded relational database, auto-generated REST
API from a declarative schema, built-in semantic search, and a from-scratch
client-first frontend toolchain. Copy one binary to a box, run it, done.

## Constitutional principles (do not violate)

1. **Zero runtime dependencies.** The shipped binary links NO external crates —
   `std` only. Internal workspace crates are fine. Dev/test/bench tooling
   (proptest, criterion, Playwright) is allowed; it never enters the binary.
2. **TLS terminates at the edge** (Caddy/nginx). The server speaks plain HTTP on
   localhost. std cannot do TLS and we will not pull a crate for it.
3. **Client-first.** The browser does rendering, routing, and state. The server
   serves the data API and does SSR only for SEO / dynamic content that needs it.
   Keep the server lean.
4. **No-build frontend.** Native ES modules + import maps + web components +
   server-rendered HTML. NO JS bundler/transpiler. Win DX/memory by subtraction.
5. **Declarative source of truth.** `backend/collections.toml` defines the data
   model; the API, validation, migrations, and embeddings all derive from it.
6. **Self-describing.** `GET /api/_meta` emits a machine-readable manifest of
   every generated route. Agents discover the whole surface in one call.
7. **TDD, always.** Failing test first, every phase. No subsystem advances
   without its test layer (unit → property → integration → e2e/visual).
8. **Performance is a gate, not a hope.** Budgets (cold start, idle memory,
   hot-reload latency, throughput) are asserted; regressions fail the release.
9. **Small scoped files.** One responsibility per file. If a file grows two
   concerns, split it and index it here.
10. **Docs are first-class.** Maintain a `/docs` documentation site in a
    Next.js/Vue-style layout (sidebar nav, sectioned guides + API reference) and
    keep it updated as the framework evolves — every new crate or feature ships
    with its docs in the same commit.
11. **Data updates without a rebuild — essential.** All application data lives
    in the runtime data store (crash-safe, WAL-style durability) and editable
    context files (e.g. `backend/page.json`), never compiled into the binary.
    Changing data must NEVER require recompiling or redeploying the binary.

## Crate map

| Crate | Owns | Status |
|-------|------|--------|
| `crates/http` | HTTP/1.1 server, request/response, thread pool, connection upgrade, SSE — pure std | 🟢 working |
| `crates/ws` | WebSocket server (RFC 6455): handshake, framing, sha1+base64, conn — pure std | 🟢 working |
| `crates/router` | URL pattern matcher: static/`:param`/`*wildcard` → params, specificity-ranked — pure std; wired into `serve` via `backend/routes.json` | 🟢 working |
| `crates/cli` | `akurai new \| serve \| dev` — bootstrap + lean static server | 🟢 working |
| `crates/json` | std-only JSON parse/serialize/value (int/float preserved) | 🟢 working |
| `crates/storage` | single-file pager ✅, node codec ✅, CoW B+tree + atomic meta + free list ✅; **wired into `serve`** via cli `store.rs`; blobs/rebalance next | 🟢 working |
| `crates/sql` | lexer ✅ + recursive-descent parser ✅ (SQL text → AST) for SELECT/INSERT/CREATE TABLE + WHERE expr tree; **parser-only** — planner/executor/catalog/types/MVCC next | 🟡 parser-only |
| `crates/vector` | embedding client, vector store, cosine + HNSW semantic search | ⬜ planned |
| `crates/api` | schema, auto-router, filter/rules DSL, auth, records, `/_meta` | ⬜ planned |
| `crates/template` | std-only SSR template engine (vars, if/for/include) | 🟢 working |
| `crates/markdown` | std-only Markdown → HTML (docs + changelog) | 🟢 working |
| `crates/css` | from-scratch atomic/utility CSS engine (Tailwind-class): scan classes → generate only-used utilities via `build()` — pure std | 🟢 working |
| `crates/assets` | static-asset pipeline: content-hash fingerprinting (`fingerprint`/`hashed_name`) + conservative `minify_css`/`minify_js` — pure std | 🟢 working |
| `crates/server` | (folded into `crates/cli` for now) SSR-on-demand later | ⬜ planned |
| `bench` | criterion micro-benchmarks + whole-stack load gen + perf budgets | ⬜ planned |

### `crates/http` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/request.rs` | parse the HTTP request head + `body`/`content_length`/`body_str` | ✅ |
| `src/form.rs` | `application/x-www-form-urlencoded` parse + percent-decode | ✅ |
| `src/lib.rs` | crate root, module exports | ✅ |
| `src/response.rs` | build/write HTTP responses (`to_bytes` + head-only `to_head_bytes`) | ✅ |
| `src/reply.rs` | `Reply` (Response \| Upgrade) — the connection-hijack seam | ✅ |
| `src/server.rs` | `TcpListener` accept loop; upgrades go to a dedicated thread; `run`/`run_with(stack, handler)` | ✅ |
| `src/pool.rs` | std thread pool (`mpsc` + workers) | ✅ |
| `src/sse.rs` | Server-Sent Events stream (`text/event-stream`, spec framing) | ✅ |
| `src/middleware.rs` | `Middleware` trait + ordered `MiddlewareStack` (first pushed = outermost) | ✅ |
| `src/middleware_builtins.rs` | built-ins: `SecurityHeaders`, `RequestLogger`, `Timing` | ✅ |
| `tests/middleware.rs` | end-to-end: `run_with` stack adds headers + short-circuits over a real socket | ✅ |

### `crates/ws` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/lib.rs` | crate root + `upgrade(req, on_conn)` entry (101 or 400) | ✅ |
| `src/handshake.rs` | recognise WS upgrade + compute `Sec-WebSocket-Accept` | ✅ |
| `src/sha1.rs` | from-scratch SHA-1 (handshake only) + FIPS test vectors | ✅ |
| `src/base64.rs` | from-scratch base64 encode (RFC 4648) | ✅ |
| `src/frame.rs` | RFC 6455 §5 frame read/write, masking, length, limits | ✅ |
| `src/message.rs` | `Message` enum + RFC 6455 §7.4.1 close codes | ✅ |
| `src/conn.rs` | `WsConn`: reassembly, auto ping/pong, close handshake | ✅ |
| `tests/echo.rs` | end-to-end: real handshake + masked echo + close | ✅ |

### `crates/json` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/value.rs` | `Value` enum (order-preserving objects) + serializer | ✅ |
| `src/parse.rs` | recursive-descent parser (escapes, unicode, int/float) | ✅ |
| `src/error.rs` | parse error with character position | ✅ |

### `crates/sql` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/lib.rs` | crate root + `parse(sql) -> Result<Statement, SqlError>` + AST re-exports | ✅ |
| `src/token.rs` | `Token` + `Keyword` table (case-insensitive) + position-tagged `SpannedToken` | ✅ |
| `src/lexer.rs` | `tokenize` — SQL text → token stream; strings (`''` escape), numbers, operators, positions | ✅ |
| `src/ast.rs` | AST types: `Statement`, `SelectStmt`, `InsertStmt`, `CreateTableStmt`, `Expr`, `Literal`, … | ✅ |
| `src/parser.rs` | recursive-descent parser; WHERE expr tree with `AND`>`OR` precedence climbing | ✅ |
| `src/error.rs` | `SqlError { message, position }` — positioned, never panics | ✅ |
| _next_ | planner + executor over the storage B+tree, catalog, type checking, txn/MVCC | ⬜ |

### `crates/storage` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/pager.rs` | single-file fixed-size page read/write/allocate + `sync` | ✅ |
| `src/node.rs` | B+tree node byte layout: leaf + interior encode/decode | ✅ |
| `src/meta.rs` | double-buffered checksummed meta page + inline free list | ✅ |
| `src/tree.rs` | CoW `BTree`: get/insert/delete/range, splits, atomic commit | ✅ |
| `tests/pager.rs` | integration: round-trip, persistence, durability, bounds | ✅ |
| `tests/tree.rs` | integration: torn-commit recovery, bulk reopen, range | ✅ |
| _next_ | underfull-node merge/rebalance, blobs (overflow pages), MVCC | ⬜ |

### `crates/cli` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/main.rs` | arg parsing + command dispatch (`new`/`serve`/`dev`/`version`) | ✅ |
| `src/cmd_new.rs` | bootstrap a project from embedded templates | ✅ |
| `src/cmd_serve.rs` | static server + `/api/health`, `/api/_meta`, SPA fallback; route layouts (wrap a page in a shared shell via `{{{ content }}}`); per-route data loaders (merge `backend/<data>.json` into the render context, traversal-safe) | ✅ |
| `src/mime.rs` | file-extension → MIME mapping | ✅ |
| `src/dev_reload.rs` | dev-only SSE live-reload: file watcher + broadcast + script inject | ✅ |
| `src/routes.rs` | load `backend/routes.json` → `akurai-router` of `RouteDef { template, layout, data }`; inject params into context; optional per-route `layout` + `data` loader file | ✅ |
| `src/seo.rs` | `robots.txt` + `sitemap.xml` (static routes only) + per-route `<head>` meta (`meta_title`/`meta_description`); `site_url` from `page.json` | ✅ |
| `src/store.rs` | append/list record store on the B+tree (`data/store.db`), JSON values, u64 keys | ✅ |
| `src/guestbook.rs` | form-actions demo: POST validate + **persist to B+tree** + PRG redirect | ✅ |
| `assets/*` | embedded starter page + config/collection templates | ✅ |

### `crates/css` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/lib.rs` | crate root + `build(sources: &[&str]) -> String` (scan all → emit only-used utilities, first-seen order) | ✅ |
| `src/scan.rs` | extract class tokens from `class="…"`/`class='…'` attrs; word-boundary match, dedup, first-seen order | ✅ |
| `src/utilities.rs` | utility grammar: class → CSS declaration body (keyword table + parametric 4px spacing) | ✅ |
| `src/generate.rs` | assemble compact `.class{decl}` rules for recognised utilities, preserving order | ✅ |
| `tests/build.rs` | end-to-end: HTML snippet → exactly the used rules; cross-source dedup | ✅ |

### `crates/assets` files

| File | Responsibility | Status |
|------|----------------|--------|
| `src/lib.rs` | crate root + re-exports (`fingerprint`, `hashed_name`, `minify_css`, `minify_js`) | ✅ |
| `src/fingerprint.rs` | 64-bit FNV-1a content hash → lowercase hex; `hashed_name` inserts hash before the extension | ✅ |
| `src/minify.rs` | conservative `minify_css` (comments/whitespace, preserves strings + `url()`) and `minify_js` (comment/blank-line strip, preserves strings + templates) | ✅ |
| `tests/pipeline.rs` | end-to-end: minify → fingerprint → hashed name; determinism + sensitivity | ✅ |

## Directory layout

```
AkurAI-Framework/
├── AGENTS.md            ← this file (the index)
├── CHANGELOG.md         ← Keep-a-Changelog; deploy.sh cuts releases
├── VERSION              ← starts 0.0.1; deploy.sh bumps lockstep
├── deploy.sh            ← gate → bump → changelog → tag → push (creates repo)
├── Cargo.toml           ← workspace root
├── crates/              ← one subsystem per crate, small files
├── frontend/            ← native-ESM SPA + admin UI (embedded at build)
├── backend/             ← collections.toml, rules/, migrations/ (declarative SSOT)
├── data/                ← store.db + blobs/ (gitignored)
├── site/                ← the framework's OWN website (the framework serves it):
│                          frontend/ (landing, docs.html, components.html,
│                          signals.js = no-build reactivity runtime + reactivity.html,
│                          spa.js = opt-in client-side SPA router + spa.html) +
│                          content/ (docs/*.md, changelog.md) + backend/page.json.
│                          Deployed to akurai-framework.olibuijr.com via deploy.sh ec2.
└── tests/e2e/           ← Playwright visual scripts + screenshot snapshots
```

## Semantic search (built-in, all collections)

Embedding model runs externally (OpenAI-compatible endpoint, e.g. Titan
EmbeddingGemma at `:8081`). The framework owns storage + search in pure Rust:
auto-embed configured text fields on write → store vector → rank by similarity.
Brute-force cosine first (fine at small/medium scale), HNSW later for scale.
Every collection gets `?search=<text>` for free.

## Testing & release

- **Unit:** inline `#[cfg(test)]` per module.
- **Property/fuzz:** proptest against SQL parser + B-tree invariants (dev-dep).
- **Integration:** `tests/` per crate (real DB files, real HTTP).
- **E2E/visual:** Playwright in `tests/e2e/` with screenshot snapshots; locally
  also verify with Interceptor (real Chrome).
- **Perf:** `bench/` with criterion + a load generator; budgets enforced in `deploy.sh`.
- **Release:** `./deploy.sh [patch|minor|major]` runs the gate, bumps VERSION +
  crate manifests, cuts the CHANGELOG, tags `vX.Y.Z`, pushes (creating the GitHub
  repo on first run).

### Changelog policy

**Every feature ships its changelog entry in the same commit** — the same rule
the docs follow (principle #10). Two files, always together:

- `CHANGELOG.md` — developer-facing, detailed; under `## [Unreleased]`.
- `site/content/changelog.md` — visitor-facing, curated; under `## Unreleased`.

A non-blocking `pre-commit` hook nudges you when a commit touches `crates/**` or
`site/frontend/**` without staging `CHANGELOG.md`. It only warns (always exits
0) so docs-only / refactor / WIP commits are never blocked. Enable it once per
clone:

```
git config core.hooksPath scripts/hooks
```

`deploy.sh` then cuts both `## [Unreleased]` / `## Unreleased` sections into a
dated, versioned release in lockstep.

## Roadmap (build order — each gated by its tests)

1. HTTP core + JSON
2. Storage engine (CoW B+tree, crash-safe) — the bedrock
3. SQL-A: single-table SELECT/INSERT/UPDATE/DELETE, WHERE, ORDER BY, LIMIT
4. SQL-B: indexes + index selection, JOIN, GROUP BY/aggregates
5. SQL-C: optimizer, hash joins, subqueries, txn/MVCC hardening
6. Vector/semantic search
7. Auto-API layer (schema → routes → `/_meta`)
8. Auth + relations + SSE realtime + uploads
9. CSS engine (dev watch + build) + frontend + admin UI
10. SSR-on-demand + perf-budget enforcement