- Dart 57.4%
- JavaScript 23.3%
- Go 16.1%
- Astro 1.7%
- HTML 0.7%
- Other 0.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
# Description Backend implementation as per the spec #11 (backend.md) # Testing Checklist This testing can be fully automated using an LLM and cURL , this list is merely a checklist of the possibilities covered by the changes in this branch. ## Setup - Server running with `JWT_SECRET` set (no SMTP → OTP codes appear in the server log). - One sys-admin seeded out-of-band: `karriba-seed -email [email protected]`. - Base URL: `http://localhost:8080`. All responses are JSON; errors use `{"error":{"code","message"}}`. ## 1. Health & Auth - [x] `GET /v1/health` → `200 {"status":"ok","version":...}` (no auth) - [x] `POST /v1/auth/otp/request` (registered contact) → `200`, `expires_in:900`; code appears in log - [x] `POST /v1/auth/otp/request` (unregistered contact) → identical `200` (no code generated) - [x] `POST /v1/auth/otp/verify` with the logged code → `200` with `access_token`, `refresh_token`, correct `user` payload - [x] `POST /v1/auth/otp/verify` wrong code → `400 INVALID_OTP` - [x] `POST /v1/auth/refresh` with the returned token → `200` with a **new** `refresh_token`; reusing the old one → `401 REVOKED_TOKEN` ## 2. Access Control - [x] Any protected endpoint with no / invalid token → `401` - [x] Sys-admin token on a manager-only endpoint (list users) → `403 INSUFFICIENT_ROLE` - [x] Member accessing another org → `403` ## 3. Orgs (sys-admin token) - [x] `POST /v1/orgs` → `201`; `initial_manager.role:"manager"`; a tenant DB file for the new org id is created - [x] `GET /v1/orgs/:id` → `200` with `user_count` - [x] `PATCH /v1/orgs/:id` rename → `200`; archive, then confirm members get `403` while sys-admin still reads it ## 4. Users (manager token) - [x] `GET /v1/orgs/:id/users` → `200` - [x] `POST /v1/orgs/:id/users` invite member → `201` - [x] Invite with a bad role (e.g. `"supervisor"`) → `400 INVALID_ROLE` - [x] Demote the only manager → `400 ORG_REQUIRES_MANAGER` - [x] Member self-leave `DELETE .../users/:selfId` → `204` ## 5. Pagination - [x] `GET /v1/orgs/:id/users?limit=1` → 1 item + non-null `next_cursor` - [x] Re-request with `?limit=1&cursor=<value>` → next page; last page has `next_cursor:null` ## 6. Entitlements - [x] `GET /v1/orgs/:id/entitlements` (any member) → `200` - [x] `PUT /v1/orgs/:id/entitlements` (sys-admin) `["pesticide","cloud_sync"]` → `200` - [x] `PUT` `["cloud_sync"]` alone → `400 ENHANCEMENT_REQUIRES_STANDALONE` (with `module`/`requires`) - [x] `PUT` unknown module → `400 INVALID_MODULE` - [x] `PUT` as manager/member → `403` ## 7. Rate Limiting (needs a proxy-free direct hit) - [x] Fire >30 auth requests from one IP within a minute → excess → `429 RATE_LIMITED` - [x] Confirm normal traffic recovers after the window ## Notes - Timestamps are RFC 3339 UTC; IDs are UUIDv7. - Automated coverage exists for: OTP lockout/expiry, refresh reuse family-revocation, all role guards, invalid module/role codes, and the entitlement→tenant-DB sync. Co-authored-by: Julian Campana <[email protected]> Co-authored-by: Addison Emig <[email protected]> Reviewed-on: #158 Reviewed-by: addison <[email protected]> |
||
| .agents | ||
| .forgejo | ||
| .github/workflows | ||
| app | ||
| backend | ||
| meetings/2025 | ||
| site | ||
| specs | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| AGENTS.md | ||
| CONTRIBUTING.md | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| LICENSE | ||
| MAINTAINERS | ||
| README.md | ||
Karriba 🌾
Records for the field
Karriba is an offline-first agricultural record keeping app for farms and agricultural operations.
Learn more at karriba.com.
Features
- 📱 Mobile & Web - Works on Android and in the browser
- 📶 Local-First - Your data stays on your device. Works offline.
- 📄 PDF Reports - Generate professional documentation
- 💾 Data Sovereignty - Your data, your control. Export anytime.
Modules
Available
- 🧪 Pesticides - Track pesticide applications and generate compliance reports
Coming Soon
- 🚜 Manure - Log manure and litter
- 🐄 Livestock - Track births, breeding, and lineage
- 🗺️ Maps - Pin locations and draw field boundaries
- 🍎 Orchard Bin Tracking - Track bins picked and send daily updates
- 🚁 Spray Drone - Log flight records for spray drone operations
- 🔄 Crop Rotation - Plan and track crop rotations
See specs/ for detailed module specifications.
Development
Prerequisites
Getting Started
just deps # Install dependencies
specture ls # List available specifications
just run # Run the app
just run-web # Run on web
Building
just build-apk # Android APK
just build-web # Web
Backend
The backend is a Go REST API. See specs/backend.md for the full spec.
- Stack: Go 1.23, chi router,
mattn/go-sqlite3(CGO) - Auth: email OTP + thin JWT (only
sub+sidclaims; authority is loaded from the Admin DB on every request so role changes take effect immediately) - Multi-tenancy: one SQLite database per organization under
data/tenants/<org-id>.db, plus a single Admin DB atdata/admin.dbfor cross-tenant identity, memberships, and entitlements - Account creation is invite-only — new users only enter the system via a manager invite, an initial-manager assignment by a sys-admin, or the seed CLI below
just backend-deps # Download Go dependencies
just backend-run # Start dev server (port 8080)
just backend-test # Run tests
just backend-check # Run vet + build + tests (matches CI)
just backend-build # Compile the server binary
just backend-build-seed # Compile the sys-admin seed CLI
just backend-docker # Build Docker image
Provisioning a sys-admin
Sys-admins are platform-level operators (they can create orgs, manage entitlements, and archive orgs). They cannot be created through the API — only via the out-of-band seed CLI:
just backend-seed-sysadmin EMAIL=[email protected]
If the user already exists with no org membership, they are promoted; otherwise a new sys-admin user is created.
Required environment variables
| Variable | Description | Default |
|---|---|---|
JWT_SECRET |
Secret key for signing JWTs | (required) |
PORT |
Server port | 8080 |
DATA_DIR |
Directory for SQLite databases | data |
LOG_LEVEL |
Log level (debug, info, warn, error) |
info |
SMTP_HOST |
SMTP host for OTP delivery | (logs OTPs if unset) |
SMTP_PORT |
SMTP port | 587 |
SMTP_FROM |
Sender email address | — |
SMTP_USER |
SMTP username | — |
SMTP_PASS |
SMTP password | — |
Continuous integration
Forgejo workflows under .forgejo/workflows/:
pr-build.yml— builds the Flutter Android APK on every PR touchingapp/**backend-ci.yml— runsgo mod tidycheck,gofmt,go vet,go build, andgo teston every push or PR touchingbackend/**flutter-ci.yml— Flutter analyze + testsrelease.yml— produces release APKs and attaches them to Forgejo releases
Documentation
Contributing
Before contributing, please review our LICENSE. All contributions are made under this license.
Contact us at [email protected]
License
Made with care by Kwila Development.