# 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` 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 ```bash 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`](./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`](./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`](./DOMAIN.md).