orjanda

package module
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

README

Orjanda

An agent-native business application framework written in Go.

Define a business entity once as a Go struct with oj tags, and Orjanda derives everything else from that single declaration — the database table, the CRUD API, the admin UI, and the AI-agent tool definitions — all enforcing the same permission rules.

Central thesis: if a Document exists in the Orjanda Registry, it is automatically operable by both a human and an embedded AI agent, with no per-entity integration code.

type LeaveRequest struct {
    schema.BaseDocument
    Reason   string `oj:"required"`
    Status   string `oj:"options=Draft|Submitted|Approved|Rejected,default=Draft"`
    Approved bool   `oj:"default=false"`
}

That struct alone gives you a leave_requests table, REST CRUD endpoints, a metadata-driven form in the admin UI, and agent tools — simultaneously, from one declaration.


Why Orjanda

Business applications share ~80% of their infrastructure — CRUD, forms, lists, permissions, search, audit — and every Go project rebuilds it by hand (PRD §3.1). Adding an AI agent to such an app is a second, parallel engineering effort: a tool definition, an input schema, a permission mapping, and error handling per entity, which then drifts out of sync with the source schema (PRD §3.2).

Orjanda collapses this to O(1) per entity: define the Document once, get the database, API, UI, and agent layer for free (PRD §2, §8). It is the closest Go equivalent to Frappe or Django Admin, purpose-built for Go's type system and for the reality that AI agents are first-class consumers of business applications.

Key Features

  • Code-first schemas — Documents are Go structs annotated with oj tags, compiled into a read-only Registry at startup. No runtime-editable metadata (PRD §8.4).
  • One declaration → four layers — a single Document yields the database table, REST + RPC API, metadata-driven admin UI, and agent tools, from the same compiled schema (PRD §9, §24).
  • Embedded AI Agent Runtime — a ReAct agent that calls the same document.* functions as the REST API. No separate agent backend, no separate permission path (PRD §23.1, §25.1).
  • Automatic tool generation — CRUD tools are generated per Document from the Registry at startup, and permission-checked per identity (TAD §10).
  • Secure by default — JWT auth, RBAC permissions, human approval gates for agent write operations, and transactional audit logging (PRD §25, §28, §29).
  • PostgreSQL + SQLite — pluggable dialect adapters with a custom query builder and Atlas/Goose-backed migrations (orjanda migrate diff/up).
  • Declared workflows & hooks — lifecycle hooks (before_save, after_insert, …) and role-gated state machines (PRD §19).
  • Single binary — the React admin UI is embedded in the Go binary via embed.FS; modular monolith, one deployable (PRD §9.1, §17.4).

Architecture at a Glance

Orjanda is a modular monolith: one Go binary that embeds the REST/RPC API, the admin UI, and the agent runtime. The compiled Registry is the single source of truth every layer reads from.

              ┌──────────────────────────────────────────────┐
              │            Single Go binary                  │
              │  ┌──────────┐  ┌──────────┐  ┌─────────────┐ │
              │  │ Admin UI │  │ REST/RPC │  │ Agent Chat  │ │
              │  │ (React,  │  │ API (Chi)│  │ (WebSocket) │ │
              │  │ embedded)│  └────┬─────┘  └──────┬──────┘ │
              │  └──────────┘       │               │        │
              │            ┌───────▼───────────────▼───┐    │
              │            │   Agent Runtime (ReAct)    │    │
              │            └───────┬───────────────▲───┘    │
              │            ┌───────▼───────────────┴───┐    │
              │            │  Document Engine (CRUD,    │    │
              │            │  validation, hooks, perms) │    │
              │            └───────┬───────────────────┘    │
              │        ┌───────────▼───────────┐            │
              │        │  Registry · Perm ·    │            │
              │        │  Audit · Workflows    │            │
              │        └───────────┬───────────┘            │
              │                    ▼                        │
              │        ┌─────────────────────┐              │
              │        │ DAL (dialects:      │              │
              │        │  PostgreSQL, SQLite)│              │
              │        └─────────────────────┘              │
              └──────────────────────────────────────────────┘

Every read and write — REST, RPC, agent tool, workflow transition — passes through the same perm.Engine (PRD §25.1). Full detail in the Technical Architecture Document.

Getting Started

Orjanda is a framework you consume, not a repository you clone. You install the orjanda CLI once, then orjanda init scaffolds your own Application — a new Go module that imports Orjanda as a dependency. You build your application on top of the framework; you never modify the framework source itself. This is the same model as django-admin startproject or bench init in Frappe.

1. go install the orjanda CLI           →  you get the orjanda command
2. orjanda init myapp                   →  your new Application (a Go module)
3. cd myapp && orjanda serve   →  your app's dev server, on :8080 (development is the default environment)
Prerequisites
  • Go 1.26+
  • Node.js 22+ (only if you are a framework contributor developing the admin UI — application users never need it, the UI ships embedded)
Install the CLI

Install the orjanda command once with Go:

go install github.com/orjanda-framework/orjanda/cmd/orjanda@latest

That is the only installation step. You do not clone the Orjanda repository to build an application. (Framework contributors who want to build the CLI from source should see Contributing.)

Scaffold your first Application
orjanda init myapp
cd myapp

myapp is your project — a new Go module built on top of Orjanda. This generates go.mod, main.go, app.go, an orjanda.yaml (SQLite dev defaults, with a commented auth.jwt_secret placeholder), and a migrations/ directory, with Orjanda wired in as a dependency.

Add a Document
orjanda new document LeaveRequest --module=leave --submittable

Then open documents/leave_request.go and declare your fields:

package documents

import (
	orjerrors "github.com/orjanda-framework/orjanda/errors"
	"github.com/orjanda-framework/orjanda/schema"
)

// LeaveRequest is a LeaveRequest business entity.
type LeaveRequest struct {
	schema.BaseDocument
	Reason   string `oj:"required"`
	Status   string `oj:"options=Draft|Submitted|Approved|Rejected,default=Draft"`
	Approved bool   `oj:"default=false"`
}

func (d *LeaveRequest) DocMeta() schema.Meta {
	return schema.Meta{
		Name:        "LeaveRequest",
		Module:      "leave",
		Submittable: true,
		Description: "Employee leave request",
	}
}

func (d *LeaveRequest) Get(field string) any {
	switch field {
	case "Reason":
		return d.Reason
	case "Status":
		return d.Status
	case "Approved":
		return d.Approved
	}
	return d.BaseDocument.Get(field)
}

func (d *LeaveRequest) Set(field string, value any) orjerrors.Error {
	switch field {
	case "Reason":
		if v, ok := value.(string); ok {
			d.Reason = v
			return nil
		}
	case "Status":
		if v, ok := value.(string); ok {
			d.Status = v
			return nil
		}
	case "Approved":
		if v, ok := value.(bool); ok {
			d.Approved = v
			return nil
		}
	}
	return d.BaseDocument.Set(field, value)
}
Run it

Still inside your myapp directory, start your application's server:

orjanda serve

orjanda serve runs in the development environment by default — selected by ORJANDA_ENV (or the env config key) only when you set it explicitly:

  • The development server compiles the Registry, auto-creates missing tables, and starts on http://127.0.0.1:8080 (SQLite by default).
  • On first run it bootstraps a system administrator (admin@localhost) and prints a one-time password to stdout.
  • When auth.jwt_secret is not configured, development orjanda serve generates an ephemeral dev secret (warns on startup) — fine for local exploration, but set a real secret in orjanda.yaml to keep sessions across restarts.
  • For production, run ORJANDA_ENV=production orjanda serve: it fails fast on any Registry, migration, or stale-codegen error, never auto-creates tables, and requires a real auth.jwt_secret (see the Configuration section and TAD §16).
  • Open the admin UI at http://127.0.0.1:8080LeaveRequest already appears in the sidebar with an auto-generated form and list.
  • Open http://127.0.0.1:8080/agent to chat with the embedded agent, which can already query and create LeaveRequest records under the same permissions as the UI.
Call the REST API

Log in to get a JWT, then use the standard CRUD endpoints:

TOKEN=$(curl -s -X POST http://127.0.0.1:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@localhost","password":"<one-time-password>"}' \
  | jq -r '.data.access_token')

curl http://127.0.0.1:8080/api/v1/document/LeaveRequest \
  -H "Authorization: Bearer $TOKEN"

REST routes live under /api/v1/document/{doctype}; see PRD §14 for the full API surface.

CLI Reference

Command Description
orjanda init <name> Scaffold a new Application (go.mod, main.go, app.go, orjanda.yaml, migrations/)
orjanda new document <name> Generate a Document scaffold and register it in app.go
orjanda new module <name> Generate a Module scaffold (documents/hooks/workflows/api/ui)
orjanda serve Start the site. ORJANDA_ENV (or the env config key) selects the environment: development (default) auto-creates tables, warns-and-continues on Registry errors, and generates an ephemeral JWT secret if unset; production (ORJANDA_ENV=production) fails fast on any Registry, migration, or stale-codegen error and requires a real auth.jwt_secret
orjanda migrate diff Generate migration SQL from schema changes
orjanda migrate up Apply pending migrations
orjanda migrate status Show migration status
orjanda console Interactive REPL with the site context
orjanda install <app> / uninstall <app> Run Application lifecycle hooks
orjanda test Run application tests against an ephemeral SQLite database
orjanda agent chat Terminal-based agent chat (great for testing)
orjanda registry list List all registered Documents
orjanda registry describe <doc> Show a Document's full compiled schema

Configuration

Configuration lives in orjanda.yaml (Viper), overridable by ORJANDA_ prefixed environment variables: the env deployment environment (development or production, via ORJANDA_ENV), server port/host/CORS, the database driver (postgres or sqlite) and DSN, the auth.jwt_secret JWT signing key (min 32 characters, via ORJANDA_AUTH_JWT_SECRET; development orjanda serve generates an ephemeral key when it is absent — production requires a real one), and LLM providers (OpenAI, Anthropic, and any OpenAI-compatible endpoint) plus agent safety limits. See TAD §1.3 for the authoritative schema.

Documentation

Document Answers
Product Requirements (PRD) Why and what — goals, decisions, rationale, worked examples
Technical Architecture (TAD) Exact shape — interfaces, data flows, algorithms, contracts

Project Status

Orjanda is a pre-1.0 MVP, developed against the scope in PRD §44. The MVP feature set — schema system, Registry, document engine, PostgreSQL + SQLite, migrations, REST/RPC API, JWT auth, RBAC permissions, admin UI, embedded agent runtime, auto tool generation, approval gates, audit log, hooks, workflows, and the orjanda CLI — is implemented and covered by unit and integration tests.

Post-MVP scope (multi-tenancy, MySQL, OpenTelemetry, background jobs, MCP server, and more) is explicitly deferred per PRD §44.3.

Versioning

Orjanda follows Semantic Versioning (MAJOR.MINOR.PATCH). Until 1.0, releases use 0.x.y where minor bumps may include breaking changes. The CHANGELOG tracks releases; the first public release will be v0.1.0.

License

Orjanda is licensed under the Apache License 2.0. See LICENSE.

Contributing

Orjanda is developed as a framework in its own repository. Application developers never clone it — if you want to work on the framework itself, welcome! Please read CONTRIBUTING.md first — it covers development setup, build/test commands, formatting, and the branch/PR workflow.

To build the orjanda CLI from framework source:

git clone https://github.com/orjanda-framework/orjanda.git
cd orjanda
go build -o orjanda ./cmd/orjanda

Report bugs and request features via the issue templates. This project adheres to the Contributor Covenant. For security vulnerabilities, follow the responsible-disclosure process in SECURITY.md.


Orjanda — if a Document exists in the Registry, it is automatically operable by both a human and an embedded AI agent.

Documentation

Overview

Package orjanda provides the central Site composition root and Application registration.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Site

type Site struct {
	Config      config.Config
	Registry    schema.Registry
	DB          dal.Database
	Permissions perm.Engine
	EventBus    event.Bus
	AuditLog    audit.Log
	Cache       cache.Store
	Auth        auth.Provider
	DocEngine   *document.Engine
	Workflows   workflow.Engine
	Tools       tools.ToolRegistry
	Pages       ui.Registry
	Router      *chi.Mux
	// contains filtered or unexported fields
}

Site is the central composition root wiring database, schema registry, permission engine, event bus, audit log, cache, auth provider, document engine, workflow engine, agent tool registry, admin UI page registry, and HTTP router. See TAD §12.4.

func NewSite

func NewSite(cfg config.Config) (*Site, error)

NewSite initializes a new Site with the provided configuration.

func (*Site) Compile

func (s *Site) Compile() error

Compile compiles the schema registry, wires engines, and mounts HTTP routes.

func (*Site) HTTPHandler

func (s *Site) HTTPHandler() http.Handler

HTTPHandler returns the composed request handler: API routes plus the embedded Admin UI single-page application (PRD §17.4). It is the handler the server package serves; ServeHTTP delegates to it.

func (*Site) InitAuditLog

func (s *Site) InitAuditLog() error

InitAuditLog upgrades the site's audit log to a DB-backed log when the configured database supports it: it creates the audit table (TAD §13) and registers the table's docType mapping so Engine writes commit inside the same dal.Tx. Without a supporting database the in-memory log is kept, so a nil DB or an embedding that can't reach the raw connection degrades safely. Called by Compile; exported for harnesses that wire engines by hand.

func (*Site) Install

func (s *Site) Install(appDef app.Definition)

Install registers an Application definition into the site before compilation.

func (*Site) InstalledApps

func (s *Site) InstalledApps() []app.Definition

InstalledApps returns the Application definitions registered via Install. Used by the CLI's install/uninstall commands (TAD §16).

func (*Site) RegisterPage

func (s *Site) RegisterPage(p ui.Page)

RegisterPage adds a custom Admin UI page (TAD §9.1 / PRD §18.3).

func (*Site) ServeHTTP

func (s *Site) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler, delegating to the composed handler.

Directories

Path Synopsis
Package agent is the embedded AI Agent Runtime package (PRD §23).
Package agent is the embedded AI Agent Runtime package (PRD §23).
llm
Package llm defines the llm.Provider interface and implements the OpenAI, openai_compatible, and Anthropic adapters with streaming, tool-calling, structured-output support, failover, circuit-breaking, and token tracking.
Package llm defines the llm.Provider interface and implements the OpenAI, openai_compatible, and Anthropic adapters with streaming, tool-calling, structured-output support, failover, circuit-breaking, and token tracking.
planner
Package planner defines the Plan/PlanStep structured-output contract and the whole-plan pre-execution validation logic used in Plan-and-Execute mode.
Package planner defines the Plan/PlanStep structured-output contract and the whole-plan pre-execution validation logic used in Plan-and-Execute mode.
runtime
Package runtime implements the agent execution loop (Runtime.Execute), Session Manager, and Context Manager with the discovery/operation tool split (TAD §11.1) and ReAct/Plan-and-Execute mode switching (TAD §11.2).
Package runtime implements the agent execution loop (Runtime.Execute), Session Manager, and Context Manager with the discovery/operation tool split (TAD §11.1) and ReAct/Plan-and-Execute mode switching (TAD §11.2).
safety
Package safety implements SafetyPolicy and SafetyLayer: the five-step approval-evaluation order (Always → Bulk → RoleOverride → RequireApproval → AutoApprove), rate limiting, token budgets, and tool allowlists.
Package safety implements SafetyPolicy and SafetyLayer: the five-step approval-evaluation order (Always → Bulk → RoleOverride → RequireApproval → AutoApprove), rate limiting, token budgets, and tool allowlists.
tools
Package tools implements the ToolRegistry: Compile (run once after Registry.Compile) and ForIdentity (run per agent turn) following the deterministic O(len(CompiledDocs)) generation algorithm in TAD §10.
Package tools implements the ToolRegistry: Compile (run once after Registry.Compile) and ForIdentity (run per agent turn) following the deterministic O(len(CompiledDocs)) generation algorithm in TAD §10.
api
Package api implements the HTTP API surface on Chi: REST CRUD handlers, RPC method dispatch, the Metadata API, and the middleware chain (CORS → Auth → RateLimit → Permission → Handler).
Package api implements the HTTP API surface on Chi: REST CRUD handlers, RPC method dispatch, the Metadata API, and the middleware chain (CORS → Auth → RateLimit → Permission → Handler).
middleware
Package middleware contains the Chi middleware stack applied to every incoming HTTP request: CORS, Auth (JWT extraction), Rate Limit, and Permission (perm.Engine.CheckAction).
Package middleware contains the Chi middleware stack applied to every incoming HTTP request: CORS, Auth (JWT extraction), Rate Limit, and Permission (perm.Engine.CheckAction).
render
Package render provides HTTP response serialization and standardized error formatting.
Package render provides HTTP response serialization and standardized error formatting.
rest
Package rest contains the REST handler implementations for the six standard Document operations (list, get, create, update, delete, submit).
Package rest contains the REST handler implementations for the six standard Document operations (list, get, create, update, delete, submit).
rpc
Package rpc dispatches POST /api/v1/method/{app}.{module}.{method} requests to registered api.MethodHandler implementations, enforcing AllowedRoles through the shared perm.Engine path (TAD §9.2).
Package rpc dispatches POST /api/v1/method/{app}.{module}.{method} requests to registered api.MethodHandler implementations, enforcing AllowedRoles through the shared perm.Engine path (TAD §9.2).
Package app defines the Application and Module system: app.Definition, app.Module, app.Dependency, dependency-DAG resolution, and the Installable/ Upgradable/Uninstallable lifecycle interfaces resolved via Definition.Hooks (the TAD §7 "associated init type").
Package app defines the Application and Module system: app.Definition, app.Module, app.Dependency, dependency-DAG resolution, and the Installable/ Upgradable/Uninstallable lifecycle interfaces resolved via Definition.Hooks (the TAD §7 "associated init type").
Package audit provides the immutable audit log: Entry, FieldChange, and Log.Write/Query.
Package audit provides the immutable audit log: Entry, FieldChange, and Log.Write/Query.
Package auth defines the Identity and UserInfo types, the auth.Provider interface, and the default JWT-based implementation (bcrypt passwords, 15-minute access tokens, 7-day rotating refresh tokens).
Package auth defines the Identity and UserInfo types, the auth.Provider interface, and the default JWT-based implementation (bcrypt passwords, 15-minute access tokens, 7-day rotating refresh tokens).
Package background defines the background.Job and background.Queue interfaces plus an in-memory, non-durable stub Queue for the MVP.
Package background defines the background.Job and background.Queue interfaces plus an in-memory, non-durable stub Queue for the MVP.
Package cache exposes the cache.Store interface and an in-process LRU default implementation used for Registry metadata caching and per-request permission-check caching.
Package cache exposes the cache.Store interface and an in-process LRU default implementation used for Registry metadata caching and per-request permission-check caching.
Package cli contains the Cobra command implementations backing the orjanda binary: serve, migrate, new, init, console, agent, registry, install, uninstall, and test.
Package cli contains the Cobra command implementations backing the orjanda binary: serve, migrate, new, init, console, agent, registry, install, uninstall, and test.
cmd
orjanda command
Command orjanda is the Orjanda framework CLI binary (TAD §16, PRD §21).
Command orjanda is the Orjanda framework CLI binary (TAD §16, PRD §21).
Package config implements the Viper-backed configuration loader for Orjanda.
Package config implements the Viper-backed configuration loader for Orjanda.
dal
Package dal implements the Data Access Layer: Database/Tx/Dialect interfaces, query builder, transaction management, and Migrator (TAD §2.3, §14, PRD §13).
Package dal implements the Data Access Layer: Database/Tx/Dialect interfaces, query builder, transaction management, and Migrator (TAD §2.3, §14, PRD §13).
dialect/postgres
Package postgres provides the PostgreSQL dialect for Orjanda's DAL.
Package postgres provides the PostgreSQL dialect for Orjanda's DAL.
dialect/sqlite
Package sqlite provides the SQLite dialect for Orjanda's DAL.
Package sqlite provides the SQLite dialect for Orjanda's DAL.
Package document implements the Document Engine: Create, Read, Update, Delete, and List operations driven by the compiled Registry schema, with field validation, lifecycle hooks, permission enforcement, and audit logging.
Package document implements the Document Engine: Create, Read, Update, Delete, and List operations driven by the compiled Registry schema, with field validation, lifecycle hooks, permission enforcement, and audit logging.
Package errors defines the framework-wide error model: ErrorCode enum, the Error interface, constructor helpers, and HTTP status mapping.
Package errors defines the framework-wide error model: ErrorCode enum, the Error interface, constructor helpers, and HTTP status mapping.
Package event provides the synchronous, in-process event bus used for Document lifecycle hooks (before_save, after_insert, etc.).
Package event provides the synchronous, in-process event bus used for Document lifecycle hooks (before_save, after_insert, etc.).
internal
version
Package version reads version metadata from the running binary's build info.
Package version reads version metadata from the running binary's build info.
Package core defines the bootstrapped core application for identity, roles, and permissions.
Package core defines the bootstrapped core application for identity, roles, and permissions.
Package perm implements the permission engine: RBAC document-level checks from DocPermission metadata, ABAC via registered perm.Rules, and field-level filtering via FilterRead/FilterWrite.
Package perm implements the permission engine: RBAC document-level checks from DocPermission metadata, ABAC via registered perm.Rules, and field-level filtering via FilterRead/FilterWrite.
Package schema contains the Document contract, BaseDocument/BaseChild embed types, the CompiledDoc/Field metadata types, the oj struct-tag parser, and the Registry that stores every registered Document after compilation.
Package schema contains the Document contract, BaseDocument/BaseChild embed types, the CompiledDoc/Field metadata types, the oj struct-tag parser, and the Registry that stores every registered Document after compilation.
Package search exposes the search.Backend interface and a default adapter that delegates to the active dal.Dialect's FullTextSearch — no external search process is required for the MVP.
Package search exposes the search.Backend interface and a default adapter that delegates to the active dal.Dialect's FullTextSearch — no external search process is required for the MVP.
Package server is the HTTP assembly root: it wires the Registry, Database, permission engine, event bus, cache, and Admin UI into the orjanda.Site composition root and starts the Chi HTTP server.
Package server is the HTTP assembly root: it wires the Registry, Database, permission engine, event bus, cache, and Admin UI into the orjanda.Site composition root and starts the Chi HTTP server.
Package testing (imported as orjanda/testing) provides the first-class test harness: NewTestSite, WithApps, WithDialect, CreateUser, WithUser, SeedFixtures, MockLLM, ToolCall, TextResponse, and ApprovalPrompt.
Package testing (imported as orjanda/testing) provides the first-class test harness: NewTestSite, WithApps, WithDialect, CreateUser, WithUser, SeedFixtures, MockLLM, ToolCall, TextResponse, and ApprovalPrompt.
Package ui provides the admin UI page registry (TAD §9.1) and the codegen input contract consumed by the @orjanda/codegen pass (TAD §6.3).
Package ui provides the admin UI page registry (TAD §9.1) and the codegen input contract consumed by the @orjanda/codegen pass (TAD §6.3).
Package workflow implements the state-machine workflow engine: Definition, State, Transition, GuardFunc, and Engine.Execute — all enforced through the shared perm.Engine (no bespoke permission path).
Package workflow implements the state-machine workflow engine: Definition, State, Transition, GuardFunc, and Engine.Execute — all enforced through the shared perm.Engine (no bespoke permission path).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL