- clarify BEDS is compliance-friendly architecture, not certification - add healthcare/regulated deployment framing to visual brief - document controls BEDS provides vs contract implementation responsibilities - update wiki index description for regulated-deployment positioning
185 lines
8.7 KiB
Markdown
185 lines
8.7 KiB
Markdown
# Architecture Overview
|
|
|
|
## The Central Principle
|
|
|
|
**BEDS is AMQP-first. No component in the application layer ever touches a database directly. Ever.**
|
|
|
|
This is not a guideline. It is the architectural constraint that makes everything else possible. If you find yourself writing code that calls a database adapter directly from outside the broker layer, you are breaking the framework.
|
|
|
|
## System Diagram
|
|
|
|
```
|
|
External Client
|
|
│
|
|
│ HTTP / WebSocket / REST
|
|
▼
|
|
┌─────────────┐
|
|
│ appServer │ ← your application logic lives here
|
|
│ node │
|
|
└──────┬──────┘
|
|
│
|
|
│ AMQP event (routing key: rec.write, rel.read, log, etc.)
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ RabbitMQ Broker │
|
|
│ │
|
|
│ Exchange: beds.events (topic) │
|
|
│ Exchange: beds.logs (topic) │
|
|
└──────┬──────────────────┬───────┘
|
|
│ │
|
|
▼ ▼
|
|
┌────────────┐ ┌────────────┐
|
|
│ Broker │ │ admin │
|
|
│ Pool │ │ node │
|
|
│ (Tokio │ │ │
|
|
│ tasks) │ │ logging │
|
|
└──────┬─────┘ │ auditing │
|
|
│ │ metrics │
|
|
▼ └─────┬──────┘
|
|
┌────────────┐ │
|
|
│ Factory │ ▼
|
|
│ Dispatch │ ┌────────────┐
|
|
└──────┬─────┘ │ MongoDB │
|
|
│ │ msLogs │
|
|
▼ └────────────┘
|
|
┌────────────────────────┐
|
|
│ NamasteCore Trait │
|
|
│ (unified CRUD iface) │
|
|
└──────┬─────────────────┘
|
|
│
|
|
├──────────────────────────┐
|
|
▼ ▼
|
|
┌────────────┐ ┌────────────┐
|
|
│ MongoDB │ │ MariaDB │
|
|
│ Adapter │ │ Adapter │
|
|
│ (REC) │ │ (REL) │
|
|
└──────┬─────┘ └──────┬─────┘
|
|
│ │
|
|
▼ ▼
|
|
┌────────────┐ ┌────────────┐
|
|
│ MongoDB │ │ MariaDB │
|
|
│ Collections│ │ Tables / │
|
|
│ │ │ Procs / │
|
|
│ │ │ Views │
|
|
└────────────┘ └────────────┘
|
|
```
|
|
|
|
## Layers
|
|
|
|
### 1. Transport Layer (AMQP)
|
|
|
|
RabbitMQ is the backbone. All inter-component communication flows through it. This includes:
|
|
|
|
- Client data requests (read, write, update, delete)
|
|
- Log events from all nodes
|
|
- Audit records
|
|
- Migration jobs
|
|
- Warehouse operations
|
|
|
|
The transport layer knows nothing about databases. It routes messages. That is all.
|
|
|
|
### 2. Broker Pool (Tokio tasks)
|
|
|
|
Each node runs a pool of async broker tasks. Each task listens on one queue, processes one message at a time, and routes the result back via AMQP. The pool size is configured per broker type in `beds.toml`.
|
|
|
|
The broker pool is the throttle for the entire system. By adjusting instance counts, you control how many concurrent database operations the node performs — without changing a line of code.
|
|
|
|
Broker tasks are supervised. A panicked task is logged and replaced. The pool does not shrink on failure.
|
|
|
|
### 3. Factory Dispatch
|
|
|
|
A broker task receives an event containing a template name (e.g. `"Users"`, `"Sessions"`). The factory maps that name to the correct adapter — MongoDB for REC templates, MariaDB for REL templates. The factory does not know which template will be requested at compile time; dispatch is runtime.
|
|
|
|
### 4. NamasteCore Trait
|
|
|
|
The unified CRUD interface. Every database adapter implements it. Every template is a struct that selects an adapter and delegates to it. The application layer calls `NamasteCore` methods — it never calls adapter methods directly.
|
|
|
|
```rust
|
|
pub trait NamasteCore {
|
|
async fn create_record(&self, payload: &Payload) -> Result<Response, BedsError>;
|
|
async fn fetch_records(&self, query: &Query) -> Result<Vec<Response>, BedsError>;
|
|
async fn update_record(&self, payload: &Payload) -> Result<Response, BedsError>;
|
|
async fn delete_record(&self, id: &str) -> Result<Response, BedsError>;
|
|
}
|
|
```
|
|
|
|
### 5. Database Adapters
|
|
|
|
Two adapters, one interface:
|
|
|
|
- **REC adapter** — MongoDB. Document store. Schema-flexible. High-throughput appends. Used for logs, events, user profiles, audit records, anything that benefits from document structure.
|
|
- **REL adapter** — MariaDB. Relational store. SQL joins, transactions, strict schema. Used for anything that benefits from referential integrity.
|
|
|
|
Adapters do not write SQL or MongoDB queries. They call named database objects — stored procedures, views, functions — that the DBA owns. The adapter layer calls the object by name and passes parameters. It does not construct queries.
|
|
|
|
### 6. DBA-Owned Schema
|
|
|
|
The application layer never writes a query. All data access goes through named database objects. This is the separation of concerns that made Namaste maintainable across years and multiple development teams.
|
|
|
|
Adding a new data domain means:
|
|
1. DBA writes the schema (table/collection, views, stored procedures)
|
|
2. Developer writes a BEDS template (a TOML config file)
|
|
3. BEDS generates the adapter binding
|
|
|
|
Nothing else changes.
|
|
|
|
## The CALGON Pattern
|
|
|
|
Some operations cannot return an immediate result — long-running aggregations, migration jobs, warehouse operations. BEDS handles these with the **CALGON** pattern (async ticket):
|
|
|
|
1. Client submits a request
|
|
2. BEDS immediately returns a GUID ticket
|
|
3. The operation executes asynchronously
|
|
4. Client polls with the GUID to retrieve the result when ready
|
|
|
|
The client is never blocked on a long operation. The broker absorbs the work. This is the same pattern used by every major async job queue system, implemented natively in BEDS.
|
|
|
|
## Event Lineage
|
|
|
|
Every BEDS event carries a compound identifier:
|
|
|
|
```
|
|
event_id = "{node}.{env}.{guid}" # e.g. "ms.production.a1b2c3d4..."
|
|
parent_id = "" # empty string if this is a root event
|
|
depth = 0 # levels from the root event
|
|
```
|
|
|
|
A root event (an incoming client request) has `depth=0` and no parent. Every event it spawns (database calls, log events, audit records) carries the root's `event_id` as its `parent_id` and increments `depth`. This creates a complete, queryable tree of every operation triggered by a single client request.
|
|
|
|
Event lineage is how you answer "what actually happened when request X came in?" — without distributed tracing infrastructure.
|
|
|
|
## Configuration Drives Everything
|
|
|
|
BEDS has no node types in code. All nodes run the same binary. The configuration file determines:
|
|
|
|
- Which services this node runs (`is_local` per service)
|
|
- How many brokers of each type to spawn
|
|
- Which databases to connect to
|
|
- Whether this node is in production mode (fatal IPL failures) or development mode (non-fatal)
|
|
|
|
Changing a node's role means changing its config file and restarting. No code changes. No redeployment.
|
|
|
|
## Compliance-Oriented Deployment Pattern
|
|
|
|
BEDS can be used as the architecture baseline for regulated workloads (including healthcare contracts) because it enforces transport and execution boundaries by design.
|
|
|
|
Important framing:
|
|
|
|
- BEDS is not a compliance certification
|
|
- BEDS is a control-friendly runtime architecture
|
|
- Final compliance posture depends on infrastructure, policy, and operational practice
|
|
|
|
Why this architecture helps:
|
|
|
|
- AMQP-first messaging centralizes request flow and transport governance
|
|
- Template-driven dispatch limits ad hoc query behavior in application code
|
|
- Class -> Schema -> Base I/O layering keeps business logic separate from storage concerns
|
|
- Event lineage enables request-chain reconstruction for audits and incident review
|
|
|
|
What must be added in deployment for HIPAA-class programs:
|
|
|
|
- At-rest encryption and key lifecycle controls
|
|
- Strong service identity and TLS policy in production
|
|
- Access governance, least privilege, and operator accountability
|
|
- Log retention, backup/restore validation, and incident response processes
|