No description
Find a file
David Kong 96b6bc1e78 docs: harmonize AGENTS.md, DOMAIN.md, and README.md — fix inconsistencies across all three documents
- Expand BDP section in AGENTS.md from 4 entities to 18+ (Invoices, Inventory, Employees, Business Units, Locations, Suppliers, Manufacturers, Returns/RMA, Templates, Tasks & Task Lists, Service Jobs, Status Definitions, Sequences, Financial Accounts)
- Add Rust edition 2024 and missing crates to AGENTS.md Technical Implementation (serde, config, dotenvy, thiserror, tracing)
- Add Coding Conventions table for BDP section in AGENTS.md
- Update Database Configuration with specific variables (DATABASE_URL, server__host, server__port)
- Add Domain Concepts section referencing DOMAIN.md in AGENTS.md (_underscore fields, reference resolution pattern, AUD default currency, BU allocation)
- Add Domain Concepts section to README.md filling gaps
- Peer harmonization approach: no single source of truth; all three docs are peers with cross-references

See HARMONIZATION_DIFF.md for before/after diff summary.
2026-06-26 21:11:17 +10:00
AGENTS.md docs: harmonize AGENTS.md, DOMAIN.md, and README.md — fix inconsistencies across all three documents 2026-06-26 21:11:17 +10:00
README.md docs: harmonize AGENTS.md, DOMAIN.md, and README.md — fix inconsistencies across all three documents 2026-06-26 21:11:17 +10:00

GraphQL Business Data Platform

A performant GraphQL API that provides structured access, storage, and organisation of business data, optimized for agentic applications.

Background

A business data platform serving as the backbone for agentic and user facing applications. It stores and manages a comprehensive array of business data such as orders, documents, customers and products providing the foundation to build more complex applications and workflows.

Tech Stack

Component Details
Language Rust (edition 2024)
GraphQL Juniper (juniper, juniper_actix)
HTTP Server Actix-web
Async Runtime Tokio
Database PostgreSQL via SQLx (sqlx-postgres)
Serialization Serde / serde_json
Config Config crate (.env + env vars with __ separator)
Env Loading Dotenvy
Error Handling Thiserror
Logging Tracing, tracing-subscriber, tracing-actix-web

Folder Structure

Pending — source code has not yet been scaffolded.

The server repo is in early-stage development. Once the codebase is scaffolded, a folder structure section will be added here reflecting the actual layout. Refer to AGENTS.md for architectural patterns (repository pattern, context object, middleware chain) that guide the expected structure.

Coding Conventions

Convention Detail
Indentation 4 spaces for Rust; 2 spaces for YAML/JSON/TOML
File naming One struct/type per file; file name matches type (e.g. product_card.rs)
Module visibility pub(crate) for internal-only modules; pub for public-facing ones (graphql/models, canonical)
Struct naming PascalCase (e.g. ProductCard, MeilisearchRepository)
Enum naming PascalCase names, uppercase variants (e.g. ProductTagStyle::STANDARD)
Field naming snake_case (e.g. product_id, price_as_cents)
Derive macros GraphQL objects: #[derive(Debug, Deserialize, Serialize, GraphQLObject)]; enums use GraphQLEnum
Error handling Box<dyn Error> in repository layer; context errors propagated via FieldResult
Async traits Repository interfaces use #[async_trait] for async method definitions
Configuration loading Config crate builder pattern: defaults → .env (via dotenvy) → env vars (__ separator). E.g. server__host maps to server.host

Build Setup

Prerequisites

  • Rust toolchain (edition 2024 compatible)
  • PostgreSQL database server

Running the Server

cargo run

Environment Configuration

Database connection parameters are configured via environment variables using the __ separator convention:

Variable Purpose
DATABASE_URL Full PostgreSQL connection string (e.g. postgres://user:pass@host:port/dbname)
server__host Server bind host address
server__port Server bind port number

Create a .env file with your configuration values before running the server. The config crate loads defaults → .env → environment variables in that priority order.

Architecture Decisions

Repository Pattern

Abstract repository interfaces are defined as traits, with concrete implementations for each external data source or database operation. This decouples GraphQL resolvers from infrastructure details:

  • Interface: trait definitions in infra/repositories/traits/ (once scaffolded)
  • Implementation: concrete structs in infra/repositories/ (once scaffolded)

Context Object

A single shared context struct is passed to all GraphQL resolvers. It holds application configuration and repository clones, providing a uniform dependency injection point across the resolver layer.

Middleware Chain

HTTP middleware sits between Actix-web request handling and GraphQL execution, handling cross-cutting concerns (authentication, logging, CORS) before requests reach the schema layer.

Entity Overview Summary

The API manages the following entity types:

Entity Purpose
Orders Business transactions linking customers to products/services; supports MASTER/SUBORDER aggregation
Customers Person or company records with contacts, addresses, credit terms, and web portal access
Sales Quotes Proposed price lists presented to customers before order creation; includes optional items and system quotes
Products Items/services sold by the business with pricing, stock info, supplier part numbers, and category hierarchy
Invoices Billing documents (sales invoices, RMA returns, employee invoices) with payment tracking and tax breakdown
Inventory Individual stock units tracked by serial number or batch; supports scan-in/out and manufacturing tracking
Employees Staff records with payroll, schedule, entitlements, PAYG tax settings, and authentication links
Business Units Top-level organizational entities grouping employees, locations, customers, and financial accounts
Locations Physical sites associated with business units (warehouses, offices) with operating hours and addresses
Suppliers External vendors/service providers with credit terms, registration, and category profiles
Manufacturers External entities that produce goods; referenced by products for identification
Returns (RMA) Return merchandise authorization tracking: fault reporting, replacements, resolution actions
Templates Reusable blueprints for orders, quotes, emails, leads, tickets, and articles
Tasks & Task Lists Work items with scheduling, assignment, progress tracking, status history, and work done entries
Service Jobs Paid or warranty service performed for customers; includes work tracking and scheduling
Status Definitions Central registry of reusable status states with visual styling and allowed actions
Sequences Shared counters for auto-generating unique identifiers (order numbers, invoice numbers)
Financial Accounts Bank accounts or payment methods used by the business for transactions

Domain Concepts

Key domain concepts that agents should understand when working with the BDP:

  • _underscore fields — System-managed metadata prefixed with underscore (_id, _entered.by, _modified.ts, _total, _active). Never set by agents directly — computed or managed by the platform internally. See DOMAIN.md for full list.
  • Reference resolution pattern — All entity references follow reference._id → query the referenced entity using GraphQL. The referenced entity may have its own nested references (e.g., Order → Product → Category). See DOMAIN.md for reference resolution guide.
  • Default currency — AUD (Australian Dollar) across the platform. Other currencies supported: USD, EUR, NZD, GBP, HKD, SGD, RMB, CAD, AED, INR, PHP.
  • Business Unit & Location allocation — Every entity that participates in business operations must be assigned to a Business Unit and often a Location (required on save). Business Units define currency, locale (en-AU default), and tax settings (GST or No GST).
  • Master/Suborder aggregation — Orders can be grouped hierarchically; Master orders aggregate totals (_total, _exTotal, _payments, _owing) from all linked Suborders.
  • Classification/Profile pattern — Customers and Products use extendable schema-driven classification via classification.name, classification.profile._id, classification.profile.fields without hard-coding every possible attribute.

For comprehensive domain terminology, entity relationships, enums, and business concepts, see DOMAIN.md.