Readme
Cufflink
Deploy CRUD microservices in seconds. Define your data model in Rust, run cufflink deploy , and get a full REST API with PostgreSQL persistence, automatic schema migrations, NATS events, and multi-tenant isolation.
Architecture
┌─────────────┐ ┌──────────────┐ ┌───────────┐
│ Cufflink │────> │ Platform │────> │ PostgreSQL│
│ CLI │ │ ( Axum) │ │ │
└─────────────┘ └──────┬───────┘ └───────────┘
│
┌─────────────┐ ┌──────┴───────┐ ┌───────────┐
│ Web Admin │────> │ Dynamic │────> │ NATS │
│ ( Next. js) │ │ CRUD Router │ │ JetStream │
└─────────────┘ └──────────────┘ └───────────┘
SDK — # [ derive ( Table ) ] proc macros generate JSON manifests from Rust structs
CLI — cufflink deploy captures the manifest and POSTs it to the platform
Platform — Applies schema migrations, registers CRUD routes, publishes events
Web Admin — Dashboard for browsing services, data, schemas, and deployments
Quick Start
Prerequisites
Rust 1.70+
Docker & Docker Compose
docker compose up - d
This starts PostgreSQL, NATS, Keycloak, the Cufflink platform, and the web admin.
Platform API: http://localhost:8080
Web Admin: http://localhost:3000
NATS Monitoring: http://localhost:8222
2. Define a service
// examples/todo-service/src/main.rs
use cufflink:: prelude:: * ;
# [ derive ( Table, Serialize, Deserialize, Clone ) ]
# [ table ( name = " todos" ) ]
pub struct Todo {
# [ key ] pub id : Uuid,
pub title : String,
pub completed : bool ,
# [ timestamp ] pub created_at : DateTime< Utc> ,
# [ timestamp ] pub updated_at : DateTime< Utc> ,
}
cufflink:: service! {
name: " todo-service" ,
tables: [ Todo] ,
}
For services with authentication and permissions:
# [ derive ( Table, Serialize, Deserialize, Clone ) ]
# [ table ( name = " todos" , auth_required, permission_area = " todos" ) ]
pub struct Todo { /* ... */ }
cufflink:: service! {
name: " todo-service" ,
tables: [ Todo] ,
authorization: [
areas: [ ( " todos" , [ " create" , " view" , " edit" , " delete" ] ) ] ,
default_roles: [
( " admin" , " Full access" , [ " todos:*" ] ) ,
( " viewer" , " Read-only" , [ " todos:view" ] ) ,
] ,
] ,
}
3. Deploy
cd examples/todo-service
cargo run - p cufflink -- deploy
4. Use the API
# Create
curl -X POST http://localhost:8080/svc/default/todo-service/todos \
-H "Content-Type: application/json" \
-d '{"title": "Buy groceries", "completed": false}'
# List (with filtering, sorting, search, pagination)
curl "http://localhost:8080/svc/default/todo-service/todos?sort=-created_at&per_page=10"
# Search
curl "http://localhost:8080/svc/default/todo-service/todos?search=groceries"
# Filter
curl --get http://localhost:8080/svc/default/todo-service/todos \
--data-urlencode 'filter=[{"n":"completed","f":"=","v":"false"}]'
# Get by ID
curl http://localhost:8080/svc/default/todo-service/todos/{id}
# Update
curl -X PUT http://localhost:8080/svc/default/todo-service/todos/{id} \
-H "Content-Type: application/json" \
-d '{"completed": true}'
# Delete
curl -X DELETE http://localhost:8080/svc/default/todo-service/todos/{id}
SDK Reference
Table Attributes
Attribute
Description
# [ table ( name = " ..." ) ]
SQL table name (required)
# [ table ( auth_required ) ]
Require authentication for CRUD access
# [ table ( permission_area = " ..." ) ]
Enable CRUD permission enforcement (e.g. " staff" checks staff: view , staff: create , etc.)
# [ key ]
Primary key (auto-generated UUID)
# [ timestamp ]
Auto-generated timestamp (DEFAULT now())
# [ default ( " value" ) ]
Default value
# [ references ( " table.column" ) ]
Foreign key reference
# [ on_delete ( " cascade" ) ]
FK delete action: cascade, set_null, restrict, no_action
# [ hooks ( before_create = " ..." ) ]
CRUD lifecycle hooks — call WASM handlers before/after operations
Supported Types
Rust Type
SQL Type
Uuid
UUID
String
TEXT
bool
BOOLEAN
i32
INTEGER
i64
BIGINT
f32
REAL
f64
DOUBLE PRECISION
DateTime< Utc>
TIMESTAMPTZ
NaiveDate
DATE
Value
JSONB
Option < T>
Nullable version of T
Foreign Keys
# [ derive ( Table, Serialize, Deserialize, Clone ) ]
# [ table ( name = " comments" ) ]
pub struct Comment {
# [ key ] pub id : Uuid,
# [ references ( " posts.id" ) ]
# [ on_delete ( " cascade" ) ]
pub post_id : Uuid,
pub body : String,
}
CLI Reference
Command
Description
cufflink init < name>
Scaffold a new service project
cufflink deploy
Deploy the service in the current directory
cufflink deploy - - allow- destructive
Allow DROP COLUMN / DROP TABLE
cufflink rollback
Rollback to previous version
cufflink rollback - - version N
Rollback to specific version
cufflink status
Show service status and endpoints
cufflink services
List all deployed services
cufflink logs
Stream service logs
cufflink openapi
Print OpenAPI spec
cufflink openapi - - output spec. json
Save OpenAPI spec to file
cufflink generate- client
Generate TypeScript client
cufflink login
Authenticate with the platform
Configuration
Env Var
Default
Description
CUFFLINK_API_URL
http://localhost:8080
Platform API URL
CUFFLINK_TENANT
default
Tenant slug
CUFFLINK_KEYCLOAK_URL
http://localhost:8180
Keycloak URL
CUFFLINK_CLIENT_ID
cufflink-cli
Keycloak client ID
API Endpoints
Management API
Method
Path
Description
GET
/health
Health check
POST
/api/auth/bootstrap
Create first API key (no auth)
POST
/api/auth/api-keys
Create API key (requires auth)
GET
/api/auth/me
Get authenticated user info
GET
/api/services
List all services
GET
/api/services/{id}
Get service details
DELETE
/api/services/{id}
Delete a service
POST
/api/services/deploy
Deploy a service
GET
/api/services/{id}/deployments
Deployment history
POST
/api/services/{id}/rollback
Rollback deployment
GET
/api/services/{id}/openapi.json
Auto-generated OpenAPI spec
POST
/api/services/{id}/wasm
Upload WASM module
GET
/api/services/{id}/wasm/status
WASM runtime status
Dynamic CRUD Routes
Method
Path
Description
GET
/svc/{tenant}/{service}/{table}
List records
POST
/svc/{tenant}/{service}/{table}
Create record
GET
/svc/{tenant}/{service}/{table}/{id}
Get record
PUT
/svc/{tenant}/{service}/{table}/{id}
Update record
DELETE
/svc/{tenant}/{service}/{table}/{id}
Delete record
Query Parameters
Parameter
Example
Description
page
? page= 2
Page number
per_page
? per_page= 25
Items per page (max 200)
sort
? sort= - created_at, title
Sort (prefix - for DESC)
search
? search= hello
Full-text search across text columns
filter
? filter= [ { " n" : " status" , " f" : " =" , " v" : " active" } ]
JSON filter array
select
? select= id, title
Column selection
Filter Operators
= , != , > , < , >= , <= , LIKE , ILIKE , IN , IS NULL , IS NOT NULL
Authentication
Bootstrap (first-time setup)
curl - X POST http://localhost:8080/api/auth/bootstrap \
-H " Content-Type: application/json" \
-d ' {"tenant_name": "My Org", "tenant_slug": "my-org"}'
Using API Keys
curl - H " Authorization: ApiKey ck_..." http://localhost:8080/api/auth/me
CLI Login
cufflink login
Project Structure
cufflink/
├── platform/ # Axum- based platform server
├── worker/ # WASM worker process ( scales independently)
├── cli/ # CLI tool ( cufflink binary)
├── sdk/ # User- facing SDK crate
├── sdk- macros/ # Proc macros ( # [ derive ( Table ) ] , service! { } )
├── types/ # Shared types ( ServiceManifest, etc. )
├── web/ # Next. js web admin dashboard
├── examples/
│ ├── todo- service/ # Simple single- table example
│ └── blog- service/ # Multi- table example with FK
├── docker- compose. yml
├── Dockerfile. platform
└── Dockerfile. worker
Development
# Build everything
cargo build --workspace
# Run tests
cargo test --workspace
# Run platform locally (requires Docker services)
docker compose up -d postgres nats keycloak
cargo run -p cufflink-platform
# Run web admin locally
cd web && npm install && npm run dev
License
MIT